OSCR

eFEL: electrophysiology feature extraction library.

Code ↔ Paper

10 matches between paragraphs of the paper and lines of its authors' code, computed by the harvester (lexical-v1). Click a colored paragraph or line to see its counterpart.

The 10 matches
  1. [1] § 3 Results › 3.6 MEA recording extracellular features ↔ efel/pyfeatures/extrafeats.py, lines 1–39 · score 0.98 · neg_image, neg_peak_diff, neg_peak_relative, peak_trough_ratio, pos_image, pos_peak_diff
  2. [2] § 3 Results › 3.5 Phase-plane analysis features ↔ efel/cppcore/FillFptrTable.cpp, lines 123–195 · score 0.92 · AP_fall_rate_change, AP_peak_downstroke, AP_peak_upstroke, AP_phaseslope, AP_rise_rate_change, max
  3. [3] § 3 Results › 3.5 Phase-plane analysis features ↔ efel/cppcore/cfeature.cpp, lines 83–138 · score 0.77 · AP_fall_rate_change, AP_rise_rate_change, max, peak, spiking
  4. [4] § 2 Materials and methods › 2.3 Electrical features ↔ bluepyefe/auto_targets.py, lines 119–190 · score 0.66 · steady state voltage, sag amplitude, decay, ohmic, resistance, hyperpolarized
  5. [5] § 3 Results › 3.3 Classification of neuron firing types ↔ bluepyemodel/efeatures_extraction/auto_targets.py, lines 24–83 · score 0.61 · strict burst, firing patterns, ISI CV, irregularity, spike
  6. [6] § 2 Materials and methods › 2.3 Electrical features ↔ efel/cppcore/Subthreshold.cpp, lines 590–643 · score 0.61 · steady state voltage, sag amplitude, decay, Subthreshold, stimulus
  7. [7] § 2 Materials and methods › 2.3 Electrical features ↔ efel/cppcore/SpikeShape.cpp, lines 1374–1454 · score 0.58 · rising phase, falling phases, AHP, AP, peak, Spike
  8. [8] § 2 Materials and methods › 2.3 Electrical features ↔ efel/cppcore/FillFptrTable.cpp, lines 123–195 · score 0.58 · AP1_peak, AP2_peak, eFEL
  9. [9] § 2 Materials and methods › 2.3 Electrical features ↔ efel/cppcore/cfeature.cpp, lines 140–201 · score 0.58 · AP1_peak, AP2_peak, eFEL
  10. [10] § 2 Materials and methods › 2.3 Electrical features ↔ efel/pyfeatures/extrafeats.py, lines 1–39 · score 0.51 · trough ratio, extracellular features, peak

Paper

Loaded from Europe PMC by your browser, not stored by OSCR: doi.org · Europe PMC

The paper is loaded when this pane is shown.

The authors' code

Python · 491 lines · 15 KB · GPL-3.0 · 2 matches

  1. """Extracellular features functions"""
  2. """
  3. Copyright (c) 2024, EPFL/Blue Brain Project
  4. Copyright (c) 2025-2026 Open Brain Institute
  5. This file is part of eFEL <https://github.com/BlueBrain/eFEL>
  6. This library is free software; you can redistribute it and/or modify it under
  7. the terms of the GNU Lesser General Public License version 3.0 as published
  8. by the Free Software Foundation.
  9. This library is distributed in the hope that it will be useful, but WITHOUT
  10. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  11. FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
  12. details.
  13. You should have received a copy of the GNU Lesser General Public License
  14. along with this library; if not, write to the Free Software Foundation, Inc.,
  15. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  16. """
  17. import numpy as np
  18. from scipy.stats import linregress
  19. from scipy.signal import resample_poly
  20. all_1D_features = [
  21. "peak_to_valley",
  22. "halfwidth",
  23. "peak_trough_ratio",
  24. "repolarization_slope",
  25. "recovery_slope",
  26. "neg_peak_relative",
  27. "pos_peak_relative",
  28. "neg_peak_diff",
  29. "pos_peak_diff",
  30. "neg_image",
  31. "pos_image",
  32. ]
  33. def _get_slope(x, y):
  34. """
  35. Return the slope of x and y data, using scipy.signal.linregress
  36. """
  37. slope = linregress(x, y)
  38. return slope
  39. def _get_trough_and_peak_idx(waveform, after_max_trough=False):
  40. """
  41. Return the indices of the detected troughs (minimum of waveform)
  42. and peaks (maximum of waveform, after trough) of the input waveforms.
  43. Assumes negative troughs and positive peaks
  44. Returns 0 if not detected
  45. """
  46. if after_max_trough:
  47. max_trough_idx = np.unravel_index(
  48. np.argmin(waveform),
  49. waveform.shape)[1]
  50. trough_idx = (
  51. np.argmin(waveform[:, max_trough_idx:], axis=1) + max_trough_idx
  52. )
  53. peak_idx = (
  54. np.argmax(waveform[:, max_trough_idx:], axis=1) + max_trough_idx
  55. )
  56. else:
  57. trough_idx = np.argmin(waveform, axis=1)
  58. peak_idx = np.argmax(waveform, axis=1)
  59. return trough_idx, peak_idx
  60. def calculate_features(
  61. waveforms,
  62. sampling_frequency,
  63. upsample=None,
  64. feature_names=None,
  65. recovery_slope_window=0.7
  66. ):
  67. """Calculate features for all waveforms
  68. Args:
  69. waveforms : numpy.ndarray (num_waveforms x num_samples)
  70. waveforms to compute features for
  71. sampling_frequency : float
  72. rate at which the waveforms are sampled (Hz)
  73. feature_names : list or None (if None, compute all)
  74. features to compute
  75. recovery_slope_window : float
  76. window length in ms after peak wherein recovery slope is computed
  77. Returns:
  78. dict (num_waveforms x num_metrics): Dictionary with computed metrics.
  79. Keys are the metric names, values are the computed features
  80. """
  81. metrics = dict()
  82. if feature_names is None:
  83. feature_names = all_1D_features
  84. else:
  85. for name in feature_names:
  86. assert name in all_1D_features, f"{name} not in {all_1D_features}"
  87. if upsample is not None:
  88. assert upsample > 0
  89. waveforms = _upsample_wf(waveforms, int(upsample))
  90. sampling_frequency = upsample * sampling_frequency
  91. if "peak_to_valley" in feature_names:
  92. metrics["peak_to_valley"] = peak_to_valley(
  93. waveforms=waveforms, sampling_frequency=sampling_frequency
  94. )
  95. if "peak_trough_ratio" in feature_names:
  96. metrics["peak_trough_ratio"] = peak_trough_ratio(waveforms=waveforms)
  97. if "halfwidth" in feature_names:
  98. metrics["halfwidth"] = halfwidth(
  99. waveforms=waveforms, sampling_frequency=sampling_frequency
  100. )
  101. if "repolarization_slope" in feature_names:
  102. metrics["repolarization_slope"] = repolarization_slope(
  103. waveforms=waveforms,
  104. sampling_frequency=sampling_frequency,
  105. )
  106. if "recovery_slope" in feature_names:
  107. metrics["recovery_slope"] = recovery_slope(
  108. waveforms=waveforms,
  109. sampling_frequency=sampling_frequency,
  110. window=recovery_slope_window,
  111. )
  112. if "neg_peak_diff" in feature_names:
  113. metrics["neg_peak_diff"] = peak_time_diff(
  114. waveforms=waveforms, fs=sampling_frequency, sign="negative"
  115. )
  116. if "pos_peak_diff" in feature_names:
  117. metrics["pos_peak_diff"] = peak_time_diff(
  118. waveforms=waveforms, fs=sampling_frequency, sign="positive"
  119. )
  120. if "neg_peak_relative" in feature_names:
  121. metrics["neg_peak_relative"] = relative_amplitude(
  122. waveforms=waveforms, sign="negative"
  123. )
  124. if "pos_peak_relative" in feature_names:
  125. metrics["pos_peak_relative"] = relative_amplitude(
  126. waveforms=waveforms, sign="positive"
  127. )
  128. if "neg_image" in feature_names:
  129. metrics["neg_image"] = peak_image(waveforms=waveforms, sign="negative")
  130. if "pos_image" in feature_names:
  131. metrics["pos_image"] = peak_image(waveforms=waveforms, sign="positive")
  132. return metrics
  133. def peak_to_valley(waveforms, sampling_frequency):
  134. """
  135. Time between trough and peak. If the peak precedes the trough,
  136. peak_to_valley is negative.
  137. Args:
  138. waveforms : numpy.ndarray (num_waveforms x num_samples)
  139. waveforms to compute feature for
  140. sampling_frequency : float
  141. rate at which the waveforms are sampled (Hz)
  142. Returns:
  143. np.ndarray (num_waveforms): peak_to_valley in seconds
  144. """
  145. trough_idx, peak_idx = _get_trough_and_peak_idx(waveforms)
  146. ptv = (peak_idx - trough_idx) * (1 / sampling_frequency)
  147. ptv[ptv == 0] = np.nan
  148. return ptv
  149. def peak_trough_ratio(waveforms):
  150. """
  151. Normalized ratio of peak height over trough depth
  152. Assumes baseline is 0
  153. Args:
  154. waveforms : numpy.ndarray (num_waveforms x num_samples)
  155. waveforms to compute feature for
  156. Returns:
  157. np.ndarray (num_waveforms): Peak to trough ratio
  158. """
  159. trough_idx, peak_idx = _get_trough_and_peak_idx(waveforms)
  160. ptratio = np.empty(trough_idx.shape[0])
  161. ptratio[:] = np.nan
  162. for i in range(waveforms.shape[0]):
  163. if peak_idx[i] == 0 and trough_idx[i] == 0:
  164. continue
  165. ptratio[i] = np.abs(waveforms[i, peak_idx[i]] /
  166. waveforms[i, trough_idx[i]])
  167. return ptratio
  168. def halfwidth(
  169. waveforms,
  170. sampling_frequency,
  171. return_idx=False
  172. ):
  173. """
  174. Width of waveform at half of its amplitude.
  175. If the peak precedes the trough, halfwidth is negative.
  176. Computes the width of the waveform peak at half its height
  177. Args:
  178. waveforms : numpy.ndarray (num_waveforms x num_samples)
  179. waveforms to compute features for
  180. sampling_frequency : float
  181. rate at which the waveforms are sampled (Hz)
  182. return_idx : bool
  183. if true, also returns index of threshold crossing before and
  184. index of threshold crossing after peak
  185. Returns:
  186. np.ndarray or (np.ndarray, np.ndarray, np.ndarray):
  187. Halfwidth of the waveforms or (Halfwidth of the waveforms,
  188. index_cross_pre_peak, index_cross_post_peak)
  189. """
  190. trough_idx, peak_idx = _get_trough_and_peak_idx(waveforms)
  191. hw = np.empty(waveforms.shape[0])
  192. hw[:] = np.nan
  193. cross_pre_pk = np.empty(waveforms.shape[0], dtype=int)
  194. cross_post_pk = np.empty(waveforms.shape[0], dtype=int)
  195. for i in range(waveforms.shape[0]):
  196. if peak_idx[i] >= trough_idx[i]:
  197. trough_val = waveforms[i, trough_idx[i]]
  198. threshold = (
  199. 0.5 * trough_val
  200. ) # threshold is half of peak heigth (assuming baseline is 0)
  201. cpre_idx = np.where(waveforms[i, :trough_idx[i]] < threshold)[0]
  202. cpost_idx = np.where(waveforms[i, trough_idx[i]:] < threshold)[0]
  203. if len(cpre_idx) == 0 or len(cpost_idx) == 0:
  204. continue
  205. cross_pre_pk[i] = (
  206. cpre_idx[0] - 1
  207. ) # last occurence of waveform lower than thr, before peak
  208. cross_post_pk[i] = (
  209. cpost_idx[-1] + 1 + trough_idx[i]
  210. ) # first occurence of waveform lower than peak, after peak
  211. hw[i] = (cross_post_pk[i] - cross_pre_pk[i]) * (
  212. 1 / sampling_frequency
  213. ) # + peak_idx[i]
  214. else:
  215. peak_val = waveforms[i, peak_idx[i]]
  216. threshold = (
  217. 0.5 * peak_val
  218. ) # threshold is half of peak heigth (assuming baseline is 0)
  219. cpre_idx = np.where(waveforms[i, :peak_idx[i]] > threshold)[0]
  220. cpost_idx = np.where(waveforms[i, peak_idx[i]:] > threshold)[0]
  221. if len(cpre_idx) == 0 or len(cpost_idx) == 0:
  222. continue
  223. cross_pre_pk[i] = (
  224. cpre_idx[0] - 1
  225. ) # last occurence of waveform lower than thr, before peak
  226. cross_post_pk[i] = (
  227. cpost_idx[-1] + 1 + trough_idx[i]
  228. ) # first occurence of waveform lower than peak, after peak
  229. hw[i] = -(cross_post_pk[i] - cross_pre_pk[i]) * (
  230. 1 / sampling_frequency
  231. ) # + peak_idx[i]
  232. if not return_idx:
  233. return hw
  234. return hw, cross_pre_pk, cross_post_pk
  235. def repolarization_slope(waveforms,
  236. sampling_frequency,
  237. return_idx=False
  238. ):
  239. """
  240. Return slope of repolarization period between trough and baseline
  241. After reaching its maxumum polarization, the neuron potential will
  242. recover. The repolarization slope is defined as the dV/dT of the action
  243. potential between trough and baseline.
  244. Optionally the function returns also the indices per waveform where the
  245. potential crosses baseline.
  246. Args:
  247. waveforms : numpy.ndarray (num_waveforms x num_samples)
  248. waveforms to compute features for
  249. sampling_frequency : float
  250. rate at which the waveforms are sampled (Hz)
  251. return_idx : bool
  252. if true, also returns index of threshold crossing before and
  253. index of threshold crossing after peak
  254. Returns:
  255. np.ndarray or (np.ndarray, np.ndarray): Repolarization slope of the
  256. waveforms or (Repolarization slope of the waveforms, return to base
  257. index)
  258. """
  259. trough_idx, peak_idx = _get_trough_and_peak_idx(waveforms)
  260. rslope = np.empty(waveforms.shape[0])
  261. rslope[:] = np.nan
  262. return_to_base_idx = np.empty(waveforms.shape[0], dtype=np.int_)
  263. return_to_base_idx[:] = 0
  264. time = np.arange(0, waveforms.shape[1]) * (1 / sampling_frequency) # in s
  265. for i in range(waveforms.shape[0]):
  266. if trough_idx[i] == 0:
  267. continue
  268. rtrn_idx = np.where(waveforms[i, trough_idx[i]:] >= 0)[0]
  269. if len(rtrn_idx) == 0:
  270. continue
  271. return_to_base_idx[i] = (
  272. rtrn_idx[0] + trough_idx[i]
  273. ) # first time after trough, where waveform is at baseline
  274. if return_to_base_idx[i] - trough_idx[i] < 3:
  275. continue
  276. slope = _get_slope(
  277. time[trough_idx[i]:return_to_base_idx[i]],
  278. waveforms[i, trough_idx[i]:return_to_base_idx[i]]
  279. )
  280. rslope[i] = slope[0]
  281. if not return_idx:
  282. return rslope
  283. return rslope, return_to_base_idx
  284. def recovery_slope(waveforms, sampling_frequency, window):
  285. """
  286. Return the recovery slope of input waveforms. After repolarization,
  287. the neuron hyperpolarizes until it peaks. The recovery slope is the
  288. slope of the action potential after the peak, returning to the baseline
  289. in dV/dT. The slope is computed within a user-defined window after
  290. the peak.
  291. Takes a numpy array of waveforms and returns an array with
  292. recovery slopes per waveform.
  293. Args:
  294. waveforms : numpy.ndarray (num_waveforms x num_samples)
  295. waveforms to compute features for
  296. sampling_frequency : float
  297. rate at which the waveforms are sampled (Hz)
  298. window : float
  299. length after peak wherein to compute recovery slope (ms)
  300. Returns:
  301. np.ndarray: Recovery slope of the waveforms
  302. """
  303. _, peak_idx = _get_trough_and_peak_idx(waveforms)
  304. rslope = np.empty(waveforms.shape[0])
  305. rslope[:] = np.nan
  306. time = np.arange(0, waveforms.shape[1]) * (1 / sampling_frequency) # in s
  307. for i in range(waveforms.shape[0]):
  308. if peak_idx[i] in [0, waveforms.shape[1]]:
  309. continue
  310. max_idx = int(peak_idx[i] + ((window / 1000) * sampling_frequency))
  311. max_idx = np.min([max_idx, waveforms.shape[1]])
  312. if len(time[peak_idx[i]:max_idx]) < 3:
  313. continue
  314. slope = _get_slope(
  315. time[peak_idx[i]:max_idx], waveforms[i, peak_idx[i]:max_idx]
  316. )
  317. rslope[i] = slope[0]
  318. return rslope
  319. def peak_image(waveforms, sign="negative"):
  320. """
  321. Normalized amplitude at the time of peak minimum or maximum.
  322. Args:
  323. waveforms : numpy.ndarray (num_waveforms x num_samples)
  324. waveforms to compute features for
  325. sign : str
  326. "positive" | "negative"
  327. Returns:
  328. np.ndarray: Peak images for the waveforms
  329. """
  330. assert len(waveforms) > 1
  331. if sign == "negative":
  332. funarg = np.argmin
  333. fun = np.min
  334. else:
  335. funarg = np.argmax
  336. fun = np.max
  337. peak_channel, peak_time = np.unravel_index(
  338. funarg(waveforms), waveforms.shape
  339. )
  340. relative_peaks = waveforms[:, peak_time] / fun(waveforms[peak_channel])
  341. return relative_peaks
  342. def relative_amplitude(waveforms, sign="negative"):
  343. """
  344. Normalized amplitude with respect to channel with largest amplitude.
  345. Args:
  346. waveforms : numpy.ndarray (num_waveforms x num_samples)
  347. waveforms to compute features for
  348. sign : str
  349. "positive" | "negative"
  350. Returns:
  351. np.ndarray: Relative amplitudes for the waveforms
  352. """
  353. assert len(waveforms) > 1
  354. if sign == "negative":
  355. fun = np.min
  356. else:
  357. fun = np.max
  358. peak_amp = np.abs(fun(waveforms))
  359. relative_peaks = np.abs(fun(waveforms, 1)) / peak_amp
  360. return relative_peaks
  361. def peak_time_diff(waveforms, fs, sign="negative"):
  362. """
  363. Peak time differences with respect to channel with largest amplitude.
  364. Args:
  365. waveforms : numpy.ndarray (num_waveforms x num_samples)
  366. waveforms to compute features for
  367. fs : float
  368. Sampling rate in Hz
  369. sign : str
  370. "positive" | "negative"
  371. Returns:
  372. np.ndarray: Peak time differences for the waveforms
  373. """
  374. assert len(waveforms) > 1
  375. if sign == "negative":
  376. argfun = np.argmin
  377. else:
  378. argfun = np.argmax
  379. peak_chan = np.unravel_index(argfun(waveforms), waveforms.shape)[0]
  380. peak_time = argfun(waveforms[peak_chan])
  381. relative_peak_times = (argfun(waveforms, 1) - peak_time) / fs
  382. return relative_peak_times
  383. def _upsample_wf(waveforms, upsample):
  384. ndim = len(waveforms.shape)
  385. waveforms_up = resample_poly(waveforms, up=upsample, down=1, axis=ndim - 1)
  386. return waveforms_up

extrafeats.py at commit 3a16526, under GPL-3.0 · at the source

Overview

Authors: Darshan Mandge1, Anıl Tuncel1, Aurélien Jaquier1, Ilkan Kilic1, Tanguy Damart1, Henry Markram1,2, Werner Van Geit1, Rajnish Ranjan1,2
  1. Blue Brain Project, École Polytechnique Fédérale de Lausanne (EPFL), Campus Biotech, Geneva 1202, Switzerland
  2. Laboratory of Neural Microcircuitry, Brain Mind Institute, École Polytechnique Fédérale de Lausanne (EPFL), Lausanne 1015, Switzerland
Journal: Bioinformatics (Oxford, England), volume 42, issue 6, article btag328
Dates: received 3 October 2025; accepted 12 May 2026; published online 22 May 2026; in print June 2026
Type: Research article · Language: English
License: CC BY
Identifiers: DOI 10.1093/bioinformatics/btag328 · PMID 42172582 · PMCID PMC13257855 · OpenAlex W7162133769
Open access: gold, a free copy (OpenAlex)
Status: code verified
Categories: none (in silico) (organism), methods / tools (subfield)
Methods: Single-unit activity, calcium imaging
MeSH: Computational Biology*, Electrophysiological Phenomena*, Electrophysiology*, Software*, Action Potentials, Algorithms (* major topic)
Topic: Neural dynamics and brain function (Cognitive Neuroscience, Neuroscience), according to OpenAlex
Funding: Swiss government’s ETH Board of the Swiss Federal Institutes of Technology
Citations: cited by 2 papers (Europe PMC); 48 references in the paper

Abstract

Motivation: Electrophysiological recordings are essential in experimental and computational neuroscience, providing insights into neuronal excitability and network behaviour. Extracting features such as action potential thresholds, widths, and firing patterns is conceptually straightforward, but in practice it is complicated by heterogeneous datasets and software environments, which hinder reproducibility and interoperability. A standardized, efficient, and portable framework is needed to ensure consistent analysis across platforms and alignment with community data standards.

Results: We present the Electrophysiology Feature Extraction Library (eFEL), a cross-platform, open-source library that implements standardized definitions for over 90 electrophysiological features. eFEL combines a high-performance C++ core with a Python interface, supporting customizable feature dependencies, caching, and parallelization. It integrates with community standards such as Neurodata Without Borders and works seamlessly with common electrophysiology formats and simulation environments. Since its initial release in 2015, eFEL has been used in published studies spanning single-cell analysis, model optimization, multimodal fitting, and circuit simulations. eFEL provides a FAIR-compliant, versatile resource for reproducible electrophysiological data analysis.

Availability and implementation: The eFEL library is publicly available at https://github.com/openbraininstitute/eFEL and the associated study data and scripts have been deposited in Zenodo at https://zenodo.org/records/17241835.

Reproduced under the paper's license (CC BY), from the paper cited above.

Repositories

Its files are read in the Code ↔ Paper reader above, with 10 matches between paragraphs and lines of code.

berenslab/ephyspy

License: GPL-3.0
State: the link answers, verified on 27 September 2026
Evidence: files inventoried
Commit: 9cd7ca5f1c66584e85601cd1079d306246f177eb, 19 March 2025
Languages: Python (20), JavaScript (12), Jupyter (1)
Size: 108 files, 33 scripts
Software Heritage: archived
Found in: the resources table
Holds: README, license file, environment (pyproject.toml, uv.lock, docs/requirements.txt), tests, continuous integration, documentation, 1 notebook
Not found: CITATION.cff
Tools: NumPy (13 files), Matplotlib (10 files), pandas (4 files), SciPy (2 files), scikit-learn (1 file)
Availability: 1 check, the latest on 27 September 2026: the link answers
  • 27 September 2026: the link answers
35 files

AllenInstitute/ipfx

License: BSD-2-Clause
State: the link answers, verified on 27 September 2026
Evidence: files inventoried
Commit: c607a36e25618a6bb8ba5438c1cd945fb429e659, 10 December 2025
Languages: Python (131), Shell (6), JavaScript (5)
Size: 264 files, 142 scripts
Software Heritage: not archived
Found in: the resources table
Holds: README, license file, environment (pyproject.toml, requirements-docs.txt, requirements-test.txt, requirements.txt, setup.cfg, docker/Dockerfile), tests, continuous integration, documentation
Not found: CITATION.cff
Tools: NumPy (57 files), Neurodata Without Borders (PyNWB, MatNWB) (15 files), pandas (15 files), Matplotlib (9 files), SciPy (9 files), h5py (7 files), pyABF (1 file), seaborn (1 file)
Availability: 1 check, the latest on 27 September 2026: the link answers
  • 27 September 2026: the link answers
144 files

openbraininstitute/eFEL

License: GPL-3.0
State: the link answers, verified on 27 September 2026
Evidence: files inventoried
Commit: 3a1652676fc05608f4616a33e874cba049b5a213, 25 August 2026
Languages: Python (41), NEURON (24), C/C++ (13), C++ (10), Jupyter (10), Shell (3)
Size: 209 files, 101 scripts
Software Heritage: not archived
Found in: the resources table
Holds: README, license file, environment (pyproject.toml, requirements_docs.txt, setup.cfg, setup.py), tests, continuous integration, documentation, 10 notebooks
Not found: CITATION.cff
Tools: NEURON (33 files), NumPy (32 files), Matplotlib (10 files), SciPy (6 files), Neo (4 files), h5py (3 files), pandas (2 files), Neurodata Without Borders (PyNWB, MatNWB) (1 file)
Availability: 1 check, the latest on 27 September 2026: the link answers
  • 27 September 2026: the link answers
104 files

Zenodo 8283490

License: Apache-2.0
State: the link answers, verified on 27 September 2026
Evidence: files inventoried
Size: 1 file
Software Heritage: not checked
Found in: the references
Not found: README, license file, CITATION.cff, environment file, tests, continuous integration, documentation
Tools: NumPy (43 files), NEURON (31 files), Matplotlib (6 files), pandas (5 files), SciPy (2 files), h5py (1 file)
Availability: 1 check, the latest on 27 September 2026: the link answers (HTTP 200)
  • 27 September 2026: the link answers (HTTP 200)
191 files
At the source:

Zenodo 14002264

License: LGPL-3.0
State: the link answers, verified on 27 September 2026
Evidence: files inventoried
Size: 1 file
Software Heritage: not checked
Found in: the references
Not found: README, license file, CITATION.cff, environment file, tests, continuous integration, documentation
Tools: NumPy (25 files), Matplotlib (4 files), h5py (3 files), SciPy (3 files), Neo (1 file)
Availability: 1 check, the latest on 27 September 2026: the link answers (HTTP 200)
  • 27 September 2026: the link answers (HTTP 200)
47 files
At the source:

bluebrain/bluepyefe

License: LGPL-3.0
State: the link answers, verified on 27 September 2026
Evidence: files inventoried
Commit: 11a1e0c59e2541362e22279f6c78edbff44db975, 26 February 2025
Languages: Python (43), Jupyter (2)
Size: 100 files, 45 scripts
Software Heritage: not checked
Found in: the Zenodo archive record
Holds: README, license file, CITATION.cff, environment (pyproject.toml, requirements.txt, requirements_docs.txt), tests, continuous integration, documentation, 2 notebooks
Tools: NumPy (25 files), Matplotlib (4 files), h5py (3 files), SciPy (3 files), Neo (1 file)
Availability: 1 check, the latest on 27 September 2026: the link answers
  • 27 September 2026: the link answers
47 files

bluebrain/bluepyemodel

License: Apache-2.0
State: the link answers, verified on 27 September 2026
Evidence: files inventoried
Commit: 5e9546a395ba9295626bb8295cb5466f8f7e1de1, 26 February 2025
Languages: Python (145), NEURON (25), Shell (10), Jupyter (8)
Size: 286 files, 188 scripts
Software Heritage: not checked
Found in: the Zenodo archive record
Holds: README, license file, CITATION.cff, environment (pyproject.toml), tests, continuous integration, documentation, 8 notebooks
Tools: NumPy (43 files), NEURON (31 files), Matplotlib (6 files), pandas (5 files), SciPy (2 files), h5py (1 file)
Availability: 1 check, the latest on 27 September 2026: the link answers
  • 27 September 2026: the link answers
191 files

Availability and implementation

The eFEL library is publicly available at https://github.com/openbraininstitute/eFEL and the associated study data and scripts have been deposited in Zenodo at https://zenodo.org/records/17241835.

Reproduced under the paper's license (CC BY), from the paper cited above.

Tracing map

Proposed by the machine: these links were found in the paper and verified at the source, without human review. The map will receive a Zenodo DOI once one of the paper's authors has validated it with their ORCID.

What the map holds:

  • 7 repositories of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
  • 742 scripts, each with its path and the digest of its content;
  • 10 matches between paragraphs of the paper and lines of the code (method lexical-v1);
  • neither the text of the paper nor the code itself.

Its JSON (tracing-map.json) is deposited on Zenodo with its DOI once the map is validated.

Data

Datasets cited

Versions

The history of this record: each version stored by the harvester or made by a correction of its authors or of the maintainers of its code, and what changed in its facts. The texts of the paper (its abstract, its availability statements) are not part of it; versions that changed only those are not listed.

Version 1, 27 September 2026: the first record

Recorded: type, language, journal, volume, issue, pages, dates, 8 authors, 6 MeSH terms, 1 funder, 37 references.

Cite

This paper

Mandge, D., Tuncel, A., Jaquier, A., Kilic, I., Damart, T., Markram, H., Van Geit, W., & Ranjan, R. (2026). eFEL: electrophysiology feature extraction library. Bioinformatics (Oxford, England), 42(6), btag328. https://doi.org/10.1093/bioinformatics/btag328

BibTeX

@article{mandge2026efel,
author = {Mandge, Darshan and Tuncel, Anıl and Jaquier, Aurélien and Kilic, Ilkan and Damart, Tanguy and Markram, Henry and Van Geit, Werner and Ranjan, Rajnish},
title = {{eFEL: electrophysiology feature extraction library}},
journal = {Bioinformatics (Oxford, England)},
year = {2026},
month = jun,
volume = {42},
number = {6},
pages = {btag328},
publisher = {Oxford University Press},
issn = {1367-4803},
doi = {10.1093/bioinformatics/btag328},
url = {https://doi.org/10.1093/bioinformatics/btag328},
pmid = {42172582},
pmcid = {PMC13257855}
}

RIS

TY - JOUR
AU - Mandge, Darshan
AU - Tuncel, Anıl
AU - Jaquier, Aurélien
AU - Kilic, Ilkan
AU - Damart, Tanguy
AU - Markram, Henry
AU - Van Geit, Werner
AU - Ranjan, Rajnish
TI - eFEL: electrophysiology feature extraction library
T2 - Bioinformatics (Oxford, England)
J2 - Bioinformatics
PY - 2026
DA - 2026/06/01
VL - 42
IS - 6
SP - btag328
SN - 1367-4803
PB - Oxford University Press
DO - 10.1093/bioinformatics/btag328
UR - https://doi.org/10.1093/bioinformatics/btag328
LA - en
ER -

CSL-JSON

{
"id": "10.1093/bioinformatics/btag328",
"type": "article-journal",
"title": "eFEL: electrophysiology feature extraction library",
"container-title": "Bioinformatics (Oxford, England)",
"author": [
{
"family": "Mandge",
"given": "Darshan"
},
{
"family": "Tuncel",
"given": "Anıl"
},
{
"family": "Jaquier",
"given": "Aurélien"
},
{
"family": "Kilic",
"given": "Ilkan"
},
{
"family": "Damart",
"given": "Tanguy"
},
{
"family": "Markram",
"given": "Henry"
},
{
"family": "Van Geit",
"given": "Werner"
},
{
"family": "Ranjan",
"given": "Rajnish"
}
],
"container-title-short": "Bioinformatics",
"volume": "42",
"issue": "6",
"page": "btag328",
"DOI": "10.1093/bioinformatics/btag328",
"PMID": "42172582",
"PMCID": "PMC13257855",
"ISSN": "1367-4803",
"publisher": "Oxford University Press",
"URL": "https://doi.org/10.1093/bioinformatics/btag328",
"language": "en",
"issued": {
"date-parts": [
[
2026,
6,
1
]
]
}
}

The tracing map gets a citation of its own once an author has validated it and it has a DOI.

Similar papers

The papers with a page that share the most with this one: the tools found in their code, their categories, datasets, cited references and authors, the rarest counting most.

[1] doi:10.1016/j.crmeth.2026.101421 [code]
EthoPy provides an accessible platform for reproducible behavioral neuroscience.
Journal: Cell reports methods
In common: Neurodata Without Borders (PyNWB, MatNWB), h5py, seaborn, 5 other tools, methods / tools, 3 references
[2] doi:10.7554/elife.110588 [code]
Opening the black box toward a modular approach to spike sorting.
Journal: eLife
In common: Neo, Neurodata Without Borders (PyNWB, MatNWB), h5py, 6 other tools, methods / tools, 1 reference
[3] doi:10.1016/j.isci.2026.115488 [code]
An integrated &lt;i&gt;i&lt;/i&gt; &lt;i&gt;n vitro&lt;/i&gt; platform and biophysical modeling approach for studying synaptic transmission in isolated neuronal pairs.
Journal: iScience
In common: Neo, NEURON, h5py, 6 other tools, 1 reference
[4] doi:10.1371/journal.pcbi.1014283 [code]
Spatial richness of neural magnetic fields.
Journal: PLoS computational biology
In common: Neo, NEURON, h5py, 4 other tools, 2 references
[5] doi:10.1371/journal.pcbi.1014458 [code]
Neuronal excitability and parameter variability in the Hodgkin-Huxley model.
Journal: PLoS computational biology
In common: pandas, SciPy, Matplotlib, 1 other tool, none (in silico), 4 references
[6] doi:10.1016/j.patter.2026.101590 [code]
Density-based longitudinal neuron tracking in high-density electrophysiological recordings.
Journal: Patterns (New York, N.Y.)
In common: Neo, h5py, seaborn, 5 other tools, 1 reference
[7] doi: [code]
Naturalistic behavior and self-generated neural activity predictive of self-correction
Journal: bioRxiv : the preprint server for biology
In common: Neo, Neurodata Without Borders (PyNWB, MatNWB), seaborn, 5 other tools
[8] doi:10.1038/s41593-026-02232-0 [code]
Entorhinal cortex represents task-relevant remote locations independently of CA1.
Journal: Nature neuroscience
In common: Neurodata Without Borders (PyNWB, MatNWB), h5py, seaborn, 5 other tools, 1 reference
[9] doi:10.1038/s41467-026-76939-w [code]
HIPPIE: a generative model for electrophysiological analysis across species, technologies, and modalities.
Journal: Nature communications
In common: Neurodata Without Borders (PyNWB, MatNWB), h5py, seaborn, 5 other tools, methods / tools
[10] doi:10.1073/pnas.2533168123 [code]
Dendritic morphology and synaptic nonlinearities enhance functional complexity in human cortical neurons.
Journal: Proceedings of the National Academy of Sciences of the United States of America
In common: NEURON, h5py, scikit-learn, 4 other tools, 1 reference

Contribute

The authors of this paper can claim it, correct its record and validate its tracing map, and the maintainers of its code (its owner, or a public member of its organization) correct what it says of their repository; anyone signed in can ask for its removal. Every request goes to OSCR's own machine, which answers it; your account page follows them.

Sign in with ORCID to claim this paper as one of its authors, correct its record or validate its tracing map: when the paper's metadata lists your ORCID iD, you are recognized at once. Maintainers of its code: sign in with GitHub, then claim the repository on your account page.

Request its removal

To ask OSCR to remove this record, the copies of its authors' scripts or its tracing map, use the removal request page: signed in, you say who you are, what to remove and why, then review and confirm the request. Published rules decide every request (how).

Discussion, reproductions, activity

Discussion: questions and error reports about this paper and its code, from signed-in readers and its authors. It opens with sign-in.

Reproductions: reports from readers who ran the authors' code: what they reproduced, with which environment, commit and data. It opens with sign-in.

Activity: what happens around this paper: new versions of its record, its map's validation, discussions and reproductions. It opens with sign-in.