I’ve got a 2D NumPy Array derived from a Digital Elevation Model. I’m iterating through a series of specific row/col locations in the array and for each specified location, I’d like to define the nearest element whose value is lower than the current element I’m querying. Through the help of @dmh126 (Nearest numpy array element whose value is less than the current element), I’ve figured out the slice and the distance calculations, but I’m having trouble getting the coordinates of the “nearest” element from the sliced array back to the original. When the search element is near the center of the array, things work fine, but when the search element is near the axis edges, my slice entries become negative; which I believe can be a problem. I can’t seem to get the logic correct to transfer the coordinates of my “nearest” element from the sliced array back to the original for further processing. Any thoughts on what I’m doing wrong?
So far I’ve got:
# Window dimensions in metres
max_search_dist_m = 100
# Cell size of source DEM
CELLX = 1.0
# Array dimensions
arrayRowCount = array.shape[0]
arrayColCount = array.shape[1]
# Get the element value at the search location
theSinkZ = float(array[theSinkRow][theSinkCol])
# Define search window size
SinkWindow = int((float(max_search_dist_m) / float(CELLX)) / 2)
# Define corner elements for search window
col_min = theSinkCol - SinkWindow
col_max = theSinkCol + SinkWindow
row_min = theSinkRow - SinkWindow
row_max = theSinkRow + SinkWindow
col_min_orig = col_min
row_min_orig = row_min
# Define “windowed sink row/col” location. This is intended to be the row/col of the original search element relative to the sliced array.
if col_min < 0:
col_min = 0
WindowedSinkCol = SinkWindow + col_min_orig
else:
WindowedSinkCol = SinkWindow
if col_max > arrayColCount: col_max = arrayColCount
if row_min < 0:
row_min = 0
WindowedSinkRow = SinkWindow + row_min_orig
else:
WindowedSinkRow = SinkWindow
# Slice array to search window
# Get rows and columns where value is less than theSinkZ
c,e = np.where(array[int(col_min):int(col_max), int(row_min):int(row_max)] < theSinkZ)
# Create a list of row/cols less than theSinkZ
y = zip(c,e)
# If solution exists, proceed.
if len(y) > 0:
# first distances are calculated between (row, col) of your input value, than nearest index value is selected.
d = np.argmin(cdist(np.array([[WindowedSinkRow,WindowedSinkCol]]), y))
# Extract nearest row/col location of Sliced array
WindowedOutCol = y[d][1]
WindowedOutRow = y[d][0]
# Identify outlet location relative to original full array
theOutCol = theSinkCol + col_min
theOutRow = theSinkRow + row_min