bluecellulab 2.4.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 (56) hide show
  1. bluecellulab/__init__.py +10 -3
  2. bluecellulab/analysis/__init__.py +0 -0
  3. bluecellulab/analysis/inject_sequence.py +165 -0
  4. bluecellulab/cell/cell_dict.py +1 -1
  5. bluecellulab/cell/core.py +95 -76
  6. bluecellulab/cell/injector.py +8 -10
  7. bluecellulab/cell/plotting.py +2 -1
  8. bluecellulab/cell/random.py +1 -1
  9. bluecellulab/cell/recording.py +8 -0
  10. bluecellulab/cell/section_distance.py +1 -1
  11. bluecellulab/cell/serialized_sections.py +4 -6
  12. bluecellulab/cell/sonata_proxy.py +1 -1
  13. bluecellulab/cell/stimuli_generator.py +26 -8
  14. bluecellulab/cell/template.py +12 -4
  15. bluecellulab/circuit/circuit_access/bluepy_circuit_access.py +12 -20
  16. bluecellulab/circuit/circuit_access/definition.py +1 -1
  17. bluecellulab/circuit/circuit_access/sonata_circuit_access.py +5 -4
  18. bluecellulab/circuit/config/bluepy_simulation_config.py +1 -1
  19. bluecellulab/circuit/config/definition.py +1 -1
  20. bluecellulab/circuit/config/sections.py +1 -1
  21. bluecellulab/circuit/config/sonata_simulation_config.py +1 -1
  22. bluecellulab/circuit/format.py +1 -1
  23. bluecellulab/circuit/iotools.py +2 -2
  24. bluecellulab/circuit/node_id.py +1 -1
  25. bluecellulab/circuit/simulation_access.py +11 -8
  26. bluecellulab/circuit/synapse_properties.py +25 -9
  27. bluecellulab/circuit/validate.py +1 -1
  28. bluecellulab/{ssim.py → circuit_simulation.py} +36 -34
  29. bluecellulab/connection.py +1 -1
  30. bluecellulab/dendrogram.py +1 -1
  31. bluecellulab/exceptions.py +1 -1
  32. bluecellulab/graph.py +1 -1
  33. bluecellulab/importer.py +6 -8
  34. bluecellulab/neuron_interpreter.py +1 -1
  35. bluecellulab/plotwindow.py +1 -1
  36. bluecellulab/psection.py +11 -16
  37. bluecellulab/psegment.py +4 -4
  38. bluecellulab/rngsettings.py +4 -4
  39. bluecellulab/simulation/__init__.py +0 -1
  40. bluecellulab/simulation/neuron_globals.py +48 -4
  41. bluecellulab/simulation/parallel.py +40 -0
  42. bluecellulab/simulation/simulation.py +28 -32
  43. bluecellulab/stimulus/circuit_stimulus_definitions.py +11 -6
  44. bluecellulab/stimulus/factory.py +537 -102
  45. bluecellulab/synapse/synapse_factory.py +8 -4
  46. bluecellulab/synapse/synapse_types.py +1 -1
  47. bluecellulab/tools.py +20 -13
  48. bluecellulab/type_aliases.py +4 -1
  49. bluecellulab/utils.py +20 -16
  50. {bluecellulab-2.4.0.dist-info → bluecellulab-2.6.37.dist-info}/LICENSE +0 -7
  51. {bluecellulab-2.4.0.dist-info → bluecellulab-2.6.37.dist-info}/METADATA +42 -25
  52. bluecellulab-2.6.37.dist-info/RECORD +70 -0
  53. {bluecellulab-2.4.0.dist-info → bluecellulab-2.6.37.dist-info}/WHEEL +1 -1
  54. bluecellulab-2.4.0.dist-info/RECORD +0 -66
  55. {bluecellulab-2.4.0.dist-info → bluecellulab-2.6.37.dist-info}/AUTHORS.txt +0 -0
  56. {bluecellulab-2.4.0.dist-info → bluecellulab-2.6.37.dist-info}/top_level.txt +0 -0
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.
@@ -52,8 +52,8 @@ def import_mod_lib(neuron: ModuleType) -> str:
52
52
  return res
53
53
 
54
54
 
55
- def import_neurodamus(neuron: ModuleType) -> None:
56
- """Import neurodamus."""
55
+ def import_hoc(neuron: ModuleType) -> None:
56
+ """Import hoc dependencies."""
57
57
  neuron.h.load_file("stdrun.hoc") # nrn
58
58
  hoc_files = [
59
59
  "Cell.hoc", # ND
@@ -75,17 +75,15 @@ def print_header(neuron: ModuleType, mod_lib_path: str) -> None:
75
75
 
76
76
 
77
77
  @run_once
78
- def _load_hoc_and_mod_files() -> None:
78
+ def _load_mod_files() -> None:
79
79
  """Import hoc and mod files."""
80
80
  logger.debug("Loading the mod files.")
81
81
  mod_lib_paths = import_mod_lib(neuron)
82
- logger.debug("Loading the hoc files.")
83
- import_neurodamus(neuron)
84
82
  print_header(neuron, mod_lib_paths)
85
83
 
86
84
 
87
- def load_hoc_and_mod_files(func):
85
+ def load_mod_files(func):
88
86
  def wrapper(*args, **kwargs):
89
- _load_hoc_and_mod_files()
87
+ _load_mod_files()
90
88
  return func(*args, **kwargs)
91
89
  return wrapper
@@ -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.
@@ -20,7 +20,7 @@ from typing import Optional
20
20
  import neuron
21
21
  from bluecellulab.circuit.config.definition import SimulationConfig
22
22
  from bluecellulab.exceptions import UndefinedRNGException
23
- from bluecellulab.importer import load_hoc_and_mod_files
23
+ from bluecellulab.importer import load_mod_files
24
24
 
25
25
  logger = logging.getLogger(__name__)
26
26
 
@@ -37,7 +37,7 @@ class RNGSettings:
37
37
  cls._instance = cls()
38
38
  return cls._instance
39
39
 
40
- @load_hoc_and_mod_files
40
+ @load_mod_files
41
41
  def __init__(
42
42
  self,
43
43
  mode="Random123",
@@ -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:
@@ -3,4 +3,3 @@
3
3
  from .simulation import Simulation
4
4
  from .neuron_globals import set_global_condition_parameters
5
5
  from .neuron_globals import set_minis_single_vesicle_values
6
- from .neuron_globals import set_tstop_value
@@ -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,49 @@ def set_minis_single_vesicle_values(mech_conditions: MechanismConditions) -> Non
62
63
  )
63
64
 
64
65
 
65
- def set_tstop_value(tstop: float) -> None:
66
- """Set the tstop value required by Tstim noise stimuli."""
67
- neuron.h.tstop = tstop
66
+ class NeuronGlobalParams(NamedTuple):
67
+ temperature: float
68
+ v_init: float
69
+
70
+
71
+ class NeuronGlobals:
72
+ _instance = None
73
+
74
+ def __init__(self):
75
+ raise RuntimeError('Call get_instance() instead')
76
+
77
+ @classmethod
78
+ def get_instance(cls):
79
+ if cls._instance is None:
80
+ cls._instance = cls.__new__(cls)
81
+ # Initialize default values
82
+ cls._instance._temperature = 34.0 # Default temperature
83
+ cls._instance.v_init = neuron.h.v_init
84
+ # Set the default values in NEURON
85
+ neuron.h.celsius = cls._instance._temperature
86
+ return cls._instance
87
+
88
+ @property
89
+ def temperature(self):
90
+ return self._temperature
91
+
92
+ @temperature.setter
93
+ def temperature(self, value):
94
+ self._temperature = value
95
+ neuron.h.celsius = value
96
+
97
+ @property
98
+ def v_init(self):
99
+ return self._v_init
100
+
101
+ @v_init.setter
102
+ def v_init(self, value):
103
+ self._v_init = value
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)
@@ -88,13 +92,11 @@ class Simulation:
88
92
  cvode=True,
89
93
  cvode_minstep=None,
90
94
  cvode_maxstep=None,
91
- celsius=34,
92
- v_init=-65,
93
95
  dt=0.025,
94
96
  forward_skip=None,
95
97
  forward_skip_value=False,
96
- show_progress=None,
97
- use_random123_stochkv=False):
98
+ show_progress=None
99
+ ):
98
100
  """Run the simulation."""
99
101
  # if maxtime <= neuron.h.t:
100
102
  # raise Exception("Simulation: need to provide a maxtime (=%f) "
@@ -108,7 +110,6 @@ class Simulation:
108
110
  self.progress_dt = maxtime / 100
109
111
  self.init_progress_callback()
110
112
 
111
- neuron.h.celsius = celsius
112
113
  neuron.h.tstop = maxtime
113
114
 
114
115
  cvode_old_status = neuron.h.cvode_active()
@@ -125,11 +126,9 @@ class Simulation:
125
126
  "was set")
126
127
  neuron.h.cvode_active(0)
127
128
 
128
- neuron.h.v_init = v_init
129
-
130
129
  for cell in self.cells:
131
130
  with contextlib.suppress(AttributeError):
132
- cell.re_init_rng(use_random123_stochkv=use_random123_stochkv)
131
+ cell.re_init_rng()
133
132
  neuron.h.dt = dt
134
133
  neuron.h.steps_per_ms = 1.0 / dt
135
134
 
@@ -176,6 +175,3 @@ class Simulation:
176
175
  neuron.h.cvode_active(cvode_old_status)
177
176
 
178
177
  logger.debug("Finished simulation.")
179
-
180
- def __del__(self):
181
- pass
@@ -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):