bluecellulab 2.6.46__tar.gz → 2.6.48__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 (107) hide show
  1. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/PKG-INFO +3 -2
  2. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/analysis/analysis.py +47 -11
  3. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/analysis/inject_sequence.py +96 -24
  4. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/analysis/plotting.py +47 -4
  5. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/stimulus/factory.py +104 -74
  6. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/tools.py +20 -13
  7. bluecellulab-2.6.48/bluecellulab/validation/validation.py +401 -0
  8. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab.egg-info/PKG-INFO +3 -2
  9. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab.egg-info/SOURCES.txt +1 -0
  10. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/.compile_mod.sh +0 -0
  11. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/.gitattributes +0 -0
  12. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/.github/dependabot.yml +0 -0
  13. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/.github/workflows/release.yml +0 -0
  14. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/.github/workflows/test.yml +0 -0
  15. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/.gitignore +0 -0
  16. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/.gitlab-ci.yml +0 -0
  17. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/.readthedocs.yml +0 -0
  18. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/.zenodo.json +0 -0
  19. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/AUTHORS.txt +0 -0
  20. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/CHANGELOG.rst +0 -0
  21. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/CITATION.cff +0 -0
  22. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/CONTRIBUTING.rst +0 -0
  23. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/LICENSE +0 -0
  24. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/MANIFEST.in +0 -0
  25. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/Makefile +0 -0
  26. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/README.rst +0 -0
  27. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/__init__.py +0 -0
  28. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/analysis/__init__.py +0 -0
  29. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/cell/__init__.py +0 -0
  30. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/cell/ballstick/__init__.py +0 -0
  31. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/cell/ballstick/emodel.hoc +0 -0
  32. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/cell/ballstick/morphology.asc +0 -0
  33. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/cell/cell_dict.py +0 -0
  34. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/cell/core.py +0 -0
  35. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/cell/injector.py +0 -0
  36. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/cell/plotting.py +0 -0
  37. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/cell/random.py +0 -0
  38. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/cell/recording.py +0 -0
  39. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/cell/section_distance.py +0 -0
  40. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/cell/serialized_sections.py +0 -0
  41. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/cell/sonata_proxy.py +0 -0
  42. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/cell/stimuli_generator.py +0 -0
  43. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/cell/template.py +0 -0
  44. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/circuit/__init__.py +0 -0
  45. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/circuit/circuit_access/__init__.py +0 -0
  46. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/circuit/circuit_access/bluepy_circuit_access.py +0 -0
  47. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/circuit/circuit_access/definition.py +0 -0
  48. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/circuit/circuit_access/sonata_circuit_access.py +0 -0
  49. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/circuit/config/__init__.py +0 -0
  50. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/circuit/config/bluepy_simulation_config.py +0 -0
  51. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/circuit/config/definition.py +0 -0
  52. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/circuit/config/sections.py +0 -0
  53. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/circuit/config/sonata_simulation_config.py +0 -0
  54. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/circuit/format.py +0 -0
  55. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/circuit/iotools.py +0 -0
  56. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/circuit/node_id.py +0 -0
  57. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/circuit/simulation_access.py +0 -0
  58. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/circuit/synapse_properties.py +0 -0
  59. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/circuit/validate.py +0 -0
  60. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/circuit_simulation.py +0 -0
  61. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/connection.py +0 -0
  62. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/dendrogram.py +0 -0
  63. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/exceptions.py +0 -0
  64. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/graph.py +0 -0
  65. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/hoc/Cell.hoc +0 -0
  66. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/hoc/RNGSettings.hoc +0 -0
  67. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/hoc/TDistFunc.hoc +0 -0
  68. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/hoc/TStim.hoc +0 -0
  69. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/hoc/fileUtils.hoc +0 -0
  70. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/importer.py +0 -0
  71. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/neuron_interpreter.py +0 -0
  72. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/plotwindow.py +0 -0
  73. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/psection.py +0 -0
  74. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/psegment.py +0 -0
  75. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/rngsettings.py +0 -0
  76. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/simulation/__init__.py +0 -0
  77. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/simulation/neuron_globals.py +0 -0
  78. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/simulation/parallel.py +0 -0
  79. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/simulation/simulation.py +0 -0
  80. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/stimulus/__init__.py +0 -0
  81. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/stimulus/circuit_stimulus_definitions.py +0 -0
  82. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/stimulus/stimulus.py +0 -0
  83. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/synapse/__init__.py +0 -0
  84. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/synapse/synapse_factory.py +0 -0
  85. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/synapse/synapse_types.py +0 -0
  86. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/type_aliases.py +0 -0
  87. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/utils.py +0 -0
  88. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab/verbosity.py +0 -0
  89. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab.egg-info/dependency_links.txt +0 -0
  90. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab.egg-info/requires.txt +0 -0
  91. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/bluecellulab.egg-info/top_level.txt +0 -0
  92. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/docs/Makefile +0 -0
  93. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/docs/images/voltage-readme.png +0 -0
  94. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/docs/make.bat +0 -0
  95. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/docs/requirements_docs.txt +0 -0
  96. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/docs/source/_static/.gitkeep +0 -0
  97. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/docs/source/api.rst +0 -0
  98. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/docs/source/changelog.rst +0 -0
  99. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/docs/source/compiling-mechanisms.rst +0 -0
  100. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/docs/source/conf.py +0 -0
  101. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/docs/source/contributing.rst +0 -0
  102. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/docs/source/index.rst +0 -0
  103. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/docs/source/list_of_stim.rst +0 -0
  104. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/docs/source/logo/BlueCelluLabBanner.jpg +0 -0
  105. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/pyproject.toml +0 -0
  106. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/setup.cfg +0 -0
  107. {bluecellulab-2.6.46 → bluecellulab-2.6.48}/tox.ini +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: bluecellulab
3
- Version: 2.6.46
3
+ Version: 2.6.48
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
 
@@ -5,10 +5,10 @@ except ImportError:
5
5
  efel = None
6
6
  import numpy as np
7
7
 
8
- from bluecellulab.stimulus import StimulusFactory
9
- from bluecellulab.tools import calculate_rheobase
10
8
  from bluecellulab.analysis.inject_sequence import run_stimulus
11
9
  from bluecellulab.analysis.plotting import plot_iv_curve, plot_fi_curve
10
+ from bluecellulab.stimulus import StimulusFactory
11
+ from bluecellulab.tools import calculate_rheobase
12
12
 
13
13
 
14
14
  def compute_plot_iv_curve(cell,
@@ -19,8 +19,13 @@ def compute_plot_iv_curve(cell,
19
19
  stim_start=100.0,
20
20
  duration=500.0,
21
21
  post_delay=100.0,
22
- threshold_voltage=-30,
23
- nb_bins=11):
22
+ threshold_voltage=-20,
23
+ nb_bins=11,
24
+ rheobase=None,
25
+ show_figure=True,
26
+ save_figure=False,
27
+ output_dir="./",
28
+ output_fname="iv_curve.pdf"):
24
29
  """Compute and plot the Current-Voltage (I-V) curve for a given cell by
25
30
  injecting a range of currents.
26
31
 
@@ -46,6 +51,12 @@ def compute_plot_iv_curve(cell,
46
51
  response. Default is -30 mV.
47
52
  nb_bins (int, optional): The number of discrete current levels between 0 and the maximum current.
48
53
  Default is 11.
54
+ rheobase (float, optional): The rheobase current (in nA) for the cell. If not provided, it will
55
+ be calculated using the `calculate_rheobase` function.
56
+ show_figure (bool): Whether to display the figure. Default is True.
57
+ save_figure (bool): Whether to save the figure. Default is False.
58
+ output_dir (str): The directory to save the figure if save_figure is True. Default is "./".
59
+ output_fname (str): The filename to save the figure as if save_figure is True. Default is "iv_curve.png".
49
60
 
50
61
  Returns:
51
62
  tuple: A tuple containing:
@@ -57,7 +68,8 @@ def compute_plot_iv_curve(cell,
57
68
  ValueError: If the cell object is invalid, the specified sections/segments are not found, or if
58
69
  the simulation results are inconsistent.
59
70
  """
60
- rheobase = calculate_rheobase(cell=cell, section=injecting_section, segx=injecting_segment)
71
+ if rheobase is None:
72
+ rheobase = calculate_rheobase(cell=cell, section=injecting_section, segx=injecting_segment)
61
73
 
62
74
  list_amp = np.linspace(rheobase - 2, rheobase - 0.1, nb_bins) # [nA]
63
75
 
@@ -89,7 +101,7 @@ def compute_plot_iv_curve(cell,
89
101
  'stim_end': [stim_start + duration]
90
102
  }
91
103
  features_results = efel.get_feature_values([trace], ['steady_state_voltage_stimend'])
92
- steady_state = features_results[0]['steady_state_voltage_stimend']
104
+ steady_state = features_results[0]['steady_state_voltage_stimend'][0]
93
105
  steady_states.append(steady_state)
94
106
 
95
107
  plot_iv_curve(list_amp,
@@ -97,7 +109,11 @@ def compute_plot_iv_curve(cell,
97
109
  injecting_section=injecting_section,
98
110
  injecting_segment=injecting_segment,
99
111
  recording_section=recording_section,
100
- recording_segment=recording_segment)
112
+ recording_segment=recording_segment,
113
+ show_figure=show_figure,
114
+ save_figure=save_figure,
115
+ output_dir=output_dir,
116
+ output_fname=output_fname)
101
117
 
102
118
  return np.array(list_amp), np.array(steady_states)
103
119
 
@@ -111,7 +127,13 @@ def compute_plot_fi_curve(cell,
111
127
  duration=500.0,
112
128
  post_delay=100.0,
113
129
  max_current=0.8,
114
- nb_bins=11):
130
+ threshold_voltage=-20,
131
+ nb_bins=11,
132
+ rheobase=None,
133
+ show_figure=True,
134
+ save_figure=False,
135
+ output_dir="./",
136
+ output_fname="fi_curve.pdf"):
115
137
  """Compute and plot the Frequency-Current (F-I) curve for a given cell by
116
138
  injecting a range of currents.
117
139
 
@@ -135,8 +157,16 @@ def compute_plot_fi_curve(cell,
135
157
  (in ms). Default is 100.0 ms.
136
158
  max_current (float, optional): The maximum amplitude of the injected current (in nA).
137
159
  Default is 0.8 nA.
160
+ threshold_voltage (float, optional): The voltage threshold (in mV) for detecting a steady-state
161
+ response. Default is -30 mV.
138
162
  nb_bins (int, optional): The number of discrete current levels between 0 and `max_current`.
139
163
  Default is 11.
164
+ rheobase (float, optional): The rheobase current (in nA) for the cell. If not provided, it will
165
+ be calculated using the `calculate_rheobase` function.
166
+ show_figure (bool): Whether to display the figure. Default is True.
167
+ save_figure (bool): Whether to save the figure. Default is False.
168
+ output_dir (str): The directory to save the figure if save_figure is True. Default is "./".
169
+ output_fname (str): The filename to save the figure as if save_figure is True. Default is "iv_curve.png".
140
170
 
141
171
  Returns:
142
172
  tuple: A tuple containing:
@@ -146,7 +176,8 @@ def compute_plot_fi_curve(cell,
146
176
  Raises:
147
177
  ValueError: If the cell object is invalid or the specified sections/segments are not found.
148
178
  """
149
- rheobase = calculate_rheobase(cell=cell, section=injecting_section, segx=injecting_segment)
179
+ if rheobase is None:
180
+ rheobase = calculate_rheobase(cell=cell, section=injecting_section, segx=injecting_segment)
150
181
 
151
182
  list_amp = np.linspace(rheobase, max_current, nb_bins) # [nA]
152
183
  steps = []
@@ -161,7 +192,8 @@ def compute_plot_fi_curve(cell,
161
192
  segment=injecting_segment,
162
193
  recording_section=recording_section,
163
194
  recording_segment=recording_segment,
164
- enable_spike_detection=True)
195
+ enable_spike_detection=True,
196
+ threshold_spike_detection=threshold_voltage)
165
197
  steps.append(step_stimulus)
166
198
  spikes.append(recording.spike)
167
199
 
@@ -172,6 +204,10 @@ def compute_plot_fi_curve(cell,
172
204
  injecting_section=injecting_section,
173
205
  injecting_segment=injecting_segment,
174
206
  recording_section=recording_section,
175
- recording_segment=recording_segment)
207
+ recording_segment=recording_segment,
208
+ show_figure=show_figure,
209
+ save_figure=save_figure,
210
+ output_dir=output_dir,
211
+ output_fname=output_fname)
176
212
 
177
213
  return np.array(list_amp), np.array(spike_count)
@@ -36,18 +36,17 @@ class Recording(NamedTuple):
36
36
  StimulusRecordings = Dict[str, Recording]
37
37
 
38
38
 
39
- def run_stimulus(
39
+ def run_multirecordings_stimulus(
40
40
  template_params: TemplateParams,
41
41
  stimulus: Stimulus,
42
42
  section: str,
43
43
  segment: float,
44
44
  cvode: bool = True,
45
45
  add_hypamp: bool = True,
46
- recording_section: str = "soma[0]",
47
- recording_segment: float = 0.5,
46
+ recording_locations: list[tuple[str, float]] = [("soma[0]", 0.5)],
48
47
  enable_spike_detection: bool = False,
49
- threshold_spike_detection: float = -30.0,
50
- ) -> Recording:
48
+ threshold_spike_detection: float = -20.0,
49
+ ) -> list[Recording]:
51
50
  """Creates a cell from template parameters, applies a stimulus, and records
52
51
  the response.
53
52
 
@@ -66,16 +65,17 @@ def run_stimulus(
66
65
  cvode (bool, optional): Whether to use variable time-step integration. Defaults to True.
67
66
  add_hypamp (bool, optional): If True, adds a hyperpolarizing stimulus before applying
68
67
  the main stimulus. Defaults to True.
69
- recording_section (str): Name of the section of the cell where voltage is recorded.
70
- recording_segment (float): The normalized position (0.0 to 1.0) along the recording
68
+ recording_location (list): List of tuples containing the name of the section of the cell
69
+ where voltage is recorded and the normalized position (0.0 to 1.0) along the recording
71
70
  section where voltage is recorded.
71
+ (e.g. [("soma[0]", 0.5), ("dend[0]", 0.5)])
72
72
  enable_spike_detection (bool, optional): If True, enables spike detection at the
73
73
  recording location. Defaults to False.
74
74
  threshold_spike_detection (float, optional): The voltage threshold (mV) for spike detection.
75
- Defaults to -30 mV.
75
+ Defaults to -20 mV.
76
76
 
77
77
  Returns:
78
- Recording: A `Recording` object containing the following:
78
+ list[Recording]: `Recording` objects containing the following:
79
79
  - `current` (np.ndarray): The injected current waveform (nA).
80
80
  - `voltage` (np.ndarray): The recorded membrane potential (mV) over time.
81
81
  - `time` (np.ndarray): The simulation time points (ms).
@@ -88,19 +88,22 @@ def run_stimulus(
88
88
  cell = Cell.from_template_parameters(template_params)
89
89
 
90
90
  validate_section_and_segment(cell, section, segment)
91
- validate_section_and_segment(cell, recording_section, recording_segment)
91
+ for recording_section, recording_segment in recording_locations:
92
+ validate_section_and_segment(cell, recording_section, recording_segment)
92
93
 
93
94
  if add_hypamp:
94
95
  hyp_stim = Hyperpolarizing(target="", delay=0.0, duration=stimulus.stimulus_time)
95
96
  cell.add_replay_hypamp(hyp_stim)
96
97
 
97
- cell.add_voltage_recording(cell.sections[recording_section], recording_segment)
98
+ for recording_section, recording_segment in recording_locations:
99
+ cell.add_voltage_recording(cell.sections[recording_section], recording_segment)
98
100
 
99
101
  # Set up spike detection if enabled
100
102
  spikes: Optional[np.ndarray] = None
101
103
  if enable_spike_detection:
102
- recording_location = f"{recording_section}({str(recording_segment)})"
103
- cell.start_recording_spikes(None, location=recording_location, threshold=threshold_spike_detection)
104
+ for recording_section, recording_segment in recording_locations:
105
+ recording_location = f"{recording_section}({str(recording_segment)})"
106
+ cell.start_recording_spikes(None, location=recording_location, threshold=threshold_spike_detection)
104
107
 
105
108
  # Inject the stimulus and run the simulation
106
109
  iclamp, _ = cell.inject_current_waveform(
@@ -113,21 +116,90 @@ def run_stimulus(
113
116
  simulation.run(stimulus.stimulus_time, cvode=cvode)
114
117
 
115
118
  # Retrieve simulation results
119
+ recordings = []
116
120
  current = np.array(current_vector.to_python())
117
- voltage = cell.get_voltage_recording(cell.sections[recording_section], recording_segment)
118
- time = cell.get_time()
121
+ for recording_section, recording_segment in recording_locations:
122
+ recording_location = f"{recording_section}({str(recording_segment)})"
123
+ voltage = cell.get_voltage_recording(cell.sections[recording_section], recording_segment)
124
+ time = cell.get_time()
119
125
 
120
- if len(time) != len(voltage) or len(time) != len(current):
121
- raise ValueError("Time, current, and voltage arrays are not the same length")
126
+ if len(time) != len(voltage) or len(time) != len(current):
127
+ raise ValueError("Time, current, and voltage arrays are not the same length")
122
128
 
123
- if enable_spike_detection:
124
- results = cell.get_recorded_spikes(location=recording_location, threshold=threshold_spike_detection)
125
- if results is not None:
126
- spikes = np.array(results)
127
- else:
128
- spikes = None
129
+ if enable_spike_detection:
130
+ results = cell.get_recorded_spikes(location=recording_location, threshold=threshold_spike_detection)
131
+ if results is not None:
132
+ spikes = np.array(results)
133
+ else:
134
+ spikes = None
135
+
136
+ recordings.append(
137
+ Recording(current=current, voltage=voltage, time=time, spike=spikes)
138
+ )
129
139
 
130
- return Recording(current=current, voltage=voltage, time=time, spike=spikes)
140
+ return recordings
141
+
142
+
143
+ def run_stimulus(
144
+ template_params: TemplateParams,
145
+ stimulus: Stimulus,
146
+ section: str,
147
+ segment: float,
148
+ cvode: bool = True,
149
+ add_hypamp: bool = True,
150
+ recording_section: str = "soma[0]",
151
+ recording_segment: float = 0.5,
152
+ enable_spike_detection: bool = False,
153
+ threshold_spike_detection: float = -20.0,
154
+ ) -> Recording:
155
+ """Creates a cell from template parameters, applies a stimulus, and records
156
+ the response.
157
+
158
+ This function simulates the electrical activity of a neuronal cell model by injecting
159
+ a stimulus into a specified section and segment, recording the voltage response, and
160
+ optionally detecting spikes.
161
+
162
+ Args:
163
+ template_params (TemplateParams): Parameters required to create the cell from a
164
+ specified template, including morphology and mechanisms.
165
+ stimulus (Stimulus): The stimulus waveform to inject, defined by time and current arrays.
166
+ section (str): Name of the section of the cell where the stimulus is applied.
167
+ (e.g. soma[0])
168
+ segment (float): The normalized position (0.0 to 1.0) along the injecting
169
+ section where the stimulus is applied.
170
+ cvode (bool, optional): Whether to use variable time-step integration. Defaults to True.
171
+ add_hypamp (bool, optional): If True, adds a hyperpolarizing stimulus before applying
172
+ the main stimulus. Defaults to True.
173
+ recording_section (str): Name of the section of the cell where voltage is recorded.
174
+ recording_segment (float): The normalized position (0.0 to 1.0) along the recording
175
+ section where voltage is recorded.
176
+ enable_spike_detection (bool, optional): If True, enables spike detection at the
177
+ recording location. Defaults to False.
178
+ threshold_spike_detection (float, optional): The voltage threshold (mV) for spike detection.
179
+ Defaults to -20 mV.
180
+
181
+ Returns:
182
+ Recording: A `Recording` object containing the following:
183
+ - `current` (np.ndarray): The injected current waveform (nA).
184
+ - `voltage` (np.ndarray): The recorded membrane potential (mV) over time.
185
+ - `time` (np.ndarray): The simulation time points (ms).
186
+ - `spike` (np.ndarray or None): The detected spikes, if spike detection is enabled.
187
+
188
+ Raises:
189
+ ValueError: If the time, current, and voltage arrays do not have the same length,
190
+ or if the specified sections or segments are not found in the cell model.
191
+ """
192
+ return run_multirecordings_stimulus(
193
+ template_params=template_params,
194
+ stimulus=stimulus,
195
+ section=section,
196
+ segment=segment,
197
+ cvode=cvode,
198
+ add_hypamp=add_hypamp,
199
+ recording_locations=[(recording_section, recording_segment)],
200
+ enable_spike_detection=enable_spike_detection,
201
+ threshold_spike_detection=threshold_spike_detection,
202
+ )[0]
131
203
 
132
204
 
133
205
  def apply_multiple_stimuli(
@@ -1,9 +1,21 @@
1
1
  """Module for plotting analysis results of cell simulations."""
2
2
 
3
3
  import matplotlib.pyplot as plt
4
+ import pathlib
4
5
 
5
6
 
6
- def plot_iv_curve(currents, voltages, injecting_section, injecting_segment, recording_section, recording_segment):
7
+ def plot_iv_curve(
8
+ currents,
9
+ voltages,
10
+ injecting_section,
11
+ injecting_segment,
12
+ recording_section,
13
+ recording_segment,
14
+ show_figure=True,
15
+ save_figure=False,
16
+ output_dir="./",
17
+ output_fname="iv_curve.pdf",
18
+ ):
7
19
  """Plots the IV curve.
8
20
 
9
21
  Args:
@@ -13,6 +25,10 @@ def plot_iv_curve(currents, voltages, injecting_section, injecting_segment, reco
13
25
  injecting_segment (float): The segment position (0.0 to 1.0) where the current was injected.
14
26
  recording_section (str): The section in the cell where spikes were recorded.
15
27
  recording_segment (float): The segment position (0.0 to 1.0) where spikes were recorded.
28
+ show_figure (bool): Whether to display the figure. Default is True.
29
+ save_figure (bool): Whether to save the figure. Default is False.
30
+ output_dir (str): The directory to save the figure if save_figure is True. Default is "./".
31
+ output_fname (str): The filename to save the figure as if save_figure is True. Default is "iv_curve.pdf".
16
32
 
17
33
  Raises:
18
34
  ValueError: If the lengths of currents and voltages do not match.
@@ -27,10 +43,27 @@ def plot_iv_curve(currents, voltages, injecting_section, injecting_segment, reco
27
43
  plt.ylabel(f"Steady state voltage [mV] at {recording_section}({recording_segment:.2f})")
28
44
  plt.grid(True)
29
45
  plt.tight_layout()
30
- plt.show()
46
+ if show_figure:
47
+ plt.show()
31
48
 
49
+ if save_figure:
50
+ pathlib.Path(output_dir).mkdir(parents=True, exist_ok=True)
51
+ plt.savefig(pathlib.Path(output_dir) / output_fname, format='pdf')
52
+ plt.close()
32
53
 
33
- def plot_fi_curve(currents, spike_count, injecting_section, injecting_segment, recording_section, recording_segment):
54
+
55
+ def plot_fi_curve(
56
+ currents,
57
+ spike_count,
58
+ injecting_section,
59
+ injecting_segment,
60
+ recording_section,
61
+ recording_segment,
62
+ show_figure=True,
63
+ save_figure=False,
64
+ output_dir="./",
65
+ output_fname="fi_curve.pdf",
66
+ ):
34
67
  """Plots the F-I (Frequency-Current) curve.
35
68
 
36
69
  Args:
@@ -40,6 +73,10 @@ def plot_fi_curve(currents, spike_count, injecting_section, injecting_segment, r
40
73
  injecting_segment (float): The segment position (0.0 to 1.0) where the current was injected.
41
74
  recording_section (str): The section in the cell where spikes were recorded.
42
75
  recording_segment (float): The segment position (0.0 to 1.0) where spikes were recorded.
76
+ show_figure (bool): Whether to display the figure. Default is True.
77
+ save_figure (bool): Whether to save the figure. Default is False.
78
+ output_dir (str): The directory to save the figure if save_figure is True. Default is "./".
79
+ output_fname (str): The filename to save the figure as if save_figure is True. Default is "fi_curve.pdf".
43
80
 
44
81
  Raises:
45
82
  ValueError: If the lengths of currents and spike counts do not match.
@@ -54,4 +91,10 @@ def plot_fi_curve(currents, spike_count, injecting_section, injecting_segment, r
54
91
  plt.ylabel(f"Spike Count recorded at {recording_section}({recording_segment:.2f})")
55
92
  plt.grid(True)
56
93
  plt.tight_layout()
57
- plt.show()
94
+ if show_figure:
95
+ plt.show()
96
+
97
+ if save_figure:
98
+ pathlib.Path(output_dir).mkdir(parents=True, exist_ok=True)
99
+ plt.savefig(pathlib.Path(output_dir) / output_fname, format='pdf')
100
+ plt.close()