myokit 1.33.9__py3-none-any.whl → 1.35.0__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.
Files changed (229) hide show
  1. myokit/__init__.py +9 -36
  2. myokit/__main__.py +76 -142
  3. myokit/_aux.py +62 -16
  4. myokit/_bin/example.mmt +1 -2
  5. myokit/_bin/install-win/menu.json +7 -7
  6. myokit/_config.py +22 -31
  7. myokit/_datablock.py +30 -74
  8. myokit/_datalog.py +49 -72
  9. myokit/_err.py +25 -24
  10. myokit/_expressions.py +50 -68
  11. myokit/_io.py +15 -27
  12. myokit/_model_api.py +453 -249
  13. myokit/_myokit_version.py +1 -5
  14. myokit/_parsing.py +38 -44
  15. myokit/_progress.py +5 -8
  16. myokit/_protocol.py +99 -9
  17. myokit/_sim/__init__.py +7 -24
  18. myokit/_sim/cable.c +6 -8
  19. myokit/_sim/cable.py +6 -8
  20. myokit/_sim/cmodel.h +125 -70
  21. myokit/_sim/cmodel.py +12 -14
  22. myokit/_sim/compiler.py +1 -4
  23. myokit/_sim/cvodessim.c +196 -118
  24. myokit/_sim/cvodessim.py +130 -103
  25. myokit/_sim/differential.hpp +4 -4
  26. myokit/_sim/fiber_tissue.c +4 -8
  27. myokit/_sim/fiber_tissue.py +11 -13
  28. myokit/_sim/jacobian.cpp +2 -2
  29. myokit/_sim/jacobian.py +11 -8
  30. myokit/_sim/mcl.h +53 -55
  31. myokit/_sim/opencl.py +21 -27
  32. myokit/_sim/openclsim.c +3 -7
  33. myokit/_sim/openclsim.cl +3 -3
  34. myokit/_sim/openclsim.py +49 -40
  35. myokit/_sim/pacing.h +36 -16
  36. myokit/_sim/rhs.c +6 -13
  37. myokit/_sim/rhs.py +5 -14
  38. myokit/_sim/sundials.py +1 -4
  39. myokit/_system.py +10 -16
  40. myokit/_unit.py +4 -13
  41. myokit/float.py +0 -3
  42. myokit/formats/__init__.py +8 -10
  43. myokit/formats/ansic/__init__.py +0 -3
  44. myokit/formats/ansic/_ewriter.py +2 -4
  45. myokit/formats/ansic/_exporter.py +1 -4
  46. myokit/formats/ansic/template/cable.c +4 -4
  47. myokit/formats/ansic/template/euler.c +5 -5
  48. myokit/formats/ansic/template/sim.c +6 -6
  49. myokit/formats/axon/__init__.py +1 -3
  50. myokit/formats/axon/_abf.py +12 -17
  51. myokit/formats/axon/_atf.py +5 -6
  52. myokit/formats/axon/_importer.py +0 -3
  53. myokit/formats/cellml/__init__.py +0 -3
  54. myokit/formats/cellml/_ewriter.py +3 -6
  55. myokit/formats/cellml/_exporter.py +3 -6
  56. myokit/formats/cellml/_importer.py +1 -4
  57. myokit/formats/cellml/v1/__init__.py +0 -4
  58. myokit/formats/cellml/v1/_api.py +8 -11
  59. myokit/formats/cellml/v1/_parser.py +2 -5
  60. myokit/formats/cellml/v1/_writer.py +2 -11
  61. myokit/formats/cellml/v2/__init__.py +0 -3
  62. myokit/formats/cellml/v2/_api.py +8 -17
  63. myokit/formats/cellml/v2/_parser.py +2 -5
  64. myokit/formats/cellml/v2/_writer.py +1 -4
  65. myokit/formats/channelml/__init__.py +0 -3
  66. myokit/formats/channelml/_importer.py +11 -21
  67. myokit/formats/cpp/__init__.py +1 -3
  68. myokit/formats/cpp/_ewriter.py +0 -3
  69. myokit/formats/cuda/__init__.py +0 -3
  70. myokit/formats/cuda/_ewriter.py +2 -4
  71. myokit/formats/cuda/_exporter.py +0 -3
  72. myokit/formats/cuda/template/kernel.cu +8 -5
  73. myokit/formats/easyml/__init__.py +0 -3
  74. myokit/formats/easyml/_ewriter.py +9 -11
  75. myokit/formats/easyml/_exporter.py +2 -5
  76. myokit/formats/html/__init__.py +0 -3
  77. myokit/formats/html/_exporter.py +0 -3
  78. myokit/formats/html/_flatten.py +5 -21
  79. myokit/formats/latex/__init__.py +0 -3
  80. myokit/formats/latex/_ewriter.py +1 -4
  81. myokit/formats/latex/_exporter.py +4 -6
  82. myokit/formats/mathml/__init__.py +0 -3
  83. myokit/formats/mathml/_ewriter.py +2 -11
  84. myokit/formats/mathml/_parser.py +4 -6
  85. myokit/formats/matlab/__init__.py +0 -3
  86. myokit/formats/matlab/_ewriter.py +1 -4
  87. myokit/formats/matlab/_exporter.py +2 -5
  88. myokit/formats/matlab/template/main.m +3 -2
  89. myokit/formats/opencl/__init__.py +0 -3
  90. myokit/formats/opencl/_ewriter.py +2 -4
  91. myokit/formats/opencl/_exporter.py +2 -5
  92. myokit/formats/opencl/template/cable.c +10 -10
  93. myokit/formats/opencl/template/kernel.cl +1 -1
  94. myokit/formats/opencl/template/minilog.py +1 -1
  95. myokit/formats/python/__init__.py +0 -3
  96. myokit/formats/python/_ewriter.py +2 -5
  97. myokit/formats/python/_exporter.py +0 -3
  98. myokit/formats/python/template/sim.py +14 -14
  99. myokit/formats/sbml/__init__.py +0 -3
  100. myokit/formats/sbml/_api.py +50 -44
  101. myokit/formats/sbml/_importer.py +1 -4
  102. myokit/formats/sbml/_parser.py +2 -5
  103. myokit/formats/stan/__init__.py +0 -3
  104. myokit/formats/stan/_ewriter.py +2 -4
  105. myokit/formats/stan/_exporter.py +2 -5
  106. myokit/formats/stan/template/cell.stan +3 -3
  107. myokit/formats/sympy/__init__.py +0 -3
  108. myokit/formats/sympy/_ereader.py +1 -4
  109. myokit/formats/sympy/_ewriter.py +2 -5
  110. myokit/formats/wcp/__init__.py +0 -3
  111. myokit/formats/wcp/_wcp.py +2 -8
  112. myokit/formats/xml/__init__.py +0 -3
  113. myokit/formats/xml/_exporter.py +0 -3
  114. myokit/formats/xml/_split.py +0 -3
  115. myokit/gui/__init__.py +80 -246
  116. myokit/gui/datablock_viewer.py +103 -86
  117. myokit/gui/datalog_viewer.py +214 -66
  118. myokit/gui/explorer.py +15 -21
  119. myokit/gui/ide.py +171 -144
  120. myokit/gui/progress.py +9 -9
  121. myokit/gui/source.py +406 -375
  122. myokit/gui/vargrapher.py +2 -12
  123. myokit/lib/deps.py +12 -13
  124. myokit/lib/guess.py +3 -4
  125. myokit/lib/hh.py +20 -18
  126. myokit/lib/markov.py +21 -20
  127. myokit/lib/multi.py +1 -3
  128. myokit/lib/plots.py +20 -9
  129. myokit/pacing.py +0 -3
  130. myokit/pype.py +7 -18
  131. myokit/tests/__init__.py +3 -6
  132. myokit/tests/ansic_event_based_pacing.py +1 -4
  133. myokit/tests/ansic_fixed_form_pacing.py +3 -6
  134. myokit/tests/data/beeler-1977-model-compare-b.mmt +2 -2
  135. myokit/tests/data/clancy-1999-fitting.mmt +1 -0
  136. myokit/tests/test_aux.py +13 -28
  137. myokit/tests/test_cellml_v1_api.py +4 -19
  138. myokit/tests/test_cellml_v1_parser.py +0 -15
  139. myokit/tests/test_cellml_v1_writer.py +0 -9
  140. myokit/tests/test_cellml_v2_api.py +4 -19
  141. myokit/tests/test_cellml_v2_parser.py +0 -15
  142. myokit/tests/test_cellml_v2_writer.py +0 -9
  143. myokit/tests/test_cmodel.py +16 -22
  144. myokit/tests/test_compiler_detection.py +1 -11
  145. myokit/tests/test_component.py +108 -56
  146. myokit/tests/test_config.py +34 -67
  147. myokit/tests/test_datablock.py +1 -9
  148. myokit/tests/test_datalog.py +19 -24
  149. myokit/tests/test_dependency_checking.py +8 -23
  150. myokit/tests/test_expressions.py +0 -9
  151. myokit/tests/test_float.py +1 -5
  152. myokit/tests/test_formats.py +0 -9
  153. myokit/tests/test_formats_axon.py +1 -9
  154. myokit/tests/test_formats_cellml.py +0 -15
  155. myokit/tests/test_formats_channelml.py +0 -15
  156. myokit/tests/test_formats_easyml.py +0 -14
  157. myokit/tests/test_formats_exporters.py +1 -16
  158. myokit/tests/test_formats_expression_writers.py +1 -17
  159. myokit/tests/test_formats_html.py +0 -3
  160. myokit/tests/test_formats_importers.py +1 -16
  161. myokit/tests/test_formats_mathml_content.py +0 -9
  162. myokit/tests/test_formats_mathml_presentation.py +0 -9
  163. myokit/tests/test_formats_opencl.py +0 -10
  164. myokit/tests/test_formats_sbml.py +0 -15
  165. myokit/tests/test_formats_sympy.py +0 -9
  166. myokit/tests/test_formats_wcp.py +1 -3
  167. myokit/tests/test_io.py +27 -27
  168. myokit/tests/test_jacobian_calculator.py +6 -14
  169. myokit/tests/test_jacobian_tracer.py +0 -9
  170. myokit/tests/test_lib_deps.py +0 -9
  171. myokit/tests/test_lib_guess.py +0 -9
  172. myokit/tests/test_lib_hh.py +18 -12
  173. myokit/tests/test_lib_markov.py +21 -13
  174. myokit/tests/test_lib_multi.py +0 -9
  175. myokit/tests/test_lib_plots.py +13 -8
  176. myokit/tests/test_meta.py +0 -3
  177. myokit/tests/test_model.py +390 -96
  178. myokit/tests/test_model_building.py +44 -96
  179. myokit/tests/test_opencl_info.py +5 -14
  180. myokit/tests/test_pacing_factory.py +0 -3
  181. myokit/tests/test_pacing_system_c.py +1 -23
  182. myokit/tests/test_pacing_system_py.py +0 -9
  183. myokit/tests/test_parsing.py +139 -56
  184. myokit/tests/test_progress_reporters.py +0 -3
  185. myokit/tests/test_protocol.py +0 -9
  186. myokit/tests/test_protocol_floating_point.py +1 -10
  187. myokit/tests/test_protocol_time_series.py +82 -0
  188. myokit/tests/test_pype.py +0 -9
  189. myokit/tests/test_quantity.py +0 -9
  190. myokit/tests/test_rhs_benchmarker.py +1 -9
  191. myokit/tests/test_sbml_api.py +27 -42
  192. myokit/tests/test_sbml_parser.py +4 -19
  193. myokit/tests/test_simulation_1d.py +45 -25
  194. myokit/tests/test_simulation_cvodes.py +321 -55
  195. myokit/tests/test_simulation_cvodes_from_disk.py +0 -3
  196. myokit/tests/test_simulation_fiber_tissue.py +39 -12
  197. myokit/tests/test_simulation_log_interval.py +1 -431
  198. myokit/tests/test_simulation_opencl.py +69 -48
  199. myokit/tests/test_simulation_opencl_log_interval.py +1 -3
  200. myokit/tests/test_simulation_opencl_vs_cvode.py +1 -10
  201. myokit/tests/test_simulation_opencl_vs_sim1d.py +1 -10
  202. myokit/tests/test_system_info.py +1 -11
  203. myokit/tests/test_tools.py +0 -9
  204. myokit/tests/test_unit.py +1 -10
  205. myokit/tests/test_user_functions.py +0 -10
  206. myokit/tests/test_variable.py +231 -27
  207. myokit/tools.py +5 -21
  208. myokit/units.py +5 -3
  209. {myokit-1.33.9.dist-info → myokit-1.35.0.dist-info}/METADATA +12 -15
  210. myokit-1.35.0.dist-info/RECORD +391 -0
  211. {myokit-1.33.9.dist-info → myokit-1.35.0.dist-info}/WHEEL +1 -1
  212. {myokit-1.33.9.dist-info → myokit-1.35.0.dist-info}/entry_points.txt +0 -1
  213. myokit/_exec_new.py +0 -15
  214. myokit/_exec_old.py +0 -15
  215. myokit/_sim/cvodesim.c +0 -1551
  216. myokit/_sim/cvodesim.py +0 -674
  217. myokit/_sim/icsim.cpp +0 -563
  218. myokit/_sim/icsim.py +0 -363
  219. myokit/_sim/psim.cpp +0 -656
  220. myokit/_sim/psim.py +0 -493
  221. myokit/lib/common.py +0 -1094
  222. myokit/tests/test_lib_common.py +0 -130
  223. myokit/tests/test_simulation_cvode.py +0 -612
  224. myokit/tests/test_simulation_ic.py +0 -108
  225. myokit/tests/test_simulation_p.py +0 -223
  226. myokit-1.33.9.dist-info/RECORD +0 -403
  227. /myokit/formats/opencl/template/{test → test.sh} +0 -0
  228. {myokit-1.33.9.dist-info → myokit-1.35.0.dist-info}/LICENSE.txt +0 -0
  229. {myokit-1.33.9.dist-info → myokit-1.35.0.dist-info}/top_level.txt +0 -0
myokit/lib/common.py DELETED
@@ -1,1094 +0,0 @@
1
- #
2
- # Common experiments (activation, inactivation, etc.).
3
- #
4
- # Some functions in this module require a recent version of scipy (i.e. the
5
- # method scipy.optimize.curve_fit must exist).
6
- #
7
- # This file is part of Myokit.
8
- # See http://myokit.org for copyright, sharing, and licensing details.
9
- #
10
- from __future__ import absolute_import, division
11
- from __future__ import print_function, unicode_literals
12
-
13
- import numpy as np
14
- import myokit
15
-
16
- # Strings in Python 2 and 3
17
- try:
18
- basestring
19
- except NameError: # pragma: no python 2 cover
20
- basestring = str
21
-
22
-
23
- #
24
- # Deprecated since 2018-04-16
25
- #
26
- import warnings
27
- warnings.warn(
28
- 'The module myokit.lib.common is deprecated: it will be removed in future'
29
- ' versions of Myokit.'
30
- )
31
-
32
-
33
- class StepProtocol(object):
34
- """
35
- An abstract base class for step protocol experiments.
36
- """
37
- def __init__(self, model, var, vvar=None):
38
- # Clone model
39
- self._model = model.clone()
40
- # Get variable names
41
- self._vars = []
42
- if isinstance(var, (basestring, myokit.Variable)):
43
- var = [var]
44
- for v in var:
45
- if isinstance(v, myokit.Variable):
46
- v = v.qname()
47
- self._vars.append(self._model.get(v).qname())
48
- # Turn the membrane potential into a constant
49
- if vvar is None:
50
- vvar = self._model.label('membrane_potential')
51
- if vvar is None:
52
- raise ValueError(
53
- 'Membrane potential variable must be given as the argument'
54
- ' "vvar" or labeled in the model as "membrane_potential".')
55
- else:
56
- if isinstance(vvar, myokit.Variable):
57
- vvar = vvar.qname()
58
- vvar = self._model.get(vvar)
59
- if vvar.is_state():
60
- vvar.demote()
61
- vvar.set_binding(None)
62
- vvar.set_rhs(0)
63
- # Get membrane potential name
64
- self._vvar = vvar.qname()
65
- # Get time variable name
66
- self._tvar = self._model.time().qname()
67
- # Start without any conversion factor
68
- self._factor = None
69
- # Maximum step size during logged simulation or None
70
- self._max_step_size = None
71
- # No simulation data yet
72
- self._logs = None
73
- # Holding potential & step potentials
74
- self.set_holding_potential()
75
- self.set_step_potential()
76
-
77
- def convert_g2i(self, vrev=60, gmax=1):
78
- """
79
- Converts any data logged during this experiment from conductances to
80
- currents by multiplying each step's data by::
81
-
82
- gmax * (v - vrev)
83
-
84
- This can be useful to obtain the original current traces when a
85
- conductance value was logged or when creating an IV protocol.
86
-
87
- Calling this method will override any previously set conversion factor.
88
- """
89
- self._factor = float(gmax) * (self._steps - float(vrev))
90
-
91
- def convert_i2g(self, vrev=60, gmax=1):
92
- """
93
- Converts any data logged during this experiment from currents to
94
- conductance by multiplying each step's data by::
95
-
96
- 1 / (gmax * (v - vrev))
97
-
98
- This can be useful to obtain an activation or inactivation curve from
99
- logged current data. However, since this leads to numerical issues
100
- around ``v == vrev`` its better to run these experiments directly on a
101
- conductance variable.
102
-
103
- Calling this method will override any previously set conversion factor.
104
- """
105
- self._factor = 1.0 / (float(gmax) * (self._steps - float(vrev)))
106
-
107
- def disable_conversion(self):
108
- """
109
- Disables any previously set conversion factor.
110
- """
111
- self._factor = None
112
-
113
- def fit_boltzmann(self, var=None):
114
- """
115
- Attempts to fit a Boltzmann curve to a voltage-peaks dataset.
116
-
117
- The variable whose peaks to use can be specified as ``var``. If no
118
- variable is given the first value specified in the constructor is used.
119
- The fitted curve is given by::
120
-
121
- g = gmin + (gmax - gmin) / (1 + np.exp((v - v_half) / k))
122
-
123
- Note: This method requires a scipy installation providing the method
124
- scipy.optimize.curve_fit
125
- """
126
- from scipy.optimize import curve_fit
127
- d = self.peaks(normalize=True).npview()
128
- v = d[self._vvar]
129
- g = d[var] if var else d[self._vars[0]]
130
- o = np.ones(v.shape)
131
- gmin = np.min(g)
132
- gmax = np.max(g)
133
-
134
- def f(v, v_half, k):
135
- return np.select(
136
- [v == v_half],
137
- [o * k],
138
- gmin + (gmax - gmin) / (1.0 + np.exp((v - v_half) / k)))
139
-
140
- vmid = v[-1] - v[0]
141
- slope = -5 if g[0] < g[-1] else 5
142
- p = curve_fit(f, v, g, [vmid, slope])
143
- return p[0]
144
-
145
- def peaks(self, normalize=False):
146
- """
147
- Returns a :class:`myokit.DataLog` containing the tested step
148
- voltages and the peak values of the logged variable(s).
149
-
150
- The names used in the simulation log correspond to those used in the
151
- model. For example, when doing an experiment on a Sodium channel the
152
- simulation log might have entries ``membrane.v`` and ``ina.g`` where
153
- ``membrane.v`` contains the used voltage steps while ``ina.g`` contains
154
- the peak values measured at those voltages.
155
-
156
- If ``normalize`` is set to ``True``, the peak data returned will be
157
- normalized by dividing all values by the largest (most positive) peak
158
- in the list. If no positive, non-zero values are found no normalization
159
- will be applied.
160
-
161
- If any conversion factor was specified the data will be converted
162
- before normalization.
163
- """
164
- # Run simulation if needed
165
- if self._logs is None:
166
- self._run()
167
- # Create a copy of the voltage steps
168
- v = np.array(self._steps, copy=True)
169
- # Create a simulation log
170
- d = myokit.DataLog()
171
- d[self._vvar] = v
172
- # Factor
173
- factor = self._factor if self._factor is not None else 1
174
- # Find the peaks
175
- for var in self._vars:
176
- peaks = np.zeros(len(v))
177
- for k, log in enumerate(self._logs):
178
- peaks[k] = log[var][np.argmax(np.abs(log[var]))]
179
- d[var] = peaks * factor
180
- # Normalize (only if log contains positive values)
181
- if normalize:
182
- for var in self._vars:
183
- x = d[var]
184
- m = np.max(x)
185
- if m > 0:
186
- d[var] = x / m
187
- return d
188
-
189
- def _run(self):
190
- """
191
- Should run the simulation and save the current traces in self._logs
192
- """
193
- raise NotImplementedError
194
-
195
- def set_constant(self, var, value):
196
- """
197
- Changes the value of a constant in the used model.
198
- """
199
- if isinstance(var, myokit.Variable):
200
- var = var.qname()
201
- var = self._model.get(var)
202
- self._model.set_value(var, value)
203
- self._logs = None
204
-
205
- def set_holding_potential(self, vhold=-140, thold=1800):
206
- """
207
- Sets the holding potential and the time to hold. During the experiment,
208
- the cell will be held at ``vhold`` for ``thold`` time units before
209
- every voltage step.
210
- """
211
- vhold = float(vhold)
212
- thold = float(thold)
213
- if thold < 0:
214
- raise ValueError('Time to hold cannot be negative.')
215
- self._vhold = vhold
216
- self._thold = thold
217
- self._logs = None
218
-
219
- def set_max_step_size(self, dtmax=None):
220
- """
221
- Can be used to set a maximum step size to use in the logged parts of
222
- the simulation. Use ``dtmax==None`` to let the solver chose any size it
223
- likes.
224
- """
225
- self._max_step_size = None if dtmax is None else float(dtmax)
226
-
227
- def set_step_potential(self, vmin=-100, vmax=50, dv=1, tstep=200):
228
- """
229
- Sets the step potentials and the step duration. Each experiment will
230
- step linearly from ``vmin`` to ``vmax`` with steps of size ``dv``. The
231
- cell is held at each step for ``tstep`` time units.
232
- """
233
- vmin = float(vmin)
234
- vmax = float(vmax)
235
- dv = float(dv)
236
- tstep = float(tstep)
237
- if vmax <= vmin:
238
- raise ValueError(
239
- 'Maximum voltage must be greater than minimum voltage.')
240
- if dv <= 0:
241
- raise ValueError(
242
- 'The voltage increment dv must be greater than zero.')
243
- if tstep < 0:
244
- raise ValueError('Step duration cannot be negative.')
245
- self._vmin = vmin
246
- self._vmax = vmax
247
- self._dv = dv
248
- self._tstep = tstep
249
- self._steps = np.arange(self._vmin, self._vmax + self._dv, self._dv)
250
- self._logs = None
251
-
252
- def steps(self):
253
- """
254
- Returns the list of steps this protocol will use.
255
- """
256
- return list(self._steps)
257
-
258
- def times(self):
259
- """
260
- Returns a :class:`myokit.DataLog` containing the time-to-peak for
261
- each logged variable at each voltage step.
262
- """
263
- # Run simulation if needed
264
- if self._logs is None:
265
- self._run()
266
- # Create a copy of the voltage steps
267
- v = np.array(self._steps, copy=True)
268
- # Create a simulation log
269
- d = myokit.DataLog()
270
- d[self._vvar] = v
271
- # Find the peaks
272
- for var in self._vars:
273
- times = np.zeros(len(v))
274
- for k, log in enumerate(self._logs):
275
- times[k] = log[self._tvar][np.argmax(np.abs(log[var]))]
276
- d[var] = times
277
- return d
278
-
279
- def traces(self):
280
- """
281
- Returns the logged traces for each variable as an ordered list of
282
- tuples ``(v, DataLog)``.
283
-
284
- If any conversion factor was specified the data will be converted
285
- before returning.
286
- """
287
- if self._logs is None:
288
- self._run()
289
- data = []
290
- steps = iter(self._steps)
291
- factor = self._factor
292
- if factor is None:
293
- factor = np.ones(len(self._steps))
294
- for k, log in enumerate(self._logs):
295
- v = next(steps)
296
- d = myokit.DataLog()
297
- for var in self._vars:
298
- d[var] = np.array(log[var]) * factor[k]
299
- d[self._tvar] = log[self._tvar]
300
- data.append((v, d))
301
- return data
302
-
303
-
304
- class Activation(StepProtocol):
305
- """
306
- Runs a step protocol and measures during the step. Can be used to create
307
- activation curves and I-V curves.
308
-
309
- The protocol is defined as follows: Initially, the membrane potential is
310
- held at a holding potential ``vhold`` for the duration of ``thold`` time
311
- units. Then, the voltage is changed to ``vstep`` and held there for
312
- ``vstep`` time units. During this step, the cell's response is logged. The
313
- experiment is repeated for ``vstep`` values ranging linearly from ``vmin``
314
- to ``vmax`` with an increment of ``dv``.
315
-
316
- ::
317
-
318
- . +--- vstep ---+
319
- . +-------------+
320
- . +-------------+
321
- . | |
322
- . vhold -------+ +-
323
- . t=0 t=thold t=thold+tstep
324
- . no current current!
325
-
326
- Accepts the following input arguments:
327
-
328
- ``model``
329
- The model for which to run the simulations
330
- ``var``
331
- A variable or a list of variables to log and use in calculations
332
- ``vvar``
333
- The membrane potential variable or its qname. If not given, the method
334
- will search for a variable labelled ``membrane_potential``.
335
-
336
- Depending on the experiment being run, ``var`` could be a conductance or a
337
- current variable (or a list of conductances or currents).
338
-
339
- The experiment is not performed until a call to one of the post-processing
340
- methods is made. After this, the raw data will be cached. Any change to the
341
- protocol variables after this point will delete the cached data.
342
- """
343
- def __init__(self, model, var, vvar=None):
344
- super(Activation, self).__init__(model, var, vvar)
345
-
346
- def _run(self):
347
- """
348
- Runs the experiment, logs during the voltage steps.
349
- """
350
- log = self._vars + [self._tvar]
351
- s = myokit.Simulation(self._model)
352
- d = []
353
- for v in self._steps:
354
- s.reset()
355
- s.set_constant(self._vvar, self._vhold)
356
- s.set_max_step_size(None)
357
- s.pre(self._thold)
358
- s.set_constant(self._vvar, v)
359
- s.set_max_step_size(self._max_step_size)
360
- d.append(s.run(self._tstep, log=log))
361
- self._logs = d
362
-
363
-
364
- class Inactivation(StepProtocol):
365
- """
366
- Can run an inactivation step protocol on a model and calculate various
367
- entities using the results.
368
-
369
- The protocol starts by holding the membrane potential at a high value,
370
- causing the channels to fully activate and then inactivate. Next, the
371
- potential is stepped to a lower value, causing the inactivation to go away
372
- while the activation stays close to full. Current is measured after the
373
- step, when the cell is at the holding potential.
374
-
375
- ::
376
-
377
- . --- vstep ---+
378
- . -------------+
379
- . -------------+
380
- . |
381
- . +--- vhold ---+-
382
- . t=0 t=tstep t=tstep+thold
383
-
384
- Accepts the following input arguments:
385
-
386
- ``model``
387
- The model for which to run the simulations
388
- ``var``
389
- A variable or a list of variables to log and use in calculations
390
- ``vvar``
391
- The membrane potential variable or its qname. If not given, the method
392
- will search for a variable labelled ``membrane_potential``.
393
-
394
- Depending on the experiment being run, ``var`` could be a conductance or a
395
- current variable (or a list of conductances or currents).
396
-
397
- The experiment is not performed until a call to one of the post-processing
398
- methods is made. After this, the raw data will be cached. Any change to the
399
- protocol variables after this point will delete the cached data.
400
- """
401
- def __init__(self, model, var, vvar=None):
402
- super(Inactivation, self).__init__(model, var, vvar)
403
-
404
- def _run(self):
405
- """
406
- Runs the simulation, saves the current traces.
407
- """
408
- log = self._vars + [self._tvar]
409
- d = []
410
- s = myokit.Simulation(self._model)
411
- for v in self._steps:
412
- s.reset()
413
- s.set_constant(self._vvar, v)
414
- s.pre(self._tstep)
415
- s.set_constant(self._vvar, self._vhold)
416
- d.append(s.run(self._thold, log=log))
417
- self._logs = d
418
-
419
- def set_holding_potential(self, vhold=-20, thold=50):
420
- """
421
- Sets the holding potential and the time to hold. During the experiment,
422
- the cell will be held at ``vhold`` for ``thold`` time units before
423
- every voltage step.
424
- """
425
- super(Inactivation, self).set_holding_potential(vhold, thold)
426
-
427
- def set_step_potential(self, vmin=-100, vmax=-40, dv=1, tstep=1000):
428
- """
429
- Sets the step potentials and the step duration. Each experiment will
430
- step linearly from ``vmin`` to ``vmax`` with steps of size ``dv``. The
431
- cell is held at each step for ``tstep`` time units.
432
- """
433
- super(Inactivation, self).set_step_potential(vmin, vmax, dv, tstep)
434
-
435
-
436
- class Recovery(object):
437
- """
438
- Can run a two-pulse recovery from inactivation experiment and process the
439
- results.
440
-
441
- The experiment proceeds as follows: first, the cell is held at a low
442
- holding potential ``vhold`` for ``thold`` time units. This causes the
443
- channels to fully deactivate (activation=0) and fully recover from
444
- inactivation (inactivation=1). Next, the membrane is stepped up to a
445
- voltage ``vstep`` and kept there for ``tstep1`` time units. This causes the
446
- channels to activate (activation=1) and then inactivate (inactivation=0).
447
- The model then steps back down to ``vhold`` for ``twait`` time units,
448
- during which partial recovery from inactivation is expected. After this
449
- short recovery period, the cell is stepped back to ``vstep`` for another
450
- ``tstep2`` time units. The recovery from inactivation can then be judged
451
- by comparing the peak current during step2 with the peak current during
452
- step1. By varying the time between steps ``twait`` a plot of recovery
453
- characteristics can be made.
454
-
455
- ::
456
-
457
- . +--- vstep ---+ +- vstep -+
458
- . | | twait | |
459
- . | | <-----> | |
460
- . | | | |
461
- . +--- vhold ---+ +- vhold -+ +---
462
- . t=0 t=thold t+=tstep1 t+=twait t+=tstep2
463
-
464
- Accepts the following input arguments:
465
-
466
- ``model``
467
- The model for which to run the simulations
468
- ``var``
469
- A conductance variable (or a list of variables) to record during the
470
- experiment. Variables can be specified using Variable objects or
471
- through their fully qualified names.
472
- ``vvar``
473
- The membrane potential variable or its qname. If not given, the method
474
- will search for a variable labelled ``membrane_potential``.
475
-
476
- The argument ``var`` expects conduction variables, not currents. In other
477
- words, it expects the name of a variable ``g`` such that
478
- ``I = Gmax * g * (V - E)``. Using conductance in this test rather than
479
- current avoids the numerical problems incurred by dividing ``I`` through
480
- ``(V-E)``.
481
- """
482
- def __init__(self, model, var, vvar=None):
483
- if not model.is_valid():
484
- raise ValueError('This method requires a valid model.')
485
- # Clone model & variables
486
- self._model = model.clone()
487
-
488
- # Get time variable
489
- self._tvar = self._model.time()
490
-
491
- # Check conductance variables
492
- self._vars = []
493
- if isinstance(var, (basestring, myokit.Variable)):
494
- var = [var]
495
- for v in var:
496
- if isinstance(v, myokit.Variable):
497
- v = v.qname()
498
- elif '.' not in v:
499
- raise ValueError(
500
- 'The variable name(s) given as var must be given as fully'
501
- ' qualified names <component.variable>.')
502
- self._vars.append(self._model.get(v))
503
-
504
- # Check membrane potential
505
- if vvar is None:
506
- self._vvar = self._model.label('membrane_potential')
507
- if self._vvar is None:
508
- raise ValueError(
509
- 'Membrane potential variable must be given by vvar or'
510
- ' specified using the label "membrane_potential".')
511
- else:
512
- if isinstance(vvar, myokit.Variable):
513
- vvar = vvar.qname()
514
- elif '.' not in vvar:
515
- raise ValueError(
516
- 'The variable name vvar must be given as a fully qualified'
517
- ' variable name <component.var>.')
518
- self._vvar = self._model.get(vvar)
519
-
520
- # Update membrane potential variable
521
- if self._vvar.is_state():
522
- self._vvar.demote()
523
- self._vvar.set_binding(None)
524
-
525
- # Set voltages
526
- self.set_holding_potential()
527
- self.set_step_potential()
528
- self.set_pause_duration()
529
-
530
- def ratio(self):
531
- """
532
- Returns the ratios of the peak conductances (p1 / p2) for step 1 and
533
- step 2.
534
-
535
- The returned value is a :class:`myokit.DataLog` with entries
536
- corresponding to the given variable names.
537
- """
538
- # Times to wait
539
- twaits = np.exp(
540
- np.linspace(np.log(self._tmin), np.log(self._tmax), self._nt))
541
-
542
- # Variables to log
543
- log_vars = [x.qname() for x in self._vars]
544
-
545
- # Run simulations
546
- self._vvar.set_rhs(self._vhold) # Make V a constant
547
- s = myokit.Simulation(self._model)
548
- log = myokit.DataLog()
549
- gvars = [x.qname() for x in self._vars]
550
- for g in gvars:
551
- log[g] = []
552
- log[self._tvar.qname()] = list(twaits)
553
- for twait in twaits:
554
- s.set_constant(self._vvar, self._vhold)
555
- s.run(self._thold, log=myokit.LOG_NONE)
556
- s.set_constant(self._vvar, self._vstep)
557
- d1 = s.run(self._tstep1, log=log_vars)
558
- s.set_constant(self._vvar, self._vhold)
559
- s.run(twait, log=myokit.LOG_NONE)
560
- s.set_constant(self._vvar, self._vstep)
561
- d2 = s.run(self._tstep2, log=log_vars)
562
- for g in gvars:
563
- ratio = np.max(d1[g])
564
- ratio = np.nan if ratio == 0 else np.max(d2[g]) / ratio
565
- log[g].append(ratio)
566
- return log
567
-
568
- def set_holding_potential(self, vhold=-120, thold=2000):
569
- """
570
- Sets the holding potential and the time to hold. During the experiment,
571
- the cell will be held at ``vhold`` for ``thold`` time units before
572
- every voltage step.
573
- """
574
- vhold = float(vhold)
575
- thold = float(thold)
576
- if thold < 0:
577
- raise ValueError('Time to hold cannot be negative.')
578
- self._vhold = vhold
579
- self._thold = thold
580
-
581
- def set_pause_duration(self, tmin=0.5, tmax=1000, nt=50):
582
- """
583
- Sets the duration of the pauses between the steps.
584
-
585
- ``tmin``
586
- The shortest time between steps
587
- ``tmax``
588
- The longest time between steps
589
- ``nt``
590
- The number of times to test
591
-
592
- """
593
- tmin = float(tmin)
594
- tmax = float(tmax)
595
- nt = int(nt)
596
- if tmin < 0:
597
- raise ValueError('Minimum time cannot be negative.')
598
- if tmax < 0:
599
- raise ValueError('Maximum time cannot be positive.')
600
- if tmin >= tmax:
601
- raise ValueError('Maximum time must be grater than minimum.')
602
- if nt < 2:
603
- raise ValueError(
604
- 'The number of times to test must be greater than one.')
605
- self._tmin = tmin
606
- self._tmax = tmax
607
- self._nt = nt
608
-
609
- def set_step_potential(self, vstep=-20, tstep1=500, tstep2=25):
610
- """
611
- Sets the step potential and the step durations.
612
-
613
- ``vstep``
614
- The potential used during the steps
615
- ``tstep1``
616
- The duration of the first pulse
617
- ``tstep2``
618
- The duration of the second pulse
619
-
620
- """
621
- vstep = float(vstep)
622
- tstep1 = float(tstep1)
623
- tstep2 = float(tstep2)
624
- if tstep1 < 0:
625
- raise ValueError('Time of first step cannot be negative.')
626
- if tstep2 < 0:
627
- raise ValueError('Time of second step cannot be negative.')
628
- self._vstep = vstep
629
- self._tstep1 = tstep1
630
- self._tstep2 = tstep2
631
-
632
-
633
- class Restitution(object):
634
- """
635
- Can run a restitution experiment and return the values needed to make a
636
- plot.
637
-
638
- Accepts the following input arguments:
639
-
640
- ``model``
641
- The model for which to run the simulations
642
- ``vvar``
643
- The variable or variable name representing membrane potential. If not
644
- given, the method will look for the label ``membrane_potential``, if
645
- that's not found an exception is raised.
646
-
647
- """
648
- def __init__(self, model, vvar=None):
649
- # Check model
650
- self._model = model.clone()
651
-
652
- # Check membrane potential
653
- if vvar is None:
654
- self._vvar = self._model.label('membrane_potential')
655
- if self._vvar is None:
656
- raise ValueError(
657
- 'Membrane potential variable must be given by vvar or'
658
- ' specified using the label "membrane_potential".')
659
- else:
660
- if isinstance(vvar, myokit.Variable):
661
- vvar = vvar.qname()
662
- elif '.' not in vvar:
663
- raise ValueError(
664
- 'The variable name vvar must be given as a fully qualified'
665
- ' variable name <component.var>.')
666
- self._vvar = self._model.get(vvar)
667
-
668
- # Set default arguments
669
- self.set_max_step_size()
670
- self.set_times()
671
- self.set_beats()
672
- self.set_stimulus()
673
- self.set_threshold()
674
-
675
- # No data yet!
676
- self._data = None
677
-
678
- def _run(self):
679
- """
680
- Runs the simulations, saves the data.
681
- """
682
- # Create protocol
683
- e = {
684
- 'level': self._stim_level,
685
- 'start': 0,
686
- 'duration': self._stim_duration,
687
- 'period': self._clmin,
688
- 'multiplier': 0,
689
- }
690
-
691
- # Create simulation
692
- s = myokit.Simulation(self._model)
693
- s.set_max_step_size(self._max_step_size)
694
-
695
- # Start testing
696
- i = 0
697
- pcls = []
698
- apds = []
699
- c = self._clmax
700
- while c >= self._clmin:
701
- # Update cycle length
702
- c = self._clmax - i * self._dcl
703
- i += 1
704
-
705
- # Create and set new protocol
706
- p = myokit.Protocol()
707
- e['period'] = c
708
- p.schedule(**e)
709
- s.set_protocol(p)
710
-
711
- # Run simulation
712
- s.reset()
713
- s.pre(c * self._pre_beats)
714
- d, a = s.run(
715
- c * self._beats,
716
- log=myokit.LOG_NONE,
717
- apd_variable=self._vvar,
718
- apd_threshold=self._apd_threshold
719
- )
720
-
721
- # Save apds
722
- for apd in a['duration']:
723
- pcls.append(c)
724
- apds.append(apd)
725
-
726
- # Store data
727
- self._data = pcls, apds
728
-
729
- def run(self):
730
- """
731
- Returns a :class:`DataLog` containing the tested cycle lengths as
732
- ``cl`` and the measured action potential durations as ``apd``. The
733
- diastolic intervals are given as ``di``.
734
-
735
- Each cycle length is repeated ``beats`` number of times, where
736
- ``beats`` is the number of beats specified in the constructor.
737
- """
738
- # Run
739
- if self._data is None:
740
- self._run()
741
- # Get data
742
- cl, apd = self._data
743
- d = myokit.DataLog()
744
- d['cl'] = list(cl)
745
- d['apd'] = list(apd)
746
- d['di'] = list(np.array(cl, copy=False) - np.array(apd, copy=False))
747
- return d
748
-
749
- def set_beats(self, beats=2, pre=50):
750
- """
751
- Sets the number of beats each cycle length is tested for.
752
-
753
- ``beats``
754
- The number of beats during which apd is measured
755
- ``pre``
756
- The number of pre-pacing beats done at each cycle length before the
757
- measurement.
758
- """
759
- beats = int(beats)
760
- pre = int(pre)
761
- if beats < 1:
762
- raise ValueError(
763
- 'The number of beats must be an integer greater than zero.')
764
- if pre < 0:
765
- raise ValueError(
766
- 'The number of pre-pacing beats must be a positive integer.')
767
- self._beats = beats
768
- self._pre_beats = pre
769
- self._data = None
770
-
771
- def set_max_step_size(self, dtmax=None):
772
- """
773
- Sets an (optional) maximum step size for the solver. To let the solver
774
- pick any step size it likes, use ``dtmax=None``.
775
-
776
- This method can be useful to avoid "CVODES flag 22" errors.
777
- """
778
- if dtmax is None:
779
- self._max_step_size = None
780
- else:
781
- dtmax = float(dtmax)
782
- if dtmax <= 0:
783
- raise ValueError(
784
- 'Maximum step size must be greater than zero.')
785
- self._max_step_size = dtmax
786
- self._data = None
787
-
788
- def set_stimulus(self, duration=2.0, level=1):
789
- """
790
- Sets the stimulus used to pace the model.
791
-
792
- ``stim_duration``
793
- The duration of the pacing stimulus.
794
- ``stim_level``
795
- The level of the dimensionless pacing stimulus.
796
-
797
- """
798
- duration = float(duration)
799
- level = float(level)
800
- if duration < 0:
801
- raise ValueError('The duratio cannot be negative.')
802
- self._stim_duration = duration
803
- self._stim_level = level
804
- self._data = None
805
-
806
- def set_threshold(self, threshold=-70):
807
- """
808
- Sets the APD threshold, specified as a fixed membrane potential.
809
- """
810
- self._apd_threshold = float(threshold)
811
- self._data = None
812
-
813
- def set_times(self, clmin=300, clmax=1200, dcl=20):
814
- """
815
- Sets the pacing cycle lengths tested in this experiment.
816
-
817
- ``clmin``
818
- The shortest cycle length tested.
819
- ``clmax``
820
- The longest cycle length tested.
821
- ``dcl``
822
- The size of the steps from ``clmin`` to ``clmax``
823
-
824
- """
825
- clmin = float(clmin)
826
- clmax = float(clmax)
827
- dcl = float(dcl)
828
- if clmin < 0:
829
- raise ValueError('Minimum time cannot be negative.')
830
- if clmin >= clmax:
831
- raise ValueError('Minimum time must be smaller than maximum time.')
832
- if dcl <= 0:
833
- raise ValueError('Step size must be greater than zero')
834
- self._clmin = clmin
835
- self._clmax = clmax
836
- self._dcl = dcl
837
- self._data = None
838
-
839
-
840
- class StrengthDuration(object):
841
- """
842
- For a range of durations, this experiment checks the stimulus size needed
843
- to excite a cell.
844
-
845
- Accepts the following input arguments:
846
-
847
- ``model``
848
- The model to run the experiment with.
849
- ``ivar``
850
- A variable that can be used as the stimulus current. It's value will
851
- be set as ``pace * amplitude`` where pace is a variable bound to the
852
- pacing signal and amplitude is varied by the method.
853
- ``vvar``
854
- A variable that indicates the membrane potential. If not specified (or
855
- given as ``None``), the method will search for a variable labeled as
856
- ``membrane_potential``.
857
-
858
- """
859
- def __init__(self, model, ivar, vvar=None):
860
- # Clone model
861
- self._model = model.clone()
862
- del model
863
-
864
- # Get stimulus current variable
865
- if isinstance(ivar, myokit.Variable):
866
- ivar = ivar.qname()
867
- self._ivar = self._model.get(ivar)
868
- del ivar
869
-
870
- # Get membrane potential variable
871
- if vvar is None:
872
- self._vvar = self._model.label('membrane_potential')
873
- if self._vvar is None:
874
- raise ValueError(
875
- 'This method requires the membrane potential variable to'
876
- ' be passed in as `vvar` or indicated in the model using'
877
- ' the label `membrane_potential`.')
878
- else:
879
- if isinstance(vvar, myokit.Variable):
880
- vvar = vvar.qname()
881
- self._vvar = self._model.get(vvar)
882
- del vvar
883
-
884
- # Get time variable
885
- self._tvar = self._model.time()
886
-
887
- # Unbind any existing pace variable
888
- var = self._model.binding('pace')
889
- if var is not None:
890
- var.set_binding(None)
891
-
892
- # Create new pacing variable
893
- c = self._ivar.parent(myokit.Component)
894
-
895
- def add_variable(c, name):
896
- try:
897
- return c.add_variable(name)
898
- except myokit.DuplicateName:
899
- i = 2
900
- n = name + str(i)
901
- while True:
902
- try:
903
- return c.add_variable(n)
904
- except myokit.DuplicateName:
905
- i += 1
906
- n = name + str(i)
907
- self._pvar = add_variable(c, 'pace')
908
- self._pvar.set_binding('pace')
909
- self._pvar.set_rhs(0)
910
-
911
- # Create new amplitude variable
912
- self._avar = add_variable(c, 'amplitude')
913
- self._avar.set_rhs(0)
914
-
915
- # Set rhs of current variable
916
- if self._ivar.is_state():
917
- self._ivar.demote()
918
- self._ivar.set_rhs(myokit.Multiply(self._pvar.lhs(), self._avar.lhs()))
919
-
920
- # Set default parameters
921
- self.set_currents()
922
- self.set_precision()
923
- self.set_threshold()
924
- self.set_times()
925
-
926
- # No data yet!
927
- self._data = None
928
-
929
- def run(self, debug=False):
930
- """
931
- Runs the experiment, returning a :class:`myokit.DataLog` with the
932
- entries ``duration`` and ``strength``, where each strenght is the
933
- minimum required to create a depolarisation at the corresponding
934
- duration.
935
- """
936
- if self._data is None:
937
- self._run(debug)
938
- return self._data
939
-
940
- def _run(self, debug=False):
941
- """
942
- Inner version of run()
943
- """
944
- if debug:
945
- import traceback
946
-
947
- # Create simulation
948
- s = myokit.Simulation(self._model)
949
-
950
- # Variables to log
951
- vvar = self._vvar.qname()
952
-
953
- # Output data
954
- durations = np.array(self._durations, copy=True)
955
- amplitudes = np.zeros(durations.shape)
956
-
957
- # Test every duration
958
- for k, duration in enumerate(durations):
959
- if debug:
960
- print('Testing duration: ' + str(duration))
961
- s.set_protocol(myokit.pacing.blocktrain(self._time + 1, duration))
962
- a1 = self._amin
963
- a2 = self._amax
964
-
965
- # Test minimum amplitude
966
- s.reset()
967
- s.set_constant(self._avar, a1)
968
- try:
969
- d = s.run(self._time, log=[vvar]).npview()
970
- t1 = (np.max(d[vvar]) > self._threshold)
971
- except Exception:
972
- if debug:
973
- traceback.print_exc()
974
- t1 = False
975
- if debug:
976
- print(t1)
977
-
978
- # Test maximum amplitude
979
- s.reset()
980
- s.set_constant(self._avar, a2)
981
- try:
982
- d = s.run(self._time, log=[vvar]).npview()
983
- t2 = (np.max(d[vvar]) > self._threshold)
984
- except Exception:
985
- if debug:
986
- traceback.print_exc()
987
- t2 = False
988
- if debug:
989
- print(t2)
990
- if t1 == t2:
991
- # No zero crossing found
992
- amplitudes[k] = np.nan
993
- if debug:
994
- print('> no zero crossing')
995
- continue
996
-
997
- # Zero must lie in between. Start bisection search
998
- a = 0.5 * a1 + 0.5 * a2
999
- for j in range(0, self._precision):
1000
- s.reset()
1001
- s.set_constant(self._avar, a)
1002
- try:
1003
- d = s.run(self._time, log=[vvar]).npview()
1004
- except Exception:
1005
- if debug:
1006
- traceback.print_exc()
1007
- break
1008
- t = (np.max(d[vvar]) > self._threshold)
1009
- if t1 == t:
1010
- a1 = a
1011
- else:
1012
- a2 = a
1013
- a = 0.5 * a1 + 0.5 * a2
1014
- amplitudes[k] = a
1015
- if debug:
1016
- print('> ' + str(a))
1017
-
1018
- # Set output data
1019
- self._data = myokit.DataLog()
1020
- self._data['duration'] = durations
1021
- self._data['strength'] = amplitudes
1022
-
1023
- def set_currents(self, imin=-250, imax=0):
1024
- """
1025
- Sets the range of current levels tested.
1026
-
1027
- ``imin``
1028
- The lowest (or most negative) current amplitude to test.
1029
- ``imax``
1030
- The greatest (or least negative) current amplitude to test.
1031
- """
1032
- amin = float(imin)
1033
- amax = float(imax)
1034
- if amin >= amax:
1035
- raise ValueError(
1036
- 'Minimum current amplitude must be smaller than maximum'
1037
- ' value.')
1038
- self._amin = amin
1039
- self._amax = amax
1040
- self._data = None
1041
-
1042
- def set_precision(self, precision=10):
1043
- """
1044
- Sets the number of different amplitudes tried. This is done using a
1045
- bisection algorithm, so low values of ``precision`` can still produce a
1046
- good result.
1047
- """
1048
- precision = int(precision)
1049
- if precision < 1:
1050
- raise ValueError('The number of tries must be greater than zero.')
1051
- self._precision = precision
1052
- self._data = None
1053
-
1054
- def set_threshold(self, threshold=10):
1055
- """
1056
- Sets the level above which the membrane potential must rise to count as
1057
- a depolarization.
1058
- """
1059
- self._threshold = float(threshold)
1060
- self._data = None
1061
-
1062
- def set_times(self, tmin=0.2, tmax=2.0, dt=0.1, twait=50):
1063
- """
1064
- Sets the tested stimulus durations.
1065
-
1066
- ``tmin``
1067
- The smallest stimulus time tested.
1068
- ``tmax``
1069
- The largest stimulus time tested.
1070
- ``dt``
1071
- The step size when going from tmin to tmax.
1072
- ``twait``
1073
- The duration of the experiment that tries to measure a
1074
- depolarization.
1075
-
1076
- """
1077
- tmin = float(tmin)
1078
- tmax = float(tmax)
1079
- if tmin < 0:
1080
- raise ValueError('Minimum time cannot be negative.')
1081
- if tmax < 0:
1082
- raise ValueError('Maximum time cannot be negative.')
1083
- if tmin >= tmax:
1084
- raise ValueError(
1085
- 'The maximum time must be greater than the minimum time.')
1086
- dt = float(dt)
1087
- if dt <= 0:
1088
- raise ValueError('The step size must be greater than zero.')
1089
- twait = float(twait)
1090
- if twait < 0:
1091
- raise ValueError('The time "twait" must be greater than zero.')
1092
- self._durations = np.arange(tmin, tmax, dt)
1093
- self._time = twait
1094
- self._data = None