Skip to content

Commit

Permalink
Deprecate alternative ways of computing inter-spike-intervals [vcs: #…
Browse files Browse the repository at this point in the history
…minor] (#368)

* add remoevFirstISI to C++

* ISI_values to use removeFirstISI

* separate cppfeature_access and isi from pyfeatures

* move ISI_CV to python

* FIX: _get_cpp_data to check Int map as well

* move single_burst_ratio to pyfeatures

* FIX wrong single_burst_ratio in expectedresults

* move irregularity_index to pyfeatures

* FIX wrong irregularity_index val in test

* fix code style

* move ISI_log_slopes to pyfeatures

* implement burst_ISI_indices in python

* burst_ISI_indices to not to depend on peak_indices but only ISI_values

* format

* add TestBurstISIIndices

* move burst_mean_freq from test_basic to isi

* move interburst_voltage to isi from tests

* update .gitignore

* remove _get_voltage and _get_time

* remove LibV1 interburst_voltage

* pytest ignore DeprecationWarnings

* remove LibV1::burst_mean_freq

* remove LibV1:burst_ISI_indices

* add future annotations to test_isi

* add scipy as a requirement

* move ISI_values to pyfeatures

* Edge Case: ISIs to return None instead of [] when n_spikes < 2

* update test_ISIs_single_spike

* merge dictionary assignment with decleration

* add inv isi values func to api.py

* remove LibV5 inv_first_ISI ... inv_last_ISI

* shorten inv_ISI_values impl

* new feature: inv_ISI_values

* set upperbound 'scipy>=1.8.0,<=1.10.0'

* use all_ISI_values instead of ISIs

* scipy>=1.12.0,<2.0.0 otherwise no py3.12

* drop python3.8 for python3.12 support in scipy

* add unit for inv_ISI_values

* update CHANGELOG.rst
  • Loading branch information
anilbey authored Feb 20, 2024
1 parent 1c02c12 commit bffef33
Show file tree
Hide file tree
Showing 27 changed files with 726 additions and 790 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
runs-on: ubuntu-22.04
strategy:
matrix:
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
python-version: ["3.9", "3.10", "3.11", "3.12"]

steps:
- uses: actions/checkout@v4
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ bin
lib
fllog.txt
*.DS_Store
pyvenv.cfg
9 changes: 9 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,15 @@ 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.6.0 - 2024-02
----------------

- Reduce 3 alternative implementations to get ISIs into 1.
- "all_ISI_values" is recommended, "ISI_values" and "ISIs" are deprecated.
- The features depending on "ISI_values" are moved to Python and now they depend on "all_ISI_values".
- BUGFIX: single_burst_ratio, irregularity_index, burst_mean_freq, interburst_voltage features were ignoring the first two ISIs when the ignore_first_ISI was set.
- Added new feature: inv_ISI_values that computes and returns all of the inverse isi values.

5.5.5 - 2024-01
----------------
- Type annotate api.py's functions.
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ When you use this eFEL software for your research, we ask you to cite the follow
Requirements
============

* [Python 3.8+](https://www.python.org/downloads/)
* [Python 3.9+](https://www.python.org/downloads/)
* [Pip](https://pip.pypa.io) (installed by default in newer versions of Python)
* C++ compiler that can be used by pip
* [Numpy](http://www.numpy.org) (will be installed automatically by pip)
Expand Down
2 changes: 2 additions & 0 deletions docs/source/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ Submodules

api
io
pyfeatures.cppfeature_access
pyfeatures.isi
pyfeatures.multitrace
pyfeatures.pyfeatures
pyfeatures.validation
Expand Down
62 changes: 35 additions & 27 deletions docs/source/eFeatures.rst
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,10 @@ Time from the start of the stimulus to the maximum of the second peak
inv_time_to_first_spike = 0


`LibV1`_ : ISI_values
~~~~~~~~~~~~~~~~~~~~~
`Python efeature`_ : ISI_values
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The interspike intervals (i.e. time intervals) between adjacent peaks.
If ignore_first_ISI is True, the 1st spike will not be taken into account, because some cells spike right after the stimulus onset and then stay silent for a while.

- **Required features**: peak_time (ms)
- **Units**: ms
Expand Down Expand Up @@ -94,8 +93,8 @@ The interspike intervals, i.e., the time intervals between adjacent peaks.
all_isi_values_vec = numpy.diff(peak_time)


`LibV5`_ : inv_first_ISI, inv_second_ISI, inv_third_ISI, inv_fourth_ISI, inv_fifth_ISI, inv_last_ISI
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
`Python efeature`_ : inv_first_ISI, inv_second_ISI, inv_third_ISI, inv_fourth_ISI, inv_fifth_ISI, inv_last_ISI
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

1.0 over first/second/third/fourth/fith/last ISI; returns 0 when no ISI

Expand Down Expand Up @@ -135,6 +134,17 @@ The interspike intervals, i.e., the time intervals between adjacent peaks.
else:
inv_last_ISI = 0

`Python efeature`: inv_ISI_values
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Computes all inverse spike interval values.

- **Required features**: peak_time (ms)
- **Units**: Hz
- **Pseudocode**: ::

all_isi_values_vec = numpy.diff(peak_time)
inv_isi_values = 1000.0 / all_isi_values_vec

`LibV5`_ : time_to_last_spike
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand Down Expand Up @@ -214,7 +224,7 @@ The mean frequency of the firing rate
The slope of a linear fit to a semilog plot of the ISI values.

Attention: the 1st ISI is not taken into account unless ignore_first_ISI is set to 0.
See LibV1: ISI_values feature for more details.
See Python efeature: ISIs feature for more details.

- **Required features**: t, V, stim_start, stim_end, ISI_values
- **Units**: ms
Expand All @@ -226,13 +236,13 @@ See LibV1: ISI_values feature for more details.

ISI_semilog_slope = slope

`LibV5`_ : ISI_log_slope
~~~~~~~~~~~~~~~~~~~~~~~~
`Python efeature`_ : ISI_log_slope
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The slope of a linear fit to a loglog plot of the ISI values.

Attention: the 1st ISI is not taken into account unless ignore_first_ISI is set to 0.
See LibV1: ISI_values feature for more details.
See Python efeature: ISIs feature for more details.

- **Required features**: t, V, stim_start, stim_end, ISI_values
- **Units**: ms
Expand All @@ -244,8 +254,8 @@ See LibV1: ISI_values feature for more details.

ISI_log_slope = slope

`LibV5`_ : ISI_log_slope_skip
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
`Python efeature`_ : ISI_log_slope_skip
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The slope of a linear fit to a loglog plot of the ISI values, but not taking into account the first ISI values.

Expand All @@ -265,27 +275,25 @@ However, if this number of ISI values to skip is higher than max_spike_skip, the

ISI_log_slope = slope

`LibV1`_ : ISI_CV
~~~~~~~~~~~~~~~~~
`Python efeature`_ : ISI_CV
~~~~~~~~~~~~~~~~~~~~~~~~~~~

The coefficient of variation of the ISIs.

Attention: the 1st ISI is not taken into account unless ignore_first_ISI is set to 0.
See LibV1: ISI_values feature for more details.
See Python efeature: ISIs feature for more details.

- **Required features**: ISI_values
- **Required features**: ISIs
- **Units**: constant
- **Pseudocode**: ::

ISI_mean = numpy.mean(ISI_values)
ISI_variance = numpy.sum(numpy.square(ISI_values-ISI_mean)) / (len(ISI_values)-1)
ISI_std = math.sqrt(ISI_variance)
ISI_CV = ISI_std / ISI_mean
ISI_CV = np.std(isi_values, ddof=1) / ISI_mean

`LibV5`_ : irregularity_index
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
`Python efeature`_ : irregularity_index
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Mean of the absolute difference of all ISIs, except the first one (see LibV1: ISI_values feature for more details.)
Mean of the absolute difference of all ISIs, except the first one (see Python efeature: ISIs feature for more details.)

The first ISI can be taken into account if ignore_first_ISI is set to 0.

Expand Down Expand Up @@ -349,8 +357,8 @@ The adaptation index is zero for a constant firing rate and bigger than zero for
ISI_sub = ISI_values[1:] - ISI_values[:-1]
adaptation_index = numpy.mean(ISI_sum / ISI_sub)

`LibV1`_ : burst_mean_freq
~~~~~~~~~~~~~~~~~~~~~~~~~~
`Python efeature`_ : burst_mean_freq
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The mean frequency during a burst for each burst

Expand Down Expand Up @@ -436,8 +444,8 @@ The burst detection can be fine-tuned by changing the setting strict_burst_facto

burst_number = len(strict_burst_mean_freq)

`LibV1`_ : interburst_voltage
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
`Python efeature`_ : interburst_voltage
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The voltage average in between two bursts

Expand Down Expand Up @@ -565,8 +573,8 @@ The burst detection can be fine-tuned by changing the setting strict_burst_facto
for i in burst_end_indices if i + 1 < len(peak_indices)
]

`LibV1`_ : single_burst_ratio
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
`Python efeature`_ : single_burst_ratio
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Length of the second isi over the median of the rest of the isis.
The first isi is not taken into account, because it could bias the feature.
Expand Down
16 changes: 0 additions & 16 deletions efel/DependencyV5.txt
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
LibV1:interpolate
LibV5:peak_indices #LibV1:interpolate
LibV1:ISI_values #LibV1:peak_time #LibV1:interpolate
LibV1:doublet_ISI #LibV1:peak_time #LibV1:interpolate
LibV1:peak_voltage #LibV5:peak_indices #LibV1:interpolate
LibV1:burst_ISI_indices #LibV5:peak_indices #LibV1:ISI_values #LibV1:interpolate
LibV1:mean_frequency #LibV1:peak_time #LibV1:interpolate
LibV1:peak_time #LibV5:peak_indices #LibV1:interpolate
LibV1:time_to_first_spike #LibV1:peak_time #LibV1:interpolate
LibV1:adaptation_index #LibV1:peak_time #LibV1:interpolate
LibV1:adaptation_index2 #LibV1:peak_time #LibV1:interpolate
LibV1:spike_width2 #LibV5:min_AHP_indices #LibV1:interpolate
LibV1:AP_width #LibV5:peak_indices #LibV5:min_AHP_indices #LibV1:interpolate
LibV1:burst_mean_freq #LibV1:burst_ISI_indices #LibV1:peak_time #LibV1:interpolate
LibV1:interburst_voltage #LibV1:burst_ISI_indices #LibV1:interpolate
LibV1:AP_height #LibV1:peak_voltage #LibV1:interpolate
LibV1:AP_amplitude #LibV5:AP_begin_indices #LibV1:peak_voltage #LibV1:peak_time #LibV1:interpolate
LibV1:AHP_depth_abs_slow #LibV5:peak_indices #LibV1:interpolate
Expand All @@ -26,7 +22,6 @@ LibV1:maximum_voltage #LibV1:interpolate
LibV1:minimum_voltage #LibV1:interpolate
LibV1:steady_state_voltage #LibV1:interpolate
LibV3:depolarized_base #LibV5:AP_end_indices #LibV5:AP_begin_indices #LibV1:interpolate
LibV1:ISI_CV #LibV1:ISI_values #LibV1:interpolate
LibV1:AHP_depth #LibV5:voltage_base #LibV5:min_AHP_values #LibV1:interpolate
LibV1:AHP_depth_slow #LibV5:voltage_base #LibV1:AHP_depth_abs_slow #LibV1:interpolate
LibV2:AP_rise_indices #LibV5:peak_indices #LibV5:AP_begin_indices #LibV1:interpolate
Expand All @@ -45,21 +40,16 @@ LibV2:AP_rise_rate_change #LibV2:AP_rise_rate #LibV1:interpolate
LibV2:AP_fall_rate_change #LibV2:AP_fall_rate #LibV1:interpolate
LibV2:fast_AHP_change #LibV2:fast_AHP #LibV1:interpolate
LibV2:AP_duration_half_width_change #LibV2:AP_duration_half_width #LibV1:interpolate
LibV1:single_burst_ratio #LibV1:ISI_values #LibV1:interpolate
LibV2:steady_state_hyper #LibV1:interpolate
LibV2:amp_drop_first_second #LibV1:peak_voltage #LibV1:interpolate
LibV2:amp_drop_first_last #LibV1:peak_voltage #LibV1:interpolate
LibV2:amp_drop_second_last #LibV1:peak_voltage #LibV1:interpolate
LibV2:max_amp_difference #LibV1:peak_voltage #LibV1:interpolate
LibV1:AP_amplitude_diff #LibV1:AP_amplitude #LibV1:interpolate
LibV5:ISI_log_slope #LibV1:ISI_values #LibV1:interpolate
LibV5:ISI_semilog_slope #LibV1:ISI_values #LibV1:interpolate
LibV5:ISI_log_slope_skip #LibV1:ISI_values #LibV1:interpolate
LibV1:AHP_depth_diff #LibV1:AHP_depth #LibV1:interpolate
LibV5:min_AHP_indices #LibV5:peak_indices #LibV1:interpolate
LibV5:min_AHP_values #LibV5:min_AHP_indices #LibV1:interpolate
LibV5:number_initial_spikes #LibV1:peak_time #LibV1:interpolate
LibV5:irregularity_index #LibV1:ISI_values #LibV1:interpolate
LibV5:AP1_amp #LibV1:AP_amplitude #LibV1:interpolate
LibV5:APlast_amp #LibV1:AP_amplitude #LibV1:interpolate
LibV5:AP2_amp #LibV1:AP_amplitude #LibV1:interpolate
Expand All @@ -76,12 +66,6 @@ LibV5:AHP1_depth_from_peak #LibV5:AHP_depth_from_peak #LibV1:interpolate
LibV5:AHP2_depth_from_peak #LibV5:AHP_depth_from_peak #LibV1:interpolate
LibV5:time_to_second_spike #LibV1:peak_time #LibV1:interpolate
LibV5:time_to_last_spike #LibV1:peak_time #LibV1:interpolate
LibV5:inv_first_ISI #LibV5:all_ISI_values #LibV1:interpolate
LibV5:inv_second_ISI #LibV5:all_ISI_values #LibV1:interpolate
LibV5:inv_third_ISI #LibV5:all_ISI_values #LibV1:interpolate
LibV5:inv_fourth_ISI #LibV5:all_ISI_values #LibV1:interpolate
LibV5:inv_fifth_ISI #LibV5:all_ISI_values #LibV1:interpolate
LibV5:inv_last_ISI #LibV5:all_ISI_values #LibV1:interpolate
LibV5:inv_time_to_first_spike #LibV1:time_to_first_spike #LibV1:interpolate
LibV5:spike_half_width #LibV5:min_AHP_indices #LibV5:peak_indices #LibV1:interpolate
LibV5:AP_begin_indices #LibV5:min_AHP_indices #LibV5:peak_indices #LibV1:interpolate
Expand Down
37 changes: 0 additions & 37 deletions efel/cppcore/FillFptrTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,12 @@
int FillFptrTable() {
//****************** for FptrTableV1 *****************************
FptrTableV1["interpolate"] = &LibV1::interpolate;
FptrTableV1["ISI_values"] = &LibV1::ISI_values;
FptrTableV1["peak_voltage"] = &LibV1::peak_voltage;
FptrTableV1["mean_frequency"] = &LibV1::firing_rate;
FptrTableV1["peak_time"] = &LibV1::peak_time;
FptrTableV1["time_to_first_spike"] = &LibV1::first_spike_time;
FptrTableV1["burst_ISI_indices"] = &LibV1::burst_ISI_indices;
FptrTableV1["adaptation_index"] = &LibV1::adaptation_index;
FptrTableV1["spike_width2"] = &LibV1::spike_width2;
FptrTableV1["burst_mean_freq"] = &LibV1::burst_mean_freq;
FptrTableV1["interburst_voltage"] = &LibV1::interburst_voltage;
// passive properties
FptrTableV1["time_constant"] = &LibV1::time_constant;
FptrTableV1["voltage_deflection"] = &LibV1::voltage_deflection;
Expand All @@ -40,11 +36,9 @@ int FillFptrTable() {

FptrTableV1["AP_height"] = &LibV1::AP_height;
FptrTableV1["AP_amplitude"] = &LibV1::AP_amplitude;
FptrTableV1["single_burst_ratio"] = &LibV1::single_burst_ratio;
FptrTableV1["AP_width"] = &LibV1::AP_width;
FptrTableV1["doublet_ISI"] = &LibV1::doublet_ISI;
FptrTableV1["adaptation_index2"] = &LibV1::adaptation_index2;
FptrTableV1["ISI_CV"] = &LibV1::ISI_CV;
FptrTableV1["AHP_depth_abs_slow"] = &LibV1::AHP_depth_abs_slow;
FptrTableV1["AHP_slow_time"] = &LibV1::AHP_slow_time;
FptrTableV1["AHP_depth"] = &LibV1::AHP_depth;
Expand Down Expand Up @@ -94,46 +88,15 @@ int FillFptrTable() {
//****************** end of FptrTableV3 *****************************

//****************** FptrTableV5 *****************************

FptrTableV5["ISI_log_slope"] = &LibV5::ISI_log_slope;
FptrTableV5["ISI_semilog_slope"] = &LibV5::ISI_semilog_slope;
FptrTableV5["ISI_log_slope_skip"] = &LibV5::ISI_log_slope_skip;
FptrTableV5["time_to_second_spike"] = &LibV5::time_to_second_spike;
FptrTableV5["time_to_last_spike"] = &LibV5::time_to_last_spike;
FptrTableV5["inv_first_ISI"] = [](mapStr2intVec& intData,
mapStr2doubleVec& doubleData,
mapStr2Str& strData) {
return LibV5::inv_ISI_generic(intData, doubleData, strData, 0);
};
FptrTableV5["inv_second_ISI"] = [](mapStr2intVec& intData,
mapStr2doubleVec& doubleData,
mapStr2Str& strData) {
return LibV5::inv_ISI_generic(intData, doubleData, strData, 1);
};
FptrTableV5["inv_third_ISI"] = [](mapStr2intVec& intData,
mapStr2doubleVec& doubleData,
mapStr2Str& strData) {
return LibV5::inv_ISI_generic(intData, doubleData, strData, 2);
};
FptrTableV5["inv_fourth_ISI"] = [](mapStr2intVec& intData,
mapStr2doubleVec& doubleData,
mapStr2Str& strData) {
return LibV5::inv_ISI_generic(intData, doubleData, strData, 3);
};
FptrTableV5["inv_fifth_ISI"] = [](mapStr2intVec& intData,
mapStr2doubleVec& doubleData,
mapStr2Str& strData) {
return LibV5::inv_ISI_generic(intData, doubleData, strData, 4);
};
FptrTableV5["inv_last_ISI"] = &LibV5::inv_last_ISI;
FptrTableV5["inv_time_to_first_spike"] = &LibV5::inv_time_to_first_spike;
FptrTableV5["min_AHP_indices"] = &LibV5::min_AHP_indices;
FptrTableV5["min_AHP_values"] = &LibV5::min_AHP_values;
FptrTableV5["AHP_depth_abs"] = &LibV5::AHP_depth_abs;
FptrTableV5["spike_half_width"] = &LibV5::spike_width1;
FptrTableV5["AP_begin_indices"] = &LibV5::AP_begin_indices;
FptrTableV5["AP_end_indices"] = &LibV5::AP_end_indices;
FptrTableV5["irregularity_index"] = &LibV5::irregularity_index;
FptrTableV5["number_initial_spikes"] = &LibV5::number_initial_spikes;
FptrTableV5["AP1_amp"] = &LibV5::AP1_amp;
FptrTableV5["APlast_amp"] = &LibV5::APlast_amp;
Expand Down
Loading

0 comments on commit bffef33

Please sign in to comment.