bluecellulab 2.6.44__tar.gz → 2.6.45__tar.gz

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 (106) hide show
  1. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/PKG-INFO +1 -1
  2. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/cell/injector.py +9 -0
  3. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/circuit_simulation.py +13 -0
  4. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/stimulus/circuit_stimulus_definitions.py +17 -0
  5. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/stimulus/factory.py +67 -1
  6. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/stimulus/stimulus.py +103 -5
  7. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab.egg-info/PKG-INFO +1 -1
  8. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/.compile_mod.sh +0 -0
  9. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/.gitattributes +0 -0
  10. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/.github/dependabot.yml +0 -0
  11. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/.github/workflows/release.yml +0 -0
  12. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/.github/workflows/test.yml +0 -0
  13. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/.gitignore +0 -0
  14. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/.gitlab-ci.yml +0 -0
  15. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/.readthedocs.yml +0 -0
  16. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/.zenodo.json +0 -0
  17. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/AUTHORS.txt +0 -0
  18. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/CHANGELOG.rst +0 -0
  19. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/CITATION.cff +0 -0
  20. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/CONTRIBUTING.rst +0 -0
  21. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/LICENSE +0 -0
  22. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/MANIFEST.in +0 -0
  23. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/Makefile +0 -0
  24. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/README.rst +0 -0
  25. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/__init__.py +0 -0
  26. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/analysis/__init__.py +0 -0
  27. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/analysis/analysis.py +0 -0
  28. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/analysis/inject_sequence.py +0 -0
  29. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/analysis/plotting.py +0 -0
  30. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/cell/__init__.py +0 -0
  31. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/cell/ballstick/__init__.py +0 -0
  32. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/cell/ballstick/emodel.hoc +0 -0
  33. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/cell/ballstick/morphology.asc +0 -0
  34. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/cell/cell_dict.py +0 -0
  35. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/cell/core.py +0 -0
  36. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/cell/plotting.py +0 -0
  37. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/cell/random.py +0 -0
  38. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/cell/recording.py +0 -0
  39. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/cell/section_distance.py +0 -0
  40. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/cell/serialized_sections.py +0 -0
  41. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/cell/sonata_proxy.py +0 -0
  42. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/cell/stimuli_generator.py +0 -0
  43. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/cell/template.py +0 -0
  44. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/circuit/__init__.py +0 -0
  45. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/circuit/circuit_access/__init__.py +0 -0
  46. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/circuit/circuit_access/bluepy_circuit_access.py +0 -0
  47. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/circuit/circuit_access/definition.py +0 -0
  48. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/circuit/circuit_access/sonata_circuit_access.py +0 -0
  49. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/circuit/config/__init__.py +0 -0
  50. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/circuit/config/bluepy_simulation_config.py +0 -0
  51. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/circuit/config/definition.py +0 -0
  52. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/circuit/config/sections.py +0 -0
  53. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/circuit/config/sonata_simulation_config.py +0 -0
  54. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/circuit/format.py +0 -0
  55. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/circuit/iotools.py +0 -0
  56. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/circuit/node_id.py +0 -0
  57. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/circuit/simulation_access.py +0 -0
  58. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/circuit/synapse_properties.py +0 -0
  59. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/circuit/validate.py +0 -0
  60. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/connection.py +0 -0
  61. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/dendrogram.py +0 -0
  62. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/exceptions.py +0 -0
  63. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/graph.py +0 -0
  64. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/hoc/Cell.hoc +0 -0
  65. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/hoc/RNGSettings.hoc +0 -0
  66. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/hoc/TDistFunc.hoc +0 -0
  67. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/hoc/TStim.hoc +0 -0
  68. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/hoc/fileUtils.hoc +0 -0
  69. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/importer.py +0 -0
  70. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/neuron_interpreter.py +0 -0
  71. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/plotwindow.py +0 -0
  72. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/psection.py +0 -0
  73. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/psegment.py +0 -0
  74. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/rngsettings.py +0 -0
  75. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/simulation/__init__.py +0 -0
  76. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/simulation/neuron_globals.py +0 -0
  77. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/simulation/parallel.py +0 -0
  78. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/simulation/simulation.py +0 -0
  79. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/stimulus/__init__.py +0 -0
  80. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/synapse/__init__.py +0 -0
  81. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/synapse/synapse_factory.py +0 -0
  82. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/synapse/synapse_types.py +0 -0
  83. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/tools.py +0 -0
  84. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/type_aliases.py +0 -0
  85. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/utils.py +0 -0
  86. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab/verbosity.py +0 -0
  87. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab.egg-info/SOURCES.txt +0 -0
  88. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab.egg-info/dependency_links.txt +0 -0
  89. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab.egg-info/requires.txt +0 -0
  90. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/bluecellulab.egg-info/top_level.txt +0 -0
  91. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/docs/Makefile +0 -0
  92. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/docs/images/voltage-readme.png +0 -0
  93. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/docs/make.bat +0 -0
  94. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/docs/requirements_docs.txt +0 -0
  95. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/docs/source/_static/.gitkeep +0 -0
  96. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/docs/source/api.rst +0 -0
  97. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/docs/source/changelog.rst +0 -0
  98. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/docs/source/compiling-mechanisms.rst +0 -0
  99. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/docs/source/conf.py +0 -0
  100. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/docs/source/contributing.rst +0 -0
  101. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/docs/source/index.rst +0 -0
  102. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/docs/source/list_of_stim.rst +0 -0
  103. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/docs/source/logo/BlueCelluLabBanner.jpg +0 -0
  104. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/pyproject.toml +0 -0
  105. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/setup.cfg +0 -0
  106. {bluecellulab-2.6.44 → bluecellulab-2.6.45}/tox.ini +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: bluecellulab
3
- Version: 2.6.44
3
+ Version: 2.6.45
4
4
  Summary: Biologically detailed neural network simulations and analysis.
5
5
  Author: Blue Brain Project, EPFL
6
6
  License: Apache2.0
@@ -515,3 +515,12 @@ class InjectableMixin:
515
515
  syn.e = e
516
516
  self.persistent.append(syn) # type: ignore
517
517
  return syn
518
+
519
+ def add_sinusoidal(self, stimulus) -> TStim:
520
+ """Inject sinusoidal stimulus for replay."""
521
+ return self.add_sin_current(
522
+ stimulus.amp_start,
523
+ stimulus.delay,
524
+ stimulus.duration,
525
+ stimulus.frequency,
526
+ )
@@ -139,6 +139,7 @@ class CircuitSimulation:
139
139
  pre_spike_trains: None | dict[tuple[str, int], Iterable] | dict[int, Iterable] = None,
140
140
  add_shotnoise_stimuli: bool = False,
141
141
  add_ornstein_uhlenbeck_stimuli: bool = False,
142
+ add_sinusoidal_stimuli: bool = False,
142
143
  add_linear_stimuli: bool = False,
143
144
  ):
144
145
  """Instantiate a list of cells.
@@ -210,6 +211,11 @@ class CircuitSimulation:
210
211
  of the simulation config,
211
212
  Setting add_stimuli=True,
212
213
  will automatically set this option to True.
214
+ add_sinusoidal_stimuli : Process the 'sinusoidal' stimuli
215
+ blocks of the simulation config.
216
+ Setting add_stimuli=True,
217
+ will automatically set this option to
218
+ True.
213
219
  add_linear_stimuli : Process the 'linear' stimuli
214
220
  blocks of the simulation config.
215
221
  Setting add_stimuli=True,
@@ -271,6 +277,7 @@ class CircuitSimulation:
271
277
  add_hyperpolarizing_stimuli = True
272
278
  add_relativelinear_stimuli = True
273
279
  add_pulse_stimuli = True
280
+ add_sinusoidal_stimuli = True
274
281
  add_shotnoise_stimuli = True
275
282
  add_ornstein_uhlenbeck_stimuli = True
276
283
  add_linear_stimuli = True
@@ -281,6 +288,7 @@ class CircuitSimulation:
281
288
  add_relativelinear_stimuli or \
282
289
  add_shotnoise_stimuli or \
283
290
  add_ornstein_uhlenbeck_stimuli or \
291
+ add_sinusoidal_stimuli or \
284
292
  add_linear_stimuli:
285
293
  self._add_stimuli(
286
294
  add_noise_stimuli=add_noise_stimuli,
@@ -289,6 +297,7 @@ class CircuitSimulation:
289
297
  add_pulse_stimuli=add_pulse_stimuli,
290
298
  add_shotnoise_stimuli=add_shotnoise_stimuli,
291
299
  add_ornstein_uhlenbeck_stimuli=add_ornstein_uhlenbeck_stimuli,
300
+ add_sinusoidal_stimuli=add_sinusoidal_stimuli,
292
301
  add_linear_stimuli=add_linear_stimuli
293
302
  )
294
303
 
@@ -298,6 +307,7 @@ class CircuitSimulation:
298
307
  add_pulse_stimuli=False,
299
308
  add_shotnoise_stimuli=False,
300
309
  add_ornstein_uhlenbeck_stimuli=False,
310
+ add_sinusoidal_stimuli=False,
301
311
  add_linear_stimuli=False
302
312
  ):
303
313
  """Instantiate all the stimuli."""
@@ -352,6 +362,9 @@ class CircuitSimulation:
352
362
  self.cells[cell_id].add_relative_ornstein_uhlenbeck(
353
363
  self.cells[cell_id].soma, 0.5, stimulus,
354
364
  stim_count=ornstein_uhlenbeck_stim_count)
365
+ elif isinstance(stimulus, circuit_stimulus_definitions.Sinusoidal):
366
+ if add_sinusoidal_stimuli:
367
+ self.cells[cell_id].add_sinusoidal(stimulus)
355
368
  elif isinstance(stimulus, circuit_stimulus_definitions.SynapseReplay): # sonata only
356
369
  if self.circuit_access.target_contains_cell(
357
370
  stimulus.target, cell_id
@@ -49,6 +49,7 @@ class Pattern(Enum):
49
49
  RELATIVE_SHOT_NOISE = "relative_shot_noise"
50
50
  ORNSTEIN_UHLENBECK = "ornstein_uhlenbeck"
51
51
  RELATIVE_ORNSTEIN_UHLENBECK = "relative_ornstein_uhlenbeck"
52
+ SINUSOIDAL = "sinusoidal"
52
53
 
53
54
  @classmethod
54
55
  def from_blueconfig(cls, pattern: str) -> Pattern:
@@ -95,6 +96,8 @@ class Pattern(Enum):
95
96
  return Pattern.ORNSTEIN_UHLENBECK
96
97
  elif pattern == "relative_ornstein_uhlenbeck":
97
98
  return Pattern.RELATIVE_ORNSTEIN_UHLENBECK
99
+ elif pattern == "sinusoidal":
100
+ return Pattern.SINUSOIDAL
98
101
  else:
99
102
  raise ValueError(f"Unknown pattern {pattern}")
100
103
 
@@ -313,6 +316,14 @@ class Stimulus:
313
316
  mode=ClampMode(stimulus_entry.get("input_type", "current_clamp").lower()),
314
317
  reversal=stimulus_entry.get("reversal", 0.0)
315
318
  )
319
+ elif pattern == Pattern.SINUSOIDAL:
320
+ return Sinusoidal(
321
+ target=stimulus_entry["node_set"],
322
+ delay=stimulus_entry["delay"],
323
+ duration=stimulus_entry["duration"],
324
+ amp_start=stimulus_entry["amp_start"],
325
+ frequency=stimulus_entry["frequency"],
326
+ )
316
327
  else:
317
328
  raise ValueError(f"Unknown pattern {pattern}")
318
329
 
@@ -436,3 +447,9 @@ class RelativeOrnsteinUhlenbeck(Stimulus):
436
447
  seed: Optional[int] = None
437
448
  mode: ClampMode = ClampMode.CURRENT
438
449
  reversal: float = 0.0
450
+
451
+
452
+ @dataclass(frozen=True, config=dict(extra="forbid"))
453
+ class Sinusoidal(Stimulus):
454
+ amp_start: float
455
+ frequency: float
@@ -16,7 +16,7 @@
16
16
  from __future__ import annotations
17
17
  from typing import Optional
18
18
  import logging
19
- from bluecellulab.stimulus.stimulus import DelayedZap, Empty, Ramp, Slope, Step, StepNoise, Stimulus, OrnsteinUhlenbeck, ShotNoise
19
+ from bluecellulab.stimulus.stimulus import DelayedZap, Empty, Ramp, Slope, Step, StepNoise, Stimulus, OrnsteinUhlenbeck, ShotNoise, Sinusoidal
20
20
  from bluecellulab.stimulus.circuit_stimulus_definitions import Stimulus as CircuitStimulus
21
21
 
22
22
  logger = logging.getLogger(__name__)
@@ -376,6 +376,72 @@ class StimulusFactory:
376
376
 
377
377
  raise TypeError("You have to give either threshold_current or amplitude")
378
378
 
379
+ def sinusoidal(
380
+ self,
381
+ pre_delay: float,
382
+ post_delay: float,
383
+ duration: float,
384
+ frequency: float,
385
+ amplitude: Optional[float] = None,
386
+ amplitude_percent: Optional[float] = None,
387
+ threshold_current: Optional[float] = None,
388
+ dt: float = 0.025,
389
+ ) -> Stimulus:
390
+ """Creates a Sinusoidal stimulus (factory-compatible).
391
+
392
+ Args:
393
+ pre_delay: Delay before the sinusoidal stimulus starts (ms).
394
+ post_delay: Delay after the stimulus ends (ms).
395
+ duration: Duration of the stimulus (ms).
396
+ frequency: Frequency of oscillation (Hz).
397
+ amplitude: Absolute amplitude (nA). Used if provided.
398
+ amplitude_percent: Amplitude as a percentage of threshold current.
399
+ threshold_current: Reference threshold current for percentage-based calculation.
400
+ dt: Time step of the stimulus (ms).
401
+
402
+ Returns:
403
+ A `Stimulus` object (Sinusoidal) that can be plotted and injected.
404
+
405
+ Notes:
406
+ - If `amplitude` is provided, `amplitude_percent` is ignored.
407
+ - If `threshold_current` is not provided, threshold-based parameters cannot be used.
408
+ """
409
+ is_amplitude_based = amplitude is not None
410
+ is_threshold_based = (
411
+ threshold_current is not None
412
+ and threshold_current != 0
413
+ and amplitude_percent is not None
414
+ )
415
+
416
+ if is_amplitude_based:
417
+ if is_threshold_based:
418
+ logger.info(
419
+ "amplitude, threshold_current, and amplitude_percent are all set in Sinusoidal."
420
+ " Using absolute amplitude and ignoring threshold-based parameters."
421
+ )
422
+
423
+ return Sinusoidal.amplitude_based(
424
+ dt=dt,
425
+ pre_delay=pre_delay,
426
+ post_delay=post_delay,
427
+ duration=duration,
428
+ frequency=frequency,
429
+ amplitude=amplitude, # type: ignore[arg-type]
430
+ )
431
+
432
+ if is_threshold_based:
433
+ return Sinusoidal.threshold_based(
434
+ dt=dt,
435
+ pre_delay=pre_delay,
436
+ post_delay=post_delay,
437
+ duration=duration,
438
+ frequency=frequency,
439
+ amplitude_percent=amplitude_percent, # type: ignore[arg-type]
440
+ threshold_current=threshold_current, # type: ignore[arg-type]
441
+ )
442
+
443
+ raise TypeError("You have to provide either `amplitude` or `threshold_current` with `amplitude_percent`.")
444
+
379
445
  def ornstein_uhlenbeck(
380
446
  self,
381
447
  pre_delay: float,
@@ -18,6 +18,7 @@ from abc import ABC, abstractmethod
18
18
  from typing import Optional
19
19
  import logging
20
20
  import matplotlib.pyplot as plt
21
+ import neuron
21
22
  import numpy as np
22
23
  from bluecellulab.cell.stimuli_generator import get_relative_shotnoise_params
23
24
  from bluecellulab.exceptions import BluecellulabError
@@ -57,7 +58,6 @@ class Stimulus(ABC):
57
58
  ax.plot(self.time, self.current, **kwargs)
58
59
  ax.set_xlabel("Time (ms)")
59
60
  ax.set_ylabel("Current (nA)")
60
- ax.set_title(self.__class__.__name__)
61
61
  return ax
62
62
 
63
63
  def __add__(self, other: Stimulus) -> CombinedStimulus:
@@ -203,7 +203,6 @@ class OUProcess(Stimulus):
203
203
  """Generates an Ornstein-Uhlenbeck noise signal."""
204
204
  from bluecellulab.cell.stimuli_generator import gen_ornstein_uhlenbeck
205
205
  from bluecellulab.rngsettings import RNGSettings
206
- import neuron
207
206
 
208
207
  rng_settings = RNGSettings.get_instance()
209
208
  rng = neuron.h.Random()
@@ -251,7 +250,6 @@ class ShotNoiseProcess(Stimulus):
251
250
  """Generates the shot noise time and current vectors."""
252
251
  from bluecellulab.cell.stimuli_generator import gen_shotnoise_signal
253
252
  from bluecellulab.rngsettings import RNGSettings
254
- import neuron
255
253
 
256
254
  rng_settings = RNGSettings.get_instance()
257
255
  rng = neuron.h.Random()
@@ -310,12 +308,11 @@ class StepNoiseProcess(Stimulus):
310
308
  def _generate_step_noise(self):
311
309
  """Generates the step noise time and current vectors using NEURON’s
312
310
  random generator."""
313
- from neuron import h
314
311
  from bluecellulab.rngsettings import RNGSettings
315
312
 
316
313
  # Get NEURON RNG settings
317
314
  rng_settings = RNGSettings.get_instance()
318
- rng = h.Random()
315
+ rng = neuron.h.Random()
319
316
 
320
317
  if rng_settings.mode == "Random123":
321
318
  seed1, seed2, seed3 = 2997, 19216, self.seed if self.seed else 123
@@ -341,6 +338,37 @@ class StepNoiseProcess(Stimulus):
341
338
  return np.array(time_values), np.array(current_values)
342
339
 
343
340
 
341
+ class SinusoidalWave(Stimulus):
342
+ """Generates a sinusoidal current wave."""
343
+
344
+ def __init__(self, dt: float, duration: float, amplitude: float, frequency: float):
345
+ super().__init__(dt)
346
+ self.duration = duration
347
+ self.amplitude = amplitude
348
+ self.frequency = frequency
349
+
350
+ self._time, self._current = self._generate_sinusoidal_signal()
351
+
352
+ @property
353
+ def time(self) -> np.ndarray:
354
+ return self._time
355
+
356
+ @property
357
+ def current(self) -> np.ndarray:
358
+ return self._current
359
+
360
+ def _generate_sinusoidal_signal(self):
361
+ """Generate the sinusoidal waveform."""
362
+ tvec = neuron.h.Vector()
363
+ tvec.indgen(0.0, self.duration, self.dt) # Time points using NEURON
364
+
365
+ stim = neuron.h.Vector(len(tvec))
366
+ stim.sin(self.frequency, 0.0, self.dt) # Generate sinusoidal wave using NEURON
367
+ stim.mul(self.amplitude) # Scale by amplitude
368
+
369
+ return np.array(tvec.to_python()), np.array(stim.to_python())
370
+
371
+
344
372
  class Step(Stimulus):
345
373
 
346
374
  def __init__(self):
@@ -780,3 +808,73 @@ class StepNoise(Stimulus):
780
808
  sigma=sigma,
781
809
  seed=seed,
782
810
  )
811
+
812
+
813
+ class Sinusoidal(Stimulus):
814
+ """Factory-compatible Sinusoidal Stimulus."""
815
+
816
+ def __init__(self):
817
+ """Prevents direct instantiation."""
818
+ raise NotImplementedError(
819
+ "This class cannot be instantiated directly. "
820
+ "Please use 'amplitude_based' or 'threshold_based' methods."
821
+ )
822
+
823
+ @classmethod
824
+ def amplitude_based(
825
+ cls,
826
+ dt: float,
827
+ pre_delay: float,
828
+ duration: float,
829
+ post_delay: float,
830
+ amplitude: float,
831
+ frequency: float,
832
+ ) -> CombinedStimulus:
833
+ """Creates a sinusoidal stimulus with a specified amplitude.
834
+
835
+ Args:
836
+ dt: Time step of the stimulus.
837
+ pre_delay: Delay before the sinusoidal wave starts.
838
+ duration: Duration of the sinusoidal signal.
839
+ post_delay: Delay after the wave ends.
840
+ amplitude: Amplitude of the sinusoidal wave.
841
+ frequency: Frequency of the wave in Hz.
842
+ """
843
+ return (
844
+ Empty(dt, duration=pre_delay)
845
+ + SinusoidalWave(dt, duration, amplitude, frequency)
846
+ + Empty(dt, duration=post_delay)
847
+ )
848
+
849
+ @classmethod
850
+ def threshold_based(
851
+ cls,
852
+ dt: float,
853
+ pre_delay: float,
854
+ duration: float,
855
+ post_delay: float,
856
+ frequency: float,
857
+ threshold_current: float,
858
+ amplitude_percent: float,
859
+ ) -> CombinedStimulus:
860
+ """Creates a sinusoidal stimulus relative to the threshold current.
861
+
862
+ Args:
863
+ dt: Time step of the stimulus.
864
+ pre_delay: Delay before the sinusoidal wave starts.
865
+ duration: Duration of the sinusoidal signal.
866
+ post_delay: Delay after the wave ends.
867
+ frequency: Frequency of the wave in Hz.
868
+ threshold_current: Baseline threshold current.
869
+ amplitude_percent: Amplitude as a percentage of the threshold current.
870
+ """
871
+ amplitude = (amplitude_percent / 100) * threshold_current
872
+
873
+ return cls.amplitude_based(
874
+ dt,
875
+ pre_delay=pre_delay,
876
+ duration=duration,
877
+ post_delay=post_delay,
878
+ amplitude=amplitude,
879
+ frequency=frequency,
880
+ )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: bluecellulab
3
- Version: 2.6.44
3
+ Version: 2.6.45
4
4
  Summary: Biologically detailed neural network simulations and analysis.
5
5
  Author: Blue Brain Project, EPFL
6
6
  License: Apache2.0
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes