From ca4fa8eea91a317f69717cfd0b8b3b9571149fe1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaquier=20Aur=C3=A9lien=20Tristan?= Date: Wed, 29 Nov 2023 10:20:36 +0100 Subject: [PATCH 1/9] add new feature: phaseslope_max --- efel/pyfeatures/pyfeatures.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/efel/pyfeatures/pyfeatures.py b/efel/pyfeatures/pyfeatures.py index 309e16fc..4bc8ddf1 100644 --- a/efel/pyfeatures/pyfeatures.py +++ b/efel/pyfeatures/pyfeatures.py @@ -46,6 +46,7 @@ 'spikes_in_burst1_burst2_diff', 'spikes_in_burst1_burstlast_diff', 'impedance', + 'phaseslope_max', ] @@ -341,6 +342,24 @@ def spikes_in_burst1_burstlast_diff(): ]) +def phaseslope_max(): + """Calculate the maximum phase slope""" + + voltage = _get_cpp_feature("voltage") + time = _get_cpp_feature("time") + time = time[:len(voltage)] + + from numpy import diff + + phaseslope = diff(voltage) / diff(time) + phaseslope_max= max(phaseslope) + + if phaseslope_max.size == 0: + return None + else: + return numpy.array([phaseslope_max]) + + def _get_cpp_feature(feature_name): """Get cpp feature""" cppcoreFeatureValues = list() From 2fedc42b68b2c62208f59f98e1c7326ec6d76e09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaquier=20Aur=C3=A9lien=20Tristan?= Date: Wed, 17 Jan 2024 10:35:27 +0100 Subject: [PATCH 2/9] add phaseslope_max feature to documentation --- docs/source/eFeatures.rst | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/docs/source/eFeatures.rst b/docs/source/eFeatures.rst index d162db00..c1776471 100644 --- a/docs/source/eFeatures.rst +++ b/docs/source/eFeatures.rst @@ -1926,6 +1926,18 @@ with impedance_max_freq being a setting with 50.0 as a default value. else: return None +`Python efeature`_ : phaseslope_max +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Computes the maximum of the phase slope. +Attention, this feature is sensitive to interpolation timestep. + +- **Required features**: time, voltage +- **Units**: V/s +- **Pseudocode**: :: + + phaseslope_max= max(numpy.diff(voltage) / numpy.diff(time)) + .. _LibV1: https://github.com/BlueBrain/eFEL/blob/master/efel/cppcore/LibV1.cpp From 1deff0900f5ded2932e613effdce3c669488cba0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaquier=20Aur=C3=A9lien=20Tristan?= Date: Wed, 17 Jan 2024 10:45:41 +0100 Subject: [PATCH 3/9] add unit test for phaseslope_max --- efel/pyfeatures/pyfeatures.py | 4 ++-- tests/test_pyfeatures.py | 10 ++++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/efel/pyfeatures/pyfeatures.py b/efel/pyfeatures/pyfeatures.py index 8999352a..479f8690 100644 --- a/efel/pyfeatures/pyfeatures.py +++ b/efel/pyfeatures/pyfeatures.py @@ -428,8 +428,8 @@ def spikes_in_burst1_burstlast_diff(): def phaseslope_max(): """Calculate the maximum phase slope""" - voltage = _get_cpp_feature("voltage") - time = _get_cpp_feature("time") + voltage = get_cpp_feature("voltage") + time = get_cpp_feature("time") time = time[:len(voltage)] from numpy import diff diff --git a/tests/test_pyfeatures.py b/tests/test_pyfeatures.py index c7861036..4e1f5190 100644 --- a/tests/test_pyfeatures.py +++ b/tests/test_pyfeatures.py @@ -326,3 +326,13 @@ def test_trace_check(): mf1_trace["V"] = [0] * len(mf1_trace["V"]) feature_values = efel.getFeatureValues([mf1_trace], ['trace_check']) assert feature_values[0]['trace_check'][0] == 0 + + +def test_phaseslope_max(): + """Unit test for phaseslope_max.""" + expected_values = { + "mean_frequency1": 574.86769012, + "depol_block_spiking": 93.51242208, + "depol_block_db": 180.7325033, + } + _test_expected_value("phaseslope_max", expected_values) From ec663a69d9da23a5601be2559da64372c60900da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaquier=20Aur=C3=A9lien=20Tristan?= Date: Wed, 17 Jan 2024 10:46:55 +0100 Subject: [PATCH 4/9] small lint fix --- efel/pyfeatures/pyfeatures.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/efel/pyfeatures/pyfeatures.py b/efel/pyfeatures/pyfeatures.py index 479f8690..cbb96893 100644 --- a/efel/pyfeatures/pyfeatures.py +++ b/efel/pyfeatures/pyfeatures.py @@ -439,8 +439,7 @@ def phaseslope_max(): if phaseslope_max.size == 0: return None - else: - return numpy.array([phaseslope_max]) + return numpy.array([phaseslope_max]) def get_cpp_feature(featureName, raise_warnings=None): From ce5068ae46806104ddd8d299bb497e9534e5a9ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaquier=20Aur=C3=A9lien=20Tristan?= Date: Wed, 17 Jan 2024 10:48:29 +0100 Subject: [PATCH 5/9] update changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 42caa5f6..2f98aac5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [5.5.4] - 2024-01 + +- New feature: phaseslope_max + ## [5.5.3] - 2024-01 - Add type stub for cppcore module to make Python recognise the C++ functions' arguments and return values. From b98b0e1a8f022a71ede95670fef1e829a3f00442 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaquier=20Aur=C3=A9lien=20Tristan?= Date: Wed, 17 Jan 2024 10:51:12 +0100 Subject: [PATCH 6/9] lint fix --- efel/pyfeatures/pyfeatures.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/efel/pyfeatures/pyfeatures.py b/efel/pyfeatures/pyfeatures.py index cbb96893..b62f2b2c 100644 --- a/efel/pyfeatures/pyfeatures.py +++ b/efel/pyfeatures/pyfeatures.py @@ -433,9 +433,9 @@ def phaseslope_max(): time = time[:len(voltage)] from numpy import diff - + phaseslope = diff(voltage) / diff(time) - phaseslope_max= max(phaseslope) + phaseslope_max = max(phaseslope) if phaseslope_max.size == 0: return None From e69ffaeb8d496022371944e8d198bd06a410f26e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaquier=20Aur=C3=A9lien=20Tristan?= Date: Wed, 17 Jan 2024 10:52:31 +0100 Subject: [PATCH 7/9] update units.json --- efel/units/units.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/efel/units/units.json b/efel/units/units.json index e656d2a9..df18f17c 100644 --- a/efel/units/units.json +++ b/efel/units/units.json @@ -136,5 +136,6 @@ "initburst_sahp_ssse": "mV", "initburst_sahp_vb": "mV", "depol_block_bool": "constant", - "impedance": "Hz" + "impedance": "Hz", + "phaseslope_max": "V/s" } From 203a033cd4d73c44bbf43b1d482be1b2c27062d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaquier=20Aur=C3=A9lien=20Tristan?= Date: Wed, 17 Jan 2024 11:05:47 +0100 Subject: [PATCH 8/9] fix test data --- tests/featurenames.json | 3 ++- tests/test_allfeatures.py | 2 +- tests/testdata/allfeatures/expectedresults.json | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/featurenames.json b/tests/featurenames.json index 1b2a2cc1..0e4425e9 100644 --- a/tests/featurenames.json +++ b/tests/featurenames.json @@ -147,5 +147,6 @@ "postburst_min_indices", "postburst_min_values", "time_to_interburst_min", - "AHP_depth_slow" + "AHP_depth_slow", + "phaseslope_max" ] \ No newline at end of file diff --git a/tests/test_allfeatures.py b/tests/test_allfeatures.py index 1f7373ad..a7e8a91b 100644 --- a/tests/test_allfeatures.py +++ b/tests/test_allfeatures.py @@ -177,7 +177,7 @@ def test_allfeatures_on_constant_voltage(): "voltage_deflection", "voltage_deflection_begin", "voltage_deflection_vb_ssse", "depol_block", "depol_block_bool", "voltage_base", "Spikecount", "Spikecount_stimint", "burst_number", "strict_burst_number", "trace_check", - "spike_count", "spike_count_stimint" + "spike_count", "spike_count_stimint", "phaseslope_max" ] for field in array_fields: diff --git a/tests/testdata/allfeatures/expectedresults.json b/tests/testdata/allfeatures/expectedresults.json index 77144d0d..d7d7575b 100644 --- a/tests/testdata/allfeatures/expectedresults.json +++ b/tests/testdata/allfeatures/expectedresults.json @@ -60639,5 +60639,6 @@ 32.02907786238346, 32.65404519917785, 33.435288866699345 - ] + ], + "phaseslope_max": [111.6276337625179] } \ No newline at end of file From ebfeae750e9a483a8c779ccc133740893f95e553 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaquier=20Aur=C3=A9lien=20Tristan?= Date: Wed, 17 Jan 2024 12:36:22 +0100 Subject: [PATCH 9/9] fix edge case in phaseslope_max --- docs/source/eFeatures.rst | 3 ++- efel/pyfeatures/pyfeatures.py | 7 +++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/source/eFeatures.rst b/docs/source/eFeatures.rst index c1776471..0e71329d 100644 --- a/docs/source/eFeatures.rst +++ b/docs/source/eFeatures.rst @@ -1936,7 +1936,8 @@ Attention, this feature is sensitive to interpolation timestep. - **Units**: V/s - **Pseudocode**: :: - phaseslope_max= max(numpy.diff(voltage) / numpy.diff(time)) + phaseslope = numpy.diff(voltage) / numpy.diff(time) + phaseslope_max = numpy.array([numpy.max(phaseslope)]) diff --git a/efel/pyfeatures/pyfeatures.py b/efel/pyfeatures/pyfeatures.py index b62f2b2c..740380c8 100644 --- a/efel/pyfeatures/pyfeatures.py +++ b/efel/pyfeatures/pyfeatures.py @@ -435,11 +435,10 @@ def phaseslope_max(): from numpy import diff phaseslope = diff(voltage) / diff(time) - phaseslope_max = max(phaseslope) - - if phaseslope_max.size == 0: + try: + return numpy.array([numpy.max(phaseslope)]) + except ValueError: return None - return numpy.array([phaseslope_max]) def get_cpp_feature(featureName, raise_warnings=None):