myokit 1.37.1__py3-none-any.whl → 1.37.2__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.
- myokit/__init__.py +2 -2
- myokit/_datalog.py +15 -6
- myokit/_myokit_version.py +1 -1
- myokit/_sim/cvodessim.py +3 -3
- myokit/formats/heka/__init__.py +4 -0
- myokit/formats/heka/_patchmaster.py +128 -100
- myokit/formats/sbml/__init__.py +21 -1
- myokit/formats/sbml/_api.py +160 -6
- myokit/formats/sbml/_exporter.py +53 -0
- myokit/formats/sbml/_writer.py +355 -0
- myokit/tests/test_formats_exporters_run.py +3 -0
- myokit/tests/test_formats_sbml.py +57 -1
- myokit/tests/test_sbml_api.py +90 -0
- myokit/tests/test_sbml_export.py +327 -0
- {myokit-1.37.1.dist-info → myokit-1.37.2.dist-info}/LICENSE.txt +1 -1
- {myokit-1.37.1.dist-info → myokit-1.37.2.dist-info}/METADATA +4 -4
- {myokit-1.37.1.dist-info → myokit-1.37.2.dist-info}/RECORD +20 -17
- {myokit-1.37.1.dist-info → myokit-1.37.2.dist-info}/WHEEL +1 -1
- {myokit-1.37.1.dist-info → myokit-1.37.2.dist-info}/entry_points.txt +0 -0
- {myokit-1.37.1.dist-info → myokit-1.37.2.dist-info}/top_level.txt +0 -0
myokit/__init__.py
CHANGED
|
@@ -79,7 +79,7 @@ Copyright (c) 2017-2020 University of Oxford. All rights reserved.
|
|
|
79
79
|
(University of Oxford means the Chancellor, Masters and Scholars of the
|
|
80
80
|
University of Oxford, having an administrative office at Wellington Square,
|
|
81
81
|
Oxford OX1 2JD, UK).
|
|
82
|
-
Copyright (c) 2020-
|
|
82
|
+
Copyright (c) 2020-2025 University of Nottingham. All rights reserved.
|
|
83
83
|
|
|
84
84
|
Redistribution and use in source and binary forms, with or without
|
|
85
85
|
modification, are permitted provided that the following conditions are met:
|
|
@@ -118,7 +118,7 @@ LICENSE_HTML = """
|
|
|
118
118
|
<br />(University of Oxford means the Chancellor, Masters and Scholars of
|
|
119
119
|
the University of Oxford, having an administrative office at Wellington
|
|
120
120
|
Square, Oxford OX1 2JD, UK).
|
|
121
|
-
<br />Copyright (c) 2020-
|
|
121
|
+
<br />Copyright (c) 2020-2025 University of Nottingham. All rights
|
|
122
122
|
reserved.</br></p>
|
|
123
123
|
<p>
|
|
124
124
|
Redistribution and use in source and binary forms, with or without
|
myokit/_datalog.py
CHANGED
|
@@ -329,23 +329,27 @@ class DataLog(OrderedDict):
|
|
|
329
329
|
"""
|
|
330
330
|
Creates a copy of the log, split with the given ``period``.
|
|
331
331
|
|
|
332
|
-
Split signals are given indexes so that
|
|
333
|
-
|
|
332
|
+
Split signals are given indexes so that ``current`` becomes
|
|
333
|
+
``0.current``, ``1.current``, ``2.current``, etc.
|
|
334
334
|
|
|
335
335
|
If the logs entries do not divide well by ``period``, the remainder
|
|
336
336
|
will be ignored. This happens commonly due to rounding point errors (in
|
|
337
337
|
which case the remainder is a single entry). To disable this behavior,
|
|
338
338
|
set ``discard_remainder=False``.
|
|
339
|
+
|
|
340
|
+
To split a log into a list of logs, use :meth:`DataLog.split_periodic`.
|
|
339
341
|
"""
|
|
340
342
|
# Note: Using closed intervals can lead to logs of unequal length, so
|
|
341
343
|
# it should be disabled here to ensure a valid log
|
|
342
344
|
logs = self.split_periodic(period, adjust=True, closed_intervals=False)
|
|
345
|
+
|
|
343
346
|
# Discard remainder if present
|
|
344
347
|
if discard_remainder:
|
|
345
348
|
if len(logs) > 1:
|
|
346
349
|
n = logs[0].length()
|
|
347
350
|
if logs[-1].length() < n:
|
|
348
351
|
logs = logs[:-1]
|
|
352
|
+
|
|
349
353
|
# Create new log with folded data
|
|
350
354
|
out = myokit.DataLog()
|
|
351
355
|
out._time = self._time
|
|
@@ -1305,10 +1309,12 @@ class DataLog(OrderedDict):
|
|
|
1305
1309
|
|
|
1306
1310
|
def split_periodic(self, period, adjust=False, closed_intervals=True):
|
|
1307
1311
|
"""
|
|
1308
|
-
Splits this log into multiple logs,
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
+
Splits this log into multiple logs, returning a list of
|
|
1313
|
+
:class:`DataLog` objects.
|
|
1314
|
+
|
|
1315
|
+
Each returned log covers an equal ``period`` of time. For example a log
|
|
1316
|
+
covering the time span ``[0, 10000]`` split with period ``1000`` will
|
|
1317
|
+
result in a list of ten logs ``[0, 1000]``, ``[1000, 2000]`` etc.
|
|
1312
1318
|
|
|
1313
1319
|
The split log files can be returned as-is, or with the time variable's
|
|
1314
1320
|
value adjusted so that all logs appear to cover the same span. To
|
|
@@ -1319,6 +1325,9 @@ class DataLog(OrderedDict):
|
|
|
1319
1325
|
the duplication of some data points. To disable this behavior and
|
|
1320
1326
|
return half-closed endpoints (containing only the left point), set
|
|
1321
1327
|
``closed_intervals`` to ``False``.
|
|
1328
|
+
|
|
1329
|
+
To return a single log with entries ``x`` split as ``x.0``, ``x.1``,
|
|
1330
|
+
etc., use :meth:`DataLog.fold`.
|
|
1322
1331
|
"""
|
|
1323
1332
|
# Validate log before starting
|
|
1324
1333
|
self.validate()
|
myokit/_myokit_version.py
CHANGED
|
@@ -14,7 +14,7 @@ __release__ = True
|
|
|
14
14
|
# incompatibility
|
|
15
15
|
# - Changes to revision indicate bugfixes, tiny new features
|
|
16
16
|
# - There is no significance to odd/even numbers
|
|
17
|
-
__version_tuple__ = 1, 37,
|
|
17
|
+
__version_tuple__ = 1, 37, 2
|
|
18
18
|
|
|
19
19
|
# String version of the version number
|
|
20
20
|
__version__ = '.'.join([str(x) for x in __version_tuple__])
|
myokit/_sim/cvodessim.py
CHANGED
|
@@ -695,9 +695,9 @@ class Simulation(myokit.CModule):
|
|
|
695
695
|
An optional fixed size log interval. Must be ``None`` if
|
|
696
696
|
``log_times`` is used. If both are ``None`` every step is logged.
|
|
697
697
|
``log_times``
|
|
698
|
-
An optional
|
|
699
|
-
|
|
700
|
-
logged.
|
|
698
|
+
An optional sequence (e.g. a list or a numpy array) of
|
|
699
|
+
pre-determined logging times. Must be ``None`` if ``log_interval``
|
|
700
|
+
is used. If both are ``None`` every step is logged.
|
|
701
701
|
``sensitivities``
|
|
702
702
|
An optional list-of-lists to append the calculated sensitivities
|
|
703
703
|
to.
|
myokit/formats/heka/__init__.py
CHANGED
|
@@ -9,7 +9,10 @@ from ._patchmaster import ( # noqa
|
|
|
9
9
|
AmplifierSeries,
|
|
10
10
|
AmplifierState,
|
|
11
11
|
AmplifierStateRecord,
|
|
12
|
+
CSlowRange,
|
|
12
13
|
EndianAwareReader,
|
|
14
|
+
Filter1Setting,
|
|
15
|
+
Filter2Type,
|
|
13
16
|
Group,
|
|
14
17
|
NoSupportedDAChannelError,
|
|
15
18
|
PatchMasterFile,
|
|
@@ -22,6 +25,7 @@ from ._patchmaster import ( # noqa
|
|
|
22
25
|
Stimulus,
|
|
23
26
|
StimulusChannel,
|
|
24
27
|
StimulusFile,
|
|
28
|
+
StimulusFilterSetting,
|
|
25
29
|
Sweep,
|
|
26
30
|
Trace,
|
|
27
31
|
TreeNode,
|
|
@@ -973,45 +973,50 @@ class Series(TreeNode, myokit.formats.SweepSource):
|
|
|
973
973
|
|
|
974
974
|
# Add meta data
|
|
975
975
|
log.meta['time'] = self._time.strftime(myokit.DATE_FORMAT)
|
|
976
|
-
a = self.amplifier_state()
|
|
977
976
|
t = self[0][0] if len(self) and len(self[0]) else None
|
|
978
|
-
log.meta['current_gain_mV_per_pA'] = a.current_gain()
|
|
979
|
-
log.meta['filter1'] = a.filter1_str()
|
|
980
|
-
log.meta['filter2'] = a.filter2_str()
|
|
981
|
-
log.meta['stimulus_filter'] = a.stimulus_filter_str()
|
|
982
|
-
log.meta['ljp_correction_mV'] = a.ljp()
|
|
983
|
-
log.meta['voltage_offset_mV'] = a.v_off()
|
|
984
|
-
log.meta['holding_potential_mV'] = a.v_hold()
|
|
985
977
|
if t is not None:
|
|
986
978
|
log.meta['r_pipette_MOhm'] = t.r_pipette()
|
|
987
979
|
log.meta['r_seal_MOhm'] = t.r_seal()
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
log.meta['
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
log.meta['
|
|
997
|
-
log.meta['
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
a.
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
980
|
+
a = self.amplifier_state()
|
|
981
|
+
amps = [a] if a is not None else self.amplifier_states()
|
|
982
|
+
for k, a in enumerate(amps):
|
|
983
|
+
pre = '' if len(amps) == 1 else f'amp{1 + k}_'
|
|
984
|
+
log.meta[f'{pre}current_gain_mV_per_pA'] = a.current_gain()
|
|
985
|
+
log.meta[f'{pre}filter1'] = a.filter1_str()
|
|
986
|
+
log.meta[f'{pre}filter2'] = a.filter2_str()
|
|
987
|
+
log.meta[f'{pre}stimulus_filter'] = a.stimulus_filter_str()
|
|
988
|
+
log.meta[f'{pre}ljp_correction_mV'] = a.ljp()
|
|
989
|
+
log.meta[f'{pre}voltage_offset_mV'] = a.v_off()
|
|
990
|
+
log.meta[f'{pre}holding_potential_mV'] = a.v_hold()
|
|
991
|
+
if a.c_fast_enabled():
|
|
992
|
+
log.meta[f'{pre}c_fast_compensation_enabled'] = 'true'
|
|
993
|
+
log.meta[f'{pre}c_fast_pF'] = a.c_fast()
|
|
994
|
+
else:
|
|
995
|
+
log.meta[f'{pre}c_fast_compensation_enabled'] = 'false'
|
|
996
|
+
log.meta[f'{pre}c_slow_pF'] = a.c_slow()
|
|
997
|
+
if a.c_slow_enabled():
|
|
998
|
+
log.meta[f'{pre}c_slow_compensation_enabled'] = 'true'
|
|
999
|
+
log.meta[f'{pre}c_slow_range'] = a.c_slow_range()
|
|
1000
|
+
css = a.c_slow_auto_settings()
|
|
1001
|
+
log.meta[f'{pre}c_slow_auto_amplitude_mV'] = css[0]
|
|
1002
|
+
log.meta[f'{pre}c_slow_auto_cycles'] = css[1]
|
|
1003
|
+
log.meta[f'{pre}c_slow_auto_timeout'] = css[2]
|
|
1004
|
+
else:
|
|
1005
|
+
log.meta[f'{pre}c_slow_compensation_enabled'] = 'false'
|
|
1006
|
+
log.meta[f'{pre}r_series_MOhm'] = a.r_series()
|
|
1007
|
+
if a.r_series_enabled():
|
|
1008
|
+
log.meta[f'{pre}r_series_compensation_enabled'] = 'true'
|
|
1009
|
+
log.meta[f'{pre}r_series_compensation_percent'] = round(
|
|
1010
|
+
a.r_series_fraction() * 100, 1)
|
|
1011
|
+
log.meta[f'{pre}r_series_compensation_tau_us'] = \
|
|
1012
|
+
a.r_series_tau()
|
|
1013
|
+
else:
|
|
1014
|
+
log.meta[f'{pre}r_series_compensation_enabled'] = 'false'
|
|
1012
1015
|
|
|
1013
1016
|
# Add protocol to meta data
|
|
1014
1017
|
stimulus = self.stimulus()
|
|
1018
|
+
log.meta['sampling_interval_ms'] = stimulus.sampling_interval() * 1000
|
|
1019
|
+
log.meta['sweep_count'] = stimulus.sweep_count()
|
|
1015
1020
|
stimulus_channel = stimulus.supported_channel()
|
|
1016
1021
|
if stimulus_channel is not None:
|
|
1017
1022
|
log.meta['amplifier_mode'] = str(stimulus_channel.amplifier_mode())
|
|
@@ -1058,46 +1063,46 @@ class Series(TreeNode, myokit.formats.SweepSource):
|
|
|
1058
1063
|
|
|
1059
1064
|
# Info from amplifier state
|
|
1060
1065
|
a = self.amplifier_state()
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
out.append(f'
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1066
|
+
amps = [a] if a is not None else self.amplifier_states()
|
|
1067
|
+
for k, a in enumerate(amps):
|
|
1068
|
+
out.append(f'Information from amplifier state {1 + k}:')
|
|
1069
|
+
out.append(f' Current gain: {a.current_gain()} mV/pA')
|
|
1070
|
+
out.append(f' Filter 1: {a.filter1_str()}')
|
|
1071
|
+
out.append(f' Filter 2: {a.filter2_str()}')
|
|
1072
|
+
out.append(f' Stimulus filter: {a.stimulus_filter_str()}')
|
|
1073
|
+
# Voltage info
|
|
1074
|
+
out.append(f' Holding potential: {a.v_hold()} mV')
|
|
1075
|
+
if a.ljp():
|
|
1076
|
+
out.append(f' LJP correction: {round(a.ljp(), 4)} mV')
|
|
1077
|
+
else:
|
|
1078
|
+
out.append(' LJP correction: no correction')
|
|
1079
|
+
out.append(f' Voltage offset: {a.v_off()} mV')
|
|
1080
|
+
# C fast
|
|
1081
|
+
if a.c_fast_enabled():
|
|
1082
|
+
out.append(f' C fast compensation: {a.c_fast()} pF,')
|
|
1083
|
+
else:
|
|
1084
|
+
out.append(' C fast compensation: not enabled')
|
|
1085
|
+
# C slow
|
|
1086
|
+
if a.c_slow_enabled():
|
|
1087
|
+
out.append(f' C slow compensation: {a.c_slow()} pF')
|
|
1088
|
+
amp, cyc, tim = a.c_slow_auto_settings()
|
|
1089
|
+
out.append(f' C slow auto settings: amplitude {amp} mV,'
|
|
1090
|
+
f' cycles {cyc}, timeout {tim} s')
|
|
1091
|
+
else:
|
|
1092
|
+
out.append(' C slow compensation: not enabled')
|
|
1093
|
+
# Rs comp
|
|
1094
|
+
out.append(f' R series: {a.r_series()} MOhm')
|
|
1095
|
+
if a.r_series_enabled():
|
|
1096
|
+
p = round(a.r_series_fraction() * 100, 1)
|
|
1097
|
+
q = round(a.r_series_tau(), 1)
|
|
1098
|
+
out.append(f' R series compensation: {p} %, {q} us')
|
|
1099
|
+
else:
|
|
1100
|
+
out.append(' R series compensation: not enabled')
|
|
1095
1101
|
|
|
1096
1102
|
# Info from first trace
|
|
1097
1103
|
if len(self) and len(self[0]):
|
|
1098
1104
|
t = self[0][0]
|
|
1099
1105
|
out.append('Information from first trace:')
|
|
1100
|
-
|
|
1101
1106
|
out.append(f' Pipette resistance: {t.r_pipette()} MOhm')
|
|
1102
1107
|
out.append(f' Seal resistance: {t.r_seal()} MOhm')
|
|
1103
1108
|
out.append(f' Series resistance: {t.r_series()} MOhm')
|
|
@@ -1121,8 +1126,10 @@ class Series(TreeNode, myokit.formats.SweepSource):
|
|
|
1121
1126
|
out.append('-' * 60)
|
|
1122
1127
|
out.append(f'Stimulus "{stim.label()}"')
|
|
1123
1128
|
out.append(f' {stim.sweep_count()} sweeps')
|
|
1124
|
-
out.append(
|
|
1125
|
-
|
|
1129
|
+
out.append(' Delay between sweeps: '
|
|
1130
|
+
f'{stim.sweep_interval() * 1000} ms')
|
|
1131
|
+
out.append(' Sampling interval: '
|
|
1132
|
+
f'{stim.sampling_interval() * 1000} ms')
|
|
1126
1133
|
for i, ch in enumerate(stim):
|
|
1127
1134
|
out.append(f' Channel {i}, in {ch.unit()}, amplifier in'
|
|
1128
1135
|
f' {ch.amplifier_mode()} mode')
|
|
@@ -1442,7 +1449,7 @@ class Trace(TreeNode):
|
|
|
1442
1449
|
Returns the last (uncompensated) series resistance (MOhm) before
|
|
1443
1450
|
acquiring the trace.
|
|
1444
1451
|
"""
|
|
1445
|
-
return 1e-6 / self._g_series
|
|
1452
|
+
return 0 if self._g_series == 0 else 1e-6 / self._g_series
|
|
1446
1453
|
|
|
1447
1454
|
def r_pipette(self):
|
|
1448
1455
|
"""
|
|
@@ -1597,6 +1604,9 @@ class Trace(TreeNode):
|
|
|
1597
1604
|
# sOld3 = 295; (* BYTE *)
|
|
1598
1605
|
#
|
|
1599
1606
|
# sStimFilterHz = 296; (* LONGREAL *)
|
|
1607
|
+
# 2024-11-07 HEKA support says that sStimFilterHz is "antiquated", and this
|
|
1608
|
+
# value (10kHz=off or 100kHz=on) should be ignored.
|
|
1609
|
+
#
|
|
1600
1610
|
# sRsTau = 304; (* LONGREAL *)
|
|
1601
1611
|
# sDacToAdcDelay = 312; (* LONGREAL *)
|
|
1602
1612
|
# sInputFilterTau = 320; (* LONGREAL *)
|
|
@@ -1659,7 +1669,7 @@ class AmplifierState:
|
|
|
1659
1669
|
handle.seek(i + 64) # sCFastAmp2 = 64; (* LONGREAL *)
|
|
1660
1670
|
self._cf_amp2 = reader.read1('d')
|
|
1661
1671
|
handle.seek(i + 72) # sCFastTau = 72; (* LONGREAL *)
|
|
1662
|
-
self.
|
|
1672
|
+
self._cf_tau2 = reader.read1('d')
|
|
1663
1673
|
#handle.seek(i + 285) # sCCCFastOn = 285; (* BYTE *)
|
|
1664
1674
|
#self._cf_enabled = bool(reader.read1('b'))
|
|
1665
1675
|
|
|
@@ -1699,21 +1709,20 @@ class AmplifierState:
|
|
|
1699
1709
|
#handle.seek(i + 231) # sF2Mode = 231; (* BYTE *)
|
|
1700
1710
|
#self._temp['sF2Mode'] = reader.read1('b')
|
|
1701
1711
|
|
|
1702
|
-
#
|
|
1703
|
-
#
|
|
1704
|
-
#
|
|
1705
|
-
#
|
|
1706
|
-
#
|
|
1707
|
-
#
|
|
1708
|
-
#
|
|
1709
|
-
#
|
|
1710
|
-
#
|
|
1711
|
-
#
|
|
1712
|
-
#
|
|
1713
|
-
#
|
|
1714
|
-
#
|
|
1715
|
-
#
|
|
1716
|
-
# self._temp['sImon1Bandwidth'] = reader.read1('d')
|
|
1712
|
+
#self._temp = {}
|
|
1713
|
+
#handle.seek(i + 320) # sInputFilterTau = 320; (* LONGREAL *)
|
|
1714
|
+
#print('InputFilterTau', reader.read1('d'))
|
|
1715
|
+
#self._temp['sInputFilterTau'] = reader.read1('d')
|
|
1716
|
+
#handle.seek(i + 328) # sOutputFilterTau = 328; (* LONGREAL *)
|
|
1717
|
+
#print('OutputFilterTau', reader.read1('d'))
|
|
1718
|
+
#self._temp['sOutputFilterTau'] = reader.read1('d')
|
|
1719
|
+
#handle.seek(i + 384) # sVmonFiltBandwidth = 384; (* LONGREAL *)
|
|
1720
|
+
#self._temp['sVmonFiltBandwidth'] = reader.read1('d')
|
|
1721
|
+
#handle.seek(i + 392) # sVmonFiltFrequency = 392; (* LONGREAL *)
|
|
1722
|
+
#self._temp['sVmonFiltFrequency'] = reader.read1('d')
|
|
1723
|
+
#print(self._temp)
|
|
1724
|
+
#handle.seek(i + 264) # sImon1Bandwidth = 264; (* LONGREAL *)
|
|
1725
|
+
#self._temp['sImon1Bandwidth'] = reader.read1('d')
|
|
1717
1726
|
|
|
1718
1727
|
# Stimulus filter
|
|
1719
1728
|
handle.seek(i + 282) # sStimFilterOn = 282; (* BYTE *)
|
|
@@ -1725,23 +1734,28 @@ class AmplifierState:
|
|
|
1725
1734
|
|
|
1726
1735
|
HEKA amplifiers use a two-component fast capacitance cancellation, with
|
|
1727
1736
|
an instantaneous part (component 1) and a delayed part (component 2).
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
returned.
|
|
1737
|
+
This method returns the sum of both values. Individual values can be
|
|
1738
|
+
obtained from :meth:`c_fast_detailed`.
|
|
1731
1739
|
"""
|
|
1732
1740
|
# The total fast capacitance correction is a sum of two capacitances.
|
|
1733
1741
|
# See the EPC-10 manual for details.
|
|
1734
1742
|
return (self._cf_amp1 + self._cf_amp2) * 1e12
|
|
1735
1743
|
|
|
1736
|
-
def
|
|
1744
|
+
def c_fast_detailed(self):
|
|
1737
1745
|
"""
|
|
1738
|
-
Returns the
|
|
1739
|
-
|
|
1746
|
+
Returns the detailed fast capacitance correction values:
|
|
1747
|
+
``(c_fast1, c_fast2, tau_fast2)`` in (pF, pF, us).
|
|
1740
1748
|
|
|
1741
|
-
|
|
1742
|
-
cancellation,
|
|
1749
|
+
Here ``c_fast1`` is the capacitance (pF) of the instantaneous component
|
|
1750
|
+
of cancellation, ``c_fast2`` is the capacitance (pF) of the delayed
|
|
1751
|
+
cancellation, and ``tau_fast2`` is a "tau value" (in microseconds)
|
|
1752
|
+
pertaining to the delayed component (the equivalent value for the
|
|
1753
|
+
instantaneous component is 0).
|
|
1743
1754
|
"""
|
|
1744
|
-
|
|
1755
|
+
# The total fast capacitance correction is a sum of two capacitances.
|
|
1756
|
+
# See the EPC-10 manual for details.
|
|
1757
|
+
return (
|
|
1758
|
+
self._cf_amp1 * 1e12, self._cf_amp2 * 1e12, self._cf_tau2 * 1e6)
|
|
1745
1759
|
|
|
1746
1760
|
def c_fast_enabled(self):
|
|
1747
1761
|
"""
|
|
@@ -1897,7 +1911,12 @@ class AmplifierState:
|
|
|
1897
1911
|
return self._voff * 1e3
|
|
1898
1912
|
|
|
1899
1913
|
def v_hold(self):
|
|
1900
|
-
"""
|
|
1914
|
+
"""
|
|
1915
|
+
Returns the holding potential (in mV).
|
|
1916
|
+
|
|
1917
|
+
This is the potential last set in the amplifier window, before any
|
|
1918
|
+
experiments were run.
|
|
1919
|
+
"""
|
|
1901
1920
|
return self._holding * 1e3
|
|
1902
1921
|
|
|
1903
1922
|
|
|
@@ -1933,7 +1952,7 @@ class Filter1Setting(enum.Enum):
|
|
|
1933
1952
|
|
|
1934
1953
|
class Filter2Type(enum.Enum):
|
|
1935
1954
|
"""
|
|
1936
|
-
|
|
1955
|
+
Filter type for filter 2, which is applied after filter 1.
|
|
1937
1956
|
|
|
1938
1957
|
Unlike Filter 1, this filter can be disabled, and the frequency is set
|
|
1939
1958
|
separately.
|
|
@@ -1956,7 +1975,11 @@ class Filter2Type(enum.Enum):
|
|
|
1956
1975
|
|
|
1957
1976
|
|
|
1958
1977
|
class CSlowRange(enum.Enum):
|
|
1959
|
-
"""
|
|
1978
|
+
"""
|
|
1979
|
+
Available options for slow capacitance cancelling range.
|
|
1980
|
+
|
|
1981
|
+
This doubles up as the on/off setting for slow capacitance cancellation.
|
|
1982
|
+
"""
|
|
1960
1983
|
OFF = 0
|
|
1961
1984
|
pF30 = 1
|
|
1962
1985
|
pF100 = 2
|
|
@@ -1975,12 +1998,17 @@ class CSlowRange(enum.Enum):
|
|
|
1975
1998
|
|
|
1976
1999
|
class StimulusFilterSetting(enum.Enum):
|
|
1977
2000
|
"""
|
|
1978
|
-
Setting for the stimulus filter.
|
|
1979
|
-
|
|
2001
|
+
Setting for the stimulus filter: 20 us (on, default), or 2 us (off).
|
|
1980
2002
|
|
|
1981
2003
|
The stimulus filter is a 2-pole Bessel filter applied over the stimulus
|
|
1982
2004
|
signal to reduce fast capacitative currents. It is applied to voltages, the
|
|
1983
2005
|
manual is less clear whether it is applied to currents too.
|
|
2006
|
+
|
|
2007
|
+
The quoted values are stated to be the filter's "rise time", which is the
|
|
2008
|
+
time needed for the signal to go from 10% to 90% of its step response.
|
|
2009
|
+
However, measurements indicate real rise times are longer (approximately
|
|
2010
|
+
40us in the 20us setting), so these values should be treated as nominal
|
|
2011
|
+
rather than actual results.
|
|
1984
2012
|
"""
|
|
1985
2013
|
BW2 = 0
|
|
1986
2014
|
BW20 = 1
|
myokit/formats/sbml/__init__.py
CHANGED
|
@@ -16,9 +16,16 @@ from ._api import ( # noqa
|
|
|
16
16
|
Species,
|
|
17
17
|
SpeciesReference)
|
|
18
18
|
from ._importer import SBMLImporter
|
|
19
|
+
from ._exporter import SBMLExporter
|
|
19
20
|
from ._parser import ( # noqa
|
|
20
21
|
SBMLParsingError,
|
|
21
|
-
SBMLParser
|
|
22
|
+
SBMLParser
|
|
23
|
+
)
|
|
24
|
+
from ._writer import ( # noqa
|
|
25
|
+
write_file,
|
|
26
|
+
write_string,
|
|
27
|
+
SBMLWriter,
|
|
28
|
+
)
|
|
22
29
|
|
|
23
30
|
|
|
24
31
|
# Importers
|
|
@@ -33,5 +40,18 @@ def importers():
|
|
|
33
40
|
"""
|
|
34
41
|
return dict(_importers)
|
|
35
42
|
|
|
43
|
+
|
|
36
44
|
# Exporters
|
|
45
|
+
_exporters = {
|
|
46
|
+
'sbml': SBMLExporter,
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def exporters():
|
|
51
|
+
"""
|
|
52
|
+
Returns a dict of all exporters available in this module.
|
|
53
|
+
"""
|
|
54
|
+
return dict(_exporters)
|
|
55
|
+
|
|
56
|
+
|
|
37
57
|
# Expression writers
|