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
@@ -1,8 +1,12 @@
1
1
  from __future__ import annotations
2
2
  from abc import ABC, abstractmethod
3
+ from typing import Optional
4
+ import logging
3
5
  import matplotlib.pyplot as plt
4
6
  import numpy as np
5
7
 
8
+ logger = logging.getLogger(__name__)
9
+
6
10
 
7
11
  class Stimulus(ABC):
8
12
  def __init__(self, dt: float) -> None:
@@ -39,38 +43,38 @@ class Stimulus(ABC):
39
43
  ax.set_title(self.__class__.__name__)
40
44
  return ax
41
45
 
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
46
  def __add__(self, other: Stimulus) -> CombinedStimulus:
61
47
  """Override + operator to concatenate Stimulus objects."""
62
48
  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)
49
+ raise ValueError(
50
+ "Stimulus objects must have the same dt to be concatenated"
51
+ )
52
+ if len(self.time) == 0:
53
+ return CombinedStimulus(other.dt, other.time, other.current)
54
+ elif len(other.time) == 0:
55
+ return CombinedStimulus(self.dt, self.time, self.current)
56
+ else:
57
+ # shift other time
58
+ other_time = other.time + self.time[-1] + self.dt
59
+ combined_time = np.concatenate([self.time, other_time])
60
+ # Concatenate the current arrays
61
+ combined_current = np.concatenate([self.current, other.current])
62
+ return CombinedStimulus(self.dt, combined_time, combined_current)
63
+
64
+ def __eq__(self, other: object) -> bool:
65
+ if not isinstance(other, Stimulus):
66
+ return NotImplemented
67
+ else:
68
+ return (
69
+ np.allclose(self.time, other.time)
70
+ and np.allclose(self.current, other.current)
71
+ and self.dt == other.dt
72
+ )
70
73
 
71
74
 
72
75
  class CombinedStimulus(Stimulus):
73
76
  """Represents the Stimulus created by combining multiple stimuli."""
77
+
74
78
  def __init__(self, dt: float, time: np.ndarray, current: np.ndarray) -> None:
75
79
  super().__init__(dt)
76
80
  self._time = time
@@ -85,11 +89,12 @@ class CombinedStimulus(Stimulus):
85
89
  return self._current
86
90
 
87
91
 
88
- class EmptyStimulus(Stimulus):
92
+ class Empty(Stimulus):
89
93
  """Represents empty stimulus (all zeros) that has no impact on the cell.
90
94
 
91
95
  This is required by some Stimuli that expect the cell to rest.
92
96
  """
97
+
93
98
  def __init__(self, dt: float, duration: float) -> None:
94
99
  super().__init__(dt)
95
100
  self.duration = duration
@@ -103,152 +108,582 @@ class EmptyStimulus(Stimulus):
103
108
  return np.zeros_like(self.time)
104
109
 
105
110
 
106
- class Step(Stimulus):
107
- def __init__(self, dt: float, start: float, end: float, amplitude: float) -> None:
111
+ class Flat(Stimulus):
112
+ def __init__(self, dt: float, duration: float, amplitude: float) -> None:
108
113
  super().__init__(dt)
109
- self.start = start
110
- self.end = end
114
+ self.duration = duration
111
115
  self.amplitude = amplitude
112
116
 
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
117
  @property
128
118
  def time(self) -> np.ndarray:
129
- return np.arange(self.start, self.end, self.dt)
119
+ return np.arange(0.0, self.duration, self.dt)
130
120
 
131
121
  @property
132
122
  def current(self) -> np.ndarray:
133
123
  return np.full_like(self.time, self.amplitude)
134
124
 
135
125
 
136
- class Ramp(Stimulus):
126
+ class Slope(Stimulus):
137
127
  def __init__(
138
- self,
139
- dt: float,
140
- start: float,
141
- end: float,
142
- amplitude_start: float,
143
- amplitude_end: float,
128
+ self, dt: float, duration: float, amplitude_start: float, amplitude_end: float
144
129
  ) -> None:
145
130
  super().__init__(dt)
146
- self.start = start
147
- self.end = end
131
+ self.duration = duration
148
132
  self.amplitude_start = amplitude_start
149
133
  self.amplitude_end = amplitude_end
150
134
 
151
135
  @property
152
136
  def time(self) -> np.ndarray:
153
- return np.arange(self.start, self.end, self.dt)
137
+ return np.arange(0.0, self.duration, self.dt)
154
138
 
155
139
  @property
156
140
  def current(self) -> np.ndarray:
157
141
  return np.linspace(self.amplitude_start, self.amplitude_end, len(self.time))
158
142
 
159
143
 
144
+ class Zap(Stimulus):
145
+ def __init__(self, dt: float, duration: float, amplitude: float) -> None:
146
+ super().__init__(dt)
147
+ self.duration = duration
148
+ self.amplitude = amplitude
149
+
150
+ @property
151
+ def time(self) -> np.ndarray:
152
+ return np.arange(0.0, self.duration, self.dt)
153
+
154
+ @property
155
+ def current(self) -> np.ndarray:
156
+ return self.amplitude * np.sin(
157
+ 2.0 * np.pi * (1.0 + (1.0 / (5.15 - (self.time - 0.1)))) * (self.time - 0.1)
158
+ )
159
+
160
+
161
+ class Step(Stimulus):
162
+
163
+ def __init__(self):
164
+ raise NotImplementedError(
165
+ "This class cannot be instantiated directly. "
166
+ "Please use the class methods 'amplitude_based' "
167
+ "or 'threshold_based' to create objects."
168
+ )
169
+
170
+ @classmethod
171
+ def amplitude_based(
172
+ cls,
173
+ dt: float,
174
+ pre_delay: float,
175
+ duration: float,
176
+ post_delay: float,
177
+ amplitude: float,
178
+ ) -> CombinedStimulus:
179
+ """Create a Step stimulus from given time events and amplitude.
180
+
181
+ Args:
182
+ dt: The time step of the stimulus.
183
+ pre_delay: The delay before the start of the step.
184
+ duration: The duration of the step.
185
+ post_delay: The time to wait after the end of the step.
186
+ amplitude: The amplitude of the step.
187
+ """
188
+ return (
189
+ Empty(dt, duration=pre_delay)
190
+ + Flat(dt, duration=duration, amplitude=amplitude)
191
+ + Empty(dt, duration=post_delay)
192
+ )
193
+
194
+ @classmethod
195
+ def threshold_based(
196
+ cls,
197
+ dt: float,
198
+ pre_delay: float,
199
+ duration: float,
200
+ post_delay: float,
201
+ threshold_current: float,
202
+ threshold_percentage: float,
203
+ ) -> CombinedStimulus:
204
+ """Creates a Step stimulus with respect to the threshold current.
205
+
206
+ Args:
207
+
208
+ dt: The time step of the stimulus.
209
+ pre_delay: The delay before the start of the step.
210
+ duration: The duration of the step.
211
+ post_delay: The time to wait after the end of the step.
212
+ threshold_current: The threshold current of the Cell.
213
+ threshold_percentage: Percentage of desired threshold_current amplification.
214
+ """
215
+ amplitude = threshold_current * threshold_percentage / 100
216
+ res = cls.amplitude_based(
217
+ dt,
218
+ pre_delay=pre_delay,
219
+ duration=duration,
220
+ post_delay=post_delay,
221
+ amplitude=amplitude,
222
+ )
223
+ return res
224
+
225
+
226
+ class Ramp(Stimulus):
227
+
228
+ def __init__(self):
229
+ raise NotImplementedError(
230
+ "This class cannot be instantiated directly. "
231
+ "Please use the class methods 'amplitude_based' "
232
+ "or 'threshold_based' to create objects."
233
+ )
234
+
235
+ @classmethod
236
+ def amplitude_based(
237
+ cls,
238
+ dt: float,
239
+ pre_delay: float,
240
+ duration: float,
241
+ post_delay: float,
242
+ amplitude: float,
243
+ ) -> CombinedStimulus:
244
+ """Create a Ramp stimulus from given time events and amplitudes.
245
+
246
+ Args:
247
+ dt: The time step of the stimulus.
248
+ pre_delay: The delay before the start of the ramp.
249
+ duration: The duration of the ramp.
250
+ post_delay: The time to wait after the end of the ramp.
251
+ amplitude: The final amplitude of the ramp.
252
+ """
253
+ return (
254
+ Empty(dt, duration=pre_delay)
255
+ + Slope(
256
+ dt,
257
+ duration=duration,
258
+ amplitude_start=0.0,
259
+ amplitude_end=amplitude,
260
+ )
261
+ + Empty(dt, duration=post_delay)
262
+ )
263
+
264
+ @classmethod
265
+ def threshold_based(
266
+ cls,
267
+ dt: float,
268
+ pre_delay: float,
269
+ duration: float,
270
+ post_delay: float,
271
+ threshold_current: float,
272
+ threshold_percentage: float,
273
+ ) -> CombinedStimulus:
274
+ """Creates a Ramp stimulus with respect to the threshold current.
275
+
276
+ Args:
277
+
278
+ dt: The time step of the stimulus.
279
+ pre_delay: The delay before the start of the ramp.
280
+ duration: The duration of the ramp.
281
+ post_delay: The time to wait after the end of the ramp.
282
+ threshold_current: The threshold current of the Cell.
283
+ threshold_percentage: Percentage of desired threshold_current amplification.
284
+ """
285
+ amplitude = threshold_current * threshold_percentage / 100
286
+ res = cls.amplitude_based(
287
+ dt,
288
+ pre_delay=pre_delay,
289
+ duration=duration,
290
+ post_delay=post_delay,
291
+ amplitude=amplitude,
292
+ )
293
+ return res
294
+
295
+
296
+ class DelayedZap(Stimulus):
297
+
298
+ def __init__(self):
299
+ raise NotImplementedError(
300
+ "This class cannot be instantiated directly. "
301
+ "Please use the class methods 'amplitude_based' "
302
+ "or 'threshold_based' to create objects."
303
+ )
304
+
305
+ @classmethod
306
+ def amplitude_based(
307
+ cls,
308
+ dt: float,
309
+ pre_delay: float,
310
+ duration: float,
311
+ post_delay: float,
312
+ amplitude: float,
313
+ ) -> CombinedStimulus:
314
+ """Create a DelayedZap stimulus from given time events and amplitude.
315
+
316
+ Args:
317
+ dt: The time step of the stimulus.
318
+ pre_delay: The delay before the start of the step.
319
+ duration: The duration of the step.
320
+ post_delay: The time to wait after the end of the step.
321
+ amplitude: The amplitude of the step.
322
+ """
323
+ return (
324
+ Empty(dt, duration=pre_delay)
325
+ + Zap(dt, duration=duration, amplitude=amplitude)
326
+ + Empty(dt, duration=post_delay)
327
+ )
328
+
329
+ @classmethod
330
+ def threshold_based(
331
+ cls,
332
+ dt: float,
333
+ pre_delay: float,
334
+ duration: float,
335
+ post_delay: float,
336
+ threshold_current: float,
337
+ threshold_percentage: float,
338
+ ) -> CombinedStimulus:
339
+ """Creates a SineSpec stimulus with respect to the threshold current.
340
+
341
+ Args:
342
+
343
+ dt: The time step of the stimulus.
344
+ pre_delay: The delay before the start of the step.
345
+ duration: The duration of the step.
346
+ post_delay: The time to wait after the end of the step.
347
+ threshold_current: The threshold current of the Cell.
348
+ threshold_percentage: Percentage of desired threshold_current amplification.
349
+ """
350
+ amplitude = threshold_current * threshold_percentage / 100
351
+ res = cls.amplitude_based(
352
+ dt,
353
+ pre_delay=pre_delay,
354
+ duration=duration,
355
+ post_delay=post_delay,
356
+ amplitude=amplitude,
357
+ )
358
+ return res
359
+
360
+
160
361
  class StimulusFactory:
161
362
  def __init__(self, dt: float):
162
363
  self.dt = dt
163
364
 
164
- def step(self, start: float, end: float, amplitude: float) -> Stimulus:
165
- return Step(self.dt, start, end, amplitude)
365
+ def step(
366
+ self, pre_delay: float, duration: float, post_delay: float, amplitude: float
367
+ ) -> Stimulus:
368
+ return Step.amplitude_based(
369
+ self.dt,
370
+ pre_delay=pre_delay,
371
+ duration=duration,
372
+ post_delay=post_delay,
373
+ amplitude=amplitude,
374
+ )
166
375
 
167
376
  def ramp(
168
- self, start: float, end: float, amplitude_start: float, amplitude_end: float
377
+ self, pre_delay: float, duration: float, post_delay: float, amplitude: float
169
378
  ) -> Stimulus:
170
- return Ramp(self.dt, start, end, amplitude_start, amplitude_end)
379
+ return Ramp.amplitude_based(
380
+ self.dt,
381
+ pre_delay=pre_delay,
382
+ duration=duration,
383
+ post_delay=post_delay,
384
+ amplitude=amplitude,
385
+ )
171
386
 
172
387
  def ap_waveform(
173
388
  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,
389
+ threshold_current: Optional[float] = None,
390
+ threshold_percentage: Optional[float] = 220.0,
391
+ amplitude: Optional[float] = None,
179
392
  ) -> Stimulus:
180
393
  """Returns the APWaveform Stimulus object, a type of Step stimulus.
181
394
 
182
395
  Args:
183
396
  threshold_current: The threshold current of the Cell.
184
397
  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.
398
+ amplitude: Raw amplitude of input current.
188
399
  """
189
- return Step.threshold_based(
190
- self.dt, threshold_current, threshold_percentage, start, end, post_wait
191
- )
400
+ pre_delay = 250.0
401
+ duration = 50.0
402
+ post_delay = 250.0
403
+
404
+ if amplitude is not None:
405
+ if threshold_current is not None and threshold_current != 0 and threshold_percentage is not None:
406
+ logger.info(
407
+ "amplitude, threshold_current and threshold_percentage are all set in ap_waveform."
408
+ " Will only keep amplitude value."
409
+ )
410
+ return Step.amplitude_based(
411
+ self.dt,
412
+ pre_delay=pre_delay,
413
+ duration=duration,
414
+ post_delay=post_delay,
415
+ amplitude=amplitude,
416
+ )
417
+
418
+ if threshold_current is not None and threshold_current != 0 and threshold_percentage is not None:
419
+ return Step.threshold_based(
420
+ self.dt,
421
+ pre_delay=pre_delay,
422
+ duration=duration,
423
+ post_delay=post_delay,
424
+ threshold_current=threshold_current,
425
+ threshold_percentage=threshold_percentage,
426
+ )
427
+
428
+ raise TypeError("You have to give either threshold_current or amplitude")
192
429
 
193
430
  def idrest(
194
431
  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,
432
+ threshold_current: Optional[float] = None,
433
+ threshold_percentage: Optional[float] = 200.0,
434
+ amplitude: Optional[float] = None,
200
435
  ) -> Stimulus:
201
436
  """Returns the IDRest Stimulus object, a type of Step stimulus.
202
437
 
203
438
  Args:
204
439
  threshold_current: The threshold current of the Cell.
205
440
  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.
441
+ amplitude: Raw amplitude of input current.
209
442
  """
210
- return Step.threshold_based(
211
- self.dt, threshold_current, threshold_percentage, start, end, post_wait
212
- )
443
+ pre_delay = 250.0
444
+ duration = 1350.0
445
+ post_delay = 250.0
446
+
447
+ if amplitude is not None:
448
+ if threshold_current is not None and threshold_current != 0 and threshold_percentage is not None:
449
+ logger.info(
450
+ "amplitude, threshold_current and threshold_percentage are all set in idrest."
451
+ " Will only keep amplitude value."
452
+ )
453
+ return Step.amplitude_based(
454
+ self.dt,
455
+ pre_delay=pre_delay,
456
+ duration=duration,
457
+ post_delay=post_delay,
458
+ amplitude=amplitude,
459
+ )
460
+
461
+ if threshold_current is not None and threshold_current != 0 and threshold_percentage is not None:
462
+ return Step.threshold_based(
463
+ self.dt,
464
+ pre_delay=pre_delay,
465
+ duration=duration,
466
+ post_delay=post_delay,
467
+ threshold_current=threshold_current,
468
+ threshold_percentage=threshold_percentage,
469
+ )
470
+
471
+ raise TypeError("You have to give either threshold_current or amplitude")
213
472
 
214
473
  def iv(
215
474
  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,
475
+ threshold_current: Optional[float] = None,
476
+ threshold_percentage: Optional[float] = -40.0,
477
+ amplitude: Optional[float] = None,
221
478
  ) -> Stimulus:
222
479
  """Returns the IV Stimulus object, a type of Step stimulus.
223
480
 
224
481
  Args:
225
482
  threshold_current: The threshold current of the Cell.
226
483
  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.
484
+ amplitude: Raw amplitude of input current.
230
485
  """
231
- return Step.threshold_based(
232
- self.dt, threshold_current, threshold_percentage, start, end, post_wait
233
- )
486
+ pre_delay = 250.0
487
+ duration = 3000.0
488
+ post_delay = 250.0
489
+
490
+ if amplitude is not None:
491
+ if threshold_current is not None and threshold_current != 0 and threshold_percentage is not None:
492
+ logger.info(
493
+ "amplitude, threshold_current and threshold_percentage are all set in iv."
494
+ " Will only keep amplitude value."
495
+ )
496
+ return Step.amplitude_based(
497
+ self.dt,
498
+ pre_delay=pre_delay,
499
+ duration=duration,
500
+ post_delay=post_delay,
501
+ amplitude=amplitude,
502
+ )
503
+
504
+ if threshold_current is not None and threshold_current != 0 and threshold_percentage is not None:
505
+ return Step.threshold_based(
506
+ self.dt,
507
+ pre_delay=pre_delay,
508
+ duration=duration,
509
+ post_delay=post_delay,
510
+ threshold_current=threshold_current,
511
+ threshold_percentage=threshold_percentage,
512
+ )
513
+
514
+ raise TypeError("You have to give either threshold_current or amplitude")
234
515
 
235
516
  def fire_pattern(
236
517
  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,
518
+ threshold_current: Optional[float] = None,
519
+ threshold_percentage: Optional[float] = 200.0,
520
+ amplitude: Optional[float] = None,
242
521
  ) -> Stimulus:
243
522
  """Returns the FirePattern Stimulus object, a type of Step stimulus.
244
523
 
245
524
  Args:
246
525
  threshold_current: The threshold current of the Cell.
247
526
  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.
527
+ amplitude: Raw amplitude of input current.
528
+ """
529
+ pre_delay = 250.0
530
+ duration = 3600.0
531
+ post_delay = 250.0
532
+
533
+ if amplitude is not None:
534
+ if threshold_current is not None and threshold_current != 0 and threshold_percentage is not None:
535
+ logger.info(
536
+ "amplitude, threshold_current and threshold_percentage are all set in fire_pattern."
537
+ " Will only keep amplitude value."
538
+ )
539
+ return Step.amplitude_based(
540
+ self.dt,
541
+ pre_delay=pre_delay,
542
+ duration=duration,
543
+ post_delay=post_delay,
544
+ amplitude=amplitude,
545
+ )
546
+
547
+ if threshold_current is not None and threshold_current != 0 and threshold_percentage is not None:
548
+ return Step.threshold_based(
549
+ self.dt,
550
+ pre_delay=pre_delay,
551
+ duration=duration,
552
+ post_delay=post_delay,
553
+ threshold_current=threshold_current,
554
+ threshold_percentage=threshold_percentage,
555
+ )
556
+
557
+ raise TypeError("You have to give either threshold_current or amplitude")
558
+
559
+ def pos_cheops(
560
+ self,
561
+ threshold_current: Optional[float] = None,
562
+ threshold_percentage: Optional[float] = 300.0,
563
+ amplitude: Optional[float] = None,
564
+ ) -> Stimulus:
565
+ """A combination of pyramid shaped Ramp stimuli with a positive
566
+ amplitude.
567
+
568
+ Args:
569
+ threshold_current: The threshold current of the Cell.
570
+ threshold_percentage: Percentage of desired threshold_current amplification.
571
+ amplitude: Raw amplitude of input current.
251
572
  """
252
- return Step.threshold_based(
253
- self.dt, threshold_current, threshold_percentage, start, end, post_wait
573
+ delay = 250.0
574
+ ramp1_duration = 4000.0
575
+ ramp2_duration = 2000.0
576
+ ramp3_duration = 1333.0
577
+ inter_delay = 2000.0
578
+ post_delay = 250.0
579
+
580
+ if amplitude is None:
581
+ if threshold_current is None or threshold_current == 0 or threshold_percentage is None:
582
+ raise TypeError("You have to give either threshold_current or amplitude")
583
+ amplitude = threshold_current * threshold_percentage / 100
584
+ elif threshold_current is not None and threshold_current != 0 and threshold_percentage is not None:
585
+ logger.info(
586
+ "amplitude, threshold_current and threshold_percentage are all set in pos_cheops."
587
+ " Will only keep amplitude value."
588
+ )
589
+ result = (
590
+ Empty(self.dt, duration=delay)
591
+ + Slope(self.dt, duration=ramp1_duration, amplitude_start=0.0, amplitude_end=amplitude)
592
+ + Slope(self.dt, duration=ramp1_duration, amplitude_start=amplitude, amplitude_end=0.0)
593
+ + Empty(self.dt, duration=inter_delay)
594
+ + Slope(self.dt, duration=ramp2_duration, amplitude_start=0.0, amplitude_end=amplitude)
595
+ + Slope(self.dt, duration=ramp2_duration, amplitude_start=amplitude, amplitude_end=0.0)
596
+ + Empty(self.dt, duration=inter_delay)
597
+ + Slope(self.dt, duration=ramp3_duration, amplitude_start=0.0, amplitude_end=amplitude)
598
+ + Slope(self.dt, duration=ramp3_duration, amplitude_start=amplitude, amplitude_end=0.0)
599
+ + Empty(self.dt, duration=post_delay)
254
600
  )
601
+ return result
602
+
603
+ def neg_cheops(
604
+ self,
605
+ threshold_current: Optional[float] = None,
606
+ threshold_percentage: Optional[float] = 300.0,
607
+ amplitude: Optional[float] = None,
608
+ ) -> Stimulus:
609
+ """A combination of pyramid shaped Ramp stimuli with a negative
610
+ amplitude.
611
+
612
+ Args:
613
+ threshold_current: The threshold current of the Cell.
614
+ threshold_percentage: Percentage of desired threshold_current amplification.
615
+ amplitude: Raw amplitude of input current.
616
+ """
617
+ delay = 1750.0
618
+ ramp1_duration = 3333.0
619
+ ramp2_duration = 1666.0
620
+ ramp3_duration = 1111.0
621
+ inter_delay = 2000.0
622
+ post_delay = 250.0
623
+
624
+ if amplitude is None:
625
+ if threshold_current is None or threshold_current == 0 or threshold_percentage is None:
626
+ raise TypeError("You have to give either threshold_current or amplitude")
627
+ amplitude = - threshold_current * threshold_percentage / 100
628
+ elif threshold_current is not None and threshold_current != 0 and threshold_percentage is not None:
629
+ logger.info(
630
+ "amplitude, threshold_current and threshold_percentage are all set in neg_cheops."
631
+ " Will only keep amplitude value."
632
+ )
633
+ result = (
634
+ Empty(self.dt, duration=delay)
635
+ + Slope(self.dt, duration=ramp1_duration, amplitude_start=0.0, amplitude_end=amplitude)
636
+ + Slope(self.dt, duration=ramp1_duration, amplitude_start=amplitude, amplitude_end=0.0)
637
+ + Empty(self.dt, duration=inter_delay)
638
+ + Slope(self.dt, duration=ramp2_duration, amplitude_start=0.0, amplitude_end=amplitude)
639
+ + Slope(self.dt, duration=ramp2_duration, amplitude_start=amplitude, amplitude_end=0.0)
640
+ + Empty(self.dt, duration=inter_delay)
641
+ + Slope(self.dt, duration=ramp3_duration, amplitude_start=0.0, amplitude_end=amplitude)
642
+ + Slope(self.dt, duration=ramp3_duration, amplitude_start=amplitude, amplitude_end=0.0)
643
+ + Empty(self.dt, duration=post_delay)
644
+ )
645
+ return result
646
+
647
+ def sinespec(
648
+ self,
649
+ threshold_current: Optional[float] = None,
650
+ threshold_percentage: Optional[float] = 60.0,
651
+ amplitude: Optional[float] = None,
652
+ pre_delay: float = 0,
653
+ ) -> Stimulus:
654
+ """Returns the SineSpec Stimulus object, a type of Zap stimulus.
655
+
656
+ Args:
657
+ threshold_current: The threshold current of the Cell.
658
+ threshold_percentage: Percentage of desired threshold_current amplification.
659
+ amplitude: Raw amplitude of input current.
660
+ pre_delay: delay before the start of the stimulus
661
+ """
662
+ duration = 5000.0
663
+ post_delay = 0
664
+
665
+ if amplitude is not None:
666
+ if threshold_current is not None and threshold_current != 0 and threshold_percentage is not None:
667
+ logger.info(
668
+ "amplitude, threshold_current and threshold_percentage are all set in sinespec."
669
+ " Will only keep amplitude value."
670
+ )
671
+ return DelayedZap.amplitude_based(
672
+ self.dt,
673
+ pre_delay=pre_delay,
674
+ duration=duration,
675
+ post_delay=post_delay,
676
+ amplitude=amplitude,
677
+ )
678
+
679
+ if threshold_current is not None and threshold_current != 0 and threshold_percentage is not None:
680
+ return DelayedZap.threshold_based(
681
+ self.dt,
682
+ pre_delay=pre_delay,
683
+ duration=duration,
684
+ post_delay=post_delay,
685
+ threshold_current=threshold_current,
686
+ threshold_percentage=threshold_percentage,
687
+ )
688
+
689
+ raise TypeError("You have to give either threshold_current or amplitude")