bluecellulab 2.2.7__py3-none-any.whl → 2.3.2__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/cell/core.py CHANGED
@@ -27,12 +27,11 @@ import numpy as np
27
27
  import pandas as pd
28
28
 
29
29
  import bluecellulab
30
- from bluecellulab import psection
30
+ from bluecellulab.psection import PSection, init_psections
31
31
  from bluecellulab.cell.injector import InjectableMixin
32
32
  from bluecellulab.cell.plotting import PlottableMixin
33
33
  from bluecellulab.cell.section_distance import EuclideanSectionDistance
34
34
  from bluecellulab.cell.sonata_proxy import SonataProxy
35
- from bluecellulab.cell.serialized_sections import SerializedSections
36
35
  from bluecellulab.cell.template import NeuronTemplate, public_hoc_cell
37
36
  from bluecellulab.circuit.config.sections import Conditions
38
37
  from bluecellulab.circuit import EmodelProperties, SynapseProperty
@@ -42,7 +41,7 @@ from bluecellulab.exceptions import BluecellulabError
42
41
  from bluecellulab.importer import load_hoc_and_mod_files
43
42
  from bluecellulab.neuron_interpreter import eval_neuron
44
43
  from bluecellulab.rngsettings import RNGSettings
45
- from bluecellulab.stimuli import SynapseReplay
44
+ from bluecellulab.stimulus.circuit_stimulus_definitions import SynapseReplay
46
45
  from bluecellulab.synapse import SynapseFactory, Synapse
47
46
  from bluecellulab.synapse.synapse_types import SynapseID
48
47
  from bluecellulab.type_aliases import HocObjectType, NeuronSection
@@ -99,8 +98,6 @@ class Cell(InjectableMixin, PlottableMixin):
99
98
  # diameters of the loaded morph are wrong
100
99
  neuron.h.finitialize()
101
100
 
102
- self.cellname = neuron.h.secname(sec=self.soma).split(".")[0]
103
-
104
101
  if rng_settings is None:
105
102
  self.rng_settings = RNGSettings("Random123") # SONATA value
106
103
  else:
@@ -112,25 +109,17 @@ class Cell(InjectableMixin, PlottableMixin):
112
109
 
113
110
  self.ips: dict[SynapseID, HocObjectType] = {}
114
111
  self.syn_mini_netcons: dict[SynapseID, HocObjectType] = {}
115
- self.serialized: Optional[SerializedSections] = None
116
112
 
117
113
  # Be careful when removing this,
118
114
  # time recording needs this push
119
115
  self.soma.push()
120
116
  self.hocname = neuron.h.secname(sec=self.soma).split(".")[0]
121
- self.somatic = list(public_hoc_cell(self.cell).somatic)
122
- self.basal = list(public_hoc_cell(self.cell).basal) # dend is same as basal
123
- self.apical = list(public_hoc_cell(self.cell).apical)
124
- self.axonal = list(public_hoc_cell(self.cell).axonal)
125
- self.all = list(public_hoc_cell(self.cell).all)
126
117
  self.record_dt = record_dt
127
118
  self.add_recordings(['self.soma(0.5)._ref_v', 'neuron.h._ref_t'],
128
119
  dt=self.record_dt)
129
120
 
130
121
  self.delayed_weights = queue.PriorityQueue() # type: ignore
131
- self.secname_to_isec: dict[str, int] = {}
132
- self.secname_to_hsection: dict[str, HocObjectType] = {}
133
- self.secname_to_psection: dict[str, psection.PSection] = {}
122
+ self.psections, self.secname_to_psection = init_psections(public_hoc_cell(self.cell))
134
123
 
135
124
  self.emodel_properties = emodel_properties
136
125
  if template_format == 'v6':
@@ -153,12 +142,29 @@ class Cell(InjectableMixin, PlottableMixin):
153
142
  # Used to know when re_init_rng() can be executed
154
143
  self.is_made_passive = False
155
144
 
156
- self.psections: dict[int, psection.PSection] = {}
157
-
158
145
  neuron.h.pop_section() # Undoing soma push
159
- # self.init_psections()
160
146
  self.sonata_proxy: Optional[SonataProxy] = None
161
147
 
148
+ @property
149
+ def somatic(self) -> list[NeuronSection]:
150
+ return list(public_hoc_cell(self.cell).somatic)
151
+
152
+ @property
153
+ def basal(self) -> list[NeuronSection]:
154
+ return list(public_hoc_cell(self.cell).basal)
155
+
156
+ @property
157
+ def apical(self) -> list[NeuronSection]:
158
+ return list(public_hoc_cell(self.cell).apical)
159
+
160
+ @property
161
+ def axonal(self) -> list[NeuronSection]:
162
+ return list(public_hoc_cell(self.cell).axonal)
163
+
164
+ @property
165
+ def all(self) -> list[NeuronSection]:
166
+ return list(public_hoc_cell(self.cell).all)
167
+
162
168
  def __repr__(self) -> str:
163
169
  base_info = f"Cell Object: {super().__repr__()}"
164
170
  hoc_info = f"NEURON ID: {self.template_id}"
@@ -168,47 +174,6 @@ class Cell(InjectableMixin, PlottableMixin):
168
174
  """Connect this cell to a circuit via sonata proxy."""
169
175
  self.sonata_proxy = sonata_proxy
170
176
 
171
- def init_psections(self) -> None:
172
- """Initialize the psections list.
173
-
174
- This list contains the Python representation of the psections of
175
- this morphology.
176
- """
177
- for hsection in self.all:
178
- secname = neuron.h.secname(sec=hsection)
179
- self.secname_to_hsection[secname] = hsection
180
- self.secname_to_psection[secname] = psection.PSection(hsection)
181
-
182
- # section are not serialized yet, do it now
183
- if self.serialized is None:
184
- self.serialized = SerializedSections(public_hoc_cell(self.cell))
185
-
186
- for isec in self.serialized.isec2sec:
187
- hsection = self.get_hsection(isec)
188
- if hsection:
189
- secname = neuron.h.secname(sec=hsection)
190
- self.psections[isec] = self.secname_to_psection[secname]
191
- self.psections[isec].isec = isec
192
- self.secname_to_isec[secname] = isec
193
-
194
- # Set the parents and children of all the psections
195
- for psec in self.psections.values():
196
- hparent = psec.hparent
197
- if hparent:
198
- parentname = neuron.h.secname(sec=hparent)
199
- psec.pparent = self.get_psection(secname=parentname)
200
- else:
201
- psec.pparent = None
202
-
203
- for hchild in psec.hchildren:
204
- childname = neuron.h.secname(sec=hchild)
205
- pchild = self.get_psection(secname=childname)
206
- psec.add_pchild(pchild)
207
-
208
- def get_section_id(self, secname: str) -> int:
209
- """Returns the id of the section with name secname."""
210
- return self.secname_to_psection[secname].isec
211
-
212
177
  def re_init_rng(self, use_random123_stochkv: bool = False) -> None:
213
178
  """Reinitialize the random number generator for stochastic channels."""
214
179
 
@@ -233,44 +198,16 @@ class Cell(InjectableMixin, PlottableMixin):
233
198
  else:
234
199
  self.cell.re_init_rng()
235
200
 
236
- def get_psection(self, section_id=None, secname=None):
237
- """Return a python section with the specified section id or name.
238
-
239
- Parameters
240
- ----------
241
- section_id: int
242
- Return the PSection object based on section id
243
- secname: string
244
- Return the PSection object based on section name
245
-
246
- Returns
247
- -------
248
- psection: PSection
249
- PSection object of the specified section id or name
250
- """
251
- if section_id is not None:
201
+ def get_psection(self, section_id: int | str) -> PSection:
202
+ """Return a python section with the specified section id."""
203
+ if isinstance(section_id, int):
252
204
  return self.psections[section_id]
253
- elif secname is not None:
254
- return self.secname_to_psection[secname]
205
+ elif isinstance(section_id, str):
206
+ return self.secname_to_psection[section_id]
255
207
  else:
256
- raise Exception(
257
- "Cell: get_psection requires or a section_id or a secname")
258
-
259
- def get_hsection(self, section_id: int | float) -> NeuronSection:
260
- """Use the serialized object to find a hoc section from a section
261
- id."""
262
- section_id = int(section_id)
263
- # section are not serialized yet, do it now
264
- if self.serialized is None:
265
- self.serialized = SerializedSections(public_hoc_cell(self.cell))
266
-
267
- try:
268
- sec_ref = self.serialized.isec2sec[section_id]
269
- except IndexError as e:
270
- raise IndexError(
271
- f"bluecellulab get_hsection: section-id {section_id} not found in {self.morphology_path}"
272
- ) from e
273
- return sec_ref.sec
208
+ raise BluecellulabError(
209
+ f"Section id must be an int or a str, not {type(section_id)}"
210
+ )
274
211
 
275
212
  def make_passive(self) -> None:
276
213
  """Make the cell passive by deactivating all the active channels."""
@@ -551,7 +488,8 @@ class Cell(InjectableMixin, PlottableMixin):
551
488
 
552
489
  base_seed = self.rng_settings.base_seed
553
490
  weight = syn_description[SynapseProperty.G_SYNX]
554
- post_sec_id = syn_description[SynapseProperty.POST_SECTION_ID]
491
+ # numpy int to int
492
+ post_sec_id = int(syn_description[SynapseProperty.POST_SECTION_ID])
555
493
 
556
494
  location = SynapseFactory.determine_synapse_location(
557
495
  syn_description, self
@@ -572,7 +510,7 @@ class Cell(InjectableMixin, PlottableMixin):
572
510
  spont_minis_rate = inh_mini_frequency
573
511
 
574
512
  if spont_minis_rate is not None and spont_minis_rate > 0:
575
- sec = self.get_hsection(post_sec_id)
513
+ sec = self.get_psection(post_sec_id).hsection
576
514
  # add the *minis*: spontaneous synaptic events
577
515
  self.ips[synapse_id] = neuron.h.\
578
516
  InhPoissonStim(location, sec=sec)
@@ -12,7 +12,7 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
  """Contains injection functionality for the cell."""
15
-
15
+ from __future__ import annotations
16
16
  import math
17
17
  import warnings
18
18
  import logging
@@ -27,7 +27,7 @@ from bluecellulab.cell.stimuli_generator import (
27
27
  get_relative_shotnoise_params,
28
28
  )
29
29
  from bluecellulab.exceptions import BluecellulabError
30
- from bluecellulab.stimuli import (
30
+ from bluecellulab.stimulus.circuit_stimulus_definitions import (
31
31
  ClampMode,
32
32
  Hyperpolarizing,
33
33
  Noise,
@@ -36,7 +36,8 @@ from bluecellulab.stimuli import (
36
36
  RelativeOrnsteinUhlenbeck,
37
37
  RelativeShotNoise,
38
38
  )
39
- from bluecellulab.type_aliases import HocObjectType
39
+ from bluecellulab.stimulus.factory import StimulusFactory
40
+ from bluecellulab.type_aliases import NeuronSection
40
41
 
41
42
 
42
43
  logger = logging.getLogger(__name__)
@@ -69,36 +70,62 @@ class InjectableMixin:
69
70
  self.persistent.append(tstim)
70
71
  return tstim
71
72
 
72
- def add_step(self, start_time, stop_time, level, section=None, segx=0.5):
73
- """Add a step current injection."""
74
- if section is None:
75
- section = self.soma
76
-
77
- tstim = neuron.h.TStim(segx, sec=section)
78
- duration = stop_time - start_time
79
- tstim.pulse(start_time, duration, level)
80
- self.persistent.append(tstim)
81
- return tstim
73
+ def add_step(
74
+ self,
75
+ start_time: float,
76
+ stop_time: float,
77
+ level: float,
78
+ section: NeuronSection | None = None,
79
+ segx: float = 0.5,
80
+ dt: float = 0.025
81
+ ) -> tuple[np.ndarray, np.ndarray]:
82
+ """Add a step current injection.
82
83
 
83
- def add_ramp(self, start_time, stop_time, start_level, stop_level,
84
- section=None, segx=0.5):
85
- """Add a ramp current injection."""
86
- if section is None:
87
- section = self.soma
84
+ Args:
85
+ start_time: Start time of the step injection in seconds.
86
+ stop_time: Stop time of the step injection in seconds.
87
+ level: Current level to inject in nanoamperes (nA).
88
+ section: The section to inject current into.
89
+ Defaults to the soma section.
90
+ segx: The fractional location within the section to inject.
91
+ Defaults to 0.5 (center of the section).
92
+
93
+ Returns:
94
+ Tuple of time and current data.
95
+ """
96
+ stim = StimulusFactory(dt=dt).step(start_time, stop_time, level)
97
+ t_content, i_content = stim.time, stim.current
98
+ self.inject_current_waveform(t_content, i_content, section, segx)
99
+ return (t_content, i_content)
88
100
 
89
- tstim = neuron.h.TStim(segx, sec=section)
101
+ def add_ramp(
102
+ self,
103
+ start_time: float,
104
+ stop_time: float,
105
+ start_level: float,
106
+ stop_level: float,
107
+ section: NeuronSection | None = None,
108
+ segx: float = 0.5,
109
+ dt: float = 0.025
110
+ ) -> tuple[np.ndarray, np.ndarray]:
111
+ """Add a ramp current injection.
90
112
 
91
- tstim.ramp(
92
- 0.0,
93
- start_time,
94
- start_level,
95
- stop_level,
96
- stop_time - start_time,
97
- 0.0,
98
- 0.0)
113
+ Args:
114
+ start_time: Start time of the ramp injection in seconds.
115
+ stop_time: Stop time of the ramp injection in seconds.
116
+ start_level: Current level at the start of the ramp in nanoamperes (nA).
117
+ stop_level: Current level at the end of the ramp in nanoamperes (nA).
118
+ section: The section to inject current into (optional). Defaults to soma.
119
+ segx: The fractional location within the section to inject (optional).
120
+
121
+ Returns:
122
+ A tuple of numpy arrays containing time and current data.
123
+ """
124
+ stim = StimulusFactory(dt=dt).ramp(start_time, stop_time, start_level, stop_level)
125
+ t_content, i_content = stim.time, stim.current
126
+ self.inject_current_waveform(t_content, i_content, section, segx)
99
127
 
100
- self.persistent.append(tstim)
101
- return tstim
128
+ return t_content, i_content
102
129
 
103
130
  def add_voltage_clamp(
104
131
  self, stop_time, level, rs=None, section=None, segx=0.5,
@@ -395,32 +422,22 @@ class InjectableMixin:
395
422
  else:
396
423
  return self.inject_current_clamp_signal(section, segx, tvec, svec)
397
424
 
398
- def inject_current_waveform(self, t_content, i_content, section=None,
399
- segx=0.5):
400
- """Inject a custom current to the cell."""
401
- start_time = t_content[0]
402
- stop_time = t_content[-1]
403
- time = neuron.h.Vector()
404
- currents = neuron.h.Vector()
405
- time = time.from_python(t_content)
406
- currents = currents.from_python(i_content)
407
-
425
+ def inject_current_waveform(self, t_content, i_content, section=None, segx=0.5):
426
+ """Inject a custom current waveform into the cell."""
408
427
  if section is None:
409
428
  section = self.soma
429
+
430
+ time_vector = neuron.h.Vector().from_python(t_content)
431
+ current_vector = neuron.h.Vector().from_python(i_content)
432
+
410
433
  pulse = neuron.h.IClamp(segx, sec=section)
411
- self.persistent.append(pulse)
412
- self.persistent.append(time)
413
- self.persistent.append(currents)
414
- setattr(pulse, 'del', start_time)
415
- pulse.dur = stop_time - start_time
416
- currents.play(pulse._ref_amp, time)
417
- return currents
418
-
419
- @deprecated("Use inject_current_waveform instead.")
420
- def injectCurrentWaveform(self, t_content, i_content, section=None,
421
- segx=0.5):
422
- """Inject a current in the cell."""
423
- return self.inject_current_waveform(t_content, i_content, section, segx)
434
+ self.persistent.extend([pulse, time_vector, current_vector])
435
+
436
+ pulse.delay = t_content[0]
437
+ pulse.dur = t_content[-1] - t_content[0]
438
+ current_vector.play(pulse._ref_amp, time_vector)
439
+
440
+ return current_vector
424
441
 
425
442
  @deprecated("Use add_sin_current instead.")
426
443
  def addSineCurrentInject(self, start_time, stop_time, freq,
@@ -435,7 +452,7 @@ class InjectableMixin:
435
452
  t_content = np.arange(start_time, stop_time, dt)
436
453
  i_content = [amplitude * math.sin(freq * (x - start_time) * (
437
454
  2 * math.pi)) + mid_level for x in t_content]
438
- self.injectCurrentWaveform(t_content, i_content)
455
+ self.inject_current_waveform(t_content, i_content)
439
456
  return (t_content, i_content)
440
457
 
441
458
  def add_sin_current(self, amp, start_time, duration, frequency,
@@ -454,9 +471,9 @@ class InjectableMixin:
454
471
  tau: float,
455
472
  gmax: float,
456
473
  e: float,
457
- section: HocObjectType,
474
+ section: NeuronSection,
458
475
  segx=0.5,
459
- ) -> HocObjectType:
476
+ ) -> NeuronSection:
460
477
  """Add an AlphaSynapse NEURON point process stimulus to the cell."""
461
478
  syn = neuron.h.AlphaSynapse(segx, sec=section)
462
479
  syn.onset = onset
@@ -60,7 +60,6 @@ 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()
64
63
  cell_dendrogram = bluecellulab.Dendrogram(
65
64
  self.psections,
66
65
  variable=variable,
@@ -13,11 +13,11 @@
13
13
  # limitations under the License.
14
14
  """Module that allows morphology sections to be accessed from an array by
15
15
  index."""
16
-
16
+ from __future__ import annotations
17
17
  import logging
18
18
  import warnings
19
19
  import neuron
20
- from bluecellulab.type_aliases import HocObjectType
20
+ from bluecellulab.type_aliases import HocObjectType, NeuronSection
21
21
 
22
22
 
23
23
  logger = logging.getLogger(__name__)
@@ -27,7 +27,7 @@ warnings.filterwarnings("once", category=UserWarning, module=__name__)
27
27
  class SerializedSections:
28
28
 
29
29
  def __init__(self, cell: HocObjectType) -> None:
30
- self.isec2sec = {}
30
+ self.isec2sec: dict[int, NeuronSection] = {}
31
31
  n = cell.nSecAll
32
32
 
33
33
  for index, sec in enumerate(cell.all, start=1):
@@ -25,7 +25,7 @@ if BLUEPY_AVAILABLE:
25
25
  from bluepy.utils import open_utf8
26
26
 
27
27
  from bluecellulab.circuit.config.sections import Conditions, ConnectionOverrides
28
- from bluecellulab.stimuli import Stimulus
28
+ from bluecellulab.stimulus.circuit_stimulus_definitions import Stimulus
29
29
 
30
30
 
31
31
  class BluepySimulationConfig:
@@ -18,7 +18,7 @@ from typing import Optional, Protocol
18
18
 
19
19
 
20
20
  from bluecellulab.circuit.config.sections import Conditions, ConnectionOverrides
21
- from bluecellulab.stimuli import Stimulus
21
+ from bluecellulab.stimulus.circuit_stimulus_definitions import Stimulus
22
22
 
23
23
 
24
24
  class SimulationConfig(Protocol):
@@ -17,7 +17,7 @@ from pathlib import Path
17
17
  from typing import Optional
18
18
 
19
19
  from bluecellulab.circuit.config.sections import Conditions, ConnectionOverrides
20
- from bluecellulab.stimuli import Stimulus
20
+ from bluecellulab.stimulus.circuit_stimulus_definitions import Stimulus
21
21
 
22
22
  from bluepysnap import Simulation as SnapSimulation
23
23
 
@@ -12,8 +12,54 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
  """Class that represents a dendrogram window."""
15
-
15
+ from __future__ import annotations
16
16
  import numpy as np
17
+ import pylab
18
+
19
+ from bluecellulab.psection import PSection
20
+ from bluecellulab.psegment import PSegment
21
+
22
+
23
+ def setup_draw(psegments: list[PSegment], maxsegdiam: float, figure, x, y, variable=None, varbounds=None) -> None:
24
+ """Setup draw of psection."""
25
+ y_accum = 0.0
26
+ for psegment in psegments:
27
+ psegment.setupDraw(figure,
28
+ x + (maxsegdiam - psegment.diam) / 2,
29
+ y + y_accum,
30
+ variable=variable,
31
+ varbounds=varbounds)
32
+ y_accum += psegment.L
33
+
34
+
35
+ def draw_tree(psection: PSection, figure, x, y, variable=None, varbounds=None) -> None:
36
+ """Draw a dendritic tree."""
37
+ # Draw myself
38
+ setup_draw(
39
+ psection.psegments, psection.maxsegdiam, figure, x, y, variable=variable, varbounds=varbounds
40
+ )
41
+
42
+ # Draw children
43
+
44
+ # First child is a same x coordinate
45
+ new_x = x # + self.L + self.xSpacing
46
+
47
+ # Children drawn L + ySpacing heigher
48
+ new_y = y + psection.L + psection.ySpacing
49
+
50
+ for child in psection.pchildren:
51
+ draw_tree(child, figure, new_x, new_y, variable=variable, varbounds=varbounds)
52
+ pylab.plot(
53
+ [x + psection.diam / 2, new_x + child.diam / 2],
54
+ [y + psection.L, new_y], 'k')
55
+ # Prepare new_x for next child
56
+ new_x = new_x + child.tree_width()
57
+
58
+
59
+ def redraw_psection(psection: PSection) -> None:
60
+ """Redraw psection."""
61
+ for psegment in psection.psegments:
62
+ psegment.redraw()
17
63
 
18
64
 
19
65
  class Dendrogram:
@@ -21,7 +67,7 @@ class Dendrogram:
21
67
 
22
68
  def __init__(
23
69
  self,
24
- psections,
70
+ psections: list[PSection],
25
71
  variable=None,
26
72
  active=False,
27
73
  save_fig_path=None,
@@ -30,7 +76,6 @@ class Dendrogram:
30
76
  scale_bar_size=10.0,
31
77
  fig_title=None,
32
78
  fig_show=True):
33
- import pylab
34
79
 
35
80
  if interactive:
36
81
  pylab.ion()
@@ -48,15 +93,14 @@ class Dendrogram:
48
93
  self.psections = psections
49
94
  # neuron.h.finitialize()
50
95
 
51
- # self.hroot = neuron.h.SectionRef(sec=self.sections[0]).root
52
- self.proot = psections[0]
53
- # self.psections = [self.proot] + self.proot.getAllPDescendants()
96
+ self.proot: PSection = psections[0]
97
+ self.psections = [self.proot] + self.proot.all_descendants()
54
98
 
55
99
  xSpacing = self.proot.xSpacing
56
100
  ySpacing = self.proot.ySpacing
57
101
 
58
- max_y = self.proot.treeHeight() + self.proot.ySpacing + title_space
59
- max_x = self.proot.treeWidth() + self.proot.xSpacing + scale_bar_size
102
+ max_y = self.proot.tree_height() + self.proot.ySpacing + title_space
103
+ max_x = self.proot.tree_width() + self.proot.xSpacing + scale_bar_size
60
104
  pylab.xlim([0, max_x])
61
105
  pylab.ylim([0, max_y])
62
106
  pylab.gca().set_xticks([])
@@ -79,9 +123,9 @@ class Dendrogram:
79
123
  cbar.ax.set_yticklabels(["%.2e" % (
80
124
  varbounds[0]), "%.2e" % (varbounds[1])])
81
125
 
82
- self.proot.drawTree(self.dend_figure, self.proot.xSpacing,
83
- self.proot.ySpacing, variable=variable,
84
- varbounds=varbounds)
126
+ draw_tree(self.proot, self.dend_figure, self.proot.xSpacing,
127
+ self.proot.ySpacing, variable=variable,
128
+ varbounds=varbounds)
85
129
 
86
130
  if scale_bar:
87
131
  pylab.plot(
@@ -119,8 +163,10 @@ class Dendrogram:
119
163
 
120
164
  self.dend_figure.canvas.draw()
121
165
 
122
- for secid in self.psections:
123
- psections[secid].redraw()
166
+ for section in self.psections:
167
+ section_id = section.isec
168
+ if section_id is not None:
169
+ redraw_psection(psections[section_id])
124
170
 
125
171
  self.canvas = self.dend_figure.gca().figure.canvas
126
172
  self.ax = self.dend_figure.gca()
@@ -138,15 +184,13 @@ class Dendrogram:
138
184
  if not interactive and fig_show:
139
185
  pylab.show()
140
186
 
141
- def redraw(self):
187
+ def redraw(self) -> None:
142
188
  """Redraw the dendrogram."""
143
189
  if self.active:
144
190
  if not self.drawCount:
145
191
  for psection in self.psections:
146
- psection.redraw()
192
+ redraw_psection(psection)
147
193
  self.canvas.blit(self.ax.bbox)
148
194
  self.drawCount = 1
149
195
  else:
150
196
  self.drawCount = self.drawCount - 1
151
-
152
- return True
bluecellulab/psection.py CHANGED
@@ -12,23 +12,67 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
  """Represents a python version of NEURON Section (for drawing)."""
15
-
15
+ from __future__ import annotations
16
16
  import neuron
17
17
 
18
18
  import bluecellulab
19
+ from bluecellulab.cell.serialized_sections import SerializedSections
20
+ from bluecellulab.psegment import PSegment
21
+ from bluecellulab.type_aliases import HocObjectType, NeuronSection
22
+
23
+
24
+ def init_psections(
25
+ hoc_cell: HocObjectType,
26
+ ) -> tuple[dict[int, PSection], dict[str, PSection]]:
27
+ """Initialize the psections list.
28
+
29
+ This list contains the Python representation of the psections of
30
+ this morphology.
31
+ """
32
+ psections: dict[int, PSection] = {}
33
+ secname_to_psection: dict[str, PSection] = {}
34
+ for sec in hoc_cell.all:
35
+ secname = neuron.h.secname(sec=sec)
36
+ secname_to_psection[secname] = PSection(sec)
37
+
38
+ serial_sections = SerializedSections(hoc_cell)
39
+ for isec, val in serial_sections.isec2sec.items():
40
+ hsection: NeuronSection = val.sec
41
+ if hsection:
42
+ secname = neuron.h.secname(sec=hsection)
43
+ psections[isec] = secname_to_psection[secname]
44
+ psections[isec].isec = isec
45
+
46
+ # Set the parents and children of all the psections
47
+ for psec in psections.values():
48
+ hparent = psec.hparent
49
+ if hparent:
50
+ parentname = hparent.name()
51
+ psec.pparent = secname_to_psection[parentname]
52
+ else:
53
+ psec.pparent = None
54
+
55
+ for hchild in psec.hchildren:
56
+ childname = hchild.name()
57
+ if "myelin" in childname:
58
+ continue
59
+ pchild = secname_to_psection[childname]
60
+ psec.add_pchild(pchild)
61
+
62
+ return psections, secname_to_psection
19
63
 
20
64
 
21
65
  class PSection:
22
66
  """Class that represents a cell section."""
23
67
 
24
- def __init__(self, hsection, isec=None):
25
- self.L = hsection.L
26
- self.diam = hsection.diam
68
+ def __init__(self, hsection: NeuronSection, isec: int | None = None):
69
+ self.L: float = hsection.L
70
+ self.diam: float = hsection.diam
27
71
  self.hsection = hsection
28
- self.name = neuron.h.secname(sec=hsection)
29
- self.href = neuron.h.SectionRef(sec=self.hsection)
30
- self.pparent = None
31
- self.pchildren = []
72
+ self.name: str = neuron.h.secname(sec=hsection)
73
+ self.href: NeuronSection = neuron.h.SectionRef(sec=self.hsection)
74
+ self.pparent: PSection | None = None
75
+ self.pchildren: list[PSection] = []
32
76
  self.isec = isec
33
77
 
34
78
  if 'apic' in self.name:
@@ -46,24 +90,24 @@ class PSection:
46
90
  "PSection: Section of unknown type: %s" %
47
91
  self.name)
48
92
 
49
- self.psegments = []
50
- self.maxsegdiam = 0
93
+ self.psegments: list[PSegment] = []
94
+ self.maxsegdiam = 0.0
51
95
  for hsegment in hsection:
52
96
  # psegment = bluecellulab.PSegment(hsection(hsegment.x), self)
53
97
  psegment = bluecellulab.PSegment(hsegment, self)
54
98
  self.psegments.append(psegment)
55
99
  self.maxsegdiam = max(self.maxsegdiam, psegment.diam)
56
100
 
57
- self.xSpacing = 1
58
- self.ySpacing = 5
101
+ self.xSpacing = 1.0
102
+ self.ySpacing = 5.0
59
103
 
60
104
  @property
61
- def isLeaf(self):
105
+ def is_leaf(self) -> bool:
62
106
  """Return true if section is a leaf in the morphological structure."""
63
107
  return not self.hchildren
64
108
 
65
109
  @property
66
- def hparent(self):
110
+ def hparent(self) -> NeuronSection | None:
67
111
  """Return the hoc section of the parent."""
68
112
  if self.href.has_parent():
69
113
  return self.href.parent
@@ -71,37 +115,22 @@ class PSection:
71
115
  return None
72
116
 
73
117
  @property
74
- def hchildren(self):
118
+ def hchildren(self) -> list[NeuronSection]:
75
119
  """Return a list with the hoc sections of the children."""
76
120
  return [self.href.child[index] for index in
77
121
  range(0, int(self.href.nchild()))]
78
122
 
79
- def add_pchild(self, pchild):
123
+ def add_pchild(self, pchild: PSection) -> None:
80
124
  """Add a python represent of a child section."""
81
125
  self.pchildren.append(pchild)
82
-
83
- def setupDraw(self, figure, x, y, variable=None, varbounds=None):
84
- """Setup draw of psection."""
85
- y_accum = 0
86
- for psegment in self.psegments:
87
- psegment.setupDraw(figure,
88
- x + (self.maxsegdiam - psegment.diam) / 2,
89
- y + y_accum,
90
- variable=variable,
91
- varbounds=varbounds)
92
- y_accum += psegment.L
93
-
94
- def redraw(self):
95
- """Redraw psection."""
96
- for psegment in self.psegments:
97
- psegment.redraw()
126
+ pchild.pparent = self
98
127
 
99
128
  def getSectionVarBounds(self, variable):
100
129
  """Get bounds a variable in a section."""
101
130
  varmin = None
102
131
  varmax = None
103
132
  for psegment in self.psegments:
104
- value = psegment.getVariableValue(variable)
133
+ value = psegment.get_variable_value(variable)
105
134
  if value:
106
135
  varmin = min(value, varmin) if varmin else value
107
136
  varmax = max(value, varmax) if varmax else value
@@ -122,51 +151,23 @@ class PSection:
122
151
 
123
152
  return varbounds
124
153
 
125
- def getAllPDescendants(self):
154
+ def all_descendants(self) -> list[PSection]:
126
155
  """Return all the psection that are descendants of this psection."""
127
156
  pdescendants = list(self.pchildren)
128
157
  for child in self.pchildren:
129
- pdescendants += child.getAllPDescendants()
158
+ pdescendants += child.all_descendants()
130
159
  return pdescendants
131
160
 
132
- def drawTree(self, figure, x, y, variable=None, varbounds=None):
133
- """Draw a dendritic tree."""
134
- import pylab
135
-
136
- # Draw myself
137
- self.setupDraw(figure, x, y, variable=variable, varbounds=varbounds)
138
-
139
- # Draw children
140
-
141
- # First child is a same x coordinate
142
- new_x = x # + self.L + self.xSpacing
143
-
144
- # Children drawn L + ySpacing heigher
145
- new_y = y + self.L + self.ySpacing
146
-
147
- for child in self.pchildren:
148
- child.drawTree(
149
- figure, new_x, new_y, variable=variable, varbounds=varbounds)
150
- pylab.plot(
151
- [x + self.diam / 2, new_x + child.diam / 2],
152
- [y + self.L, new_y], 'k')
153
- # Prepare new_x for next child
154
- new_x = new_x + child.treeWidth()
155
-
156
- def treeWidth(self):
161
+ def tree_width(self) -> float:
157
162
  """Width of a dendritic tree."""
158
- if self.isLeaf:
159
- treeWidth = self.maxsegdiam + self.xSpacing
163
+ if self.is_leaf:
164
+ width = self.maxsegdiam + self.xSpacing
160
165
  else:
161
- treeWidth = sum(child.treeWidth() for child in self.pchildren)
162
- return max(self.diam + self.xSpacing, treeWidth)
166
+ width = sum(child.tree_width() for child in self.pchildren)
167
+ return max(self.diam + self.xSpacing, width)
163
168
 
164
- def treeHeight(self):
169
+ def tree_height(self) -> float:
165
170
  """Height of dendritic tree."""
166
171
  return self.L + self.ySpacing + \
167
- (max([child.treeHeight() for child in self.pchildren])
172
+ (max([child.tree_height() for child in self.pchildren])
168
173
  if self.pchildren else 0)
169
-
170
- def getHChildren(self):
171
- """All hoc children of a section."""
172
- return self.hchildren
bluecellulab/psegment.py CHANGED
@@ -61,7 +61,7 @@ class PSegment:
61
61
  def redraw(self):
62
62
  """Redraw a segment."""
63
63
  if self.plotvariable:
64
- plotvariable_value = self.getVariableValue(self.plotvariable)
64
+ plotvariable_value = self.get_variable_value(self.plotvariable)
65
65
  if plotvariable_value is not None:
66
66
  self.patch.set_facecolor(self.color_map(
67
67
  (plotvariable_value - self.varbounds[0]) /
@@ -71,7 +71,7 @@ class PSegment:
71
71
  self.patch.set_hatch("/")
72
72
  self.ax.draw_artist(self.patch)
73
73
 
74
- def getVariableValue(self, variable):
74
+ def get_variable_value(self, variable):
75
75
  """Get a variable value in a segment."""
76
76
  if variable == "v" or neuron.h.execute1(
77
77
  "{%s.%s(%f)}"
bluecellulab/ssim.py CHANGED
@@ -40,8 +40,8 @@ from bluecellulab.circuit.format import determine_circuit_format, CircuitFormat
40
40
  from bluecellulab.circuit.node_id import create_cell_id, create_cell_ids
41
41
  from bluecellulab.circuit.simulation_access import BluepySimulationAccess, SimulationAccess, SonataSimulationAccess, _sample_array
42
42
  from bluecellulab.importer import load_hoc_and_mod_files
43
- from bluecellulab.stimuli import Noise, OrnsteinUhlenbeck, RelativeOrnsteinUhlenbeck, RelativeShotNoise, ShotNoise
44
- import bluecellulab.stimuli as stimuli
43
+ from bluecellulab.stimulus.circuit_stimulus_definitions import Noise, OrnsteinUhlenbeck, RelativeOrnsteinUhlenbeck, RelativeShotNoise, ShotNoise
44
+ import bluecellulab.stimulus.circuit_stimulus_definitions as circuit_stimulus_definitions
45
45
  from bluecellulab.exceptions import BluecellulabError
46
46
  from bluecellulab.simulation import (
47
47
  set_global_condition_parameters,
@@ -298,40 +298,40 @@ class SSim:
298
298
  for cell_id in self.cells:
299
299
  if cell_id not in gids_of_target:
300
300
  continue
301
- if isinstance(stimulus, stimuli.Noise):
301
+ if isinstance(stimulus, circuit_stimulus_definitions.Noise):
302
302
  if add_noise_stimuli:
303
303
  self.cells[cell_id].add_replay_noise(
304
304
  stimulus, noisestim_count=noisestim_count)
305
- elif isinstance(stimulus, stimuli.Hyperpolarizing):
305
+ elif isinstance(stimulus, circuit_stimulus_definitions.Hyperpolarizing):
306
306
  if add_hyperpolarizing_stimuli:
307
307
  self.cells[cell_id].add_replay_hypamp(stimulus)
308
- elif isinstance(stimulus, stimuli.Pulse):
308
+ elif isinstance(stimulus, circuit_stimulus_definitions.Pulse):
309
309
  if add_pulse_stimuli:
310
310
  self.cells[cell_id].add_pulse(stimulus)
311
- elif isinstance(stimulus, stimuli.RelativeLinear):
311
+ elif isinstance(stimulus, circuit_stimulus_definitions.RelativeLinear):
312
312
  if add_relativelinear_stimuli:
313
313
  self.cells[cell_id].add_replay_relativelinear(stimulus)
314
- elif isinstance(stimulus, stimuli.ShotNoise):
314
+ elif isinstance(stimulus, circuit_stimulus_definitions.ShotNoise):
315
315
  if add_shotnoise_stimuli:
316
316
  self.cells[cell_id].add_replay_shotnoise(
317
317
  self.cells[cell_id].soma, 0.5, stimulus,
318
318
  shotnoise_stim_count=shotnoise_stim_count)
319
- elif isinstance(stimulus, stimuli.RelativeShotNoise):
319
+ elif isinstance(stimulus, circuit_stimulus_definitions.RelativeShotNoise):
320
320
  if add_shotnoise_stimuli:
321
321
  self.cells[cell_id].add_replay_relative_shotnoise(
322
322
  self.cells[cell_id].soma, 0.5, stimulus,
323
323
  shotnoise_stim_count=shotnoise_stim_count)
324
- elif isinstance(stimulus, stimuli.OrnsteinUhlenbeck):
324
+ elif isinstance(stimulus, circuit_stimulus_definitions.OrnsteinUhlenbeck):
325
325
  if add_ornstein_uhlenbeck_stimuli:
326
326
  self.cells[cell_id].add_ornstein_uhlenbeck(
327
327
  self.cells[cell_id].soma, 0.5, stimulus,
328
328
  stim_count=ornstein_uhlenbeck_stim_count)
329
- elif isinstance(stimulus, stimuli.RelativeOrnsteinUhlenbeck):
329
+ elif isinstance(stimulus, circuit_stimulus_definitions.RelativeOrnsteinUhlenbeck):
330
330
  if add_ornstein_uhlenbeck_stimuli:
331
331
  self.cells[cell_id].add_relative_ornstein_uhlenbeck(
332
332
  self.cells[cell_id].soma, 0.5, stimulus,
333
333
  stim_count=ornstein_uhlenbeck_stim_count)
334
- elif isinstance(stimulus, stimuli.SynapseReplay): # sonata only
334
+ elif isinstance(stimulus, circuit_stimulus_definitions.SynapseReplay): # sonata only
335
335
  if self.circuit_access.target_contains_cell(
336
336
  stimulus.target, cell_id
337
337
  ):
@@ -0,0 +1 @@
1
+ from .factory import StimulusFactory
@@ -11,7 +11,11 @@
11
11
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
+ """Defines the expected data structures associated with the stimulus defined in
15
+ simulation configs.
14
16
 
17
+ Run-time validates the data via Pydantic.
18
+ """
15
19
  from __future__ import annotations
16
20
 
17
21
  from enum import Enum
@@ -0,0 +1,254 @@
1
+ from __future__ import annotations
2
+ from abc import ABC, abstractmethod
3
+ import matplotlib.pyplot as plt
4
+ import numpy as np
5
+
6
+
7
+ class Stimulus(ABC):
8
+ def __init__(self, dt: float) -> None:
9
+ self.dt = dt
10
+
11
+ @property
12
+ @abstractmethod
13
+ def time(self) -> np.ndarray:
14
+ """Time values of the stimulus."""
15
+ ...
16
+
17
+ @property
18
+ @abstractmethod
19
+ def current(self) -> np.ndarray:
20
+ """Current values of the stimulus."""
21
+ ...
22
+
23
+ def __len__(self) -> int:
24
+ return len(self.time)
25
+
26
+ @property
27
+ def stimulus_time(self) -> float:
28
+ return len(self) * self.dt
29
+
30
+ def __repr__(self) -> str:
31
+ return f"{self.__class__.__name__}(dt={self.dt})"
32
+
33
+ def plot(self, ax=None, **kwargs):
34
+ if ax is None:
35
+ ax = plt.gca()
36
+ ax.plot(self.time, self.current, **kwargs)
37
+ ax.set_xlabel("Time (ms)")
38
+ ax.set_ylabel("Current (nA)")
39
+ ax.set_title(self.__class__.__name__)
40
+ return ax
41
+
42
+ def plot_during_simulation(self, duration: float, ax=None, **kwargs):
43
+ if ax is None:
44
+ ax = plt.gca()
45
+ # Create an array for the entire duration
46
+ full_time = np.arange(0, duration, self.dt)
47
+ full_current = np.zeros_like(full_time)
48
+
49
+ # Replace the corresponding values with self.time and self.current
50
+ indices = (self.time / self.dt).astype(int)
51
+ full_current[indices] = self.current
52
+
53
+ ax.plot(full_time, full_current, **kwargs)
54
+ ax.set_xlabel("Time (ms)")
55
+ ax.set_ylabel("Current (nA)")
56
+ ax.set_title(self.__class__.__name__)
57
+ ax.set_xlim(0, duration)
58
+ return ax
59
+
60
+ def __add__(self, other: Stimulus) -> CombinedStimulus:
61
+ """Override + operator to concatenate Stimulus objects."""
62
+ if self.dt != other.dt:
63
+ raise ValueError("Stimulus objects must have the same dt to be concatenated")
64
+ # shift other time
65
+ other_time = other.time + self.time[-1] + self.dt
66
+ combined_time = np.concatenate([self.time, other_time])
67
+ # Concatenate the current arrays
68
+ combined_current = np.concatenate([self.current, other.current])
69
+ return CombinedStimulus(self.dt, combined_time, combined_current)
70
+
71
+
72
+ class CombinedStimulus(Stimulus):
73
+ """Represents the Stimulus created by combining multiple stimuli."""
74
+ def __init__(self, dt: float, time: np.ndarray, current: np.ndarray) -> None:
75
+ super().__init__(dt)
76
+ self._time = time
77
+ self._current = current
78
+
79
+ @property
80
+ def time(self) -> np.ndarray:
81
+ return self._time
82
+
83
+ @property
84
+ def current(self) -> np.ndarray:
85
+ return self._current
86
+
87
+
88
+ class EmptyStimulus(Stimulus):
89
+ """Represents empty stimulus (all zeros) that has no impact on the cell.
90
+
91
+ This is required by some Stimuli that expect the cell to rest.
92
+ """
93
+ def __init__(self, dt: float, duration: float) -> None:
94
+ super().__init__(dt)
95
+ self.duration = duration
96
+
97
+ @property
98
+ def time(self) -> np.ndarray:
99
+ return np.arange(0.0, self.duration, self.dt)
100
+
101
+ @property
102
+ def current(self) -> np.ndarray:
103
+ return np.zeros_like(self.time)
104
+
105
+
106
+ class Step(Stimulus):
107
+ def __init__(self, dt: float, start: float, end: float, amplitude: float) -> None:
108
+ super().__init__(dt)
109
+ self.start = start
110
+ self.end = end
111
+ self.amplitude = amplitude
112
+
113
+ @classmethod
114
+ def threshold_based(
115
+ cls,
116
+ dt: float,
117
+ threshold_current: float,
118
+ threshold_percentage: float,
119
+ start: float,
120
+ end: float,
121
+ post_wait: float,
122
+ ) -> CombinedStimulus:
123
+ amplitude = threshold_current * threshold_percentage / 100
124
+ res = cls(dt, start, end, amplitude) + EmptyStimulus(dt, duration=post_wait)
125
+ return res
126
+
127
+ @property
128
+ def time(self) -> np.ndarray:
129
+ return np.arange(self.start, self.end, self.dt)
130
+
131
+ @property
132
+ def current(self) -> np.ndarray:
133
+ return np.full_like(self.time, self.amplitude)
134
+
135
+
136
+ class Ramp(Stimulus):
137
+ def __init__(
138
+ self,
139
+ dt: float,
140
+ start: float,
141
+ end: float,
142
+ amplitude_start: float,
143
+ amplitude_end: float,
144
+ ) -> None:
145
+ super().__init__(dt)
146
+ self.start = start
147
+ self.end = end
148
+ self.amplitude_start = amplitude_start
149
+ self.amplitude_end = amplitude_end
150
+
151
+ @property
152
+ def time(self) -> np.ndarray:
153
+ return np.arange(self.start, self.end, self.dt)
154
+
155
+ @property
156
+ def current(self) -> np.ndarray:
157
+ return np.linspace(self.amplitude_start, self.amplitude_end, len(self.time))
158
+
159
+
160
+ class StimulusFactory:
161
+ def __init__(self, dt: float):
162
+ self.dt = dt
163
+
164
+ def step(self, start: float, end: float, amplitude: float) -> Stimulus:
165
+ return Step(self.dt, start, end, amplitude)
166
+
167
+ def ramp(
168
+ self, start: float, end: float, amplitude_start: float, amplitude_end: float
169
+ ) -> Stimulus:
170
+ return Ramp(self.dt, start, end, amplitude_start, amplitude_end)
171
+
172
+ def ap_waveform(
173
+ self,
174
+ threshold_current: float,
175
+ threshold_percentage: float = 220.0,
176
+ start: float = 250.0,
177
+ end: float = 300.0,
178
+ post_wait: float = 250.0,
179
+ ) -> Stimulus:
180
+ """Returns the APWaveform Stimulus object, a type of Step stimulus.
181
+
182
+ Args:
183
+ threshold_current: The threshold current of the Cell.
184
+ threshold_percentage: Percentage of desired threshold_current amplification.
185
+ start: The start time of the step.
186
+ end: The end time of the step.
187
+ post_wait: The time to wait after the end of the step.
188
+ """
189
+ return Step.threshold_based(
190
+ self.dt, threshold_current, threshold_percentage, start, end, post_wait
191
+ )
192
+
193
+ def idrest(
194
+ self,
195
+ threshold_current: float,
196
+ threshold_percentage: float = 200.0,
197
+ start: float = 250.0,
198
+ end: float = 1600.0,
199
+ post_wait: float = 250.0,
200
+ ) -> Stimulus:
201
+ """Returns the IDRest Stimulus object, a type of Step stimulus.
202
+
203
+ Args:
204
+ threshold_current: The threshold current of the Cell.
205
+ threshold_percentage: Percentage of desired threshold_current amplification.
206
+ start: The start time of the step.
207
+ end: The end time of the step.
208
+ post_wait: The time to wait after the end of the step.
209
+ """
210
+ return Step.threshold_based(
211
+ self.dt, threshold_current, threshold_percentage, start, end, post_wait
212
+ )
213
+
214
+ def iv(
215
+ self,
216
+ threshold_current: float,
217
+ threshold_percentage: float = -40.0,
218
+ start: float = 250.0,
219
+ end: float = 3250.0,
220
+ post_wait: float = 250.0,
221
+ ) -> Stimulus:
222
+ """Returns the IV Stimulus object, a type of Step stimulus.
223
+
224
+ Args:
225
+ threshold_current: The threshold current of the Cell.
226
+ threshold_percentage: Percentage of desired threshold_current amplification.
227
+ start: The start time of the step.
228
+ end: The end time of the step.
229
+ post_wait: The time to wait after the end of the step.
230
+ """
231
+ return Step.threshold_based(
232
+ self.dt, threshold_current, threshold_percentage, start, end, post_wait
233
+ )
234
+
235
+ def fire_pattern(
236
+ self,
237
+ threshold_current: float,
238
+ threshold_percentage: float = 200.0,
239
+ start: float = 250.0,
240
+ end: float = 3850.0,
241
+ post_wait: float = 250.0,
242
+ ) -> Stimulus:
243
+ """Returns the FirePattern Stimulus object, a type of Step stimulus.
244
+
245
+ Args:
246
+ threshold_current: The threshold current of the Cell.
247
+ threshold_percentage: Percentage of desired threshold_current amplification.
248
+ start: The start time of the step.
249
+ end: The end time of the step.
250
+ post_wait: The time to wait after the end of the step.
251
+ """
252
+ return Step.threshold_based(
253
+ self.dt, threshold_current, threshold_percentage, start, end, post_wait
254
+ )
@@ -110,8 +110,8 @@ class SynapseFactory:
110
110
  @classmethod
111
111
  def determine_synapse_location(cls, syn_description: pd.Series, cell: bluecellulab.Cell) -> SynapseHocArgs:
112
112
  """Returns the location of the synapse."""
113
- isec = syn_description[SynapseProperty.POST_SECTION_ID]
114
- section = cell.get_hsection(isec)
113
+ isec = int(syn_description[SynapseProperty.POST_SECTION_ID]) # numpy int to int
114
+ section: NeuronSection = cell.get_psection(section_id=isec).hsection
115
115
 
116
116
  # old circuits don't have it, it needs to be computed via synlocation_to_segx
117
117
  if ("afferent_section_pos" in syn_description and
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: bluecellulab
3
- Version: 2.2.7
3
+ Version: 2.3.2
4
4
  Summary: The Pythonic Blue Brain simulator access
5
5
  Home-page: https://github.com/BlueBrain/BlueCelluLab
6
6
  Author: Blue Brain Project, EPFL
@@ -1,27 +1,26 @@
1
1
  bluecellulab/__init__.py,sha256=tbFwA146uSwNPO1HeVhqHNfxUBPM0VsuNk3NeMCq-Wc,620
2
2
  bluecellulab/connection.py,sha256=volV2YKtmqAF7MOEJar5ldF1ARAo7k2vF9MB1NXybUY,4640
3
- bluecellulab/dendrogram.py,sha256=5L-kPQEBuUl26pywK1EAwJWXj7k2BX6Re0QGAfguk7g,4890
3
+ bluecellulab/dendrogram.py,sha256=w0vvv0Q169DolTX1j9dAZIvHIl4H258gAjQ1xQaNiGk,6427
4
4
  bluecellulab/exceptions.py,sha256=KIxF7s_7gPVJ07TiQ-Z1D8de7ylV74gNMhzl0339CVM,2379
5
5
  bluecellulab/graph.py,sha256=ODiQy4xjRVxtNITXeXpYnqHas0wR7gZ_aXuDAF7jMq4,3419
6
6
  bluecellulab/importer.py,sha256=Sf8_aWqBCp98WfNkLMhNSp4UdurEneFF5leNYRlXjAw,2852
7
7
  bluecellulab/neuron_interpreter.py,sha256=hXig_u3T6JmEHbkV8ZblEZtX0kY80ate4VpRtANNFrM,2185
8
8
  bluecellulab/plotwindow.py,sha256=UVHzml-BB83m5Qr-YGkjR9kB-vSW8mM0Owh2j95yIaU,2721
9
- bluecellulab/psection.py,sha256=J93VuSXXjz2oB-Xp6DsC9nSgf5qhW6wPAFjJszBTfGY,6013
10
- bluecellulab/psegment.py,sha256=9ApDIrryl0IN5hluPe4tQfIWYLttlWjhZNWsaViVfwg,3121
9
+ bluecellulab/psection.py,sha256=EgAS8IS9DcYv2xOkNISgfg_CfRc0nDfRFjvgQhyi9eY,6328
10
+ bluecellulab/psegment.py,sha256=rBryDYHC_uDK9itfXXrFZ0DL9F6WgRICL0j5EHN56QM,3125
11
11
  bluecellulab/rngsettings.py,sha256=SLvkgM8K26Z-zTTN__CnFl_KjIJNuF4n_jzviyei5P4,3986
12
- bluecellulab/ssim.py,sha256=y09WEP5efGll7ddHMJi3qAXr5XJp4O-0cWbpIEbhF9E,33282
13
- bluecellulab/stimuli.py,sha256=u3AG3u0yYIvZzvFAwl1-8UPvEbq50mERVLVajX8JXdo,15540
12
+ bluecellulab/ssim.py,sha256=_MyUObeKIHhuT4cbB1uSD7izpZZHNRACiPlO9R1TNa8,33552
14
13
  bluecellulab/tools.py,sha256=s4NTE0DzK8z8oAy1BF1C2f19nBx-qBPuArz7e7hUTnw,24231
15
14
  bluecellulab/type_aliases.py,sha256=EMrunY-pIgZrsmetpAM8lA7tr0TFEzFoU5SX9sBuiOk,312
16
15
  bluecellulab/utils.py,sha256=GKZkRYI2LY08tsIkG95MGn7EfmV4pBrIAqfRQCW14fs,300
17
16
  bluecellulab/cell/__init__.py,sha256=Sbc0QOsJ8E7tSwf3q7fsXuE_SevBN6ZmoCVyyU5zfII,208
18
17
  bluecellulab/cell/cell_dict.py,sha256=PVmZsjhZ9jp3HC-8QmdFqp-crAcVMSVeLWujcOPLlpo,1346
19
- bluecellulab/cell/core.py,sha256=5Oi8DP96RrFv8jI1XZKi2zpwq5_ZAJtWMDfTWxtidYk,34145
20
- bluecellulab/cell/injector.py,sha256=zh4Pa-q0dmiB0zzb7-jZgGHEEVgk8_bC7tKKnYtq4v4,16843
21
- bluecellulab/cell/plotting.py,sha256=V63L_qEhlv8Zo9HdX1X27kIF0Lws9XQ4RLc-shV_xGc,4031
18
+ bluecellulab/cell/core.py,sha256=UtPjq_SYX8wOehQe7GqkbPxDWG1vIIJQ5-e3T_g29YU,31480
19
+ bluecellulab/cell/injector.py,sha256=4h11fObfbKhuvexE_AawCWiAalZIUjDsbVjqOeJ34Tw,17842
20
+ bluecellulab/cell/plotting.py,sha256=_hZs5oYG4vmJBVf05cJ2O_cVazi5Eap8OkL9BtIwjW8,4001
22
21
  bluecellulab/cell/random.py,sha256=FDby9BN4eJT27COwHP59bhDE2v-c6rdOKNFj3cYZTVY,1773
23
22
  bluecellulab/cell/section_distance.py,sha256=J8-oqgCHzRaJkpfjPUR6NFtXDhwbrXad9nDaTCKNkTU,3908
24
- bluecellulab/cell/serialized_sections.py,sha256=mbx0c8yzPMLTtJaxAxkki2BdUEOlozKdOmAS3gfPYG4,1539
23
+ bluecellulab/cell/serialized_sections.py,sha256=UQUecO07ChRZ7xHuDp-QAQRUpUiIwROzHxjZliP9gfQ,1614
25
24
  bluecellulab/cell/sonata_proxy.py,sha256=dLT9mLlGVpXxj2O2lXN0g7Sq4BwroPLVdPikR2yNMv4,1529
26
25
  bluecellulab/cell/stimuli_generator.py,sha256=cJwjNwsQeEBHLjuJIFv6VBSqd9IpmbR7CuSMyotCiWc,6320
27
26
  bluecellulab/cell/template.py,sha256=EGZDS7Lb7kScwh0LqKl7BcvA6r5UdNx1_HiYo7ALbPs,8015
@@ -40,10 +39,10 @@ bluecellulab/circuit/circuit_access/bluepy_circuit_access.py,sha256=j-DYHMBTbq1T
40
39
  bluecellulab/circuit/circuit_access/definition.py,sha256=SnKBFEgdXFG-QexYRrGSzVAd7bSj7NwN0IuTsjDOrDY,4435
41
40
  bluecellulab/circuit/circuit_access/sonata_circuit_access.py,sha256=P1ElK_VA10_JyyKbAnqzuAlduEYE2c_NSec2TZuix1U,10345
42
41
  bluecellulab/circuit/config/__init__.py,sha256=aaoJXRKBJzpxxREo9NxKc-_CCPmVeuR1mcViRXcLrC4,215
43
- bluecellulab/circuit/config/bluepy_simulation_config.py,sha256=YWXlmqTf0tgLgAc6z50xIFtIzYXIgPtQ8BH5Sd1KskQ,6944
44
- bluecellulab/circuit/config/definition.py,sha256=BvDUnsRQaW-6bF9WVlUrW_gRbmVZYE28LGEbcKXgbqo,2744
42
+ bluecellulab/circuit/config/bluepy_simulation_config.py,sha256=tUyHvzlxFWRxh8rBNvU0FdUqGqJR2G8OXifATQ9W7yw,6974
43
+ bluecellulab/circuit/config/definition.py,sha256=o0751Dd83f8TWGw95EAQ8coJrYGasdshrIrXViF5lzg,2774
45
44
  bluecellulab/circuit/config/sections.py,sha256=O1198JvusdOQBWgUeOZ5OhOupbHvvt3NtP9JfBWNbn0,7151
46
- bluecellulab/circuit/config/sonata_simulation_config.py,sha256=2yPRH-XuBwsaZZfg1fHMl9SgTG-GSYGN2KkJG06a1Ho,4799
45
+ bluecellulab/circuit/config/sonata_simulation_config.py,sha256=P0IKazCuNAG97xq2xLwHLbmr_lrNAqPsa6rXi-uDqb0,4829
47
46
  bluecellulab/hoc/Cell.hoc,sha256=z77qRQG_-afj-RLX0xN6V-K6Duq3bR7vmlDrGWPdh4E,16435
48
47
  bluecellulab/hoc/RNGSettings.hoc,sha256=wOtPxVMkCBTHsFLs5jPMKyverm1llXqaX8VKsAX43r8,1413
49
48
  bluecellulab/hoc/TDistFunc.hoc,sha256=WKX-anvL83xGuGPH9g1oIORB17UM4Pi3-iIXzKO-pUQ,2663
@@ -52,12 +51,15 @@ bluecellulab/hoc/fileUtils.hoc,sha256=LSM7BgyjYVqo2DGSOKvg4W8IIusbsL45JVYK0vgwit
52
51
  bluecellulab/simulation/__init__.py,sha256=G1md-6mqaYQkfZT8pmzqRi3WW1fMQCgkeaela2kX3OM,258
53
52
  bluecellulab/simulation/neuron_globals.py,sha256=PuAxrXbr734RP-5q6YkHpnOgzTVyo_8SYZux9HABlaI,3348
54
53
  bluecellulab/simulation/simulation.py,sha256=tM5Psl-w25CHA4hp2fqs3GcZ2HSjIbu_6iyOcs-1jd8,6439
54
+ bluecellulab/stimulus/__init__.py,sha256=DgIgVaSyR-URf3JZzvO6j-tjCerzvktuK-ep8pjMRPQ,37
55
+ bluecellulab/stimulus/circuit_stimulus_definitions.py,sha256=uij_s44uNdmMwMLGmTHSRgmp9K9B_vvHHshX6YPJNJU,15686
56
+ bluecellulab/stimulus/factory.py,sha256=AOby3Sp2g8BJsRccz3afazfCyysyWIgLtcliWlyeiu0,8097
55
57
  bluecellulab/synapse/__init__.py,sha256=RW8XoAMXOvK7OG1nHl_q8jSEKLj9ZN4oWf2nY9HAwuk,192
56
- bluecellulab/synapse/synapse_factory.py,sha256=qVx8LKVIqdwSXL7_5tuSx9vXy0_pi3RYjGHfpTUGYNA,6802
58
+ bluecellulab/synapse/synapse_factory.py,sha256=ZBRpjvIRyHc4hBfBvtLukLf7E2PjHhzwqGt9O4MBOTk,6862
57
59
  bluecellulab/synapse/synapse_types.py,sha256=wWVBfvPYF6g3dSoaXsjJ6QI929yWYrTh_OmauS5Y-Uk,17027
58
- bluecellulab-2.2.7.dist-info/AUTHORS.txt,sha256=EDs3H-2HXBojbma10psixk3C2rFiOCTIREi2ZAbXYNQ,179
59
- bluecellulab-2.2.7.dist-info/LICENSE,sha256=xOouu1gC1GGklDxkITlaVl60I9Ab860O-nZsFbWydvU,11749
60
- bluecellulab-2.2.7.dist-info/METADATA,sha256=5WwQnAeKV2wAUVZc0O16ZbZjiqwiOxhP2uJwl3BrwXg,6907
61
- bluecellulab-2.2.7.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
62
- bluecellulab-2.2.7.dist-info/top_level.txt,sha256=VSyEP8w9l3pXdRkyP_goeMwiNA8KWwitfAqUkveJkdQ,13
63
- bluecellulab-2.2.7.dist-info/RECORD,,
60
+ bluecellulab-2.3.2.dist-info/AUTHORS.txt,sha256=EDs3H-2HXBojbma10psixk3C2rFiOCTIREi2ZAbXYNQ,179
61
+ bluecellulab-2.3.2.dist-info/LICENSE,sha256=xOouu1gC1GGklDxkITlaVl60I9Ab860O-nZsFbWydvU,11749
62
+ bluecellulab-2.3.2.dist-info/METADATA,sha256=1uZpRUUBcPBBCbAiudS3Qg3anmrygJBuNtQ_kTEC6O8,6907
63
+ bluecellulab-2.3.2.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
64
+ bluecellulab-2.3.2.dist-info/top_level.txt,sha256=VSyEP8w9l3pXdRkyP_goeMwiNA8KWwitfAqUkveJkdQ,13
65
+ bluecellulab-2.3.2.dist-info/RECORD,,