From 5b464ecd358e871719b47990c48ac039871cfd63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cristiano=20K=C3=B6hler?= <42555442+kohlerca@users.noreply.github.com> Date: Thu, 1 Jun 2023 09:30:02 +0200 Subject: [PATCH] Added functions to extract time bin and neuron information from SSEs obtained using ASSET (#549) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Added functions to extract time bin and neuron information from SSEs obtained using ASSET * Added functions to module docstring * Fixed Examples header in docstring --------- Co-authored-by: Cristiano Köhler --- elephant/asset/asset.py | 108 +++++++++++++++++++++++++++++++++++- elephant/test/test_asset.py | 15 +++++ 2 files changed, 122 insertions(+), 1 deletion(-) diff --git a/elephant/asset/asset.py b/elephant/asset/asset.py index ef01067e4..dfe9af719 100644 --- a/elephant/asset/asset.py +++ b/elephant/asset/asset.py @@ -26,6 +26,8 @@ synchronous_events_contained_in synchronous_events_contains_all synchronous_events_overlap + get_neurons_in_sse + get_sse_start_and_end_time_bins Tutorial @@ -165,7 +167,9 @@ "synchronous_events_no_overlap", "synchronous_events_contained_in", "synchronous_events_contains_all", - "synchronous_events_overlap" + "synchronous_events_overlap", + "get_neurons_in_sse", + "get_sse_start_and_end_time_bins" ] @@ -1769,6 +1773,108 @@ def synchronous_events_overlap(sse1, sse2): return not (contained_in or contains_all or identical or is_disjoint) +def get_neurons_in_sse(sse): + """ + Returns the IDs of all neurons present in the SSE pattern. + + This ignores repetitions (i.e., if a neuron is present in more than one + pixel, it is returned only once). + + Parameters + ---------- + sse : dict + Dictionary of pixel positions `(i, j)` as keys and sets `S` of + synchronous events as values, as returned by + :func:`ASSET.extract_synchronous_events`. + + Returns + ------- + list + All neuron IDs present in the SSE, sorted in ascending order. + + Examples + -------- + >>> sse = {(268, 51): {22, 27}, + ... (274, 54): {26}, + ... (274, 56): {77}, + ... (274, 58): {26}, + ... (275, 58): {92}, + ... (276, 59): {9}, + ... (277, 58): {26}, + ... (277, 61): {26}} + >>> neurons = get_neurons_in_sse(sse) + >>> print(neurons) + [9, 22, 26, 27, 77, 92] + + See Also + -------- + ASSET.extract_synchronous_events + """ + all_neurons = [] + for neurons in sse.values(): + all_neurons.extend(neurons) + neuron_ids = np.unique(all_neurons).tolist() + return neuron_ids + + +def get_sse_start_and_end_time_bins(sse): + """ + For each repeated sequence in the SSE pattern, returns the start and end + time bin IDs. + + For an SSE consisting of several pixels `(i, j)`, the `i` and `j` elements + represent the time bin IDs in the cluster matrix used to extract the SSE. + The combination of all `i` and `j` elements in the SSE pixels defines the + temporal profile of each repeated sequence in the SSE pattern. Therefore, + the minimum and maximum values for each `i` and `j` will define when each + repeated sequence occured in time. + + Parameters + ---------- + sse : dict + Dictionary of pixel positions `(i, j)` as keys and sets `S` of + synchronous events as values, as returned by + :func:`ASSET.extract_synchronous_events`. + + Returns + ------- + start, end: list + Two-element list containing the first bins (`start`) or the last bins + (`end`) in each repeated sequence. In each list, the first element + corresponds to the first sequence (elements `i` in the SSE pixel), and + the second element corresponds to the second sequence (elements `j` + in the SSE pixel). + + Examples + -------- + >>> sse = {(268, 51): {22, 27}, + ... (274, 54): {26}, + ... (274, 56): {77}, + ... (274, 58): {26}, + ... (275, 58): {92}, + ... (276, 59): {9}, + ... (277, 58): {26}, + ... (277, 61): {26}} + >>> start, end = get_sse_start_and_end_time_bins(sse) + >>> print(start) + [268, 51] + >>> print(end) + [277, 61] + + See Also + -------- + ASSET.extract_synchronous_events + """ + pixels = list(sse.keys()) + start = list(pixels[0]) + end = list(pixels[0]) + for pixel in pixels[1:]: + for seq in (0, 1): + start[seq] = min(start[seq], pixel[seq]) + end[seq] = max(end[seq], pixel[seq]) + return start, end + + def _signals_t_start_stop(signals, t_start=None, t_stop=None): if t_start is None: t_start = _signals_same_attribute(signals, 't_start') diff --git a/elephant/test/test_asset.py b/elephant/test/test_asset.py index 1362e8fce..432d166b0 100644 --- a/elephant/test/test_asset.py +++ b/elephant/test/test_asset.py @@ -86,6 +86,21 @@ def test_stretched_metric_2d_equals_euclidean_if_stretch_1(self): # assert D == E assert_array_almost_equal(D, E, decimal=5) + def test_get_sse_start_and_end_time_bins(self): + sse = {(1, 2): set([1, 2, 3]), + (3, 4): set([5, 6]), + (6, 7): set([0, 1])} + start, end = asset.get_sse_start_and_end_time_bins(sse) + self.assertListEqual(start, [1, 2]) + self.assertListEqual(end, [6, 7]) + + def test_get_neurons_in_sse(self): + sse = {(1, 2): set([1, 2, 3]), + (3, 4): set([5, 6]), + (6, 7): set([0, 1])} + neurons = asset.get_neurons_in_sse(sse) + self.assertListEqual(neurons, [0, 1, 2, 3, 5, 6]) + def test_sse_difference(self): a = {(1, 2): set([1, 2, 3]), (3, 4): set([5, 6]), (6, 7): set([0, 1])} b = {(1, 2): set([1, 2, 5]), (5, 6): set([0, 2]), (6, 7): set([0, 1])}