bluecellulab 2.6.49__py3-none-any.whl → 2.6.51__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of bluecellulab might be problematic. Click here for more details.
- bluecellulab/analysis/analysis.py +325 -36
- bluecellulab/analysis/utils.py +7 -0
- bluecellulab/circuit/circuit_access/bluepy_circuit_access.py +1 -1
- bluecellulab/utils.py +26 -0
- bluecellulab/validation/validation.py +169 -55
- {bluecellulab-2.6.49.dist-info → bluecellulab-2.6.51.dist-info}/METADATA +2 -1
- {bluecellulab-2.6.49.dist-info → bluecellulab-2.6.51.dist-info}/RECORD +11 -10
- {bluecellulab-2.6.49.dist-info → bluecellulab-2.6.51.dist-info}/WHEEL +1 -1
- {bluecellulab-2.6.49.dist-info → bluecellulab-2.6.51.dist-info}/licenses/AUTHORS.txt +0 -0
- {bluecellulab-2.6.49.dist-info → bluecellulab-2.6.51.dist-info}/licenses/LICENSE +0 -0
- {bluecellulab-2.6.49.dist-info → bluecellulab-2.6.51.dist-info}/top_level.txt +0 -0
|
@@ -3,14 +3,31 @@ try:
|
|
|
3
3
|
import efel
|
|
4
4
|
except ImportError:
|
|
5
5
|
efel = None
|
|
6
|
+
from itertools import islice
|
|
7
|
+
from itertools import repeat
|
|
8
|
+
import logging
|
|
9
|
+
from matplotlib.collections import LineCollection
|
|
10
|
+
import matplotlib.pyplot as plt
|
|
11
|
+
from multiprocessing import Pool
|
|
12
|
+
import neuron
|
|
6
13
|
import numpy as np
|
|
14
|
+
import pathlib
|
|
15
|
+
import seaborn as sns
|
|
7
16
|
|
|
17
|
+
|
|
18
|
+
from bluecellulab import Cell
|
|
8
19
|
from bluecellulab.analysis.inject_sequence import run_stimulus
|
|
9
20
|
from bluecellulab.analysis.plotting import plot_iv_curve, plot_fi_curve
|
|
21
|
+
from bluecellulab.analysis.utils import exp_decay
|
|
22
|
+
from bluecellulab.simulation import Simulation
|
|
10
23
|
from bluecellulab.stimulus import StimulusFactory
|
|
24
|
+
from bluecellulab.stimulus.circuit_stimulus_definitions import Hyperpolarizing
|
|
11
25
|
from bluecellulab.tools import calculate_rheobase
|
|
12
26
|
|
|
13
27
|
|
|
28
|
+
logger = logging.getLogger(__name__)
|
|
29
|
+
|
|
30
|
+
|
|
14
31
|
def compute_plot_iv_curve(cell,
|
|
15
32
|
injecting_section="soma[0]",
|
|
16
33
|
injecting_segment=0.5,
|
|
@@ -48,7 +65,7 @@ def compute_plot_iv_curve(cell,
|
|
|
48
65
|
post_delay (float, optional): The delay after the stimulation ends before the simulation stops
|
|
49
66
|
(in ms). Default is 100.0 ms.
|
|
50
67
|
threshold_voltage (float, optional): The voltage threshold (in mV) for detecting a steady-state
|
|
51
|
-
response. Default is -
|
|
68
|
+
response. Default is -20 mV.
|
|
52
69
|
nb_bins (int, optional): The number of discrete current levels between 0 and the maximum current.
|
|
53
70
|
Default is 11.
|
|
54
71
|
rheobase (float, optional): The rheobase current (in nA) for the cell. If not provided, it will
|
|
@@ -73,30 +90,35 @@ def compute_plot_iv_curve(cell,
|
|
|
73
90
|
|
|
74
91
|
list_amp = np.linspace(rheobase - 2, rheobase - 0.1, nb_bins) # [nA]
|
|
75
92
|
|
|
76
|
-
steps = []
|
|
77
|
-
times = []
|
|
78
|
-
voltages = []
|
|
79
93
|
# inject step current and record voltage response
|
|
80
94
|
stim_factory = StimulusFactory(dt=0.1)
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
95
|
+
steps = [
|
|
96
|
+
stim_factory.step(pre_delay=stim_start, duration=duration, post_delay=post_delay, amplitude=amp)
|
|
97
|
+
for amp in list_amp
|
|
98
|
+
]
|
|
99
|
+
|
|
100
|
+
with Pool(len(steps)) as p:
|
|
101
|
+
recordings = p.starmap(
|
|
102
|
+
run_stimulus,
|
|
103
|
+
zip(
|
|
104
|
+
repeat(cell.template_params),
|
|
105
|
+
steps,
|
|
106
|
+
repeat(injecting_section),
|
|
107
|
+
repeat(injecting_segment),
|
|
108
|
+
repeat(True), # cvode
|
|
109
|
+
repeat(True), # add_hypamp
|
|
110
|
+
repeat(recording_section),
|
|
111
|
+
repeat(recording_segment),
|
|
112
|
+
)
|
|
113
|
+
)
|
|
92
114
|
|
|
93
115
|
steady_states = []
|
|
94
116
|
# compute steady state response
|
|
95
117
|
efel.set_setting('Threshold', threshold_voltage)
|
|
96
|
-
for
|
|
118
|
+
for recording in recordings:
|
|
97
119
|
trace = {
|
|
98
|
-
'T':
|
|
99
|
-
'V': voltage,
|
|
120
|
+
'T': recording.time,
|
|
121
|
+
'V': recording.voltage,
|
|
100
122
|
'stim_start': [stim_start],
|
|
101
123
|
'stim_end': [stim_start + duration]
|
|
102
124
|
}
|
|
@@ -158,7 +180,7 @@ def compute_plot_fi_curve(cell,
|
|
|
158
180
|
max_current (float, optional): The maximum amplitude of the injected current (in nA).
|
|
159
181
|
Default is 0.8 nA.
|
|
160
182
|
threshold_voltage (float, optional): The voltage threshold (in mV) for detecting a steady-state
|
|
161
|
-
response. Default is -
|
|
183
|
+
response. Default is -20 mV.
|
|
162
184
|
nb_bins (int, optional): The number of discrete current levels between 0 and `max_current`.
|
|
163
185
|
Default is 11.
|
|
164
186
|
rheobase (float, optional): The rheobase current (in nA) for the cell. If not provided, it will
|
|
@@ -180,24 +202,30 @@ def compute_plot_fi_curve(cell,
|
|
|
180
202
|
rheobase = calculate_rheobase(cell=cell, section=injecting_section, segx=injecting_segment)
|
|
181
203
|
|
|
182
204
|
list_amp = np.linspace(rheobase, max_current, nb_bins) # [nA]
|
|
183
|
-
steps = []
|
|
184
|
-
spikes = []
|
|
185
|
-
# inject step current and record spike response
|
|
186
205
|
stim_factory = StimulusFactory(dt=0.1)
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
206
|
+
steps = [
|
|
207
|
+
stim_factory.step(pre_delay=stim_start, duration=duration, post_delay=post_delay, amplitude=amp)
|
|
208
|
+
for amp in list_amp
|
|
209
|
+
]
|
|
210
|
+
|
|
211
|
+
with Pool(len(steps)) as p:
|
|
212
|
+
recordings = p.starmap(
|
|
213
|
+
run_stimulus,
|
|
214
|
+
zip(
|
|
215
|
+
repeat(cell.template_params),
|
|
216
|
+
steps,
|
|
217
|
+
repeat(injecting_section),
|
|
218
|
+
repeat(injecting_segment),
|
|
219
|
+
repeat(True), # cvode
|
|
220
|
+
repeat(True), # add_hypamp
|
|
221
|
+
repeat(recording_section),
|
|
222
|
+
repeat(recording_segment),
|
|
223
|
+
repeat(True), # enable_spike_detection
|
|
224
|
+
repeat(threshold_voltage), # threshold_spike_detection
|
|
225
|
+
)
|
|
226
|
+
)
|
|
227
|
+
|
|
228
|
+
spike_count = [len(recording.spike) for recording in recordings]
|
|
201
229
|
|
|
202
230
|
plot_fi_curve(list_amp,
|
|
203
231
|
spike_count,
|
|
@@ -211,3 +239,264 @@ def compute_plot_fi_curve(cell,
|
|
|
211
239
|
output_fname=output_fname)
|
|
212
240
|
|
|
213
241
|
return np.array(list_amp), np.array(spike_count)
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
class BPAP:
|
|
245
|
+
# taken from the examples
|
|
246
|
+
|
|
247
|
+
def __init__(self, cell: Cell) -> None:
|
|
248
|
+
self.cell = cell
|
|
249
|
+
self.dt = 0.025
|
|
250
|
+
self.stim_start = 1000
|
|
251
|
+
self.stim_duration = 3
|
|
252
|
+
self.basal_cmap = sns.color_palette("crest", as_cmap=True)
|
|
253
|
+
self.apical_cmap = sns.color_palette("YlOrBr_r", as_cmap=True)
|
|
254
|
+
|
|
255
|
+
@property
|
|
256
|
+
def start_index(self) -> int:
|
|
257
|
+
"""Get the index of the start of the stimulus."""
|
|
258
|
+
return int(self.stim_start / self.dt)
|
|
259
|
+
|
|
260
|
+
@property
|
|
261
|
+
def end_index(self) -> int:
|
|
262
|
+
"""Get the index of the end of the stimulus."""
|
|
263
|
+
return int((self.stim_start + self.stim_duration) / self.dt)
|
|
264
|
+
|
|
265
|
+
def get_recordings(self):
|
|
266
|
+
"""Get the soma, basal and apical recordings."""
|
|
267
|
+
all_recordings = self.cell.get_allsections_voltagerecordings()
|
|
268
|
+
soma_rec = None
|
|
269
|
+
dend_rec = {}
|
|
270
|
+
apic_rec = {}
|
|
271
|
+
for key, value in all_recordings.items():
|
|
272
|
+
if "soma" in key:
|
|
273
|
+
soma_rec = value
|
|
274
|
+
elif "dend" in key:
|
|
275
|
+
dend_rec[key] = value
|
|
276
|
+
elif "apic" in key:
|
|
277
|
+
apic_rec[key] = value
|
|
278
|
+
|
|
279
|
+
return soma_rec, dend_rec, apic_rec
|
|
280
|
+
|
|
281
|
+
def run(self, duration: float, amplitude: float) -> None:
|
|
282
|
+
"""Apply depolarization and hyperpolarization at the same time."""
|
|
283
|
+
sim = Simulation()
|
|
284
|
+
sim.add_cell(self.cell)
|
|
285
|
+
self.cell.add_allsections_voltagerecordings()
|
|
286
|
+
self.cell.add_step(start_time=self.stim_start, stop_time=self.stim_start + self.stim_duration, level=amplitude)
|
|
287
|
+
hyperpolarizing = Hyperpolarizing("single-cell", delay=0, duration=duration)
|
|
288
|
+
self.cell.add_replay_hypamp(hyperpolarizing)
|
|
289
|
+
sim.run(duration, dt=self.dt, cvode=False)
|
|
290
|
+
|
|
291
|
+
def amplitudes(self, recs) -> list[float]:
|
|
292
|
+
"""Return amplitude across given sections."""
|
|
293
|
+
efel_feature_name = "maximum_voltage_from_voltagebase"
|
|
294
|
+
traces = [
|
|
295
|
+
{
|
|
296
|
+
'T': self.cell.get_time(),
|
|
297
|
+
'V': rec,
|
|
298
|
+
'stim_start': [self.stim_start],
|
|
299
|
+
'stim_end': [self.stim_start + self.stim_duration]
|
|
300
|
+
}
|
|
301
|
+
for rec in recs.values()
|
|
302
|
+
]
|
|
303
|
+
features_results = efel.get_feature_values(traces, [efel_feature_name])
|
|
304
|
+
amps = [feat_res[efel_feature_name][0] for feat_res in features_results]
|
|
305
|
+
|
|
306
|
+
return amps
|
|
307
|
+
|
|
308
|
+
def distances_to_soma(self, recs) -> list[float]:
|
|
309
|
+
"""Return the distance to the soma for each section."""
|
|
310
|
+
res = []
|
|
311
|
+
soma = self.cell.soma
|
|
312
|
+
for key in recs.keys():
|
|
313
|
+
section_name = key.rsplit(".")[-1].split("[")[0] # e.g. "dend"
|
|
314
|
+
section_idx = int(key.rsplit(".")[-1].split("[")[1].split("]")[0]) # e.g. 0
|
|
315
|
+
attribute_value = getattr(self.cell.cell.getCell(), section_name)
|
|
316
|
+
section = next(islice(attribute_value, section_idx, None))
|
|
317
|
+
# section e.g. cADpyr_L2TPC_bluecellulab_x[0].dend[0]
|
|
318
|
+
res.append(neuron.h.distance(soma(0.5), section(0.5)))
|
|
319
|
+
return res
|
|
320
|
+
|
|
321
|
+
def get_amplitudes_and_distances(self):
|
|
322
|
+
soma_rec, dend_rec, apic_rec = self.get_recordings()
|
|
323
|
+
soma_amp = self.amplitudes({"soma": soma_rec})[0]
|
|
324
|
+
dend_amps = None
|
|
325
|
+
dend_dist = None
|
|
326
|
+
apic_amps = None
|
|
327
|
+
apic_dist = None
|
|
328
|
+
if dend_rec:
|
|
329
|
+
dend_amps = self.amplitudes(dend_rec)
|
|
330
|
+
dend_dist = self.distances_to_soma(dend_rec)
|
|
331
|
+
if apic_rec:
|
|
332
|
+
apic_amps = self.amplitudes(apic_rec)
|
|
333
|
+
apic_dist = self.distances_to_soma(apic_rec)
|
|
334
|
+
|
|
335
|
+
return soma_amp, dend_amps, dend_dist, apic_amps, apic_dist
|
|
336
|
+
|
|
337
|
+
def fit(self, soma_amp, dend_amps, dend_dist, apic_amps, apic_dist):
|
|
338
|
+
"""Fit the amplitudes vs distances to an exponential decay function."""
|
|
339
|
+
from scipy.optimize import curve_fit
|
|
340
|
+
|
|
341
|
+
popt_dend = None
|
|
342
|
+
if dend_amps and dend_dist:
|
|
343
|
+
dist = [0] + dend_dist # add soma distance
|
|
344
|
+
amps = [soma_amp] + dend_amps # add soma amplitude
|
|
345
|
+
popt_dend, _ = curve_fit(exp_decay, dist, amps)
|
|
346
|
+
|
|
347
|
+
popt_apic = None
|
|
348
|
+
if apic_amps and apic_dist:
|
|
349
|
+
dist = [0] + apic_dist # add soma distance
|
|
350
|
+
amps = [soma_amp] + apic_amps # add soma amplitude
|
|
351
|
+
popt_apic, _ = curve_fit(exp_decay, dist, amps)
|
|
352
|
+
|
|
353
|
+
return popt_dend, popt_apic
|
|
354
|
+
|
|
355
|
+
def validate(self, soma_amp, dend_amps, dend_dist, apic_amps, apic_dist):
|
|
356
|
+
"""Check that the exponential fit is decaying."""
|
|
357
|
+
validated = True
|
|
358
|
+
notes = ""
|
|
359
|
+
popt_dend, popt_apic = self.fit(soma_amp, dend_amps, dend_dist, apic_amps, apic_dist)
|
|
360
|
+
if popt_dend is None:
|
|
361
|
+
logger.debug("No dendritic recordings found.")
|
|
362
|
+
notes += "No dendritic recordings found.\n"
|
|
363
|
+
elif popt_dend[1] <= 0:
|
|
364
|
+
logger.debug("Dendritic fit is not decaying.")
|
|
365
|
+
validated = False
|
|
366
|
+
notes += "Dendritic fit is not decaying.\n"
|
|
367
|
+
else:
|
|
368
|
+
notes += "Dendritic validation passed: dendritic amplitude is decaying with distance relative to soma.\n"
|
|
369
|
+
if popt_apic is None:
|
|
370
|
+
logger.debug("No apical recordings found.")
|
|
371
|
+
notes += "No apical recordings found.\n"
|
|
372
|
+
elif popt_apic[1] <= 0:
|
|
373
|
+
logger.debug("Apical fit is not decaying.")
|
|
374
|
+
validated = False
|
|
375
|
+
notes += "Apical fit is not decaying.\n"
|
|
376
|
+
else:
|
|
377
|
+
notes += "Apical validation passed: apical amplitude is decaying with distance relative to soma.\n"
|
|
378
|
+
|
|
379
|
+
return validated, notes
|
|
380
|
+
|
|
381
|
+
def plot_amp_vs_dist(
|
|
382
|
+
self,
|
|
383
|
+
soma_amp,
|
|
384
|
+
dend_amps,
|
|
385
|
+
dend_dist,
|
|
386
|
+
apic_amps,
|
|
387
|
+
apic_dist,
|
|
388
|
+
show_figure=True,
|
|
389
|
+
save_figure=False,
|
|
390
|
+
output_dir="./",
|
|
391
|
+
output_fname="bpap.pdf",
|
|
392
|
+
):
|
|
393
|
+
"""Plot the results of the BPAP analysis."""
|
|
394
|
+
popt_dend, popt_apic = self.fit(soma_amp, dend_amps, dend_dist, apic_amps, apic_dist)
|
|
395
|
+
|
|
396
|
+
outpath = pathlib.Path(output_dir) / output_fname
|
|
397
|
+
fig, ax1 = plt.subplots(figsize=(10, 6))
|
|
398
|
+
ax1.scatter([0], [soma_amp], marker="^", color='black', label='Soma')
|
|
399
|
+
if dend_amps and dend_dist:
|
|
400
|
+
ax1.scatter(
|
|
401
|
+
dend_dist,
|
|
402
|
+
dend_amps,
|
|
403
|
+
c=dend_dist,
|
|
404
|
+
cmap=self.basal_cmap,
|
|
405
|
+
label='Basal Dendrites',
|
|
406
|
+
)
|
|
407
|
+
if popt_dend is not None:
|
|
408
|
+
x = np.linspace(0, max(dend_dist), 100)
|
|
409
|
+
y = exp_decay(x, *popt_dend)
|
|
410
|
+
ax1.plot(x, y, color='darkgreen', linestyle='--', label='Basal Dendritic Fit')
|
|
411
|
+
if apic_amps and apic_dist:
|
|
412
|
+
ax1.scatter(
|
|
413
|
+
apic_dist,
|
|
414
|
+
apic_amps,
|
|
415
|
+
c=apic_dist,
|
|
416
|
+
cmap=self.apical_cmap,
|
|
417
|
+
label='Apical Dendrites'
|
|
418
|
+
)
|
|
419
|
+
if popt_apic is not None:
|
|
420
|
+
x = np.linspace(0, max(apic_dist), 100)
|
|
421
|
+
y = exp_decay(x, *popt_apic)
|
|
422
|
+
ax1.plot(x, y, color='goldenrod', linestyle='--', label='Apical Fit')
|
|
423
|
+
ax1.set_xlabel('Distance to Soma (um)')
|
|
424
|
+
ax1.set_ylabel('Amplitude (mV)')
|
|
425
|
+
ax1.legend()
|
|
426
|
+
fig.suptitle('Back-propagating Action Potential Analysis')
|
|
427
|
+
fig.tight_layout()
|
|
428
|
+
if save_figure:
|
|
429
|
+
fig.savefig(outpath)
|
|
430
|
+
if show_figure:
|
|
431
|
+
plt.show()
|
|
432
|
+
|
|
433
|
+
return outpath
|
|
434
|
+
|
|
435
|
+
def plot_one_axis_recordings(self, fig, ax, rec_list, dist, cmap):
|
|
436
|
+
"""Plot the soma and dendritic recordings on one axis.
|
|
437
|
+
|
|
438
|
+
Args:
|
|
439
|
+
fig (matplotlib.figure.Figure): The figure to plot on.
|
|
440
|
+
ax (matplotlib.axes.Axes): The axis to plot on.
|
|
441
|
+
rec_list (list): List of recordings to plot.
|
|
442
|
+
dist (list): List of distances from the soma for each recording.
|
|
443
|
+
cmap (matplotlib.colors.Colormap): Colormap to use for the recordings.
|
|
444
|
+
"""
|
|
445
|
+
time = self.cell.get_time()
|
|
446
|
+
line_collection = LineCollection(
|
|
447
|
+
[np.column_stack([time, rec]) for rec in rec_list],
|
|
448
|
+
array=dist,
|
|
449
|
+
cmap=cmap,
|
|
450
|
+
)
|
|
451
|
+
ax.set_xlim(
|
|
452
|
+
self.stim_start - 0.1,
|
|
453
|
+
self.stim_start + 30
|
|
454
|
+
)
|
|
455
|
+
ax.set_ylim(
|
|
456
|
+
min([min(rec[self.start_index:]) for rec in rec_list]) - 2,
|
|
457
|
+
max([max(rec[self.start_index:]) for rec in rec_list]) + 2
|
|
458
|
+
)
|
|
459
|
+
ax.add_collection(line_collection)
|
|
460
|
+
fig.colorbar(line_collection, label="soma distance (um)", ax=ax)
|
|
461
|
+
|
|
462
|
+
def plot_recordings(
|
|
463
|
+
self,
|
|
464
|
+
show_figure=True,
|
|
465
|
+
save_figure=False,
|
|
466
|
+
output_dir="./",
|
|
467
|
+
output_fname="bpap_recordings.pdf",
|
|
468
|
+
):
|
|
469
|
+
"""Plot the recordings from all dendrites."""
|
|
470
|
+
soma_rec, dend_rec, apic_rec = self.get_recordings()
|
|
471
|
+
dend_dist = []
|
|
472
|
+
apic_dist = []
|
|
473
|
+
if dend_rec:
|
|
474
|
+
dend_dist = self.distances_to_soma(dend_rec)
|
|
475
|
+
if apic_rec:
|
|
476
|
+
apic_dist = self.distances_to_soma(apic_rec)
|
|
477
|
+
# add soma_rec to the lists
|
|
478
|
+
dend_rec_list = [soma_rec] + list(dend_rec.values())
|
|
479
|
+
dend_dist = [0] + dend_dist
|
|
480
|
+
apic_rec_list = [soma_rec] + list(apic_rec.values())
|
|
481
|
+
apic_dist = [0] + apic_dist
|
|
482
|
+
|
|
483
|
+
outpath = pathlib.Path(output_dir) / output_fname
|
|
484
|
+
fig, (ax1, ax2) = plt.subplots(figsize=(10, 12), nrows=2, sharex=True)
|
|
485
|
+
|
|
486
|
+
self.plot_one_axis_recordings(fig, ax1, dend_rec_list, dend_dist, self.basal_cmap)
|
|
487
|
+
self.plot_one_axis_recordings(fig, ax2, apic_rec_list, apic_dist, self.apical_cmap)
|
|
488
|
+
|
|
489
|
+
# plt.setp(ax1.get_xticklabels(), visible=False)
|
|
490
|
+
ax1.set_title('Basal Dendritic Recordings')
|
|
491
|
+
ax2.set_title('Apical Dendritic Recordings')
|
|
492
|
+
ax1.set_ylabel('Voltage (mV)')
|
|
493
|
+
ax2.set_ylabel('Voltage (mV)')
|
|
494
|
+
ax2.set_xlabel('Time (ms)')
|
|
495
|
+
fig.suptitle('Back-propagating Action Potential Recordings')
|
|
496
|
+
fig.tight_layout()
|
|
497
|
+
if save_figure:
|
|
498
|
+
fig.savefig(outpath)
|
|
499
|
+
if show_figure:
|
|
500
|
+
plt.show()
|
|
501
|
+
|
|
502
|
+
return outpath
|
|
@@ -233,7 +233,7 @@ class BluepyCircuitAccess:
|
|
|
233
233
|
source_popid, target_popid = zip(*pop_ids)
|
|
234
234
|
|
|
235
235
|
result = result.assign(
|
|
236
|
-
source_popid=source_popid, target_popid=target_popid
|
|
236
|
+
source_popid=pd.Series(source_popid), target_popid=pd.Series(target_popid)
|
|
237
237
|
)
|
|
238
238
|
|
|
239
239
|
if result.empty:
|
bluecellulab/utils.py
CHANGED
|
@@ -4,6 +4,8 @@ from __future__ import annotations
|
|
|
4
4
|
import contextlib
|
|
5
5
|
import io
|
|
6
6
|
import json
|
|
7
|
+
import multiprocessing
|
|
8
|
+
from multiprocessing import pool
|
|
7
9
|
|
|
8
10
|
import numpy as np
|
|
9
11
|
|
|
@@ -56,3 +58,27 @@ class NumpyEncoder(json.JSONEncoder):
|
|
|
56
58
|
elif isinstance(obj, np.ndarray):
|
|
57
59
|
return obj.tolist()
|
|
58
60
|
return json.JSONEncoder.default(self, obj)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class NoDaemonProcess(multiprocessing.Process):
|
|
64
|
+
"""Class that represents a non-daemon process."""
|
|
65
|
+
|
|
66
|
+
# pylint: disable=dangerous-default-value
|
|
67
|
+
|
|
68
|
+
def __init__(self, group=None, target=None, name=None, args=(), kwargs={}):
|
|
69
|
+
"""Ensures group=None, for macosx."""
|
|
70
|
+
super().__init__(group=None, target=target, name=name, args=args, kwargs=kwargs)
|
|
71
|
+
|
|
72
|
+
@property
|
|
73
|
+
def daemon(self):
|
|
74
|
+
return False
|
|
75
|
+
|
|
76
|
+
@daemon.setter
|
|
77
|
+
def daemon(self, val):
|
|
78
|
+
pass
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
class NestedPool(pool.Pool): # pylint: disable=abstract-method
|
|
82
|
+
"""Class that represents a MultiProcessing nested pool."""
|
|
83
|
+
|
|
84
|
+
Process = NoDaemonProcess
|
|
@@ -19,10 +19,12 @@ import pathlib
|
|
|
19
19
|
|
|
20
20
|
import efel
|
|
21
21
|
|
|
22
|
+
from bluecellulab.analysis.analysis import BPAP
|
|
22
23
|
from bluecellulab.analysis.analysis import compute_plot_fi_curve
|
|
23
24
|
from bluecellulab.analysis.analysis import compute_plot_iv_curve
|
|
24
25
|
from bluecellulab.analysis.inject_sequence import run_multirecordings_stimulus
|
|
25
26
|
from bluecellulab.analysis.inject_sequence import run_stimulus
|
|
27
|
+
from bluecellulab.cell.core import Cell
|
|
26
28
|
from bluecellulab.stimulus.factory import IDRestTimings
|
|
27
29
|
from bluecellulab.stimulus.factory import StimulusFactory
|
|
28
30
|
from bluecellulab.tools import calculate_input_resistance
|
|
@@ -78,12 +80,12 @@ def plot_traces(recordings, out_dir, fname, title, labels=None, xlim=None):
|
|
|
78
80
|
return outpath
|
|
79
81
|
|
|
80
82
|
|
|
81
|
-
def spiking_test(
|
|
83
|
+
def spiking_test(template_params, rheobase, out_dir, spike_threshold_voltage=-30.):
|
|
82
84
|
"""Spiking test: cell should spike."""
|
|
83
85
|
stim_factory = StimulusFactory(dt=1.0)
|
|
84
86
|
step_stimulus = stim_factory.idrest(threshold_current=rheobase, threshold_percentage=200)
|
|
85
87
|
recording = run_stimulus(
|
|
86
|
-
|
|
88
|
+
template_params,
|
|
87
89
|
step_stimulus,
|
|
88
90
|
"soma[0]",
|
|
89
91
|
0.5,
|
|
@@ -101,20 +103,22 @@ def spiking_test(cell, rheobase, out_dir, spike_threshold_voltage=-30.):
|
|
|
101
103
|
title="Spiking Test - Step at 200% of Rheobase",
|
|
102
104
|
)
|
|
103
105
|
|
|
106
|
+
notes = "Validation passed: Spikes detected." if passed else "Validation failed: No spikes detected."
|
|
104
107
|
return {
|
|
105
|
-
"
|
|
108
|
+
"name": "Simulatable Neuron Spiking Validation",
|
|
106
109
|
"passed": passed,
|
|
110
|
+
"validation_details": notes,
|
|
107
111
|
"figures": [outpath],
|
|
108
112
|
}
|
|
109
113
|
|
|
110
114
|
|
|
111
|
-
def depolarization_block_test(
|
|
115
|
+
def depolarization_block_test(template_params, rheobase, out_dir):
|
|
112
116
|
"""Depolarization block test: no depolarization block should be detected."""
|
|
113
117
|
# Run the stimulus
|
|
114
118
|
stim_factory = StimulusFactory(dt=1.0)
|
|
115
119
|
step_stimulus = stim_factory.idrest(threshold_current=rheobase, threshold_percentage=200)
|
|
116
120
|
recording = run_stimulus(
|
|
117
|
-
|
|
121
|
+
template_params,
|
|
118
122
|
step_stimulus,
|
|
119
123
|
"soma[0]",
|
|
120
124
|
0.5,
|
|
@@ -139,20 +143,63 @@ def depolarization_block_test(cell, rheobase, out_dir):
|
|
|
139
143
|
title="Depolarization Block Test - Step at 200% of Rheobase",
|
|
140
144
|
)
|
|
141
145
|
|
|
146
|
+
notes = "Validation passed: No depolarization block detected." if not depol_block else "Validation failed: Depolarization block detected."
|
|
142
147
|
return {
|
|
143
|
-
"
|
|
148
|
+
"name": "Simulatable Neuron Depolarization Block Validation",
|
|
144
149
|
"passed": not depol_block,
|
|
150
|
+
"validation_details": notes,
|
|
145
151
|
"figures": [outpath],
|
|
146
152
|
}
|
|
147
153
|
|
|
148
154
|
|
|
149
|
-
def
|
|
155
|
+
def bpap_test(template_params, rheobase, out_dir="./"):
|
|
156
|
+
"""Back-propagating action potential test: exponential fit should decay.
|
|
157
|
+
|
|
158
|
+
Args:
|
|
159
|
+
template_params (dict): The template parameters for creating the cell.
|
|
160
|
+
rheobase (float): The rheobase current to use for the test.
|
|
161
|
+
out_dir (str): Directory to save the figure.
|
|
162
|
+
"""
|
|
163
|
+
amplitude = 10. * rheobase # Use 1000% of the rheobase current
|
|
164
|
+
bpap = BPAP(Cell.from_template_parameters(template_params))
|
|
165
|
+
bpap.run(duration=1500, amplitude=amplitude)
|
|
166
|
+
soma_amp, dend_amps, dend_dist, apic_amps, apic_dist = bpap.get_amplitudes_and_distances()
|
|
167
|
+
validated, notes = bpap.validate(soma_amp, dend_amps, dend_dist, apic_amps, apic_dist)
|
|
168
|
+
outpath_amp_dist = bpap.plot_amp_vs_dist(
|
|
169
|
+
soma_amp,
|
|
170
|
+
dend_amps,
|
|
171
|
+
dend_dist,
|
|
172
|
+
apic_amps,
|
|
173
|
+
apic_dist,
|
|
174
|
+
show_figure=False,
|
|
175
|
+
save_figure=True,
|
|
176
|
+
output_dir=out_dir,
|
|
177
|
+
output_fname="bpap.pdf"
|
|
178
|
+
)
|
|
179
|
+
outpath_recordings = bpap.plot_recordings(
|
|
180
|
+
show_figure=False,
|
|
181
|
+
save_figure=True,
|
|
182
|
+
output_dir=out_dir,
|
|
183
|
+
output_fname="bpap_recordings.pdf",
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
return {
|
|
187
|
+
"name": "Simulatable Neuron Back-propagating Action Potential Validation",
|
|
188
|
+
"validation_details": notes,
|
|
189
|
+
"passed": validated,
|
|
190
|
+
"figures": [outpath_amp_dist, outpath_recordings],
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
def ais_spiking_test(template_params, rheobase, out_dir, spike_threshold_voltage=-30.):
|
|
150
195
|
"""AIS spiking test: axon should spike before soma."""
|
|
196
|
+
name = "Simulatable Neuron AIS Spiking Validation"
|
|
151
197
|
# Check that the cell has an axon
|
|
152
|
-
if len(
|
|
198
|
+
if len(Cell.from_template_parameters(template_params).axonal) == 0:
|
|
153
199
|
return {
|
|
154
|
-
"
|
|
155
|
-
"passed":
|
|
200
|
+
"name": name,
|
|
201
|
+
"passed": True,
|
|
202
|
+
"validation_details": "Validation skipped: Cell does not have an axon section.",
|
|
156
203
|
"figures": [],
|
|
157
204
|
}
|
|
158
205
|
|
|
@@ -160,7 +207,7 @@ def ais_spiking_test(cell, rheobase, out_dir, spike_threshold_voltage=-30.):
|
|
|
160
207
|
stim_factory = StimulusFactory(dt=1.0)
|
|
161
208
|
step_stimulus = stim_factory.idrest(threshold_current=rheobase, threshold_percentage=200)
|
|
162
209
|
recordings = run_multirecordings_stimulus(
|
|
163
|
-
|
|
210
|
+
template_params,
|
|
164
211
|
step_stimulus,
|
|
165
212
|
"soma[0]",
|
|
166
213
|
0.5,
|
|
@@ -192,27 +239,35 @@ def ais_spiking_test(cell, rheobase, out_dir, spike_threshold_voltage=-30.):
|
|
|
192
239
|
for recording in recordings:
|
|
193
240
|
if recording.spike is None or len(recording.spike) == 0:
|
|
194
241
|
return {
|
|
195
|
-
"
|
|
242
|
+
"name": name,
|
|
196
243
|
"passed": False,
|
|
244
|
+
"validation_details": "Validation failed: No spikes detected in one or both recordings.",
|
|
197
245
|
"figures": [outpath1, outpath2],
|
|
198
246
|
}
|
|
199
247
|
|
|
200
248
|
# Check if axon spike happens before soma spike
|
|
201
249
|
passed = bool(axon_recording.spike[0] < soma_recording.spike[0])
|
|
250
|
+
notes = (
|
|
251
|
+
"Validation passed: Axon spikes before soma."
|
|
252
|
+
if passed
|
|
253
|
+
else "Validation failed: Axon does not spike before soma."
|
|
254
|
+
)
|
|
202
255
|
return {
|
|
203
|
-
"
|
|
256
|
+
"name": name,
|
|
204
257
|
"passed": passed,
|
|
258
|
+
"validation_details": notes,
|
|
205
259
|
"figures": [outpath1, outpath2],
|
|
206
260
|
}
|
|
207
261
|
|
|
208
262
|
|
|
209
|
-
def hyperpolarization_test(
|
|
263
|
+
def hyperpolarization_test(template_params, rheobase, out_dir):
|
|
210
264
|
"""Hyperpolarization test: hyperpolarized voltage should be lower than RMP."""
|
|
265
|
+
name = "Simulatable Neuron Hyperpolarization Validation"
|
|
211
266
|
# Run the stimulus
|
|
212
267
|
stim_factory = StimulusFactory(dt=1.0)
|
|
213
268
|
step_stimulus = stim_factory.iv(threshold_current=rheobase, threshold_percentage=-40)
|
|
214
269
|
recording = run_stimulus(
|
|
215
|
-
|
|
270
|
+
template_params,
|
|
216
271
|
step_stimulus,
|
|
217
272
|
"soma[0]",
|
|
218
273
|
0.5,
|
|
@@ -240,15 +295,22 @@ def hyperpolarization_test(cell, rheobase, out_dir):
|
|
|
240
295
|
ss_voltage = features_results[0]["steady_state_voltage_stimend"][0]
|
|
241
296
|
if rmp is None or ss_voltage is None:
|
|
242
297
|
return {
|
|
243
|
-
"
|
|
298
|
+
"name": name,
|
|
244
299
|
"passed": False,
|
|
300
|
+
"validation_details": "Validation failed: Could not determine RMP or steady state voltage.",
|
|
245
301
|
"figures": [outpath],
|
|
246
302
|
}
|
|
247
303
|
hyperpol_bool = bool(ss_voltage < rmp)
|
|
248
304
|
|
|
305
|
+
notes = (
|
|
306
|
+
f"Validation passed: Hyperpolarized voltage ({ss_voltage:.2f} mV) is lower than RMP ({rmp:.2f} mV)."
|
|
307
|
+
if hyperpol_bool
|
|
308
|
+
else f"Validation failed: Hyperpolarized voltage ({ss_voltage:.2f} mV) is not lower than RMP ({rmp:.2f} mV)."
|
|
309
|
+
)
|
|
249
310
|
return {
|
|
250
|
-
"
|
|
311
|
+
"name": name,
|
|
251
312
|
"passed": hyperpol_bool,
|
|
313
|
+
"validation_details": notes,
|
|
252
314
|
"figures": [outpath],
|
|
253
315
|
}
|
|
254
316
|
|
|
@@ -257,17 +319,24 @@ def rin_test(rin):
|
|
|
257
319
|
"""Rin should have an acceptable biological range (< 1000 MOhm)"""
|
|
258
320
|
passed = bool(rin < 1000)
|
|
259
321
|
|
|
322
|
+
notes = (
|
|
323
|
+
f"Validation passed: Input resistance (Rin) = {rin:.2f} MOhm is smaller than 1000 MOhm."
|
|
324
|
+
if passed
|
|
325
|
+
else f"Validation failed: Input resistance (Rin) = {rin:.2f} MOhm is higher than 1000 MOhm, which is not realistic."
|
|
326
|
+
)
|
|
260
327
|
return {
|
|
261
|
-
"
|
|
328
|
+
"name": "Simulatable Neuron Input Resistance Validation",
|
|
262
329
|
"passed": passed,
|
|
330
|
+
"validation_details": notes,
|
|
263
331
|
"figures": [],
|
|
264
332
|
}
|
|
265
333
|
|
|
266
334
|
|
|
267
|
-
def iv_test(
|
|
335
|
+
def iv_test(template_params, rheobase, out_dir, spike_threshold_voltage=-30.):
|
|
268
336
|
"""IV curve should have a positive slope."""
|
|
337
|
+
name = "Simulatable Neuron IV Curve Validation"
|
|
269
338
|
amps, steady_states = compute_plot_iv_curve(
|
|
270
|
-
|
|
339
|
+
Cell.from_template_parameters(template_params),
|
|
271
340
|
rheobase=rheobase,
|
|
272
341
|
threshold_voltage=spike_threshold_voltage,
|
|
273
342
|
nb_bins=5,
|
|
@@ -281,23 +350,31 @@ def iv_test(cell, rheobase, out_dir, spike_threshold_voltage=-30.):
|
|
|
281
350
|
# Check for positive slope
|
|
282
351
|
if len(amps) < 2 or len(steady_states) < 2:
|
|
283
352
|
return {
|
|
284
|
-
"
|
|
353
|
+
"name": name,
|
|
285
354
|
"passed": False,
|
|
355
|
+
"validation_details": "Validation failed: Not enough data points to determine slope.",
|
|
286
356
|
"figures": [outpath],
|
|
287
357
|
}
|
|
288
358
|
slope = numpy.polyfit(amps, steady_states, 1)[0]
|
|
289
359
|
passed = bool(slope > 0)
|
|
360
|
+
notes = (
|
|
361
|
+
f"Validation passed: Slope of IV curve = {slope:.2f} is positive."
|
|
362
|
+
if passed
|
|
363
|
+
else f"Validation failed: Slope of IV curve = {slope:.2f} is not positive."
|
|
364
|
+
)
|
|
290
365
|
return {
|
|
291
|
-
"
|
|
366
|
+
"name": name,
|
|
367
|
+
"validation_details": notes,
|
|
292
368
|
"passed": passed,
|
|
293
369
|
"figures": [outpath],
|
|
294
370
|
}
|
|
295
371
|
|
|
296
372
|
|
|
297
|
-
def fi_test(
|
|
373
|
+
def fi_test(template_params, rheobase, out_dir, spike_threshold_voltage=-30.):
|
|
298
374
|
"""FI curve should have a positive slope."""
|
|
375
|
+
name = "Simulatable Neuron FI Curve Validation"
|
|
299
376
|
amps, spike_counts = compute_plot_fi_curve(
|
|
300
|
-
|
|
377
|
+
Cell.from_template_parameters(template_params),
|
|
301
378
|
rheobase=rheobase,
|
|
302
379
|
threshold_voltage=spike_threshold_voltage,
|
|
303
380
|
nb_bins=5,
|
|
@@ -311,14 +388,21 @@ def fi_test(cell, rheobase, out_dir, spike_threshold_voltage=-30.):
|
|
|
311
388
|
# Check for positive slope
|
|
312
389
|
if len(amps) < 2 or len(spike_counts) < 2:
|
|
313
390
|
return {
|
|
314
|
-
"
|
|
391
|
+
"name": name,
|
|
315
392
|
"passed": False,
|
|
393
|
+
"validation_details": "Validation failed: Not enough data points to determine slope.",
|
|
316
394
|
"figures": [outpath],
|
|
317
395
|
}
|
|
318
396
|
slope = numpy.polyfit(amps, spike_counts, 1)[0]
|
|
319
397
|
passed = bool(slope > 0)
|
|
398
|
+
notes = (
|
|
399
|
+
f"Validation passed: Slope of FI curve = {slope:.2f} is positive."
|
|
400
|
+
if passed
|
|
401
|
+
else f"Validation failed: Slope of FI curve = {slope:.2f} is not positive."
|
|
402
|
+
)
|
|
320
403
|
return {
|
|
321
|
-
"
|
|
404
|
+
"name": name,
|
|
405
|
+
"validation_details": notes,
|
|
322
406
|
"passed": passed,
|
|
323
407
|
"figures": [outpath],
|
|
324
408
|
}
|
|
@@ -338,7 +422,6 @@ def run_validations(
|
|
|
338
422
|
out_dir = pathlib.Path(output_dir) / cell_name
|
|
339
423
|
out_dir.mkdir(parents=True, exist_ok=True)
|
|
340
424
|
|
|
341
|
-
# cell = Cell.from_template_parameters(template_params)
|
|
342
425
|
# get me-model properties
|
|
343
426
|
holding_current = cell.hypamp if cell.hypamp else 0.0
|
|
344
427
|
if cell.threshold:
|
|
@@ -354,48 +437,79 @@ def run_validations(
|
|
|
354
437
|
emodel_properties=cell.template_params.emodel_properties,
|
|
355
438
|
)
|
|
356
439
|
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
440
|
+
logger.debug("Running validations...")
|
|
441
|
+
from bluecellulab.utils import NestedPool
|
|
442
|
+
with NestedPool(processes=8) as pool:
|
|
443
|
+
# Validation 1: Spiking Test
|
|
444
|
+
spiking_test_result_future = pool.apply_async(
|
|
445
|
+
spiking_test,
|
|
446
|
+
(cell.template_params, rheobase, out_dir, spike_threshold_voltage)
|
|
447
|
+
)
|
|
360
448
|
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
449
|
+
# Validation 2: Depolarization Block Test
|
|
450
|
+
depolarization_block_result_future = pool.apply_async(
|
|
451
|
+
depolarization_block_test,
|
|
452
|
+
(cell.template_params, rheobase, out_dir)
|
|
453
|
+
)
|
|
364
454
|
|
|
365
|
-
|
|
366
|
-
|
|
455
|
+
# Validation 3: Backpropagating AP Test
|
|
456
|
+
bpap_result_future = pool.apply_async(
|
|
457
|
+
bpap_test,
|
|
458
|
+
(cell.template_params, rheobase, out_dir)
|
|
459
|
+
)
|
|
367
460
|
|
|
368
|
-
|
|
369
|
-
|
|
461
|
+
# Validation 4: Postsynaptic Potential Test
|
|
462
|
+
# We have to wait for ProbAMPANMDA_EMS to be present in entitycore to implement this test
|
|
370
463
|
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
464
|
+
# Validation 5: AIS Spiking Test
|
|
465
|
+
ais_spiking_test_result_future = pool.apply_async(
|
|
466
|
+
ais_spiking_test,
|
|
467
|
+
(cell.template_params, rheobase, out_dir, spike_threshold_voltage)
|
|
468
|
+
)
|
|
374
469
|
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
470
|
+
# Validation 6: Hyperpolarization Test
|
|
471
|
+
hyperpolarization_result_future = pool.apply_async(
|
|
472
|
+
hyperpolarization_test,
|
|
473
|
+
(cell.template_params, rheobase, out_dir)
|
|
474
|
+
)
|
|
378
475
|
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
476
|
+
# Validation 7: Rin Test
|
|
477
|
+
rin_result_future = pool.apply_async(
|
|
478
|
+
rin_test,
|
|
479
|
+
(rin,)
|
|
480
|
+
)
|
|
382
481
|
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
482
|
+
# # Validation 8: IV Test
|
|
483
|
+
iv_test_result_future = pool.apply_async(
|
|
484
|
+
iv_test,
|
|
485
|
+
(cell.template_params, rheobase, out_dir, spike_threshold_voltage)
|
|
486
|
+
)
|
|
487
|
+
|
|
488
|
+
# # Validation 9: FI Test
|
|
489
|
+
fi_test_result_future = pool.apply_async(
|
|
490
|
+
fi_test,
|
|
491
|
+
(cell.template_params, rheobase, out_dir, spike_threshold_voltage)
|
|
492
|
+
)
|
|
386
493
|
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
494
|
+
# Wait for all validations to complete
|
|
495
|
+
spiking_test_result = spiking_test_result_future.get()
|
|
496
|
+
depolarization_block_result = depolarization_block_result_future.get()
|
|
497
|
+
bpap_result = bpap_result_future.get()
|
|
498
|
+
ais_spiking_test_result = ais_spiking_test_result_future.get()
|
|
499
|
+
hyperpolarization_result = hyperpolarization_result_future.get()
|
|
500
|
+
rin_result = rin_result_future.get()
|
|
501
|
+
iv_test_result = iv_test_result_future.get()
|
|
502
|
+
fi_test_result = fi_test_result_future.get()
|
|
390
503
|
|
|
391
504
|
return {
|
|
392
505
|
"memodel_properties": {
|
|
393
|
-
"holding_current":
|
|
394
|
-
"rheobase":
|
|
395
|
-
"rin":
|
|
506
|
+
"holding_current": holding_current,
|
|
507
|
+
"rheobase": rheobase,
|
|
508
|
+
"rin": rin,
|
|
396
509
|
},
|
|
397
510
|
"spiking_test": spiking_test_result,
|
|
398
511
|
"depolarization_block_test": depolarization_block_result,
|
|
512
|
+
"bpap_test": bpap_result,
|
|
399
513
|
"ais_spiking_test": ais_spiking_test_result,
|
|
400
514
|
"hyperpolarization_test": hyperpolarization_result,
|
|
401
515
|
"rin_test": rin_result,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: bluecellulab
|
|
3
|
-
Version: 2.6.
|
|
3
|
+
Version: 2.6.51
|
|
4
4
|
Summary: Biologically detailed neural network simulations and analysis.
|
|
5
5
|
Author: Blue Brain Project, EPFL
|
|
6
6
|
License: Apache2.0
|
|
@@ -27,6 +27,7 @@ Requires-Dist: pydantic<3.0.0,>=2.5.2
|
|
|
27
27
|
Requires-Dist: typing-extensions>=4.8.0
|
|
28
28
|
Requires-Dist: networkx>=3.1
|
|
29
29
|
Requires-Dist: h5py>=3.8.0
|
|
30
|
+
Requires-Dist: seaborn
|
|
30
31
|
Dynamic: license-file
|
|
31
32
|
|
|
32
33
|
|banner|
|
|
@@ -12,12 +12,13 @@ bluecellulab/psegment.py,sha256=PTgoGLqM4oFIdF_8QHFQCU59j-8TQmtq6PakiGUQhIo,3138
|
|
|
12
12
|
bluecellulab/rngsettings.py,sha256=2Ykb4Ylk3XTs58x1UIxjg8XJqjSpnCgKRZ8avXCDpxk,4237
|
|
13
13
|
bluecellulab/tools.py,sha256=hF1HJcera0oggetsfN5PNTRYCpFS0sQiZlVxw4jRd1g,17968
|
|
14
14
|
bluecellulab/type_aliases.py,sha256=DvgjERv2Ztdw_sW63JrZTQGpJ0x5uMTFB5hcBHDb0WA,441
|
|
15
|
-
bluecellulab/utils.py,sha256=
|
|
15
|
+
bluecellulab/utils.py,sha256=0NhwlzyLnSi8kziSfDsQf7pokO4qDkMJVAO33kSX4O0,2227
|
|
16
16
|
bluecellulab/verbosity.py,sha256=T0IgX7DrRo19faxrT4Xzb27gqxzoILQ8FzYKxvUeaPM,1342
|
|
17
17
|
bluecellulab/analysis/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
18
|
-
bluecellulab/analysis/analysis.py,sha256=
|
|
18
|
+
bluecellulab/analysis/analysis.py,sha256=53g6SW_9ZbG3fbhuXJqurAPRR4VG1jsZYK6efq-EwfA,21229
|
|
19
19
|
bluecellulab/analysis/inject_sequence.py,sha256=uU6Q6y0ErMDDEgdsTZBXCJ4LgwkATY7G8Fa6mmjpL98,12523
|
|
20
20
|
bluecellulab/analysis/plotting.py,sha256=PqRoaZz33ULMw8A9YnZXXrxcUd84M_dwlYMTFhG7YT4,3999
|
|
21
|
+
bluecellulab/analysis/utils.py,sha256=eMirP557D11BuedgSqjripDxOq1haIldNbnYNetV1bg,121
|
|
21
22
|
bluecellulab/cell/__init__.py,sha256=Sbc0QOsJ8E7tSwf3q7fsXuE_SevBN6ZmoCVyyU5zfII,208
|
|
22
23
|
bluecellulab/cell/cell_dict.py,sha256=VE7pi-NsMVRSmo-PSdbiLYmolDOu0Gc6JxFBkuQpFdk,1346
|
|
23
24
|
bluecellulab/cell/core.py,sha256=BualY0WOtC0arKmvKzQ3sQ0fhc2jrtd6wqSd9M-e25E,33797
|
|
@@ -41,7 +42,7 @@ bluecellulab/circuit/simulation_access.py,sha256=keME58gzLVAPEg2nnWD_bwEm9V2Kjeq
|
|
|
41
42
|
bluecellulab/circuit/synapse_properties.py,sha256=TvUMiXZAAeYo1zKkus3z1EUvrE9QCIQ3Ze-jSnPSJWY,6374
|
|
42
43
|
bluecellulab/circuit/validate.py,sha256=wntnr7oIDyasqD1nM-kqz1NpfWDxBGhx0Ep3e5hHXIw,3593
|
|
43
44
|
bluecellulab/circuit/circuit_access/__init__.py,sha256=sgp6m5kP-pq60V1IFGUiSUR1OW01zdxXNNUJmPA8anI,201
|
|
44
|
-
bluecellulab/circuit/circuit_access/bluepy_circuit_access.py,sha256=
|
|
45
|
+
bluecellulab/circuit/circuit_access/bluepy_circuit_access.py,sha256=m5PWSYrrkORb55HN1ZgJpQFLeSHxsNBtzyJ1n0zuVro,14295
|
|
45
46
|
bluecellulab/circuit/circuit_access/definition.py,sha256=_sUU0DkesGOFW82kS1G9vki0o0aQP76z3Ltk7Vo9KK4,4435
|
|
46
47
|
bluecellulab/circuit/circuit_access/sonata_circuit_access.py,sha256=tADHxVZw4VgZAz2z4NKMUwc0rd_EO40EZggw5fDhnF4,10411
|
|
47
48
|
bluecellulab/circuit/config/__init__.py,sha256=aaoJXRKBJzpxxREo9NxKc-_CCPmVeuR1mcViRXcLrC4,215
|
|
@@ -65,10 +66,10 @@ bluecellulab/stimulus/stimulus.py,sha256=a_hKJUtZmIgjiFjbJf6RzUPokELqn0IHCgIWGw5
|
|
|
65
66
|
bluecellulab/synapse/__init__.py,sha256=RW8XoAMXOvK7OG1nHl_q8jSEKLj9ZN4oWf2nY9HAwuk,192
|
|
66
67
|
bluecellulab/synapse/synapse_factory.py,sha256=NHwRMYMrnRVm_sHmyKTJ1bdoNmWZNU4UPOGu7FCi-PE,6987
|
|
67
68
|
bluecellulab/synapse/synapse_types.py,sha256=zs_yBvGTH4QrbQF3nEViidyq1WM_ZcTSFdjUxB3khW0,16871
|
|
68
|
-
bluecellulab/validation/validation.py,sha256=
|
|
69
|
-
bluecellulab-2.6.
|
|
70
|
-
bluecellulab-2.6.
|
|
71
|
-
bluecellulab-2.6.
|
|
72
|
-
bluecellulab-2.6.
|
|
73
|
-
bluecellulab-2.6.
|
|
74
|
-
bluecellulab-2.6.
|
|
69
|
+
bluecellulab/validation/validation.py,sha256=EN9HMty70VPwnEPhWUmN5F-MGWbMN3uU0DmNnjL0ucw,18209
|
|
70
|
+
bluecellulab-2.6.51.dist-info/licenses/AUTHORS.txt,sha256=EDs3H-2HXBojbma10psixk3C2rFiOCTIREi2ZAbXYNQ,179
|
|
71
|
+
bluecellulab-2.6.51.dist-info/licenses/LICENSE,sha256=dAMAR2Sud4Nead1wGFleKiwTZfkTNZbzmuGfcTKb3kg,11335
|
|
72
|
+
bluecellulab-2.6.51.dist-info/METADATA,sha256=uWxsjFCkKomqMrGyVsZuhcUdDHi32Swj5sASJ4faKJE,8259
|
|
73
|
+
bluecellulab-2.6.51.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
74
|
+
bluecellulab-2.6.51.dist-info/top_level.txt,sha256=VSyEP8w9l3pXdRkyP_goeMwiNA8KWwitfAqUkveJkdQ,13
|
|
75
|
+
bluecellulab-2.6.51.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|