Skip to content
This repository was archived by the owner on Feb 26, 2025. It is now read-only.

Commit efef8b5

Browse files
committed
dbg
1 parent 64e62e1 commit efef8b5

File tree

4 files changed

+55
-66
lines changed

4 files changed

+55
-66
lines changed

bluepyefe/cell.py

Lines changed: 24 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
along with this library; if not, write to the Free Software Foundation, Inc.,
1919
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
2020
"""
21+
from collections import defaultdict
2122
import logging
2223
from multiprocessing import Pool
2324
import numpy
@@ -29,10 +30,19 @@
2930
from bluepyefe.plotting import _save_fig
3031
from matplotlib.backends.backend_pdf import PdfPages
3132

33+
from bluepyefe.recording import Recording
34+
3235
logger = logging.getLogger(__name__)
3336

3437

35-
class Cell(object):
38+
def extract_efeatures_helper(recording, efeatures, efeature_names, efel_settings):
39+
"""Helper function to compute efeatures for a single recording."""
40+
recording.compute_efeatures(
41+
efeatures, efeature_names, efel_settings)
42+
return recording
43+
44+
45+
class Cell:
3646

3747
"""Contains the metadata related to a cell as well as the
3848
electrophysiological recordings once they are read"""
@@ -47,7 +57,7 @@ def __init__(self, name):
4757

4858
self.name = name
4959

50-
self.recordings = []
60+
self.recordings: dict[str, list[Recording]] = defaultdict(list)
5161
self.rheobase = None
5262

5363
def reader(self, config_data, recording_reader=None):
@@ -91,9 +101,8 @@ def reader(self, config_data, recording_reader=None):
91101
)
92102

93103
def get_protocol_names(self):
94-
"""List of all the protocols available for the present cell."""
95-
96-
return list(set([rec.protocol_name for rec in self.recordings]))
104+
"""List of all the protocol names available for the present cell."""
105+
return list(self.recordings.keys())
97106

98107
def get_recordings_by_protocol_name(self, protocol_name):
99108
"""List of all the recordings available for the present cell for a
@@ -103,27 +112,7 @@ def get_recordings_by_protocol_name(self, protocol_name):
103112
protocol_name (str): name of the protocol for which to get
104113
the recordings.
105114
"""
106-
107-
return [
108-
rec
109-
for rec in self.recordings
110-
if rec.protocol_name == protocol_name
111-
]
112-
113-
def get_recordings_id_by_protocol_name(self, protocol_name):
114-
"""List of the indexes of the recordings available for the present
115-
cell for a given protocol.
116-
117-
Args:
118-
protocol_name (str): name of the protocol for which to get
119-
the recordings.
120-
"""
121-
122-
return [
123-
i
124-
for i, trace in enumerate(self.recordings)
125-
if trace.protocol_name == protocol_name
126-
]
115+
return self.recordings.get(protocol_name)
127116

128117
def read_recordings(
129118
self,
@@ -164,7 +153,7 @@ def read_recordings(
164153
protocol_name,
165154
efel_settings
166155
)
167-
self.recordings.append(rec)
156+
self.recordings[protocol_name].append(rec)
168157
break
169158
else:
170159
raise KeyError(
@@ -173,12 +162,6 @@ def read_recordings(
173162
f"the available stimuli names"
174163
)
175164

176-
def extract_efeatures_helper(self, recording_id, efeatures, efeature_names, efel_settings):
177-
"""Helper function to compute efeatures for a single recording."""
178-
self.recordings[recording_id].compute_efeatures(
179-
efeatures, efeature_names, efel_settings)
180-
return self.recordings[recording_id]
181-
182165
def extract_efeatures(
183166
self,
184167
protocol_name,
@@ -199,26 +182,26 @@ def extract_efeatures(
199182
is to be extracted several time on different sections
200183
of the same recording.
201184
"""
202-
recording_ids = self.get_recordings_id_by_protocol_name(protocol_name)
185+
recordings_of_protocol: list[Recording] = self.recordings.get(protocol_name)
203186

204187
# Run in parallel via multiprocessing
205188
with Pool(maxtasksperchild=1) as pool:
206189
tasks = [
207-
(rec_id, efeatures, efeature_names, efel_settings)
208-
for rec_id in recording_ids
190+
(recording, efeatures, efeature_names, efel_settings)
191+
for recording in recordings_of_protocol
209192
]
210-
results = pool.starmap(self.extract_efeatures_helper, tasks)
193+
results = pool.starmap(extract_efeatures_helper, tasks)
211194

212-
self.recordings = results
195+
self.recordings[protocol_name] = results
213196

214197
def compute_relative_amp(self):
215198
"""Compute the relative current amplitude for all the recordings as a
216199
percentage of the rheobase."""
217200

218201
if self.rheobase not in (0.0, None, False, numpy.nan):
219-
220-
for i in range(len(self.recordings)):
221-
self.recordings[i].compute_relative_amp(self.rheobase)
202+
for _, recordings_list in self.recordings.items():
203+
for recording in recordings_list:
204+
recording.compute_relative_amp(self.rheobase)
222205

223206
else:
224207

bluepyefe/rheobase.py

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -25,34 +25,39 @@
2525

2626

2727
def _get_list_spiking_amplitude(cell, protocols_rheobase):
28-
"""Return the list of sorted list of amplitude that triggered at least
29-
one spike"""
28+
"""Return the list of sorted amplitudes that triggered at least
29+
one spike, along with their corresponding spike counts."""
3030

3131
amps = []
3232
spike_counts = []
3333

34-
for i, rec in enumerate(cell.recordings):
35-
if rec.protocol_name in protocols_rheobase:
36-
if rec.spikecount is not None:
34+
for protocol_name, recordings_list in cell.recordings.items():
35+
if protocol_name in protocols_rheobase:
36+
for rec in recordings_list:
37+
if rec.spikecount is not None:
3738

38-
amps.append(rec.amp)
39-
spike_counts.append(rec.spikecount)
39+
amps.append(rec.amp)
40+
spike_counts.append(rec.spikecount)
4041

41-
if rec.amp < 0.01 and rec.spikecount >= 1:
42-
logger.warning(
43-
f"A recording of cell {cell.name} protocol "
44-
f"{rec.protocol_name} shows spikes at a "
45-
"suspiciously low current in a trace from file"
46-
f" {rec.files}. Check that the ton and toff are"
47-
"correct or for the presence of unwanted spikes."
48-
)
42+
if rec.amp < 0.01 and rec.spikecount >= 1:
43+
logger.warning(
44+
f"A recording of cell {cell.name} protocol "
45+
f"{protocol_name} shows spikes at a "
46+
"suspiciously low current in a trace from file "
47+
f"{rec.files}. Check that the ton and toff are "
48+
"correct or for the presence of unwanted spikes."
49+
)
4950

51+
# Sort amplitudes and their corresponding spike counts
5052
if amps:
5153
amps, spike_counts = zip(*sorted(zip(amps, spike_counts)))
54+
else:
55+
amps, spike_counts = (), ()
5256

5357
return amps, spike_counts
5458

5559

60+
5661
def compute_rheobase_absolute(cell, protocols_rheobase, spike_threshold=1):
5762
""" Compute the rheobase by finding the smallest current amplitude
5863
triggering at least one spike.

tests/test_cell.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ class CellTest(unittest.TestCase):
1111
def setUp(self):
1212

1313
self.cell = bluepyefe.cell.Cell(name="MouseNeuron")
14+
self.protocol_name = "IDRest"
1415

1516
file_metadata = {
1617
"i_file": "./tests/exp_data/B95_Ch0_IDRest_107.ibw",
@@ -25,18 +26,18 @@ def setUp(self):
2526
self.cell.read_recordings(protocol_data=[file_metadata], protocol_name="IDRest")
2627

2728
self.cell.extract_efeatures(
28-
protocol_name="IDRest", efeatures=["Spikecount", "AP1_amp"]
29+
protocol_name=self.protocol_name, efeatures=["Spikecount", "AP1_amp"]
2930
)
3031

3132
def test_efeature_extraction(self):
32-
recording = self.cell.recordings[0]
33+
recording = self.cell.recordings[self.protocol_name][0]
3334
self.assertEqual(2, len(recording.efeatures))
3435
self.assertEqual(recording.efeatures["Spikecount"], 9.0)
3536
self.assertLess(abs(recording.efeatures["AP1_amp"] - 66.4), 2.0)
3637

3738
def test_amp_threshold(self):
38-
recording = self.cell.recordings[0]
39-
compute_rheobase_absolute(self.cell, ["IDRest"])
39+
recording = self.cell.recordings[self.protocol_name][0]
40+
compute_rheobase_absolute(self.cell, [self.protocol_name])
4041
self.cell.compute_relative_amp()
4142
self.assertEqual(recording.amp, self.cell.rheobase)
4243
self.assertEqual(recording.amp_rel, 100.0)

tests/test_efel_settings.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,21 +28,21 @@ def setUp(self):
2828

2929
def test_efel_threshold(self):
3030

31-
self.cell.recordings[0].efeatures = {}
31+
self.cell.recordings["IDRest"][0].efeatures = {}
3232

3333
self.cell.extract_efeatures(
3434
protocol_name="IDRest",
3535
efeatures=["Spikecount", "AP1_amp"],
3636
efel_settings={'Threshold': 40.}
3737
)
3838

39-
recording = self.cell.recordings[0]
39+
recording = self.cell.recordings["IDRest"][0]
4040
self.assertEqual(recording.efeatures["Spikecount"], 0.)
4141
self.assertLess(abs(recording.efeatures["AP1_amp"] - 66.68), 0.01)
4242

4343
def test_efel_strictstim(self):
4444

45-
self.cell.recordings[0].efeatures = {}
45+
self.cell.recordings["IDRest"][0].efeatures = {}
4646

4747
self.cell.extract_efeatures(
4848
protocol_name="IDRest",
@@ -54,19 +54,19 @@ def test_efel_strictstim(self):
5454
}
5555
)
5656

57-
self.assertEqual(self.cell.recordings[0].efeatures["Spikecount"], 0.)
57+
self.assertEqual(self.cell.recordings["IDRest"][0].efeatures["Spikecount"], 0.)
5858

5959
def test_efel_threshold(self):
6060

61-
self.cell.recordings[0].efeatures = {}
61+
self.cell.recordings["IDRest"][0].efeatures = {}
6262

6363
self.cell.extract_efeatures(
6464
protocol_name="IDRest",
6565
efeatures=["Spikecount"],
6666
efel_settings={'Threshold': 40.}
6767
)
6868

69-
recording = self.cell.recordings[0]
69+
recording = self.cell.recordings["IDRest"][0]
7070
self.assertEqual(recording.efeatures["Spikecount"], 0.)
7171

7272

0 commit comments

Comments
 (0)