bluecellulab 2.5.0__py3-none-any.whl → 2.6.38__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of bluecellulab might be problematic. Click here for more details.

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