bluecellulab 2.6.45__py3-none-any.whl → 2.6.47__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.

@@ -16,8 +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, Sinusoidal
20
- from bluecellulab.stimulus.circuit_stimulus_definitions import Stimulus as CircuitStimulus
19
+ from bluecellulab.stimulus.stimulus import DelayedZap, Empty, Ramp, Slope, Step, StepNoise, Stimulus, OrnsteinUhlenbeck, ShotNoise, Sinusoidal, Pulse
21
20
 
22
21
  logger = logging.getLogger(__name__)
23
22
 
@@ -678,6 +677,38 @@ class StimulusFactory:
678
677
 
679
678
  raise TypeError("You must provide either `mean` and `sigma`, or `threshold_current` and `mean_percent` and `sigma_percent` with percentage values.")
680
679
 
681
- def from_sonata(cls, circuit_stimulus: CircuitStimulus):
682
- """Convert a SONATA stimulus into a factory-based stimulus."""
683
- raise ValueError(f"Unsupported circuit stimulus type: {type(circuit_stimulus)}")
680
+ def pulse(
681
+ self,
682
+ pre_delay: float,
683
+ duration: float,
684
+ post_delay: float,
685
+ frequency: float,
686
+ width: float,
687
+ threshold_current: Optional[float] = None,
688
+ threshold_percentage: Optional[float] = None,
689
+ amplitude: Optional[float] = None,
690
+ ) -> Stimulus:
691
+ """Creates a pulse stimulus.
692
+
693
+ Args:
694
+ threshold_current: The threshold current of the Cell.
695
+ threshold_percentage: Percentage of desired threshold_current amplification.
696
+ amplitude: Raw amplitude of input current.
697
+ pre_delay: Delay before the first pulse (ms).
698
+ duration: Duration of the pulse train (ms).
699
+ post_delay: Delay after the last pulse (ms).
700
+ frequency: Frequency of the pulses (Hz).
701
+ width: Width of each pulse (ms).
702
+ """
703
+ if amplitude is not None:
704
+ if threshold_current is not None and threshold_current != 0 and threshold_percentage is not None:
705
+ logger.info(
706
+ "amplitude, threshold_current and threshold_percentage are all set in pulse."
707
+ " Will only keep amplitude value."
708
+ )
709
+ return Pulse.amplitude_based(self.dt, pre_delay, duration, post_delay, amplitude, frequency, width)
710
+
711
+ if threshold_current is not None and threshold_current != 0 and threshold_percentage is not None:
712
+ return Pulse.threshold_based(self.dt, pre_delay, duration, post_delay, threshold_current, threshold_percentage, frequency, width)
713
+
714
+ raise TypeError("You have to give either threshold_current or amplitude")
@@ -369,6 +369,41 @@ class SinusoidalWave(Stimulus):
369
369
  return np.array(tvec.to_python()), np.array(stim.to_python())
370
370
 
371
371
 
372
+ class PulseTrain(Stimulus):
373
+ """Generates a pulse train signal."""
374
+
375
+ def __init__(self, dt: float, duration: float, amplitude: float, frequency: float, width: float):
376
+ super().__init__(dt)
377
+ self.duration = duration
378
+ self.amplitude = amplitude
379
+ self.frequency = frequency
380
+ self.width = width
381
+
382
+ self._time, self._current = self._generate_pulse_train()
383
+
384
+ @property
385
+ def time(self) -> np.ndarray:
386
+ return self._time
387
+
388
+ @property
389
+ def current(self) -> np.ndarray:
390
+ return self._current
391
+
392
+ def _generate_pulse_train(self):
393
+ total_duration = self.duration
394
+ time_steps = int(total_duration / self.dt)
395
+ time = np.linspace(0, total_duration, time_steps)
396
+ current = np.zeros_like(time)
397
+
398
+ start_time = 0
399
+ while start_time + self.width < self.duration:
400
+ pulse_indices = (time >= start_time) & (time < start_time + self.width)
401
+ current[pulse_indices] = self.amplitude
402
+ start_time += 1000.0 / self.frequency
403
+
404
+ return time, current
405
+
406
+
372
407
  class Step(Stimulus):
373
408
 
374
409
  def __init__(self):
@@ -878,3 +913,34 @@ class Sinusoidal(Stimulus):
878
913
  amplitude=amplitude,
879
914
  frequency=frequency,
880
915
  )
916
+
917
+
918
+ class Pulse(Stimulus):
919
+ """Factory-compatible Pulse Stimulus."""
920
+
921
+ def __init__(self):
922
+ """Prevents direct instantiation of the class."""
923
+ raise NotImplementedError(
924
+ "This class cannot be instantiated directly. "
925
+ "Please use 'amplitude_based' or 'threshold_based' methods."
926
+ )
927
+
928
+ @classmethod
929
+ def amplitude_based(
930
+ cls, dt: float, pre_delay: float, duration: float, post_delay: float, amplitude: float, frequency: float, width: float
931
+ ) -> CombinedStimulus:
932
+ """Creates a Pulse stimulus from given time events and amplitude."""
933
+ return (
934
+ Empty(dt, duration=pre_delay)
935
+ + PulseTrain(dt, duration, amplitude, frequency, width)
936
+ + Empty(dt, duration=post_delay)
937
+ )
938
+
939
+ @classmethod
940
+ def threshold_based(
941
+ cls, dt: float, pre_delay: float, duration: float, post_delay: float, threshold_current: float, threshold_percentage: float,
942
+ frequency: float, width: float
943
+ ) -> CombinedStimulus:
944
+ """Creates a Pulse stimulus with respect to the threshold current."""
945
+ amplitude = threshold_current * (threshold_percentage / 100)
946
+ return cls.amplitude_based(dt, pre_delay, duration, post_delay, amplitude, frequency, width)
bluecellulab/tools.py CHANGED
@@ -268,7 +268,8 @@ def detect_spike_step(
268
268
  inj_stop: float,
269
269
  step_level: float,
270
270
  section: str = "soma[0]",
271
- segx: float = 0.5
271
+ segx: float = 0.5,
272
+ step_thresh: float = -20.
272
273
  ) -> bool:
273
274
  """Detect if there is a spike at a certain step level."""
274
275
  with IsolatedProcess() as runner:
@@ -284,7 +285,8 @@ def detect_spike_step(
284
285
  inj_stop,
285
286
  step_level,
286
287
  section,
287
- segx
288
+ segx,
289
+ step_thresh
288
290
  ],
289
291
  )
290
292
  return spike_detected
@@ -300,7 +302,8 @@ def detect_spike_step_subprocess(
300
302
  inj_stop: float,
301
303
  step_level: float,
302
304
  section: str = "soma[0]",
303
- segx: float = 0.5
305
+ segx: float = 0.5,
306
+ step_thresh: float = -20.
304
307
  ) -> bool:
305
308
  """Detect if there is a spike at a certain step level."""
306
309
  cell = bluecellulab.Cell(
@@ -321,19 +324,19 @@ def detect_spike_step_subprocess(
321
324
  time = cell.get_time()
322
325
  voltage = cell.get_voltage_recording(section=neuron_section, segx=segx)
323
326
  voltage_step = voltage[np.where((time > inj_start) & (time < inj_stop))]
324
- spike_detected = detect_spike(voltage_step)
327
+ spike_detected = detect_spike(voltage_step, step_thresh)
325
328
 
326
329
  cell.delete()
327
330
 
328
331
  return spike_detected
329
332
 
330
333
 
331
- def detect_spike(voltage: np.ndarray) -> bool:
334
+ def detect_spike(voltage: np.ndarray, step_thresh: float = -20.) -> bool:
332
335
  """Detect if there is a spike in the voltage trace."""
333
336
  if len(voltage) == 0:
334
337
  return False
335
338
  else:
336
- return bool(np.max(voltage) > -20) # bool not np.bool_
339
+ return bool(np.max(voltage) > step_thresh) # bool not np.bool_
337
340
 
338
341
 
339
342
  def search_threshold_current(
@@ -348,7 +351,8 @@ def search_threshold_current(
348
351
  max_current: float,
349
352
  current_precision: float = 0.01,
350
353
  section: str = "soma[0]",
351
- segx: float = 0.5
354
+ segx: float = 0.5,
355
+ step_thresh: float = -20.
352
356
  ):
353
357
  """Search current necessary to reach threshold."""
354
358
  if abs(max_current - min_current) < current_precision:
@@ -359,7 +363,7 @@ def search_threshold_current(
359
363
  spike_detected = detect_spike_step(
360
364
  template_name, morphology_path, template_format, emodel_properties,
361
365
  hyp_level, inj_start, inj_stop, med_current,
362
- section=section, segx=segx
366
+ section=section, segx=segx, step_thresh=step_thresh
363
367
  )
364
368
  logger.info("Spike threshold detection at: %f nA" % med_current)
365
369
 
@@ -369,14 +373,16 @@ def search_threshold_current(
369
373
  hyp_level, inj_start, inj_stop,
370
374
  min_current, med_current,
371
375
  current_precision,
372
- section=section, segx=segx)
376
+ section=section, segx=segx,
377
+ step_thresh=step_thresh)
373
378
  else:
374
379
  return search_threshold_current(template_name, morphology_path,
375
380
  template_format, emodel_properties,
376
381
  hyp_level, inj_start, inj_stop,
377
382
  med_current, max_current,
378
383
  current_precision,
379
- section=section, segx=segx)
384
+ section=section, segx=segx,
385
+ step_thresh=step_thresh)
380
386
 
381
387
 
382
388
  def check_empty_topology() -> bool:
@@ -435,7 +441,8 @@ def calculate_rheobase(cell: Cell,
435
441
  threshold_search_stim_start: float = 300.0,
436
442
  threshold_search_stim_stop: float = 1000.0,
437
443
  section: str = "soma[0]",
438
- segx: float = 0.5) -> float:
444
+ segx: float = 0.5,
445
+ step_thresh: float = -20.) -> float:
439
446
  """Calculate the rheobase by first computing the upper bound threshold
440
447
  current.
441
448
 
@@ -474,7 +481,8 @@ def calculate_rheobase(cell: Cell,
474
481
  max_current=upperbound_threshold_current,
475
482
  current_precision=0.005,
476
483
  section=section,
477
- segx=segx
484
+ segx=segx,
485
+ step_thresh=threshold_voltage
478
486
  )
479
487
 
480
488
  return rheobase
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: bluecellulab
3
- Version: 2.6.45
3
+ Version: 2.6.47
4
4
  Summary: Biologically detailed neural network simulations and analysis.
5
5
  Author: Blue Brain Project, EPFL
6
6
  License: Apache2.0
@@ -27,6 +27,7 @@ Requires-Dist: pydantic<3.0.0,>=2.5.2
27
27
  Requires-Dist: typing-extensions>=4.8.0
28
28
  Requires-Dist: networkx>=3.1
29
29
  Requires-Dist: h5py>=3.8.0
30
+ Dynamic: license-file
30
31
 
31
32
  |banner|
32
33
 
@@ -10,7 +10,7 @@ bluecellulab/plotwindow.py,sha256=ePU-EegZ1Sqk0SoYYiQ6k24ZO4s3Hgfpx10uePiJ5xM,27
10
10
  bluecellulab/psection.py,sha256=FSOwRNuOTyB469BM-jPEf9l1J59FamXmzrQgBI6cnP4,6174
11
11
  bluecellulab/psegment.py,sha256=PTgoGLqM4oFIdF_8QHFQCU59j-8TQmtq6PakiGUQhIo,3138
12
12
  bluecellulab/rngsettings.py,sha256=2Ykb4Ylk3XTs58x1UIxjg8XJqjSpnCgKRZ8avXCDpxk,4237
13
- bluecellulab/tools.py,sha256=pljNpD7dXvnKlgKoyc3YdGH3uDvhukWPHH7ausROwVM,17604
13
+ bluecellulab/tools.py,sha256=yy2_XBANaCQEqBeCIRiQfWJUidth9_igldVOSuSp5l4,18018
14
14
  bluecellulab/type_aliases.py,sha256=DvgjERv2Ztdw_sW63JrZTQGpJ0x5uMTFB5hcBHDb0WA,441
15
15
  bluecellulab/utils.py,sha256=SbOOkzw1YGjCKV3qOw0zpabNEy7V9BRtgMLsQJiFRq4,1526
16
16
  bluecellulab/verbosity.py,sha256=T0IgX7DrRo19faxrT4Xzb27gqxzoILQ8FzYKxvUeaPM,1342
@@ -60,14 +60,14 @@ bluecellulab/simulation/parallel.py,sha256=oQ_oV2EKr8gP4yF2Dq8q9MiblDyi89_wBgLzQ
60
60
  bluecellulab/simulation/simulation.py,sha256=VhftOMYU1Rfrphvud6f0U4kvbUivSviQ5TlVljuTb88,6486
61
61
  bluecellulab/stimulus/__init__.py,sha256=DgIgVaSyR-URf3JZzvO6j-tjCerzvktuK-ep8pjMRPQ,37
62
62
  bluecellulab/stimulus/circuit_stimulus_definitions.py,sha256=dTpwfRxH4c4yJDYyKrO6X-2Nqdy-QT3GxGQjfsRhNVY,17158
63
- bluecellulab/stimulus/factory.py,sha256=ucO-lAYtGUra36FYQN88WnMhKtA-vpPyTn32gNIN4qs,28011
64
- bluecellulab/stimulus/stimulus.py,sha256=1bvki61WtPDbneG6WsyrXeKP3e5AZ4Rr71jmzCeF1yc,27971
63
+ bluecellulab/stimulus/factory.py,sha256=K8d8krPr12tchYcqGrKzm-QOdOZh9QKwcml1Mk90M1M,29359
64
+ bluecellulab/stimulus/stimulus.py,sha256=a_hKJUtZmIgjiFjbJf6RzUPokELqn0IHCgIWGw5XLm8,30322
65
65
  bluecellulab/synapse/__init__.py,sha256=RW8XoAMXOvK7OG1nHl_q8jSEKLj9ZN4oWf2nY9HAwuk,192
66
66
  bluecellulab/synapse/synapse_factory.py,sha256=NHwRMYMrnRVm_sHmyKTJ1bdoNmWZNU4UPOGu7FCi-PE,6987
67
67
  bluecellulab/synapse/synapse_types.py,sha256=zs_yBvGTH4QrbQF3nEViidyq1WM_ZcTSFdjUxB3khW0,16871
68
- bluecellulab-2.6.45.dist-info/AUTHORS.txt,sha256=EDs3H-2HXBojbma10psixk3C2rFiOCTIREi2ZAbXYNQ,179
69
- bluecellulab-2.6.45.dist-info/LICENSE,sha256=dAMAR2Sud4Nead1wGFleKiwTZfkTNZbzmuGfcTKb3kg,11335
70
- bluecellulab-2.6.45.dist-info/METADATA,sha256=QHfEioQrrmOpRexn6F7owknoNeEzvUB35bWw4uEnA9k,8214
71
- bluecellulab-2.6.45.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
72
- bluecellulab-2.6.45.dist-info/top_level.txt,sha256=VSyEP8w9l3pXdRkyP_goeMwiNA8KWwitfAqUkveJkdQ,13
73
- bluecellulab-2.6.45.dist-info/RECORD,,
68
+ bluecellulab-2.6.47.dist-info/licenses/AUTHORS.txt,sha256=EDs3H-2HXBojbma10psixk3C2rFiOCTIREi2ZAbXYNQ,179
69
+ bluecellulab-2.6.47.dist-info/licenses/LICENSE,sha256=dAMAR2Sud4Nead1wGFleKiwTZfkTNZbzmuGfcTKb3kg,11335
70
+ bluecellulab-2.6.47.dist-info/METADATA,sha256=rydGOCvn6Y2v-KNPtssf3Au4IxaW2B_mo5nT5hf1QXA,8236
71
+ bluecellulab-2.6.47.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
72
+ bluecellulab-2.6.47.dist-info/top_level.txt,sha256=VSyEP8w9l3pXdRkyP_goeMwiNA8KWwitfAqUkveJkdQ,13
73
+ bluecellulab-2.6.47.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (76.0.0)
2
+ Generator: setuptools (80.3.1)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5