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.

Files changed (52) hide show
  1. bluecellulab/__init__.py +3 -3
  2. bluecellulab/analysis/inject_sequence.py +47 -12
  3. bluecellulab/cell/cell_dict.py +1 -1
  4. bluecellulab/cell/core.py +34 -30
  5. bluecellulab/cell/injector.py +2 -4
  6. bluecellulab/cell/plotting.py +2 -1
  7. bluecellulab/cell/random.py +1 -1
  8. bluecellulab/cell/section_distance.py +1 -1
  9. bluecellulab/cell/serialized_sections.py +4 -6
  10. bluecellulab/cell/sonata_proxy.py +1 -1
  11. bluecellulab/cell/stimuli_generator.py +26 -8
  12. bluecellulab/cell/template.py +4 -3
  13. bluecellulab/circuit/circuit_access/bluepy_circuit_access.py +12 -20
  14. bluecellulab/circuit/circuit_access/definition.py +1 -1
  15. bluecellulab/circuit/circuit_access/sonata_circuit_access.py +5 -4
  16. bluecellulab/circuit/config/bluepy_simulation_config.py +1 -1
  17. bluecellulab/circuit/config/definition.py +1 -1
  18. bluecellulab/circuit/config/sections.py +1 -1
  19. bluecellulab/circuit/config/sonata_simulation_config.py +1 -1
  20. bluecellulab/circuit/format.py +1 -1
  21. bluecellulab/circuit/iotools.py +2 -2
  22. bluecellulab/circuit/node_id.py +1 -1
  23. bluecellulab/circuit/simulation_access.py +11 -8
  24. bluecellulab/circuit/synapse_properties.py +25 -9
  25. bluecellulab/circuit/validate.py +1 -1
  26. bluecellulab/{ssim.py → circuit_simulation.py} +33 -26
  27. bluecellulab/connection.py +1 -1
  28. bluecellulab/dendrogram.py +1 -1
  29. bluecellulab/exceptions.py +1 -1
  30. bluecellulab/graph.py +1 -1
  31. bluecellulab/importer.py +1 -1
  32. bluecellulab/neuron_interpreter.py +1 -1
  33. bluecellulab/plotwindow.py +1 -1
  34. bluecellulab/psection.py +11 -16
  35. bluecellulab/psegment.py +4 -4
  36. bluecellulab/rngsettings.py +2 -2
  37. bluecellulab/simulation/neuron_globals.py +14 -1
  38. bluecellulab/simulation/parallel.py +40 -0
  39. bluecellulab/simulation/simulation.py +25 -21
  40. bluecellulab/stimulus/circuit_stimulus_definitions.py +11 -6
  41. bluecellulab/stimulus/factory.py +537 -102
  42. bluecellulab/synapse/synapse_factory.py +8 -4
  43. bluecellulab/synapse/synapse_types.py +1 -1
  44. bluecellulab/tools.py +14 -11
  45. bluecellulab/utils.py +20 -22
  46. {bluecellulab-2.5.0.dist-info → bluecellulab-2.6.37.dist-info}/LICENSE +0 -7
  47. {bluecellulab-2.5.0.dist-info → bluecellulab-2.6.37.dist-info}/METADATA +42 -25
  48. bluecellulab-2.6.37.dist-info/RECORD +70 -0
  49. {bluecellulab-2.5.0.dist-info → bluecellulab-2.6.37.dist-info}/WHEEL +1 -1
  50. bluecellulab-2.5.0.dist-info/RECORD +0 -69
  51. {bluecellulab-2.5.0.dist-info → bluecellulab-2.6.37.dist-info}/AUTHORS.txt +0 -0
  52. {bluecellulab-2.5.0.dist-info → bluecellulab-2.6.37.dist-info}/top_level.txt +0 -0
@@ -1,4 +1,4 @@
1
- # Copyright 2012-2024 Blue Brain Project / EPFL
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
- return [
141
- SynapseProperty.from_bluepy(prop)
142
- if isinstance(prop, BLPSynapse)
143
- else prop
144
- for prop in props
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
- return [
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 props
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]:
@@ -1,4 +1,4 @@
1
- # Copyright 2012-2024 Blue Brain Project / EPFL
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.
@@ -1,4 +1,4 @@
1
- # Copyright 2012-2024 Blue Brain Project / EPFL
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 Exception("SSim: instantiate_gids() called twice on the \
223
- same SSim, this is not supported yet")
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 Exception("SSim: you need to set add_synapses to True "
230
- "if you want to specify use add_replay or "
231
- "pre_spike_trains")
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 Exception("SSim: add_replay option can not be used if "
249
- "add_synapses is False")
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, projections=None):
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, projections=None
370
+ self, cell_id: CellId, pre_gids=None, add_minis=False
362
371
  ) -> None:
363
- syn_descriptions = self.get_syn_descriptions(cell_id, projections=projections)
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 SSim.
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
- NeuronGlobals.get_instance().temperature = celsius
601
+ NeuronGlobals.get_instance().temperature = celsius
595
602
  if v_init is None:
596
603
  v_init = self.circuit_access.config.v_init
597
- NeuronGlobals.get_instance().v_init = v_init
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 ssim and all of its attributes.
715
+ """Delete CircuitSimulation and all of its attributes.
709
716
 
710
717
  NEURON objects are explicitly needed to be deleted.
711
718
  """
@@ -1,4 +1,4 @@
1
- # Copyright 2012-2024 Blue Brain Project / EPFL
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.
@@ -1,4 +1,4 @@
1
- # Copyright 2012-2024 Blue Brain Project / EPFL
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.
@@ -1,4 +1,4 @@
1
- # Copyright 2012-2024 Blue Brain Project / EPFL
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.
bluecellulab/graph.py CHANGED
@@ -82,4 +82,4 @@ def plot_graph(G: nx.Graph, node_size: float = 400, edge_width: float = 0.4, nod
82
82
  # Add text at the bottom of the figure
83
83
  plt.figtext(0.5, 0.01, "Network of simulated cells", ha="center", fontsize=10, va="bottom")
84
84
 
85
- plt.show()
85
+ return plt
bluecellulab/importer.py CHANGED
@@ -1,4 +1,4 @@
1
- # Copyright 2012-2024 Blue Brain Project / EPFL
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.
@@ -1,4 +1,4 @@
1
- # Copyright 2012-2024 Blue Brain Project / EPFL
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.
@@ -1,4 +1,4 @@
1
- # Copyright 2012-2024 Blue Brain Project / EPFL
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.
bluecellulab/psection.py CHANGED
@@ -1,4 +1,4 @@
1
- # Copyright 2012-2024 Blue Brain Project / EPFL
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 2012-2024 Blue Brain Project / EPFL
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 = {'apical': 'm', 'basal': 'r', 'somatic': 'k', 'axonal': 'b', 'myelin': 'g'}
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 cm
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 = cm.get_cmap("hot")
38
+ self.color_map = colormaps["hot"]
39
39
  self.ax = None
40
40
  self.patch = None
41
41
  self.plotvariable = None
@@ -1,4 +1,4 @@
1
- # Copyright 2012-2024 Blue Brain Project / EPFL
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
- "SSim: RNG mode %s not in accepted list: %s"
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 2012-2024 Blue Brain Project / EPFL
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 2012-2024 Blue Brain Project / EPFL
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.progress > 0:
54
- sys.stdout.write("\x1b[3F")
55
-
56
- self.progress += 1
57
- self.progress_closed = not self.progress_closed
58
- if self.progress_closed:
59
- sys.stdout.write(" %s%s%s \n" % (" " * (
60
- self.progress - 1), " ", " " * (100 - self.progress)))
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)))
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
- sys.stdout.write(" %s%s%s \n" % (" " * (
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 2012-2024 Blue Brain Project / EPFL
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
- amp_cv=stimulus_entry["AmpCV"],
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
- amp_cv=stimulus_entry["amp_cv"],
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
- amp_cv: float
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):