From 3ae924668fb362ecc1e7e2210a7ce85e030a6845 Mon Sep 17 00:00:00 2001 From: anilbey Date: Thu, 19 Oct 2023 14:05:46 +0200 Subject: [PATCH] bring efel to c++17 standard (#327) * Set C++17 standard * Fix efel logging on windows for caching test * remove unused using std::greater_equal statements * add using std::distance to LibV1 * fix indentation in LibV1 * using std::distance in LibV5 * using std::find_if in LibV5 --- efel/cppcore/LibV1.cpp | 40 +++++----- efel/cppcore/LibV2.cpp | 21 +++--- efel/cppcore/LibV3.cpp | 3 - efel/cppcore/LibV5.cpp | 153 +++++++++++++++++++------------------- efel/cppcore/eFELLogger.h | 8 ++ setup.py | 2 +- tests/test_cppcore.py | 3 + 7 files changed, 114 insertions(+), 116 deletions(-) diff --git a/efel/cppcore/LibV1.cpp b/efel/cppcore/LibV1.cpp index 474f7d75..80550678 100644 --- a/efel/cppcore/LibV1.cpp +++ b/efel/cppcore/LibV1.cpp @@ -29,11 +29,8 @@ #include #include -using std::bind2nd; +using std::distance; using std::find_if; -using std::greater; -using std::greater_equal; -using std::less_equal; using std::list; using std::min_element; using std::max_element; @@ -378,7 +375,7 @@ static int __AHP_depth_abs_slow_indices(const vector& t, distance(t.begin(), find_if(t.begin() + peakindices[i + 1], t.begin() + peakindices[i + 2], - bind2nd(greater_equal(), t_start))), + [t_start](double val) { return val >= t_start; })), v.begin() + peakindices[i + 2])); } return adas_indices.size(); @@ -983,10 +980,11 @@ static int __time_constant(const vector& v, const vector& t, // int stimendindex; // for(stimendindex = 0; t[stimendindex] < stimEnd; stimendindex++) ; // int stimmiddleindex = (stimstartindex + stimendindex) / 2; - int stimmiddleindex = distance( - t.begin(), - find_if(t.begin() + stimstartindex, t.end(), - bind2nd(greater_equal(), (stimStart + stimEnd) / 2.))); + double mid_stim = (stimStart + stimEnd) / 2.; + auto it_mid_stim = find_if(t.begin() + stimstartindex, t.end(), + [mid_stim](double val) { return val >= mid_stim; }); + int stimmiddleindex = distance(t.begin(), it_mid_stim); + if (stimstartindex >= v.size() || stimmiddleindex < 0 || static_cast(stimmiddleindex) >= v.size()) { return -1; @@ -1006,8 +1004,8 @@ static int __time_constant(const vector& v, const vector& t, // find start of the decay int i_start = 0; while (find_if(dvdt.begin() + i_start, dvdt.begin() + i_start + 5, - bind2nd(greater(), -min_derivative)) != - dvdt.begin() + i_start + 5) { + [min_derivative](double val) { return val > -min_derivative; }) != dvdt.begin() + i_start + 5) + { if (dvdt.begin() + i_start + 5 == dvdt.end()) { GErrorStr += "Could not find the decay.\n"; return -1; @@ -1441,11 +1439,9 @@ static int __AP_width(const vector& t, const vector& v, if (strict_stiminterval){ int start_index = distance( t.begin(), - find_if(t.begin(), t.end(), bind2nd(greater_equal(), stimstart))); - int end_index = - distance(t.begin(), - find_if(t.begin(), t.end(), - std::bind2nd(std::greater_equal(), stimend))); + find_if(t.begin(), t.end(), [stimstart](double x){ return x >= stimstart; })); + int end_index = distance(t.begin(), find_if(t.begin(), t.end(), + [stimend](double x){ return x >= stimend; })); indices.push_back(start_index); for (size_t i = 0; i < minahpindices.size(); i++) { if (start_index < minahpindices[i] && minahpindices[i] < end_index) { @@ -1470,14 +1466,14 @@ static int __AP_width(const vector& t, const vector& v, v.begin() + indices[i + 1], bind2nd(less_equal(), v_hm))); apwidth.push_back(t[hm_index2] - t[hm_index1]); */ - int onset_index = distance( - v.begin(), find_if(v.begin() + indices[i], v.begin() + indices[i + 1], - bind2nd(greater_equal(), threshold))); + auto onset_index = distance( + v.begin(), find_if(v.begin() + indices[i], v.begin() + indices[i + 1], + [threshold](double x){ return x >= threshold; })); // int end_index = distance(v.begin(), find_if(v.begin() + peakindices[i], // v.begin() + indices[i + 1], bind2nd(less_equal(), threshold))); - int end_index = distance( - v.begin(), find_if(v.begin() + onset_index, v.begin() + indices[i + 1], - bind2nd(less_equal(), threshold))); + auto end_index = distance( + v.begin(), find_if(v.begin() + onset_index, v.begin() + indices[i + 1], + [threshold](double x){ return x <= threshold; })); apwidth.push_back(t[end_index] - t[onset_index]); } return apwidth.size(); diff --git a/efel/cppcore/LibV2.cpp b/efel/cppcore/LibV2.cpp index 467d7b3b..a1895584 100644 --- a/efel/cppcore/LibV2.cpp +++ b/efel/cppcore/LibV2.cpp @@ -24,9 +24,7 @@ #include #include -using std::bind2nd; using std::find_if; -using std::greater_equal; using std::min_element; using std::max_element; using std::transform; @@ -48,9 +46,7 @@ static int __AP_rise_indices(const vector& v, const vector& apbi, } vpeak.resize(pi[i] - apbi[i]); transform(v.begin() + apbi[i], v.begin() + pi[i], vpeak.begin(), - bind2nd(std::minus(), halfheight)); - transform(vpeak.begin(), vpeak.end(), vpeak.begin(), - static_cast(fabs)); + [halfheight](double val) { return fabs(val - halfheight); }); apri[i] = distance(vpeak.begin(), min_element(vpeak.begin(), vpeak.end())) + apbi[i]; } @@ -87,9 +83,7 @@ static int __AP_fall_indices(const vector& v, const vector& apbi, double halfheight = (v[pi[i]] + v[apbi[i]]) / 2.; vector vpeak(&v[pi[i]], &v[apei[i]]); transform(vpeak.begin(), vpeak.end(), vpeak.begin(), - bind2nd(std::minus(), halfheight)); - transform(vpeak.begin(), vpeak.end(), vpeak.begin(), - static_cast(fabs)); + [halfheight](double val) { return fabs(val - halfheight); }); apfi[i] = distance(vpeak.begin(), min_element(vpeak.begin(), vpeak.end())) + pi[i]; } @@ -1264,10 +1258,13 @@ int LibV2::E27(mapStr2intVec& IntFeatureData, static int __steady_state_hyper(const vector& v, const vector& t, double stimend, vector& steady_state_hyper) { - int i_end = - distance(t.begin(), find_if(t.begin(), t.end(), - bind2nd(greater_equal(), stimend))) - - 5; + // Find the iterator pointing to the first time value greater than or equal to stimend + auto it_stimend = find_if(t.begin(), t.end(), + [stimend](double t_val) { return t_val >= stimend; }); + + // Calculate the index, ensuring you account for the offset of -5 + int i_end = distance(t.begin(), it_stimend) - 5; + const int offset = 30; if (i_end < 0 || i_end < offset) { diff --git a/efel/cppcore/LibV3.cpp b/efel/cppcore/LibV3.cpp index a03e2f0b..3f878934 100644 --- a/efel/cppcore/LibV3.cpp +++ b/efel/cppcore/LibV3.cpp @@ -23,10 +23,7 @@ #include #include -using std::bind2nd; using std::find_if; -using std::greater_equal; -using std::less_equal; using std::list; using std::min_element; diff --git a/efel/cppcore/LibV5.cpp b/efel/cppcore/LibV5.cpp index b1bd9fd3..fdb0b44d 100644 --- a/efel/cppcore/LibV5.cpp +++ b/efel/cppcore/LibV5.cpp @@ -26,6 +26,10 @@ #include #include +using std::distance; +using std::find_if; + + // slope of loglog of ISI curve static int __ISI_log_slope(const vector& isiValues, vector& slope, bool skip, double spikeSkipf, @@ -356,10 +360,9 @@ static int __min_AHP_indices(const vector& t, const vector& v, unsigned end_index = 0; if (strict_stiminterval) { - end_index = - distance(t.begin(), - find_if(t.begin(), t.end(), - std::bind2nd(std::greater_equal(), stim_end))); + end_index = distance(t.begin(), find_if(t.begin(), t.end(), [stim_end](double t_val) { + return t_val >= stim_end; + })); } else { end_index = distance(t.begin(), t.end()); } @@ -484,7 +487,7 @@ static int __spike_width1(const vector& t, const vector& v, int start_index = distance(t.begin(), find_if(t.begin(), t.end(), - std::bind2nd(std::greater_equal(), stim_start))); + [stim_start](double t_val){ return t_val >= stim_start; })); vector min_ahp_indices_plus(min_ahp_indices.size() + 1, start_index); copy(min_ahp_indices.begin(), min_ahp_indices.end(), min_ahp_indices_plus.begin() + 1); @@ -500,7 +503,7 @@ static int __spike_width1(const vector& t, const vector& v, int rise_index = distance( v.begin(), find_if(v.begin() + min_ahp_indices_plus[i - 1], v.begin() + peak_indices[i - 1], - std::bind2nd(std::greater_equal(), v_half))); + [v_half](double v_val){ return v_val >= v_half; })); v_dev = v_half - v[rise_index]; delta_v = v[rise_index] - v[rise_index - 1]; delta_t = t[rise_index] - t[rise_index - 1]; @@ -508,7 +511,7 @@ static int __spike_width1(const vector& t, const vector& v, int fall_index = distance( v.begin(), find_if(v.begin() + peak_indices[i - 1], v.begin() + min_ahp_indices_plus[i], - std::bind2nd(std::less_equal(), v_half))); + [v_half](double v_val){ return v_val <= v_half; })); v_dev = v_half - v[fall_index]; delta_v = v[fall_index] - v[fall_index - 1]; delta_t = t[fall_index] - t[fall_index - 1]; @@ -577,10 +580,9 @@ static int __AP_begin_indices(const vector& t, const vector& v, // restrict to time interval where stimulus is applied vector minima, peak_indices; - int stimbeginindex = - distance(t.begin(), - find_if(t.begin(), t.end(), - std::bind2nd(std::greater_equal(), stimstart))); + auto stimbeginindex = distance(t.begin(), + find_if(t.begin(), t.end(), + [stimstart](double time){ return time >= stimstart; })); if (stimbeginindex > 1){ // to avoid skipping AP_begin when it is exactly at stimbeginindex @@ -622,29 +624,29 @@ static int __AP_begin_indices(const vector& t, const vector& v, // Detect where the derivate crosses derivativethreshold, and make sure // this happens in a window of 'width' sampling point do { - begin = distance( - dvdt.begin(), - find_if( - // use reverse iterator to get last occurence - // and avoid false positive long before the spike - dvdt.rbegin() + v.size() - newbegin, - dvdt.rbegin() + v.size() - minima[i], - std::bind2nd(std::less_equal(), derivativethreshold)).base()); - // cover edge case to avoid going out of index in the while condition - if (begin > endindex - width){ - begin = endindex - width; - } - // printf("%d %d\n", newbegin, minima[i+1]); - if (begin == minima[i]) { - // printf("Skipping %d %d\n", newbegin, minima[i+1]); - // could not find a spike in between these minima - skip = true; - break; - } - newbegin = begin - 1; - } while (find_if(dvdt.begin() + begin, dvdt.begin() + begin + width, - std::bind2nd(std::less(), derivativethreshold)) != - dvdt.begin() + begin + width); + begin = distance( + dvdt.begin(), + find_if( + // use reverse iterator to get last occurence + // and avoid false positive long before the spike + dvdt.rbegin() + v.size() - newbegin, + dvdt.rbegin() + v.size() - minima[i], + [derivativethreshold](double val) { return val <= derivativethreshold; }).base()); + // cover edge case to avoid going out of index in the while condition + if (begin > endindex - width){ + begin = endindex - width; + } + // printf("%d %d\n", newbegin, minima[i+1]); + if (begin == minima[i]) { + // printf("Skipping %d %d\n", newbegin, minima[i+1]); + // could not find a spike in between these minima + skip = true; + break; + } + newbegin = begin - 1; + } while (find_if(dvdt.begin() + begin, dvdt.begin() + begin + width, + [derivativethreshold](double val) { return val < derivativethreshold; }) != + dvdt.begin() + begin + width); if (skip) { continue; } @@ -725,14 +727,14 @@ static int __AP_end_indices(const vector& t, const vector& v, picopy.push_back(v.size() - 1); for (size_t i = 0; i < apei.size(); i++) { - max_slope = std::distance( + max_slope = distance( dvdt.begin(), std::min_element(dvdt.begin() + picopy[i] + 1, dvdt.begin() + picopy[i + 1])); // assure that the width of the slope is bigger than 4 - apei[i] = std::distance( + apei[i] = distance( dvdt.begin(), - std::find_if(dvdt.begin() + max_slope, dvdt.begin() + picopy[i + 1], - std::bind2nd(std::greater_equal(), derivativethreshold))); + find_if(dvdt.begin() + max_slope, dvdt.begin() + picopy[i + 1], + [derivativethreshold](double x){ return x >= derivativethreshold; })); } return apei.size(); } @@ -802,18 +804,19 @@ int LibV5::irregularity_index(mapStr2intVec& IntFeatureData, } static int __number_initial_spikes(vector& peak_times, double stimstart, - double stimend, double initial_perc, - vector& number_initial_spikes) { + double stimend, double initial_perc, + vector& number_initial_spikes) { double initialLength = (stimend - stimstart) * initial_perc; int startIndex = - distance(peak_times.begin(), - find_if(peak_times.begin(), peak_times.end(), - std::bind2nd(std::greater_equal(), stimstart))); + distance(peak_times.begin(), + find_if(peak_times.begin(), peak_times.end(), + [stimstart](double t){ return t >= stimstart; })); int endIndex = distance(peak_times.begin(), - find_if(peak_times.begin(), peak_times.end(), - std::bind2nd(std::greater_equal(), - stimstart + initialLength))); + find_if(peak_times.begin(), peak_times.end(), + [stimstart, initialLength](double t){ + return t >= stimstart + initialLength; + })); number_initial_spikes.push_back(endIndex - startIndex); @@ -1193,11 +1196,10 @@ static int __AP_begin_width(const vector& t, const vector& v, // because AP_begin_indices are all after stim start // if not done, could cause cases where AP_begin_indices[i] > min_ahp_indices[i] // leading to segmentation faults - int stimbeginindex = - distance(t.begin(), - find_if(t.begin(), t.end(), - std::bind2nd(std::greater_equal(), stimstart))); - + auto it = find_if(t.begin(), t.end(), [stimstart](double val) { + return val >= stimstart; + }); + int stimbeginindex = distance(t.begin(), it); vector strict_min_ahp_indices; for (size_t i = 0; i < min_ahp_indices.size(); i++) { if (min_ahp_indices[i] > stimbeginindex) { @@ -1212,9 +1214,9 @@ static int __AP_begin_width(const vector& t, const vector& v, // the falling edge int rise_index = AP_begin_indices[i]; int fall_index = distance( - v.begin(), - find_if(v.begin() + rise_index + 1, v.begin() + strict_min_ahp_indices[i], - std::bind2nd(std::less_equal(), v_start))); + v.begin(), + find_if(v.begin() + rise_index + 1, v.begin() + strict_min_ahp_indices[i], + [v_start](const auto& val){ return val <= v_start; })); // v_dev = v_start - v[fall_index]; // delta_v = v[fall_index] - v[fall_index - 1]; // delta_t = t[fall_index] - t[fall_index - 1]; @@ -2048,11 +2050,11 @@ int LibV5::steady_state_voltage_stimend(mapStr2intVec& IntFeatureData, size_t start_index = distance(t.begin(), find_if(t.begin(), t.end(), - std::bind2nd(std::greater_equal(), start_time))); + [start_time](double x){ return x >= start_time; })); size_t stop_index = distance(t.begin(), find_if(t.begin(), t.end(), - std::bind2nd(std::greater_equal(), stimEnd[0]))); + [stimEnd](double x){ return x >= stimEnd[0]; })); size_t mean_size = 0; double mean = 0.0; @@ -2230,7 +2232,7 @@ int LibV5::current_base(mapStr2intVec& IntFeatureData, size_t get_index(const vector& times, double t) { return distance(times.begin(), find_if(times.begin(), times.end(), - std::bind2nd(std::greater_equal(), t))); + [t](double x){ return x >= t; })); } double __decay_time_constant_after_stim(const vector& times, @@ -2400,20 +2402,20 @@ static int __sag_time_constant(const vector& times, // minimal required length of each decay (indices) size_t min_length = 10; - // get start index - const size_t decayStartIdx = + // get start index + const size_t decayStartIdx = distance(voltage.begin(), - find_if(voltage.begin(), voltage.end(), - std::bind2nd(std::less_equal(), minimum_voltage))); + find_if(voltage.begin(), voltage.end(), + [minimum_voltage](double v){ return v <= minimum_voltage; })); - // voltage at which 90% of the sag amplitude has decayed - double steady_state_90 = steady_state_v - sag_amplitude * 0.1; - // get end index - const size_t decayEndIdx = + // voltage at which 90% of the sag amplitude has decayed + double steady_state_90 = steady_state_v - sag_amplitude * 0.1; + // get end index + const size_t decayEndIdx = distance(voltage.begin(), - find_if(voltage.begin() + decayStartIdx, voltage.end(), - std::bind2nd(std::greater_equal(), steady_state_90))); + find_if(voltage.begin() + decayStartIdx, voltage.end(), + [steady_state_90](double v){ return v >= steady_state_90; })); // voltage reference by which the voltage (i the decay interval) // is going to be substracted @@ -3028,10 +3030,8 @@ static int __min_between_peaks_indices(const vector& t, const vector(), stim_end))); + end_index = distance(t.begin(), find_if(t.begin(), t.end(), + [stim_end](double t_val) { return t_val >= stim_end; })); } else { end_index = distance(t.begin(), t.end()); } @@ -3146,17 +3146,17 @@ static int __AP_width_between_threshold(const vector& t, const vector indices(min_between_peaks_indices.size() + 1); int start_index = distance( t.begin(), - find_if(t.begin(), t.end(), bind2nd(std::greater_equal(), stimstart))); + find_if(t.begin(), t.end(), [stimstart](double x){return x >= stimstart;})); indices[0] = start_index; copy(min_between_peaks_indices.begin(), min_between_peaks_indices.end(), indices.begin() + 1); for (size_t i = 0; i < indices.size() - 1; i++) { int onset_index = distance( v.begin(), find_if(v.begin() + indices[i], v.begin() + indices[i + 1], - bind2nd(std::greater_equal(), threshold))); + [threshold](double x){return x >= threshold;})); int end_index = distance( v.begin(), find_if(v.begin() + onset_index, v.begin() + indices[i + 1], - bind2nd(std::less_equal(), threshold))); + [threshold](double x){return x <= threshold;})); if (end_index != indices[i + 1]){ ap_width_threshold.push_back(t[end_index] - t[onset_index]); } @@ -3555,10 +3555,7 @@ static int __postburst_min_indices(vector& t, vector& postburst_min_values, const double stim_end) { unsigned postburst_min_index, stim_end_index, end_index; - stim_end_index = - distance(t.begin(), - find_if(t.begin(), t.end(), - std::bind2nd(std::greater_equal(), stim_end))); + stim_end_index = distance(t.begin(), find_if(t.begin(), t.end(), [stim_end](double x) { return x >= stim_end; })); end_index = distance(t.begin(), t.end()); for (size_t i = 0; i < burst_end_indices.size(); i++) { if (burst_end_indices[i] + 1 < peak_indices.size()){ diff --git a/efel/cppcore/eFELLogger.h b/efel/cppcore/eFELLogger.h index a02ab106..cd6a0b27 100644 --- a/efel/cppcore/eFELLogger.h +++ b/efel/cppcore/eFELLogger.h @@ -23,6 +23,7 @@ #include #include #include +#include class eFELLogger { @@ -37,6 +38,13 @@ class eFELLogger } } + ~eFELLogger() + { + if (logfile.is_open()) { + logfile.close(); + } + } + template eFELLogger &operator<<(const std::vector &v){ if(logging){ diff --git a/setup.py b/setup.py index 95fcf704..995b333b 100644 --- a/setup.py +++ b/setup.py @@ -69,7 +69,7 @@ cppcore = Extension('efel.cppcore', sources=cppcore_sources, include_dirs=['efel/cppcore/'], - extra_compile_args=coverage_flags, + extra_compile_args=coverage_flags + ['-std=c++17'], extra_link_args=coverage_flags) setup( diff --git a/tests/test_cppcore.py b/tests/test_cppcore.py index d80b0b42..ef5131e6 100644 --- a/tests/test_cppcore.py +++ b/tests/test_cppcore.py @@ -200,6 +200,9 @@ def test_caching(self, feature_name): efel.cppcore.getFeature(feature_name, feature_values) with (Path(tempdir) / 'fllog.txt').open() as fd: contents = fd.read() + # re-call efel's Initialize with current dir to remove pointer to tempdir. + # this pointer was preventing the deletion of tempdir on windows. + efel.cppcore.Initialize(efel.getDependencyFileLocation(), '.') assert f"Calculated feature {feature_name}" in contents assert f"Reusing computed value of {feature_name}" in contents # make sure Calculated feature text occurs once