Repository: SpikeInterface/spikeinterface
Pull request #2005 (2023-09-18 09:03:43)

Add an option to flip the order by depth


Patch:
diff --git a/src/spikeinterface/core/recording_tools.py b/src/spikeinterface/core/recording_tools.py
index e5901d7ee..ff9cd9938 100644
--- a/src/spikeinterface/core/recording_tools.py
+++ b/src/spikeinterface/core/recording_tools.py
@@ -302,7 +302,7 @@ def get_chunk_with_margin(
     return traces_chunk, left_margin, right_margin
 
 
-def order_channels_by_depth(recording, channel_ids=None, dimensions=("x", "y")):
+def order_channels_by_depth(recording, channel_ids=None, dimensions=("x", "y"), flip=False):
     """
     Order channels by depth, by first ordering the x-axis, and then the y-axis.
 
@@ -316,6 +316,9 @@ def order_channels_by_depth(recording, channel_ids=None, dimensions=("x", "y")):
         If str, it needs to be 'x', 'y', 'z'.
         If tuple or list, it sorts the locations in two dimensions using lexsort.
         This approach is recommended since there is less ambiguity, by default ('x', 'y')
+    flip: bool, default: False
+        If flip is False then the order is bottom first (starting from tip of the probe).
+        If flip is True then the order is upper first.
 
     Returns
     -------
@@ -341,6 +344,8 @@ def order_channels_by_depth(recording, channel_ids=None, dimensions=("x", "y")):
             assert dim < ndim, "Invalid dimensions!"
             locations_to_sort += (locations[:, dim],)
         order_f = np.lexsort(locations_to_sort)
+    if flip:
+        order_f = order_f[::-1]
     order_r = np.argsort(order_f, kind="stable")
 
     return order_f, order_r
diff --git a/src/spikeinterface/preprocessing/depth_order.py b/src/spikeinterface/preprocessing/depth_order.py
index 0b8d8a730..55e34ba5d 100644
--- a/src/spikeinterface/preprocessing/depth_order.py
+++ b/src/spikeinterface/preprocessing/depth_order.py
@@ -18,13 +18,18 @@ class DepthOrderRecording(ChannelSliceRecording):
         If str, it needs to be 'x', 'y', 'z'.
         If tuple or list, it sorts the locations in two dimensions using lexsort.
         This approach is recommended since there is less ambiguity, by default ('x', 'y')
+    flip: bool, default: False
+        If flip is False then the order is bottom first (starting from tip of the probe).
+        If flip is True then the order is upper first.
     """
 
     name = "depth_order"
     installed = True
 
-    def __init__(self, parent_recording, channel_ids=None, dimensions=("x", "y")):
-        order_f, order_r = order_channels_by_depth(parent_recording, channel_ids=channel_ids, dimensions=dimensions)
+    def __init__(self, parent_recording, channel_ids=None, dimensions=("x", "y"), flip=False):
+        order_f, order_r = order_channels_by_depth(
+            parent_recording, channel_ids=channel_ids, dimensions=dimensions, flip=flip
+        )
         reordered_channel_ids = parent_recording.channel_ids[order_f]
         ChannelSliceRecording.__init__(
             self,
@@ -35,6 +40,7 @@ class DepthOrderRecording(ChannelSliceRecording):
             parent_recording=parent_recording,
             channel_ids=channel_ids,
             dimensions=dimensions,
+            flip=flip,
         )
 
 


Test patch:
diff --git a/src/spikeinterface/core/tests/test_recording_tools.py b/src/spikeinterface/core/tests/test_recording_tools.py
index 6e92d155f..1d99b192e 100644
--- a/src/spikeinterface/core/tests/test_recording_tools.py
+++ b/src/spikeinterface/core/tests/test_recording_tools.py
@@ -138,11 +138,13 @@ def test_order_channels_by_depth():
     order_1d, order_r1d = order_channels_by_depth(rec, dimensions="y")
     order_2d, order_r2d = order_channels_by_depth(rec, dimensions=("x", "y"))
     locations_rev = locations_copy[order_1d][order_r1d]
+    order_2d_fliped, order_r2d_fliped = order_channels_by_depth(rec, dimensions=("x", "y"), flip=True)
 
     assert np.array_equal(locations[:, 1], locations_copy[order_1d][:, 1])
     assert np.array_equal(locations_copy[order_1d][:, 1], locations_copy[order_2d][:, 1])
     assert np.array_equal(locations, locations_copy[order_2d])
     assert np.array_equal(locations_copy, locations_copy[order_2d][order_r2d])
+    assert np.array_equal(order_2d[::-1], order_2d_fliped)
 
 
 if __name__ == "__main__":