bluecellulab 2.5.0__py3-none-any.whl → 2.6.37__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/__init__.py +3 -3
- bluecellulab/analysis/inject_sequence.py +47 -12
- bluecellulab/cell/cell_dict.py +1 -1
- bluecellulab/cell/core.py +34 -30
- bluecellulab/cell/injector.py +2 -4
- bluecellulab/cell/plotting.py +2 -1
- bluecellulab/cell/random.py +1 -1
- bluecellulab/cell/section_distance.py +1 -1
- bluecellulab/cell/serialized_sections.py +4 -6
- bluecellulab/cell/sonata_proxy.py +1 -1
- bluecellulab/cell/stimuli_generator.py +26 -8
- bluecellulab/cell/template.py +4 -3
- bluecellulab/circuit/circuit_access/bluepy_circuit_access.py +12 -20
- bluecellulab/circuit/circuit_access/definition.py +1 -1
- bluecellulab/circuit/circuit_access/sonata_circuit_access.py +5 -4
- bluecellulab/circuit/config/bluepy_simulation_config.py +1 -1
- bluecellulab/circuit/config/definition.py +1 -1
- bluecellulab/circuit/config/sections.py +1 -1
- bluecellulab/circuit/config/sonata_simulation_config.py +1 -1
- bluecellulab/circuit/format.py +1 -1
- bluecellulab/circuit/iotools.py +2 -2
- bluecellulab/circuit/node_id.py +1 -1
- bluecellulab/circuit/simulation_access.py +11 -8
- bluecellulab/circuit/synapse_properties.py +25 -9
- bluecellulab/circuit/validate.py +1 -1
- bluecellulab/{ssim.py → circuit_simulation.py} +33 -26
- bluecellulab/connection.py +1 -1
- bluecellulab/dendrogram.py +1 -1
- bluecellulab/exceptions.py +1 -1
- bluecellulab/graph.py +1 -1
- bluecellulab/importer.py +1 -1
- bluecellulab/neuron_interpreter.py +1 -1
- bluecellulab/plotwindow.py +1 -1
- bluecellulab/psection.py +11 -16
- bluecellulab/psegment.py +4 -4
- bluecellulab/rngsettings.py +2 -2
- bluecellulab/simulation/neuron_globals.py +14 -1
- bluecellulab/simulation/parallel.py +40 -0
- bluecellulab/simulation/simulation.py +25 -21
- bluecellulab/stimulus/circuit_stimulus_definitions.py +11 -6
- bluecellulab/stimulus/factory.py +537 -102
- bluecellulab/synapse/synapse_factory.py +8 -4
- bluecellulab/synapse/synapse_types.py +1 -1
- bluecellulab/tools.py +14 -11
- bluecellulab/utils.py +20 -22
- {bluecellulab-2.5.0.dist-info → bluecellulab-2.6.37.dist-info}/LICENSE +0 -7
- {bluecellulab-2.5.0.dist-info → bluecellulab-2.6.37.dist-info}/METADATA +42 -25
- bluecellulab-2.6.37.dist-info/RECORD +70 -0
- {bluecellulab-2.5.0.dist-info → bluecellulab-2.6.37.dist-info}/WHEEL +1 -1
- bluecellulab-2.5.0.dist-info/RECORD +0 -69
- {bluecellulab-2.5.0.dist-info → bluecellulab-2.6.37.dist-info}/AUTHORS.txt +0 -0
- {bluecellulab-2.5.0.dist-info → bluecellulab-2.6.37.dist-info}/top_level.txt +0 -0
bluecellulab/__init__.py
CHANGED
|
@@ -7,7 +7,7 @@ try:
|
|
|
7
7
|
except ImportError:
|
|
8
8
|
BLUEPY_AVAILABLE = False
|
|
9
9
|
|
|
10
|
-
from .importer import
|
|
10
|
+
from bluecellulab.importer import import_hoc
|
|
11
11
|
from .verbosity import *
|
|
12
12
|
from .cell import Cell, create_ball_stick # NOQA
|
|
13
13
|
from .circuit import EmodelProperties
|
|
@@ -18,8 +18,8 @@ from .psection import PSection # NOQA
|
|
|
18
18
|
from .psegment import PSegment # NOQA
|
|
19
19
|
from .simulation import Simulation # NOQA
|
|
20
20
|
from .rngsettings import RNGSettings # NOQA
|
|
21
|
-
from .
|
|
22
|
-
|
|
21
|
+
from .circuit_simulation import CircuitSimulation # NOQA
|
|
22
|
+
import neuron
|
|
23
23
|
|
|
24
24
|
from .simulation.neuron_globals import NeuronGlobals
|
|
25
25
|
|
|
@@ -7,9 +7,10 @@ import neuron
|
|
|
7
7
|
import numpy as np
|
|
8
8
|
from bluecellulab.cell.core import Cell
|
|
9
9
|
from bluecellulab.cell.template import TemplateParams
|
|
10
|
+
from bluecellulab.simulation.parallel import IsolatedProcess
|
|
10
11
|
from bluecellulab.simulation.simulation import Simulation
|
|
12
|
+
from bluecellulab.stimulus.circuit_stimulus_definitions import Hyperpolarizing
|
|
11
13
|
from bluecellulab.stimulus.factory import Stimulus, StimulusFactory
|
|
12
|
-
from bluecellulab.utils import IsolatedProcess
|
|
13
14
|
|
|
14
15
|
|
|
15
16
|
class StimulusName(Enum):
|
|
@@ -18,6 +19,8 @@ class StimulusName(Enum):
|
|
|
18
19
|
IDREST = auto()
|
|
19
20
|
IV = auto()
|
|
20
21
|
FIRE_PATTERN = auto()
|
|
22
|
+
POS_CHEOPS = auto()
|
|
23
|
+
NEG_CHEOPS = auto()
|
|
21
24
|
|
|
22
25
|
|
|
23
26
|
class Recording(NamedTuple):
|
|
@@ -35,7 +38,8 @@ def run_stimulus(
|
|
|
35
38
|
stimulus: Stimulus,
|
|
36
39
|
section: str,
|
|
37
40
|
segment: float,
|
|
38
|
-
|
|
41
|
+
cvode: bool = True,
|
|
42
|
+
add_hypamp: bool = True,
|
|
39
43
|
) -> Recording:
|
|
40
44
|
"""Creates a cell and stimulates it with a given stimulus.
|
|
41
45
|
|
|
@@ -44,7 +48,7 @@ def run_stimulus(
|
|
|
44
48
|
stimulus: The input stimulus to inject into the cell.
|
|
45
49
|
section: Name of the section of cell where the stimulus is to be injected.
|
|
46
50
|
segment: The segment of the section where the stimulus is to be injected.
|
|
47
|
-
|
|
51
|
+
cvode: True to use variable time-steps. False for fixed time-steps.
|
|
48
52
|
|
|
49
53
|
Returns:
|
|
50
54
|
The voltage-time recording at the specified location.
|
|
@@ -54,6 +58,9 @@ def run_stimulus(
|
|
|
54
58
|
"""
|
|
55
59
|
cell = Cell.from_template_parameters(template_params)
|
|
56
60
|
neuron_section = cell.sections[section]
|
|
61
|
+
if add_hypamp:
|
|
62
|
+
hyp_stim = Hyperpolarizing(target="", delay=0.0, duration=stimulus.stimulus_time)
|
|
63
|
+
cell.add_replay_hypamp(hyp_stim)
|
|
57
64
|
cell.add_voltage_recording(neuron_section, segment)
|
|
58
65
|
iclamp, _ = cell.inject_current_waveform(
|
|
59
66
|
stimulus.time, stimulus.current, section=neuron_section, segx=segment
|
|
@@ -61,7 +68,7 @@ def run_stimulus(
|
|
|
61
68
|
current_vector = neuron.h.Vector()
|
|
62
69
|
current_vector.record(iclamp._ref_i)
|
|
63
70
|
simulation = Simulation(cell)
|
|
64
|
-
simulation.run(
|
|
71
|
+
simulation.run(stimulus.stimulus_time, cvode=cvode)
|
|
65
72
|
current = np.array(current_vector.to_python())
|
|
66
73
|
voltage = cell.get_voltage_recording(neuron_section, segment)
|
|
67
74
|
time = cell.get_time()
|
|
@@ -70,14 +77,16 @@ def run_stimulus(
|
|
|
70
77
|
return Recording(current, voltage, time)
|
|
71
78
|
|
|
72
79
|
|
|
73
|
-
def
|
|
80
|
+
def apply_multiple_stimuli(
|
|
74
81
|
cell: Cell,
|
|
75
82
|
stimulus_name: StimulusName,
|
|
76
83
|
amplitudes: Sequence[float],
|
|
77
|
-
|
|
84
|
+
threshold_based: bool = True,
|
|
78
85
|
section_name: str | None = None,
|
|
79
86
|
segment: float = 0.5,
|
|
80
87
|
n_processes: int | None = None,
|
|
88
|
+
cvode: bool = True,
|
|
89
|
+
add_hypamp: bool = True,
|
|
81
90
|
) -> StimulusRecordings:
|
|
82
91
|
"""Apply multiple stimuli to the cell on isolated processes.
|
|
83
92
|
|
|
@@ -85,11 +94,14 @@ def apply_multiple_step_stimuli(
|
|
|
85
94
|
cell: The cell to which the stimuli are applied.
|
|
86
95
|
stimulus_name: The name of the stimulus to apply.
|
|
87
96
|
amplitudes: The amplitudes of the stimuli to apply.
|
|
88
|
-
|
|
97
|
+
threshold_based: Whether to consider amplitudes to be
|
|
98
|
+
threshold percentages or to be raw amplitudes.
|
|
89
99
|
section_name: Section name of the cell where the stimuli are applied.
|
|
90
100
|
If None, the stimuli are applied at the soma[0] of the cell.
|
|
91
101
|
segment: The segment of the section where the stimuli are applied.
|
|
92
102
|
n_processes: The number of processes to use for running the stimuli.
|
|
103
|
+
cvode: True to use variable time-steps. False for fixed time-steps.
|
|
104
|
+
add_hypamp: True to add the cell's holding current stimulus
|
|
93
105
|
|
|
94
106
|
Returns:
|
|
95
107
|
A dictionary where the keys are the names of the stimuli and the values
|
|
@@ -105,18 +117,41 @@ def apply_multiple_step_stimuli(
|
|
|
105
117
|
|
|
106
118
|
# Prepare arguments for each stimulus
|
|
107
119
|
for amplitude in amplitudes:
|
|
120
|
+
if threshold_based:
|
|
121
|
+
thres_perc = amplitude
|
|
122
|
+
amp = None
|
|
123
|
+
else:
|
|
124
|
+
thres_perc = None
|
|
125
|
+
amp = amplitude
|
|
126
|
+
|
|
108
127
|
if stimulus_name == StimulusName.AP_WAVEFORM:
|
|
109
|
-
stimulus = stim_factory.ap_waveform(
|
|
128
|
+
stimulus = stim_factory.ap_waveform(
|
|
129
|
+
threshold_current=cell.threshold, threshold_percentage=thres_perc, amplitude=amp
|
|
130
|
+
)
|
|
110
131
|
elif stimulus_name == StimulusName.IDREST:
|
|
111
|
-
stimulus = stim_factory.idrest(
|
|
132
|
+
stimulus = stim_factory.idrest(
|
|
133
|
+
threshold_current=cell.threshold, threshold_percentage=thres_perc, amplitude=amp
|
|
134
|
+
)
|
|
112
135
|
elif stimulus_name == StimulusName.IV:
|
|
113
|
-
stimulus = stim_factory.iv(
|
|
136
|
+
stimulus = stim_factory.iv(
|
|
137
|
+
threshold_current=cell.threshold, threshold_percentage=thres_perc, amplitude=amp
|
|
138
|
+
)
|
|
114
139
|
elif stimulus_name == StimulusName.FIRE_PATTERN:
|
|
115
|
-
stimulus = stim_factory.fire_pattern(
|
|
140
|
+
stimulus = stim_factory.fire_pattern(
|
|
141
|
+
threshold_current=cell.threshold, threshold_percentage=thres_perc, amplitude=amp
|
|
142
|
+
)
|
|
143
|
+
elif stimulus_name == StimulusName.POS_CHEOPS:
|
|
144
|
+
stimulus = stim_factory.pos_cheops(
|
|
145
|
+
threshold_current=cell.threshold, threshold_percentage=thres_perc, amplitude=amp
|
|
146
|
+
)
|
|
147
|
+
elif stimulus_name == StimulusName.NEG_CHEOPS:
|
|
148
|
+
stimulus = stim_factory.neg_cheops(
|
|
149
|
+
threshold_current=cell.threshold, threshold_percentage=thres_perc, amplitude=amp
|
|
150
|
+
)
|
|
116
151
|
else:
|
|
117
152
|
raise ValueError("Unknown stimulus name.")
|
|
118
153
|
|
|
119
|
-
task_args.append((cell.template_params, stimulus, section_name, segment,
|
|
154
|
+
task_args.append((cell.template_params, stimulus, section_name, segment, cvode, add_hypamp))
|
|
120
155
|
|
|
121
156
|
with IsolatedProcess(processes=n_processes) as pool:
|
|
122
157
|
# Map expects a function and a list of argument tuples
|
bluecellulab/cell/cell_dict.py
CHANGED
bluecellulab/cell/core.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright
|
|
1
|
+
# Copyright 2023-2024 Blue Brain Project / EPFL
|
|
2
2
|
|
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
4
|
# you may not use this file except in compliance with the License.
|
|
@@ -142,7 +142,8 @@ class Cell(InjectableMixin, PlottableMixin):
|
|
|
142
142
|
dt=self.record_dt)
|
|
143
143
|
|
|
144
144
|
self.delayed_weights = queue.PriorityQueue() # type: ignore
|
|
145
|
-
self.psections,
|
|
145
|
+
self.psections: dict[int, PSection] = {}
|
|
146
|
+
self.secname_to_psection: dict[str, PSection] = {}
|
|
146
147
|
|
|
147
148
|
# Keep track of when a cell is made passive by make_passive()
|
|
148
149
|
# Used to know when re_init_rng() can be executed
|
|
@@ -155,6 +156,11 @@ class Cell(InjectableMixin, PlottableMixin):
|
|
|
155
156
|
# as the object exists
|
|
156
157
|
self.persistent: list[HocObjectType] = []
|
|
157
158
|
|
|
159
|
+
def _init_psections(self) -> None:
|
|
160
|
+
"""Initialize the psections of the cell."""
|
|
161
|
+
if not self.psections:
|
|
162
|
+
self.psections, self.secname_to_psection = init_psections(public_hoc_cell(self.cell))
|
|
163
|
+
|
|
158
164
|
def _extract_sections(self, sections) -> SectionMapping:
|
|
159
165
|
res: SectionMapping = {}
|
|
160
166
|
for section in sections:
|
|
@@ -198,6 +204,7 @@ class Cell(InjectableMixin, PlottableMixin):
|
|
|
198
204
|
|
|
199
205
|
def get_psection(self, section_id: int | str) -> PSection:
|
|
200
206
|
"""Return a python section with the specified section id."""
|
|
207
|
+
self._init_psections()
|
|
201
208
|
if isinstance(section_id, int):
|
|
202
209
|
return self.psections[section_id]
|
|
203
210
|
elif isinstance(section_id, str):
|
|
@@ -490,10 +497,6 @@ class Cell(InjectableMixin, PlottableMixin):
|
|
|
490
497
|
# numpy int to int
|
|
491
498
|
post_sec_id = int(syn_description[SynapseProperty.POST_SECTION_ID])
|
|
492
499
|
|
|
493
|
-
location = SynapseFactory.determine_synapse_location(
|
|
494
|
-
syn_description, self
|
|
495
|
-
)
|
|
496
|
-
|
|
497
500
|
weight_scalar = connection_modifiers.get('Weight', 1.0)
|
|
498
501
|
exc_mini_frequency, inh_mini_frequency = mini_frequencies \
|
|
499
502
|
if mini_frequencies is not None else (None, None)
|
|
@@ -509,13 +512,15 @@ class Cell(InjectableMixin, PlottableMixin):
|
|
|
509
512
|
spont_minis_rate = inh_mini_frequency
|
|
510
513
|
|
|
511
514
|
if spont_minis_rate is not None and spont_minis_rate > 0:
|
|
512
|
-
|
|
515
|
+
synapse_hoc_args = SynapseFactory.determine_synapse_location(
|
|
516
|
+
syn_description, self
|
|
517
|
+
)
|
|
513
518
|
# add the *minis*: spontaneous synaptic events
|
|
514
519
|
self.ips[synapse_id] = neuron.h.\
|
|
515
|
-
InhPoissonStim(location, sec=
|
|
520
|
+
InhPoissonStim(synapse_hoc_args.location, sec=synapse_hoc_args.section)
|
|
516
521
|
|
|
517
522
|
self.syn_mini_netcons[synapse_id] = neuron.h.\
|
|
518
|
-
NetCon(self.ips[synapse_id], synapse.hsynapse, sec=
|
|
523
|
+
NetCon(self.ips[synapse_id], synapse.hsynapse, sec=synapse_hoc_args.section)
|
|
519
524
|
self.syn_mini_netcons[synapse_id].delay = 0.1
|
|
520
525
|
self.syn_mini_netcons[synapse_id].weight[0] = weight * weight_scalar
|
|
521
526
|
# set netcon type
|
|
@@ -714,27 +719,26 @@ class Cell(InjectableMixin, PlottableMixin):
|
|
|
714
719
|
pre_gid = CellId(
|
|
715
720
|
source_population, int(synapse.syn_description[SynapseProperty.PRE_GID])
|
|
716
721
|
)
|
|
717
|
-
if
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
spikes_of_interest
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
self.connections[synapse_id] = connection
|
|
722
|
+
if pre_gid.id in synapse_spikes:
|
|
723
|
+
spikes_of_interest = synapse_spikes[pre_gid.id]
|
|
724
|
+
# filter spikes of interest >=stimulus.delay, <=stimulus.duration
|
|
725
|
+
spikes_of_interest = spikes_of_interest[
|
|
726
|
+
(spikes_of_interest >= stimulus.delay)
|
|
727
|
+
& (spikes_of_interest <= stimulus.duration)
|
|
728
|
+
]
|
|
729
|
+
connection = bluecellulab.Connection(
|
|
730
|
+
synapse,
|
|
731
|
+
pre_spiketrain=spikes_of_interest,
|
|
732
|
+
pre_cell=None,
|
|
733
|
+
stim_dt=self.record_dt,
|
|
734
|
+
spike_threshold=spike_threshold,
|
|
735
|
+
spike_location=spike_location,
|
|
736
|
+
)
|
|
737
|
+
logger.debug(
|
|
738
|
+
f"Added synapse replay from {pre_gid} to {self.cell_id.id}, {synapse_id}"
|
|
739
|
+
)
|
|
740
|
+
|
|
741
|
+
self.connections[synapse_id] = connection
|
|
738
742
|
|
|
739
743
|
@property
|
|
740
744
|
def info_dict(self):
|
bluecellulab/cell/injector.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright
|
|
1
|
+
# Copyright 2023-2024 Blue Brain Project / EPFL
|
|
2
2
|
|
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
4
|
# you may not use this file except in compliance with the License.
|
|
@@ -360,17 +360,15 @@ class InjectableMixin:
|
|
|
360
360
|
stimulus: RelativeShotNoise,
|
|
361
361
|
shotnoise_stim_count=0):
|
|
362
362
|
"""Add a replay relative shot noise stimulus."""
|
|
363
|
-
cv_square = stimulus.amp_cv**2
|
|
364
363
|
|
|
365
364
|
stim_mode = stimulus.mode
|
|
366
365
|
rel_prop = self.relativity_proportion(stim_mode)
|
|
367
366
|
|
|
368
367
|
mean = stimulus.mean_percent / 100 * rel_prop
|
|
369
368
|
sd = stimulus.sd_percent / 100 * rel_prop
|
|
370
|
-
var = sd * sd
|
|
371
369
|
|
|
372
370
|
rate, amp_mean, amp_var = get_relative_shotnoise_params(
|
|
373
|
-
mean,
|
|
371
|
+
mean, sd, stimulus.decay_time, stimulus.rise_time, stimulus.relative_skew)
|
|
374
372
|
|
|
375
373
|
rng = self._get_shotnoise_step_rand(shotnoise_stim_count, stimulus.seed)
|
|
376
374
|
tvec, svec = gen_shotnoise_signal(stimulus.decay_time, stimulus.rise_time, rate, amp_mean,
|
bluecellulab/cell/plotting.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright
|
|
1
|
+
# Copyright 2023-2024 Blue Brain Project / EPFL
|
|
2
2
|
|
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
4
|
# you may not use this file except in compliance with the License.
|
|
@@ -60,6 +60,7 @@ class PlottableMixin:
|
|
|
60
60
|
scale_bar_size=10.0,
|
|
61
61
|
fig_title=None):
|
|
62
62
|
"""Show a dendrogram of the cell."""
|
|
63
|
+
self._init_psections()
|
|
63
64
|
cell_dendrogram = bluecellulab.Dendrogram(
|
|
64
65
|
self.psections,
|
|
65
66
|
variable=variable,
|
bluecellulab/cell/random.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright
|
|
1
|
+
# Copyright 2023-2024 Blue Brain Project / EPFL
|
|
2
2
|
|
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
4
|
# you may not use this file except in compliance with the License.
|
|
@@ -15,17 +15,14 @@
|
|
|
15
15
|
index."""
|
|
16
16
|
from __future__ import annotations
|
|
17
17
|
import logging
|
|
18
|
-
import warnings
|
|
19
18
|
import neuron
|
|
20
19
|
from bluecellulab.type_aliases import HocObjectType, NeuronSection
|
|
21
20
|
|
|
22
21
|
|
|
23
22
|
logger = logging.getLogger(__name__)
|
|
24
|
-
warnings.filterwarnings("once", category=UserWarning, module=__name__)
|
|
25
23
|
|
|
26
24
|
|
|
27
25
|
class SerializedSections:
|
|
28
|
-
|
|
29
26
|
def __init__(self, cell: HocObjectType) -> None:
|
|
30
27
|
self.isec2sec: dict[int, NeuronSection] = {}
|
|
31
28
|
n = cell.nSecAll
|
|
@@ -37,7 +34,8 @@ class SerializedSections:
|
|
|
37
34
|
raise ValueError("Error: failure in mk2_isec2sec()")
|
|
38
35
|
|
|
39
36
|
if v_value < 0:
|
|
40
|
-
|
|
41
|
-
f"[Warning] SerializedSections: v(0.0001) < 0. index={index} v()={v_value}"
|
|
37
|
+
logging.debug(
|
|
38
|
+
f"[Warning] SerializedSections: v(0.0001) < 0. index={index} v()={v_value}"
|
|
39
|
+
)
|
|
42
40
|
else:
|
|
43
41
|
self.isec2sec[int(v_value)] = neuron.h.SectionRef(sec=sec)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright
|
|
1
|
+
# Copyright 2023-2024 Blue Brain Project / EPFL
|
|
2
2
|
|
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
4
|
# you may not use this file except in compliance with the License.
|
|
@@ -114,17 +114,35 @@ def gen_shotnoise_signal(tau_D, tau_R, rate, amp_mean, amp_var,
|
|
|
114
114
|
return tvec, P
|
|
115
115
|
|
|
116
116
|
|
|
117
|
-
def get_relative_shotnoise_params(mean,
|
|
117
|
+
def get_relative_shotnoise_params(mean, sd, tau_D, tau_R, relative_skew):
|
|
118
118
|
"""Returns Rate, amp_mean and amp_var parameters."""
|
|
119
119
|
# bi-exponential time to peak [ms]
|
|
120
120
|
t_peak = math.log(tau_D / tau_R) / (1 / tau_R - 1 / tau_D)
|
|
121
121
|
# bi-exponential peak height [1]
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
122
|
+
F_peak = math.exp(-t_peak / tau_D) - math.exp(-t_peak / tau_R)
|
|
123
|
+
|
|
124
|
+
# utility constants
|
|
125
|
+
Xi = (tau_D - tau_R) / F_peak
|
|
126
|
+
A = 1 / (tau_D + tau_R)
|
|
127
|
+
B = 1 / ((tau_D + 2 * tau_R) * (2 * tau_D + tau_R))
|
|
128
|
+
|
|
129
|
+
# skewness
|
|
130
|
+
skew_bnd_min = (8 / 3) * (B / A ** 2) * (sd / mean)
|
|
131
|
+
skew = (1 + relative_skew) * skew_bnd_min
|
|
132
|
+
if skew < skew_bnd_min or skew > 2 * skew_bnd_min:
|
|
133
|
+
raise ValueError("skewness out of bounds")
|
|
134
|
+
|
|
135
|
+
# cumulants
|
|
136
|
+
lambda2_1 = sd ** 2 / mean # lambda2 over lambda1
|
|
137
|
+
lambda3_2 = sd * skew # lambda3 over lambda2
|
|
138
|
+
theta1pk = 2 / (A * Xi) * lambda2_1 # = (1 + k) * theta
|
|
139
|
+
theta2pk = (3 * A) / (4 * B * Xi) * lambda3_2 # = (2 + k) * theta
|
|
140
|
+
|
|
141
|
+
# derived parameters
|
|
142
|
+
amp_mean = 2 * theta1pk - theta2pk # mean amplitude [nA or uS]
|
|
143
|
+
amp_var = amp_mean * (theta2pk - theta1pk) # variance of amplitude [nA^2 or uS^2]
|
|
144
|
+
rate_ms = mean / (amp_mean * Xi) # event rate in 1 / ms
|
|
145
|
+
rate = rate_ms * 1000 # event rate in 1 / s [Hz]
|
|
128
146
|
|
|
129
147
|
return rate, amp_mean, amp_var
|
|
130
148
|
|
bluecellulab/cell/template.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright
|
|
1
|
+
# Copyright 2023-2024 Blue Brain Project / EPFL
|
|
2
2
|
|
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
4
|
# you may not use this file except in compliance with the License.
|
|
@@ -21,6 +21,7 @@ from pathlib import Path
|
|
|
21
21
|
import re
|
|
22
22
|
import string
|
|
23
23
|
from typing import NamedTuple, Optional
|
|
24
|
+
import uuid
|
|
24
25
|
|
|
25
26
|
import neuron
|
|
26
27
|
|
|
@@ -126,8 +127,8 @@ class NeuronTemplate:
|
|
|
126
127
|
# templates load outside of bluecellulab
|
|
127
128
|
template_name = "%s_bluecellulab" % template_name
|
|
128
129
|
template_name = get_neuron_compliant_template_name(template_name)
|
|
129
|
-
|
|
130
|
-
template_name = f"{template_name}_{
|
|
130
|
+
unique_id = uuid.uuid4().hex
|
|
131
|
+
template_name = f"{template_name}_{unique_id}"
|
|
131
132
|
|
|
132
133
|
template_content = re.sub(
|
|
133
134
|
r"begintemplate\s*(\S*)",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright
|
|
1
|
+
# Copyright 2023-2024 Blue Brain Project / EPFL
|
|
2
2
|
|
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
4
|
# you may not use this file except in compliance with the License.
|
|
@@ -19,8 +19,9 @@ import os
|
|
|
19
19
|
from pathlib import Path
|
|
20
20
|
from typing import Optional
|
|
21
21
|
|
|
22
|
+
import neuron
|
|
22
23
|
import pandas as pd
|
|
23
|
-
from bluecellulab import circuit
|
|
24
|
+
from bluecellulab import circuit
|
|
24
25
|
from bluecellulab.circuit.circuit_access import EmodelProperties
|
|
25
26
|
from bluecellulab.circuit.config import BluepySimulationConfig
|
|
26
27
|
from bluecellulab.circuit.config.definition import SimulationConfig
|
|
@@ -57,7 +58,6 @@ class BluepyCircuitAccess:
|
|
|
57
58
|
raise FileNotFoundError(
|
|
58
59
|
f"Circuit config file {simulation_config} not found.")
|
|
59
60
|
|
|
60
|
-
# to allow the usage of SimulationConfig outside of Ssim
|
|
61
61
|
if isinstance(simulation_config, BluepySimulationConfig):
|
|
62
62
|
simulation_config = simulation_config.impl
|
|
63
63
|
|
|
@@ -191,23 +191,15 @@ class BluepyCircuitAccess:
|
|
|
191
191
|
|
|
192
192
|
if isinstance(connectome._impl, SonataConnectome):
|
|
193
193
|
logger.debug('Using sonata style synapse file, not nrn.h5')
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
)
|
|
204
|
-
synapses.columns = properties_from_bluepy(synapses.columns)
|
|
205
|
-
else:
|
|
206
|
-
connectome_properties = properties_to_bluepy(connectome_properties)
|
|
207
|
-
synapses = connectome.afferent_synapses(
|
|
208
|
-
gid, properties=connectome_properties
|
|
209
|
-
)
|
|
210
|
-
synapses.columns = properties_from_bluepy(synapses.columns)
|
|
194
|
+
connectome_properties.remove(SynapseProperty.POST_SEGMENT_OFFSET)
|
|
195
|
+
else: # afferent section_pos will be computed via post_segment_offset
|
|
196
|
+
connectome_properties.remove(SynapseProperty.AFFERENT_SECTION_POS)
|
|
197
|
+
|
|
198
|
+
connectome_properties = properties_to_bluepy(connectome_properties)
|
|
199
|
+
synapses = connectome.afferent_synapses(
|
|
200
|
+
gid, properties=connectome_properties
|
|
201
|
+
)
|
|
202
|
+
synapses.columns = properties_from_bluepy(synapses.columns)
|
|
211
203
|
|
|
212
204
|
synapses = synapses.reset_index(drop=True)
|
|
213
205
|
synapses.index = pd.MultiIndex.from_tuples(
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright
|
|
1
|
+
# Copyright 2023-2024 Blue Brain Project / EPFL
|
|
2
2
|
|
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
4
|
# you may not use this file except in compliance with the License.
|
|
@@ -22,8 +22,9 @@ from bluepysnap.bbp import Cell as SnapCell
|
|
|
22
22
|
from bluepysnap.circuit_ids import CircuitNodeId, CircuitEdgeIds
|
|
23
23
|
from bluepysnap.exceptions import BluepySnapError
|
|
24
24
|
from bluepysnap import Circuit as SnapCircuit
|
|
25
|
+
import neuron
|
|
25
26
|
import pandas as pd
|
|
26
|
-
from bluecellulab import circuit
|
|
27
|
+
from bluecellulab import circuit
|
|
27
28
|
from bluecellulab.circuit.circuit_access.definition import EmodelProperties
|
|
28
29
|
from bluecellulab.circuit import CellId, SynapseProperty
|
|
29
30
|
from bluecellulab.circuit.config import SimulationConfig
|
|
@@ -46,7 +47,7 @@ class SonataCircuitAccess:
|
|
|
46
47
|
raise FileNotFoundError(f"Circuit config file {simulation_config} not found.")
|
|
47
48
|
|
|
48
49
|
if isinstance(simulation_config, SonataSimulationConfig):
|
|
49
|
-
self.config
|
|
50
|
+
self.config = simulation_config
|
|
50
51
|
else:
|
|
51
52
|
self.config = SonataSimulationConfig(simulation_config)
|
|
52
53
|
circuit_config = self.config.impl.config["network"]
|
|
@@ -190,7 +191,7 @@ class SonataCircuitAccess:
|
|
|
190
191
|
|
|
191
192
|
@lru_cache(maxsize=16)
|
|
192
193
|
def get_target_cell_ids(self, target: str) -> set[CellId]:
|
|
193
|
-
ids = self._circuit.nodes.ids(target)
|
|
194
|
+
ids = self._circuit.nodes.ids(self.config.impl.node_sets[target])
|
|
194
195
|
return {CellId(x.population, x.id) for x in ids}
|
|
195
196
|
|
|
196
197
|
@lru_cache(maxsize=100)
|
bluecellulab/circuit/format.py
CHANGED
bluecellulab/circuit/iotools.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright
|
|
1
|
+
# Copyright 2023-2024 Blue Brain Project / EPFL
|
|
2
2
|
|
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
4
|
# you may not use this file except in compliance with the License.
|
|
@@ -32,7 +32,7 @@ def parse_outdat(path: str | Path) -> dict[CellId, np.ndarray]:
|
|
|
32
32
|
# convert Series to DataFrame with 2 columns for `groupby` operation
|
|
33
33
|
spike_df = spikes.to_frame().reset_index()
|
|
34
34
|
if (spike_df["t"] < 0).any():
|
|
35
|
-
logger.warning('
|
|
35
|
+
logger.warning('Found negative spike times in out.dat ! '
|
|
36
36
|
'Clipping them to 0')
|
|
37
37
|
spike_df["t"].clip(lower=0., inplace=True)
|
|
38
38
|
|
bluecellulab/circuit/node_id.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright
|
|
1
|
+
# Copyright 2023-2024 Blue Brain Project / EPFL
|
|
2
2
|
|
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
4
|
# you may not use this file except in compliance with the License.
|
|
@@ -18,6 +18,7 @@ import logging
|
|
|
18
18
|
from pathlib import Path
|
|
19
19
|
from typing import Optional, Protocol
|
|
20
20
|
|
|
21
|
+
import h5py
|
|
21
22
|
import pandas as pd
|
|
22
23
|
|
|
23
24
|
from bluecellulab.circuit.config import SimulationConfig, SonataSimulationConfig
|
|
@@ -171,13 +172,15 @@ class SonataSimulationAccess:
|
|
|
171
172
|
|
|
172
173
|
|
|
173
174
|
def get_synapse_replay_spikes(f_name: str) -> dict:
|
|
174
|
-
"""Read the .
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
175
|
+
"""Read the .h5 file containing the spike replays."""
|
|
176
|
+
with h5py.File(f_name, 'r') as f:
|
|
177
|
+
# Access the timestamps and node_ids datasets
|
|
178
|
+
timestamps = f['/spikes/All/timestamps'][:]
|
|
179
|
+
node_ids = f['/spikes/All/node_ids'][:]
|
|
180
|
+
|
|
181
|
+
spikes = pd.DataFrame(data={'t': timestamps, 'node_id': node_ids})
|
|
182
|
+
spikes = spikes.astype({"node_id": int})
|
|
183
|
+
|
|
181
184
|
if (spikes["t"] < 0).any():
|
|
182
185
|
logger.warning("Found negative spike times... Clipping them to 0")
|
|
183
186
|
spikes["t"].clip(lower=0., inplace=True)
|