bluecellulab 2.5.0__py3-none-any.whl → 2.6.38__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.38.dist-info}/LICENSE +0 -7
- {bluecellulab-2.5.0.dist-info → bluecellulab-2.6.38.dist-info}/METADATA +56 -38
- bluecellulab-2.6.38.dist-info/RECORD +70 -0
- {bluecellulab-2.5.0.dist-info → bluecellulab-2.6.38.dist-info}/WHEEL +1 -1
- bluecellulab-2.5.0.dist-info/RECORD +0 -69
- {bluecellulab-2.5.0.dist-info → bluecellulab-2.6.38.dist-info}/AUTHORS.txt +0 -0
- {bluecellulab-2.5.0.dist-info → bluecellulab-2.6.38.dist-info}/top_level.txt +0 -0
|
@@ -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.
|
|
@@ -40,6 +40,7 @@ class SynapseProperty(Enum):
|
|
|
40
40
|
NRRP = "NRRP"
|
|
41
41
|
U_HILL_COEFFICIENT = "u_hill_coefficient"
|
|
42
42
|
CONDUCTANCE_RATIO = "conductance_scale_factor"
|
|
43
|
+
AFFERENT_SECTION_POS = "afferent_section_pos"
|
|
43
44
|
|
|
44
45
|
@classmethod
|
|
45
46
|
def from_bluepy(cls, prop: BLPSynapse) -> SynapseProperty:
|
|
@@ -76,6 +77,7 @@ class SynapseProperties:
|
|
|
76
77
|
SynapseProperty.NRRP,
|
|
77
78
|
SynapseProperty.U_HILL_COEFFICIENT,
|
|
78
79
|
SynapseProperty.CONDUCTANCE_RATIO,
|
|
80
|
+
SynapseProperty.AFFERENT_SECTION_POS,
|
|
79
81
|
)
|
|
80
82
|
plasticity = (
|
|
81
83
|
"volume_CR", "rho0_GB", "Use_d_TM", "Use_p_TM", "gmax_d_AMPA",
|
|
@@ -98,6 +100,7 @@ snap_to_synproperty = MappingProxyType({
|
|
|
98
100
|
"n_rrp_vesicles": SynapseProperty.NRRP,
|
|
99
101
|
"u_hill_coefficient": SynapseProperty.U_HILL_COEFFICIENT,
|
|
100
102
|
"conductance_scale_factor": SynapseProperty.CONDUCTANCE_RATIO,
|
|
103
|
+
"afferent_section_pos": SynapseProperty.AFFERENT_SECTION_POS,
|
|
101
104
|
})
|
|
102
105
|
|
|
103
106
|
|
|
@@ -137,23 +140,36 @@ def properties_from_bluepy(
|
|
|
137
140
|
'str's."""
|
|
138
141
|
if not BLUEPY_AVAILABLE:
|
|
139
142
|
raise ExtraDependencyMissingError("bluepy")
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
if isinstance(prop, BLPSynapse)
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
143
|
+
res: list[SynapseProperty | str] = []
|
|
144
|
+
for prop in props:
|
|
145
|
+
if isinstance(prop, BLPSynapse):
|
|
146
|
+
res.append(SynapseProperty.from_bluepy(prop))
|
|
147
|
+
elif prop == "afferent_section_pos": # jira_url/project/issues/browse/NSETM-2313
|
|
148
|
+
res.append(SynapseProperty.AFFERENT_SECTION_POS)
|
|
149
|
+
else:
|
|
150
|
+
res.append(prop)
|
|
151
|
+
return res
|
|
146
152
|
|
|
147
153
|
|
|
148
154
|
def properties_to_bluepy(props: list[SynapseProperty | str]) -> list[BLPSynapse | str]:
|
|
149
155
|
"""Convert a list of SynapseProperty to bluepy Synapse properties, spare
|
|
150
156
|
'str's."""
|
|
151
|
-
|
|
157
|
+
# bluepy does not have AFFERENT_SECTION_POS atm.
|
|
158
|
+
# jira_url/project/issues/browse/NSETM-2313
|
|
159
|
+
bluepy_recognised_props = props.copy()
|
|
160
|
+
removed_afferent_section_pos = False
|
|
161
|
+
if SynapseProperty.AFFERENT_SECTION_POS in bluepy_recognised_props:
|
|
162
|
+
removed_afferent_section_pos = True
|
|
163
|
+
bluepy_recognised_props.remove(SynapseProperty.AFFERENT_SECTION_POS)
|
|
164
|
+
res = [
|
|
152
165
|
prop.to_bluepy()
|
|
153
166
|
if isinstance(prop, SynapseProperty)
|
|
154
167
|
else prop
|
|
155
|
-
for prop in
|
|
168
|
+
for prop in bluepy_recognised_props
|
|
156
169
|
]
|
|
170
|
+
if removed_afferent_section_pos:
|
|
171
|
+
res.append("afferent_section_pos")
|
|
172
|
+
return res
|
|
157
173
|
|
|
158
174
|
|
|
159
175
|
def synapse_property_encoder(dct: dict[SynapseProperty | str, Any]) -> dict[str, Any]:
|
bluecellulab/circuit/validate.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.
|
|
@@ -25,6 +25,9 @@ import neuron
|
|
|
25
25
|
import numpy as np
|
|
26
26
|
import pandas as pd
|
|
27
27
|
from pydantic.types import NonNegativeInt
|
|
28
|
+
from typing_extensions import deprecated
|
|
29
|
+
from typing import Optional
|
|
30
|
+
|
|
28
31
|
import bluecellulab
|
|
29
32
|
from bluecellulab.cell import CellDict
|
|
30
33
|
from bluecellulab.cell.sonata_proxy import SonataProxy
|
|
@@ -53,9 +56,14 @@ from bluecellulab.synapse.synapse_types import SynapseID
|
|
|
53
56
|
logger = logging.getLogger(__name__)
|
|
54
57
|
|
|
55
58
|
|
|
59
|
+
@deprecated("SSim will be removed, use CircuitSimulation instead.")
|
|
56
60
|
class SSim:
|
|
57
61
|
"""Class that loads a circuit simulation to do cell simulations."""
|
|
58
62
|
|
|
63
|
+
|
|
64
|
+
class CircuitSimulation:
|
|
65
|
+
"""Class that loads a circuit simulation to do cell simulations."""
|
|
66
|
+
|
|
59
67
|
@load_mod_files
|
|
60
68
|
def __init__(
|
|
61
69
|
self,
|
|
@@ -109,6 +117,8 @@ class SSim:
|
|
|
109
117
|
self.spike_threshold = self.circuit_access.config.spike_threshold
|
|
110
118
|
self.spike_location = self.circuit_access.config.spike_location
|
|
111
119
|
|
|
120
|
+
self.projections: list[str] = []
|
|
121
|
+
|
|
112
122
|
condition_parameters = self.circuit_access.config.condition_parameters()
|
|
113
123
|
set_global_condition_parameters(condition_parameters)
|
|
114
124
|
|
|
@@ -219,34 +229,34 @@ class SSim:
|
|
|
219
229
|
}
|
|
220
230
|
|
|
221
231
|
if self.gids_instantiated:
|
|
222
|
-
raise
|
|
223
|
-
|
|
232
|
+
raise BluecellulabError(
|
|
233
|
+
"instantiate_gids() is called twice on the "
|
|
234
|
+
"same CircuitSimumation, this is not supported")
|
|
224
235
|
else:
|
|
225
236
|
self.gids_instantiated = True
|
|
226
237
|
|
|
227
238
|
if pre_spike_trains or add_replay:
|
|
228
239
|
if add_synapses is False:
|
|
229
|
-
raise
|
|
230
|
-
|
|
231
|
-
|
|
240
|
+
raise BluecellulabError("You need to set add_synapses to True "
|
|
241
|
+
"if you want to specify use add_replay or "
|
|
242
|
+
"pre_spike_trains")
|
|
232
243
|
|
|
233
244
|
if add_projections is True:
|
|
234
|
-
projections = self.circuit_access.config.get_all_projection_names()
|
|
245
|
+
self.projections = self.circuit_access.config.get_all_projection_names()
|
|
235
246
|
elif add_projections is False:
|
|
236
|
-
projections = []
|
|
247
|
+
self.projections = []
|
|
237
248
|
else:
|
|
238
|
-
projections = add_projections
|
|
249
|
+
self.projections = add_projections
|
|
239
250
|
|
|
240
251
|
self._add_cells(cell_ids)
|
|
241
252
|
if add_synapses:
|
|
242
253
|
self._add_synapses(
|
|
243
254
|
pre_gids=pre_gids,
|
|
244
|
-
add_minis=add_minis
|
|
245
|
-
projections=projections)
|
|
255
|
+
add_minis=add_minis)
|
|
246
256
|
if add_replay or interconnect_cells or pre_spike_trains:
|
|
247
257
|
if add_replay and not add_synapses:
|
|
248
|
-
raise
|
|
249
|
-
|
|
258
|
+
raise BluecellulabError("add_replay option can not be used if "
|
|
259
|
+
"add_synapses is False")
|
|
250
260
|
self._add_connections(add_replay=add_replay,
|
|
251
261
|
interconnect_cells=interconnect_cells,
|
|
252
262
|
user_pre_spike_trains=pre_spike_trains) # type: ignore
|
|
@@ -349,18 +359,17 @@ class SSim:
|
|
|
349
359
|
ornstein_uhlenbeck_stim_count += 1
|
|
350
360
|
|
|
351
361
|
def _add_synapses(
|
|
352
|
-
self, pre_gids=None, add_minis=False
|
|
362
|
+
self, pre_gids=None, add_minis=False):
|
|
353
363
|
"""Instantiate all the synapses."""
|
|
354
364
|
for cell_id in self.cells:
|
|
355
365
|
self._add_cell_synapses(
|
|
356
366
|
cell_id, pre_gids=pre_gids,
|
|
357
|
-
add_minis=add_minis
|
|
358
|
-
projections=projections)
|
|
367
|
+
add_minis=add_minis)
|
|
359
368
|
|
|
360
369
|
def _add_cell_synapses(
|
|
361
|
-
self, cell_id: CellId, pre_gids=None, add_minis=False
|
|
370
|
+
self, cell_id: CellId, pre_gids=None, add_minis=False
|
|
362
371
|
) -> None:
|
|
363
|
-
syn_descriptions = self.get_syn_descriptions(cell_id
|
|
372
|
+
syn_descriptions = self.get_syn_descriptions(cell_id)
|
|
364
373
|
|
|
365
374
|
if pre_gids is not None:
|
|
366
375
|
if self.circuit_format == CircuitFormat.SONATA:
|
|
@@ -415,12 +424,10 @@ class SSim:
|
|
|
415
424
|
)
|
|
416
425
|
return syn_descriptions[filtered_rows]
|
|
417
426
|
|
|
418
|
-
def get_syn_descriptions(
|
|
419
|
-
self, cell_id: int | tuple[str, int], projections=None
|
|
420
|
-
) -> pd.DataFrame:
|
|
427
|
+
def get_syn_descriptions(self, cell_id: int | tuple[str, int]) -> pd.DataFrame:
|
|
421
428
|
"""Get synapse descriptions dataframe."""
|
|
422
429
|
cell_id = create_cell_id(cell_id)
|
|
423
|
-
return self.circuit_access.extract_synapses(cell_id, projections=projections)
|
|
430
|
+
return self.circuit_access.extract_synapses(cell_id, projections=self.projections)
|
|
424
431
|
|
|
425
432
|
@staticmethod
|
|
426
433
|
def merge_pre_spike_trains(*train_dicts) -> dict[CellId, np.ndarray]:
|
|
@@ -549,7 +556,7 @@ class SSim:
|
|
|
549
556
|
cvode: bool = False,
|
|
550
557
|
show_progress: bool = False,
|
|
551
558
|
):
|
|
552
|
-
"""Simulate the
|
|
559
|
+
"""Simulate the Circuit.
|
|
553
560
|
|
|
554
561
|
Parameters
|
|
555
562
|
----------
|
|
@@ -591,10 +598,10 @@ class SSim:
|
|
|
591
598
|
forward_skip_value = self.circuit_access.config.forward_skip
|
|
592
599
|
if celsius is None:
|
|
593
600
|
celsius = self.circuit_access.config.celsius
|
|
594
|
-
|
|
601
|
+
NeuronGlobals.get_instance().temperature = celsius
|
|
595
602
|
if v_init is None:
|
|
596
603
|
v_init = self.circuit_access.config.v_init
|
|
597
|
-
|
|
604
|
+
NeuronGlobals.get_instance().v_init = v_init
|
|
598
605
|
|
|
599
606
|
sim = bluecellulab.Simulation(self.pc)
|
|
600
607
|
for cell_id in self.cells:
|
|
@@ -705,7 +712,7 @@ class SSim:
|
|
|
705
712
|
return voltage
|
|
706
713
|
|
|
707
714
|
def delete(self):
|
|
708
|
-
"""Delete
|
|
715
|
+
"""Delete CircuitSimulation and all of its attributes.
|
|
709
716
|
|
|
710
717
|
NEURON objects are explicitly needed to be deleted.
|
|
711
718
|
"""
|
bluecellulab/connection.py
CHANGED
bluecellulab/dendrogram.py
CHANGED
bluecellulab/exceptions.py
CHANGED
bluecellulab/graph.py
CHANGED
bluecellulab/importer.py
CHANGED
bluecellulab/plotwindow.py
CHANGED
bluecellulab/psection.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.
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
"""Represents a python version of NEURON Section (for drawing)."""
|
|
15
15
|
from __future__ import annotations
|
|
16
|
+
import re
|
|
16
17
|
import neuron
|
|
17
18
|
|
|
18
19
|
import bluecellulab
|
|
@@ -75,21 +76,6 @@ class PSection:
|
|
|
75
76
|
self.pchildren: list[PSection] = []
|
|
76
77
|
self.isec = isec
|
|
77
78
|
|
|
78
|
-
if 'apic' in self.name:
|
|
79
|
-
self.section_type = 'apical'
|
|
80
|
-
elif 'dend' in self.name:
|
|
81
|
-
self.section_type = 'basal'
|
|
82
|
-
elif 'soma' in self.name:
|
|
83
|
-
self.section_type = 'somatic'
|
|
84
|
-
elif 'axon' in self.name:
|
|
85
|
-
self.section_type = 'axonal'
|
|
86
|
-
elif 'myelin' in self.name:
|
|
87
|
-
self.section_type = 'myelin'
|
|
88
|
-
else:
|
|
89
|
-
raise Exception(
|
|
90
|
-
"PSection: Section of unknown type: %s" %
|
|
91
|
-
self.name)
|
|
92
|
-
|
|
93
79
|
self.psegments: list[PSegment] = []
|
|
94
80
|
self.maxsegdiam = 0.0
|
|
95
81
|
for hsegment in hsection:
|
|
@@ -101,6 +87,15 @@ class PSection:
|
|
|
101
87
|
self.xSpacing = 1.0
|
|
102
88
|
self.ySpacing = 5.0
|
|
103
89
|
|
|
90
|
+
@property
|
|
91
|
+
def section_type(self) -> str:
|
|
92
|
+
"""Return the type of the section."""
|
|
93
|
+
# From Cell[0].soma[0] -> soma
|
|
94
|
+
matches = re.findall(r'\.([^.\[\]]+)\[', self.name)
|
|
95
|
+
if matches:
|
|
96
|
+
return matches[-1] # Return the last match
|
|
97
|
+
return 'unknown' # Return 'unknown' if no matches are found
|
|
98
|
+
|
|
104
99
|
@property
|
|
105
100
|
def is_leaf(self) -> bool:
|
|
106
101
|
"""Return true if section is a leaf in the morphological structure."""
|
bluecellulab/psegment.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.
|
|
@@ -17,7 +17,7 @@ import neuron
|
|
|
17
17
|
|
|
18
18
|
from bluecellulab.neuron_interpreter import eval_neuron
|
|
19
19
|
|
|
20
|
-
type_colormap = {'
|
|
20
|
+
type_colormap = {'apic': 'm', 'dend': 'r', 'soma': 'k', 'axon': 'b', 'myelin': 'g', 'unknown': 'c'}
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
class PSegment:
|
|
@@ -25,7 +25,7 @@ class PSegment:
|
|
|
25
25
|
|
|
26
26
|
def __init__(self, hsegment, parentsection):
|
|
27
27
|
# import matplotlib as plt
|
|
28
|
-
from matplotlib import
|
|
28
|
+
from matplotlib import colormaps
|
|
29
29
|
|
|
30
30
|
self.hsegment = hsegment
|
|
31
31
|
self.parentsection = parentsection
|
|
@@ -35,7 +35,7 @@ class PSegment:
|
|
|
35
35
|
self.figure = None
|
|
36
36
|
self.figX = None
|
|
37
37
|
self.figY = None
|
|
38
|
-
self.color_map =
|
|
38
|
+
self.color_map = colormaps["hot"]
|
|
39
39
|
self.ax = None
|
|
40
40
|
self.patch = None
|
|
41
41
|
self.plotvariable = None
|
bluecellulab/rngsettings.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.
|
|
@@ -105,7 +105,7 @@ class RNGSettings:
|
|
|
105
105
|
options = {"Compatibility": 0, "Random123": 1, "UpdatedMCell": 2}
|
|
106
106
|
if new_val not in options:
|
|
107
107
|
raise UndefinedRNGException(
|
|
108
|
-
"
|
|
108
|
+
"RNG mode's value %s is not in the accepted list: %s"
|
|
109
109
|
% (self.mode, list(options.keys()))
|
|
110
110
|
)
|
|
111
111
|
else:
|
|
@@ -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.
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
"""Module that handles the global NEURON parameters."""
|
|
15
15
|
|
|
16
|
+
from typing import NamedTuple
|
|
16
17
|
import neuron
|
|
17
18
|
from bluecellulab.circuit.config.sections import Conditions, MechanismConditions
|
|
18
19
|
from bluecellulab.exceptions import error_context
|
|
@@ -62,6 +63,11 @@ def set_minis_single_vesicle_values(mech_conditions: MechanismConditions) -> Non
|
|
|
62
63
|
)
|
|
63
64
|
|
|
64
65
|
|
|
66
|
+
class NeuronGlobalParams(NamedTuple):
|
|
67
|
+
temperature: float
|
|
68
|
+
v_init: float
|
|
69
|
+
|
|
70
|
+
|
|
65
71
|
class NeuronGlobals:
|
|
66
72
|
_instance = None
|
|
67
73
|
|
|
@@ -96,3 +102,10 @@ class NeuronGlobals:
|
|
|
96
102
|
def v_init(self, value):
|
|
97
103
|
self._v_init = value
|
|
98
104
|
neuron.h.v_init = value
|
|
105
|
+
|
|
106
|
+
def export_params(self) -> NeuronGlobalParams:
|
|
107
|
+
return NeuronGlobalParams(self.temperature, self.v_init)
|
|
108
|
+
|
|
109
|
+
def load_params(self, params: NeuronGlobalParams) -> None:
|
|
110
|
+
self.temperature = params.temperature
|
|
111
|
+
self.v_init = params.v_init
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"""Controlled simulations in parallel."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
import multiprocessing
|
|
5
|
+
from multiprocessing.pool import Pool
|
|
6
|
+
from bluecellulab.simulation.neuron_globals import NeuronGlobals
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class IsolatedProcess(Pool):
|
|
10
|
+
"""Multiprocessing Pool that restricts a worker to run max 1 process.
|
|
11
|
+
|
|
12
|
+
Use this when running isolated NEURON simulations. Running 2 NEURON
|
|
13
|
+
simulations on a single process is to be avoided. Required global
|
|
14
|
+
NEURON simulation parameters will automatically be passed to each
|
|
15
|
+
worker. `fork` mode of multiprocessing is used to pass any other
|
|
16
|
+
global NEURON parameters to each worker.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
def __init__(self, processes: int | None = 1):
|
|
20
|
+
"""Initialize the IsolatedProcess pool.
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
processes: The number of processes to use for running the simulations.
|
|
24
|
+
If set to None, then the number returned by os.cpu_count() is used.
|
|
25
|
+
"""
|
|
26
|
+
ctx = multiprocessing.get_context("fork")
|
|
27
|
+
neuron_global_params = NeuronGlobals.get_instance().export_params()
|
|
28
|
+
super().__init__(
|
|
29
|
+
processes=processes,
|
|
30
|
+
initializer=self.init_worker,
|
|
31
|
+
initargs=(neuron_global_params,),
|
|
32
|
+
maxtasksperchild=1,
|
|
33
|
+
context=ctx,
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
@staticmethod
|
|
37
|
+
def init_worker(neuron_global_params):
|
|
38
|
+
"""Load global parameters for the NEURON environment in each worker
|
|
39
|
+
process."""
|
|
40
|
+
NeuronGlobals.get_instance().load_params(neuron_global_params)
|
|
@@ -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.
|
|
@@ -28,13 +28,14 @@ logger = logging.getLogger(__name__)
|
|
|
28
28
|
class Simulation:
|
|
29
29
|
"""Class that represents a neuron simulation."""
|
|
30
30
|
|
|
31
|
-
def __init__(self, parallel_context=None) -> None:
|
|
31
|
+
def __init__(self, parallel_context=None, custom_progress_function=None) -> None:
|
|
32
32
|
self.cells: list[bluecellulab.Cell] = []
|
|
33
33
|
self.fih_progress = None
|
|
34
34
|
self.progress = None
|
|
35
35
|
self.progress_closed = None
|
|
36
36
|
self.progress_dt: Optional[float] = None
|
|
37
37
|
self.pc = parallel_context
|
|
38
|
+
self.custom_progress_function = custom_progress_function
|
|
38
39
|
|
|
39
40
|
def add_cell(self, new_cell: bluecellulab.Cell) -> None:
|
|
40
41
|
"""Add a cell to a simulation."""
|
|
@@ -50,26 +51,29 @@ class Simulation:
|
|
|
50
51
|
|
|
51
52
|
def progress_callback(self):
|
|
52
53
|
"""Callback function for the progress bar."""
|
|
53
|
-
if self.
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
54
|
+
if self.custom_progress_function is None:
|
|
55
|
+
if self.progress > 0:
|
|
56
|
+
sys.stdout.write("\x1b[3F")
|
|
57
|
+
|
|
58
|
+
self.progress += 1
|
|
59
|
+
self.progress_closed = not self.progress_closed
|
|
60
|
+
if self.progress_closed:
|
|
61
|
+
sys.stdout.write(" %s%s%s \n" % (" " * (
|
|
62
|
+
self.progress - 1), " ", " " * (100 - self.progress)))
|
|
63
|
+
sys.stdout.write("[%s%s%s]\n" % ("#" * (
|
|
64
|
+
self.progress - 1), "-", "." * (100 - self.progress)))
|
|
65
|
+
sys.stdout.write(" %s%s%s \n" % (" " * (
|
|
66
|
+
self.progress - 1), " ", " " * (100 - self.progress)))
|
|
67
|
+
else:
|
|
68
|
+
sys.stdout.write(" %s%s%s \n" % (" " * (
|
|
69
|
+
self.progress - 1), "/", " " * (100 - self.progress)))
|
|
70
|
+
sys.stdout.write("[%s%s%s]\n" % ("#" * (
|
|
71
|
+
self.progress - 1), ">", "." * (100 - self.progress)))
|
|
72
|
+
sys.stdout.write(" %s%s%s \n" % (" " * (
|
|
73
|
+
self.progress - 1), "\\", " " * (100 - self.progress)))
|
|
74
|
+
sys.stdout.flush()
|
|
65
75
|
else:
|
|
66
|
-
|
|
67
|
-
self.progress - 1), "/", " " * (100 - self.progress)))
|
|
68
|
-
sys.stdout.write("[%s%s%s]\n" % ("#" * (
|
|
69
|
-
self.progress - 1), ">", "." * (100 - self.progress)))
|
|
70
|
-
sys.stdout.write(" %s%s%s \n" % (" " * (
|
|
71
|
-
self.progress - 1), "\\", " " * (100 - self.progress)))
|
|
72
|
-
sys.stdout.flush()
|
|
76
|
+
self.custom_progress_function()
|
|
73
77
|
|
|
74
78
|
neuron.h.cvode.event(
|
|
75
79
|
neuron.h.t + self.progress_dt, self.progress_callback)
|
|
@@ -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.
|
|
@@ -170,7 +170,7 @@ class Stimulus:
|
|
|
170
170
|
decay_time=stimulus_entry["DecayTime"],
|
|
171
171
|
mean_percent=stimulus_entry["MeanPercent"],
|
|
172
172
|
sd_percent=stimulus_entry["SDPercent"],
|
|
173
|
-
|
|
173
|
+
relative_skew=stimulus_entry.get("RelativeSkew", 0.5),
|
|
174
174
|
seed=stimulus_entry.get("Seed", None),
|
|
175
175
|
mode=mode,
|
|
176
176
|
reversal=stimulus_entry.get("Reversal", 0.0)
|
|
@@ -243,7 +243,6 @@ class Stimulus:
|
|
|
243
243
|
delay=stimulus_entry["delay"],
|
|
244
244
|
duration=stimulus_entry["duration"],
|
|
245
245
|
spike_file=stimulus_entry["spike_file"],
|
|
246
|
-
source=stimulus_entry["source"],
|
|
247
246
|
)
|
|
248
247
|
elif pattern == Pattern.SHOT_NOISE:
|
|
249
248
|
return ShotNoise(
|
|
@@ -270,7 +269,7 @@ class Stimulus:
|
|
|
270
269
|
decay_time=stimulus_entry["decay_time"],
|
|
271
270
|
mean_percent=stimulus_entry["mean_percent"],
|
|
272
271
|
sd_percent=stimulus_entry["sd_percent"],
|
|
273
|
-
|
|
272
|
+
relative_skew=stimulus_entry.get("RelativeSkew", 0.5),
|
|
274
273
|
seed=stimulus_entry.get("random_seed", None),
|
|
275
274
|
mode=ClampMode(stimulus_entry.get("input_type", "current_clamp").lower()),
|
|
276
275
|
reversal=stimulus_entry.get("reversal", 0.0)
|
|
@@ -331,7 +330,6 @@ class RelativeLinear(Stimulus):
|
|
|
331
330
|
@dataclass(frozen=True, config=dict(extra="forbid"))
|
|
332
331
|
class SynapseReplay(Stimulus):
|
|
333
332
|
spike_file: str
|
|
334
|
-
source: str
|
|
335
333
|
|
|
336
334
|
@field_validator("spike_file")
|
|
337
335
|
@classmethod
|
|
@@ -367,7 +365,7 @@ class RelativeShotNoise(Stimulus):
|
|
|
367
365
|
decay_time: float
|
|
368
366
|
mean_percent: float
|
|
369
367
|
sd_percent: float
|
|
370
|
-
|
|
368
|
+
relative_skew: float = 0.5
|
|
371
369
|
dt: float = 0.25
|
|
372
370
|
seed: Optional[int] = None
|
|
373
371
|
mode: ClampMode = ClampMode.CURRENT
|
|
@@ -380,6 +378,13 @@ class RelativeShotNoise(Stimulus):
|
|
|
380
378
|
raise ValueError("decay_time must be greater than rise_time")
|
|
381
379
|
return v
|
|
382
380
|
|
|
381
|
+
@field_validator("relative_skew")
|
|
382
|
+
@classmethod
|
|
383
|
+
def relative_skew_in_range(cls, v):
|
|
384
|
+
if v < 0.0 or v > 1.0:
|
|
385
|
+
raise ValueError("relative skewness must be in [0,1]")
|
|
386
|
+
return v
|
|
387
|
+
|
|
383
388
|
|
|
384
389
|
@dataclass(frozen=True, config=dict(extra="forbid"))
|
|
385
390
|
class OrnsteinUhlenbeck(Stimulus):
|