Repository: Deltares/pyflwdir

Issue:
prioritize non-boundary cells with same elevation over boundary cells in dem.fill_depressions

Discussion:

Patch:
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index c0327c7..f240f71 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -2,6 +2,16 @@
 Change Log
 ###########
 
+Unreleased
+********************
+
+Improved
+---------
+* prioritize non-boundary cells with same elevation over boundary cells in dem.fill_depressions, #17
+
+Bugfix
+------
+
 
 0.5.3  (18-Nov-2021)
 ********************
diff --git a/pyflwdir/dem.py b/pyflwdir/dem.py
index 0d6876e..cb77f81 100644
--- a/pyflwdir/dem.py
+++ b/pyflwdir/dem.py
@@ -76,25 +76,27 @@ def fill_depressions(
     # initiate queue
     if idxs_pit is None:  # with edge cells
         queued = gis_utils.get_edge(~done, structure=struct)
-    else:  # with user difinfed outlet cells
+    else:  # with user defined outlet cells
         queued = np.array([bool(0) for s in range(elevtn.size)]).reshape((nrow, ncol))
         for idx in idxs_pit:
             queued.flat[idx] = True
-    q = [(elevtn[0, 0], np.uint32(0), np.uint32(0)) for _ in range(0)]
+    # queue contains (elevation, boundary, row, col)
+    # boundary is included to favor non-boundary cells over boundary cells with same elevation
+    q = [(elevtn[0, 0], np.uint8(1), np.uint32(0), np.uint32(0)) for _ in range(0)]
     heapq.heapify(q)
     for r, c in zip(*np.where(queued)):
-        heapq.heappush(q, (elevtn[r, c], np.uint32(r), np.uint32(c)))
+        heapq.heappush(q, (elevtn[r, c], np.uint8(1), np.uint32(r), np.uint32(c)))
     # restrict queue to global edge mimimum (single outlet)
     if outlets == "min":
         q = [heapq.heappop(q)]
         queued[:, :] = False
-        queued[q[0][1], q[0][2]] = True
+        queued[q[0][-2], q[0][-1]] = True
 
     # loop over cells and neighbors with ascending cell elevation.
     drs, dcs = np.where(struct)
     drs, dcs = drs - 1, dcs - 1
     while len(q) > 0:
-        z0, r0, c0 = heapq.heappop(q)
+        z0, _, r0, c0 = heapq.heappop(q)
         for dr, dc in zip(drs, dcs):
             r = r0 + dr
             c = c0 + dc
@@ -104,7 +106,7 @@ def fill_depressions(
             dz = z0 - z1  # local depression if dz > 0
             if max_depth >= 0:  # if positive max_depth: don't fill when dz > max_depth
                 if dz >= max_depth:
-                    heapq.heappush(q, (z1, np.uint32(r), np.uint32(c)))
+                    heapq.heappush(q, (z1, np.uint8(0), np.uint32(r), np.uint32(c)))
                     queued[r, c] = True
                     for dr, dc in zip(drs, dcs):  # (re)visit neighbors
                         done[r + dr, c + dc] = False
@@ -116,7 +118,7 @@ def fill_depressions(
                 delv[r, c] = dz
                 z1 += dz
             if ~queued[r, c]:  # add to queue
-                heapq.heappush(q, (z1, np.uint32(r), np.uint32(c)))
+                heapq.heappush(q, (z1, np.uint8(0), np.uint32(r), np.uint32(c)))
                 queued[r, c] = True
             done[r, c] = True
             d8[r, c] = core_d8._us[dr + 1, dc + 1]


Test patch:
diff --git a/tests/test_dem.py b/tests/test_dem.py
index 8d7449a..39ec1d4 100644
--- a/tests/test_dem.py
+++ b/tests/test_dem.py
@@ -24,12 +24,13 @@ def test_from_dem():
     )
     # NOTE: compared to paper same a_filled, but difference
     # in flowdir because row instead of col first ..
+    # and priority of non-boundary cells with same elevation
     d8 = np.array(
         [
             [2, 2, 4, 8, 1, 0, 16],
             [1, 1, 2, 2, 128, 64, 32],
             [128, 128, 1, 1, 2, 2, 4],
-            [64, 128, 128, 128, 1, 1, 0],
+            [128, 128, 128, 128, 1, 1, 0],
             [64, 128, 64, 32, 128, 128, 64],
         ],
         dtype=np.uint8,