@@ -79,6 +79,22 @@ def patch_touches_cell_with_value(coordinates, tile, neighbour_values):
7979 return True
8080 return False
8181
82+ def patch_touches_raster_edge (coordinates , raster_nrows , raster_ncols ):
83+ """
84+ Takes a list of [row, column] cell coordinates and inspects if at least one of the coordinates
85+ is located exactly at the specified edge of the tile.
86+ This function can be used for detecting patches touching the raster bounding box.
87+ :param coordinates: The patch of same-value raster cells.
88+ :param raster_nrows: Number of rows in the whole source raster.
89+ :param raster_ncols: Number of columns in the whole source raster.
90+ :return: True if at least one cell in the patch is located at source raster edge.
91+ """
92+ for coor in coordinates :
93+ if coor [0 ] == 0 or coor [1 ] == 0 or coor [0 ] == raster_ncols - 1 or coor [1 ] == raster_nrows - 1 :
94+ return True
95+ return False
96+
97+
8298def export (regions , raster_ds , gpkg_filepath ):
8399 """
84100 Exports a list of lessMMU region dictionaries to geopackage.
@@ -216,22 +232,22 @@ def run_check(params, status):
216232 write_percent (percent_filepath , progress_percent )
217233
218234 if tileRow == 0 :
219- # first row
235+ # First row
220236 yOff = 0
221237 yOffInner = 0
222238 yOffRelative = 0
223239 block_height = BLOCKSIZE + buffer_width
224240 block_height_inner = BLOCKSIZE
225241 else :
226- # middle row
242+ # Middle row
227243 yOff = tileRow * BLOCKSIZE
228244 yOffInner = yOff + buffer_width
229245 yOffRelative = buffer_width
230246 block_height = blocksize_with_buffer
231247 block_height_inner = BLOCKSIZE
232248
233249 if tileRow == last_row :
234- # special case for last row - adjust block width
250+ # Last row is a special case - block width must be adjusted.
235251 block_height = nRasterRows - yOff
236252 block_height_inner = block_height - buffer_width
237253
@@ -242,22 +258,22 @@ def run_check(params, status):
242258 # TILES: ITERATE COLUMNS
243259 for tileCol in range (nTileCols ):
244260 if tileCol == 0 :
245- # first column
261+ # First column
246262 xOff = 0
247263 xOffInner = 0
248264 xOffRelative = 0
249265 block_width = BLOCKSIZE + buffer_width
250266 block_width_inner = BLOCKSIZE
251267 else :
252- # middle column
268+ # Middle column
253269 xOff = tileCol * BLOCKSIZE
254270 xOffInner = xOff + buffer_width
255271 xOffRelative = buffer_width
256272 block_width = blocksize_with_buffer
257273 block_width_inner = BLOCKSIZE
258274
259275 if tileCol == last_col :
260- # special case for last column - adjust block width
276+ # Last column is a special case - block width must be adjusted.
261277 block_width = nRasterCols - xOff
262278 block_width_inner = block_width - buffer_width
263279
@@ -286,7 +302,6 @@ def run_check(params, status):
286302 tile_inner = tile_buffered [yOffRelative : yOffRelative + block_height_inner , xOffRelative : xOffRelative + block_width_inner ]
287303
288304 # read inner array (without buffer)
289- # tile_inner = ds.ReadAsArray(xOffInner, yOffInner, block_width_inner, block_height_inner)
290305
291306 # label the inner array and find patches < MMU
292307 labels_inner = measure .label (tile_inner , background = NODATA , neighbors = 4 )
@@ -327,6 +342,8 @@ def run_check(params, status):
327342 regions_lessMMU_except .append (lessMMU_info )
328343 elif patch_touches_cell_with_value (r .coords , tile_inner , neighbour_exclude_values ):
329344 regions_lessMMU_except .append (lessMMU_info )
345+ elif patch_touches_raster_edge (absolute_coords , nRasterRows , nRasterCols ):
346+ regions_lessMMU_except .append (lessMMU_info )
330347 else :
331348 regions_lessMMU .append (lessMMU_info )
332349
@@ -338,10 +355,7 @@ def run_check(params, status):
338355 msg = msg .format (tr = tileRow , ntr = nTileRows , tc = tileCol , w = block_width , h = block_height )
339356 write_progress (progress_filepath , msg )
340357
341- # read the outer array expanded by buffer with width=number of pixels in MMU
342-
343- # no need, already read ...
344- # tile_buffered = ds.ReadAsArray(xOff, yOff, block_width, block_height)
358+ # processing the outer array expanded by buffer with width=number of pixels in MMU
345359
346360 # optimization: set pixels not within buffer zone (deep inside outer array) to background.
347361 inner_buf_startcol = xOffRelative + MMU
@@ -352,11 +366,6 @@ def run_check(params, status):
352366 tile_buffered [inner_buf_startrow :inner_buf_endrow ,
353367 inner_buf_startcol :inner_buf_endcol ] = NODATA
354368
355- # no need to reclassify, already reclassified ..
356- # reclassify outer tile array if some patches should be grouped together
357- # if use_reclassify:
358- # tile_buffered = reclassify_values(tile_buffered, params["groupcodes"])
359-
360369 labels_buf = measure .label (tile_buffered , background = NODATA , neighbors = 4 )
361370 buf_regions = measure .regionprops (labels_buf )
362371 buf_regions_small = [r for r in buf_regions if r .area < MMU ]
@@ -387,11 +396,13 @@ def run_check(params, status):
387396 "area" : r_buf .area , "value" : val ,
388397 "coords" : absolute_coords }
389398
390-
399+ # handling special cases (exception patches)
391400 if val in exclude_values :
392401 regions_lessMMU_except .append (lessMMU_info )
393402 elif patch_touches_cell_with_value (r_buf .coords , tile_buffered , neighbour_exclude_values ):
394403 regions_lessMMU_except .append (lessMMU_info )
404+ elif patch_touches_raster_edge (absolute_coords , nRasterRows , nRasterCols ):
405+ regions_lessMMU_except .append (lessMMU_info )
395406 else :
396407 regions_lessMMU .append (lessMMU_info )
397408
0 commit comments