dendrotweaks 0.3.1__py3-none-any.whl → 0.4.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 (41) hide show
  1. dendrotweaks/__init__.py +2 -2
  2. dendrotweaks/analysis/ephys_analysis.py +12 -8
  3. dendrotweaks/biophys/__init__.py +7 -0
  4. dendrotweaks/{membrane → biophys}/default_templates/NEURON_template.py +5 -3
  5. dendrotweaks/{membrane → biophys}/default_templates/default.py +2 -1
  6. dendrotweaks/{membrane → biophys}/default_templates/standard_channel.mod +5 -1
  7. dendrotweaks/{membrane → biophys}/groups.py +2 -2
  8. dendrotweaks/biophys/io/__init__.py +11 -0
  9. dendrotweaks/{membrane → biophys}/io/ast.py +6 -0
  10. dendrotweaks/{membrane → biophys}/io/code_generators.py +7 -1
  11. dendrotweaks/{membrane → biophys}/io/converter.py +3 -3
  12. dendrotweaks/{membrane → biophys}/io/factories.py +8 -6
  13. dendrotweaks/biophys/io/loader.py +190 -0
  14. dendrotweaks/{membrane → biophys}/io/parser.py +8 -8
  15. dendrotweaks/{membrane → biophys}/mechanisms.py +14 -10
  16. dendrotweaks/model.py +65 -32
  17. dendrotweaks/morphology/sec_trees.py +1 -1
  18. dendrotweaks/path_manager.py +9 -11
  19. dendrotweaks/simulators.py +82 -48
  20. dendrotweaks/stimuli/populations.py +11 -0
  21. {dendrotweaks-0.3.1.dist-info → dendrotweaks-0.4.0.dist-info}/METADATA +2 -2
  22. dendrotweaks-0.4.0.dist-info/RECORD +56 -0
  23. {dendrotweaks-0.3.1.dist-info → dendrotweaks-0.4.0.dist-info}/WHEEL +1 -1
  24. dendrotweaks/membrane/__init__.py +0 -6
  25. dendrotweaks/membrane/io/__init__.py +0 -11
  26. dendrotweaks/membrane/io/loader.py +0 -90
  27. dendrotweaks-0.3.1.dist-info/RECORD +0 -56
  28. /dendrotweaks/{membrane → biophys}/default_mod/AMPA.mod +0 -0
  29. /dendrotweaks/{membrane → biophys}/default_mod/AMPA_NMDA.mod +0 -0
  30. /dendrotweaks/{membrane → biophys}/default_mod/CaDyn.mod +0 -0
  31. /dendrotweaks/{membrane → biophys}/default_mod/GABAa.mod +0 -0
  32. /dendrotweaks/{membrane → biophys}/default_mod/Leak.mod +0 -0
  33. /dendrotweaks/{membrane → biophys}/default_mod/NMDA.mod +0 -0
  34. /dendrotweaks/{membrane → biophys}/default_mod/vecstim.mod +0 -0
  35. /dendrotweaks/{membrane → biophys}/default_templates/template_jaxley.py +0 -0
  36. /dendrotweaks/{membrane → biophys}/default_templates/template_jaxley_new.py +0 -0
  37. /dendrotweaks/{membrane → biophys}/distributions.py +0 -0
  38. /dendrotweaks/{membrane → biophys}/io/grammar.py +0 -0
  39. /dendrotweaks/{membrane → biophys}/io/reader.py +0 -0
  40. {dendrotweaks-0.3.1.dist-info → dendrotweaks-0.4.0.dist-info}/licenses/LICENSE +0 -0
  41. {dendrotweaks-0.3.1.dist-info → dendrotweaks-0.4.0.dist-info}/top_level.txt +0 -0
dendrotweaks/__init__.py CHANGED
@@ -1,8 +1,8 @@
1
- __version__ = "0.3.1"
1
+ __version__ = "0.4.0"
2
2
 
3
3
  from dendrotweaks.model import Model
4
4
  from dendrotweaks.simulators import NEURONSimulator
5
- from dendrotweaks.membrane.distributions import Distribution
5
+ from dendrotweaks.biophys.distributions import Distribution
6
6
  from dendrotweaks.path_manager import PathManager
7
7
  from dendrotweaks.stimuli import Synapse, Population, IClamp
8
8
 
@@ -27,7 +27,7 @@ def get_somatic_data(model):
27
27
  seg = model.seg_tree.root
28
28
  iclamp = model.iclamps[seg]
29
29
 
30
- v = np.array(model.simulator.vs[seg])
30
+ v = np.array(model.simulator.recordings['v'][seg])
31
31
  t = np.array(model.simulator.t)
32
32
  dt = model.simulator.dt
33
33
 
@@ -165,7 +165,7 @@ def detect_somatic_spikes(model, **kwargs):
165
165
  """
166
166
  seg = model.seg_tree.root
167
167
 
168
- v = np.array(model.simulator.vs[seg])
168
+ v = np.array(model.simulator.recordings['v'][seg])
169
169
  t = np.array(model.simulator.t)
170
170
  dt = model.simulator.dt
171
171
 
@@ -271,7 +271,7 @@ def calculate_fI_curve(model, duration=1000, min_amp=0, max_amp=1, n=5, **kwargs
271
271
  n_spikes = len(spike_data['spike_times'])
272
272
  rate = n_spikes / iclamp.dur * 1000
273
273
  rates.append(rate)
274
- vs[amp] = model.simulator.vs[seg]
274
+ vs[amp] = model.simulator.recordings['v'][seg]
275
275
 
276
276
  return {
277
277
  'current_amplitudes': amps,
@@ -336,11 +336,14 @@ def calculate_voltage_attenuation(model):
336
336
  if len(stimulated_segs) != 1:
337
337
  print("Only one stimulation site is supported")
338
338
  return None
339
- recorded_segs = list(model.recordings.keys())
339
+ recorded_segs = list(model.recordings['v'].keys())
340
340
  if len(recorded_segs) < 2:
341
341
  print("At least two recording sites are required")
342
342
  return None
343
343
 
344
+ print(f"Stimulating segment: {stimulated_segs[0]}")
345
+ print(f"Recording segments: {recorded_segs}")
346
+
344
347
  stimulated_seg = stimulated_segs[0]
345
348
 
346
349
  iclamp = model.iclamps[stimulated_seg]
@@ -355,8 +358,9 @@ def calculate_voltage_attenuation(model):
355
358
  start_ts = int(iclamp.delay / model.simulator.dt)
356
359
  stop_ts = int((iclamp.delay + iclamp.dur) / model.simulator.dt)
357
360
 
358
- voltage_at_stimulated = np.array(model.simulator.vs[stimulated_seg])[start_ts:stop_ts]
359
- voltages = [np.array(model.simulator.vs[seg])[start_ts:stop_ts] for seg in recorded_segs]
361
+ voltage_at_stimulated = np.array(model.simulator.recordings['v'][stimulated_seg])[start_ts:stop_ts]
362
+ voltages = [np.array(model.simulator.recordings['v'][seg])[start_ts:stop_ts] for seg in recorded_segs]
363
+
360
364
 
361
365
  # Calculate voltage displacement from the resting potential
362
366
  delta_v_at_stimulated = voltage_at_stimulated[0] - np.min(voltage_at_stimulated)
@@ -405,7 +409,7 @@ def calculate_dendritic_nonlinearity(model, duration=1000, max_weight=None, n=No
405
409
  A dictionary containing the expected and observed voltage changes.
406
410
  """
407
411
 
408
- recorded_segs = list(model.recordings.keys())
412
+ recorded_segs = list(model.recordings['v'].keys())
409
413
  seg = recorded_segs[0]
410
414
 
411
415
  populations = [pop for pops in model.populations.values() for pop in pops.values()]
@@ -432,7 +436,7 @@ def calculate_dendritic_nonlinearity(model, duration=1000, max_weight=None, n=No
432
436
  for w in weights:
433
437
  population.update_input_params(weight=w)
434
438
  model.simulator.run(duration)
435
- v = np.array(model.simulator.vs[seg])
439
+ v = np.array(model.simulator.recordings['v'][seg])
436
440
  v_start = v[start_ts]
437
441
  v_max = np.max(v[start_ts:])
438
442
  delta_v = v_max - v_start
@@ -0,0 +1,7 @@
1
+ from dendrotweaks.biophys.mechanisms import Mechanism, IonChannel, StandardIonChannel
2
+ from dendrotweaks.biophys.mechanisms import CaDynamics, LeakChannel
3
+ from dendrotweaks.biophys.mechanisms import LeakChannel
4
+ from dendrotweaks.biophys.groups import SegmentGroup
5
+ from dendrotweaks.biophys.distributions import Distribution
6
+
7
+ import dendrotweaks.biophys.io as io
@@ -114,7 +114,7 @@ class Cell():
114
114
  {% for domain, mechanisms in domains_to_mechs.items() %}
115
115
  for sec in self.{{ domains_to_NEURON[domain] }}:
116
116
  {% for mechanism in mechanisms %}
117
- sec.insert('{{ mechanism }}')
117
+ sec.insert('{{ mechanism }}')
118
118
  {%- endfor %}
119
119
  {% endfor %}
120
120
 
@@ -235,10 +235,12 @@ class Cell():
235
235
 
236
236
  def add_recordings(self):
237
237
  recordings = []
238
- {% for seg, rec in recordings.items() %}
238
+ {% for var, recs in recordings.items() %}
239
+ {% for seg, rec in recs.items() %}
239
240
  rec = h.Vector()
240
- rec.record(self.{{seg._section.domain}}[{{seg._section.domain_idx}}]({{seg.x}})._ref_v)
241
+ rec.record(self.{{seg._section.domain}}[{{seg._section.domain_idx}}]({{seg.x}})._ref_{{ var }})
241
242
  recordings.append(rec)
243
+ {%- endfor -%}
242
244
  {% endfor %}
243
245
  return recordings
244
246
 
@@ -3,7 +3,7 @@
3
3
 
4
4
  import sys
5
5
 
6
- from dendrotweaks.membrane.mechanisms import IonChannel
6
+ from dendrotweaks.biophys.mechanisms import IonChannel
7
7
  import numpy as np
8
8
 
9
9
  class {{ class_name }}(IonChannel):
@@ -43,6 +43,7 @@ class {{ class_name }}(IonChannel):
43
43
  }
44
44
  self.ion = "{{ ion }}"
45
45
  self.current_name = "i_{{ ion }}"
46
+ self.current_available = {{ current_available }}
46
47
  self.independent_var_name = "{{ independent_var_name }}"
47
48
  self.temperature = 37
48
49
 
@@ -23,7 +23,7 @@ UNITS {
23
23
  }
24
24
 
25
25
  PARAMETER {
26
- {% for key, value, unit in range_params %}{{ "%-7s"|format(key) }} = {{ value }} ({{ unit }}){% if not loop.last %}
26
+ {% for key, value, unit in params %}{{ "%-7s"|format(key) }} = {{ value }} ({{ unit }}){% if not loop.last %}
27
27
  {% endif %}{% endfor %}
28
28
  }
29
29
 
@@ -57,7 +57,11 @@ DERIVATIVE states {
57
57
  }
58
58
 
59
59
  INITIAL {
60
+ {%- if has_tadj%}
60
61
  tadj = q10^((celsius - temp)/10(degC))
62
+ {%- else %}
63
+ tadj = 1
64
+ {%- endif %}
61
65
  rates(v)
62
66
  {% for state in state_vars %}{{ state }} = {{ state }}_inf
63
67
  {% endfor %}
@@ -3,8 +3,8 @@ from typing import List, Callable, Dict
3
3
  from dendrotweaks.morphology.trees import Node
4
4
  from dendrotweaks.morphology.sec_trees import Section
5
5
  from dendrotweaks.morphology.seg_trees import Segment
6
- from dendrotweaks.membrane.mechanisms import Mechanism
7
- from dendrotweaks.membrane.distributions import Distribution
6
+ from dendrotweaks.biophys.mechanisms import Mechanism
7
+ from dendrotweaks.biophys.distributions import Distribution
8
8
  from dendrotweaks.utils import timeit
9
9
  from dataclasses import dataclass, field, asdict
10
10
  from typing import List, Tuple, Dict, Optional
@@ -0,0 +1,11 @@
1
+ from dendrotweaks.biophys.io.loader import MODFileLoader
2
+ from dendrotweaks.biophys.io.converter import MODFileConverter
3
+
4
+ from dendrotweaks.biophys.io.reader import MODFileReader
5
+ from dendrotweaks.biophys.io.parser import MODFileParser
6
+ from dendrotweaks.biophys.io.code_generators import PythonCodeGenerator
7
+ from dendrotweaks.biophys.io.code_generators import NMODLCodeGenerator
8
+
9
+ from dendrotweaks.biophys.io.factories import create_channel
10
+ from dendrotweaks.biophys.io.factories import create_standard_channel
11
+ from dendrotweaks.biophys.io.factories import standardize_channel
@@ -90,6 +90,12 @@ class AbstracSyntaxTree():
90
90
  return {k:v for k, v in self.params.items()
91
91
  if k in self['NEURON']['range']}
92
92
 
93
+ @property
94
+ def current_available(self):
95
+ """
96
+ Returns True if the current is available in the mechanism.
97
+ """
98
+ return 'i' in self['NEURON']['range']
93
99
 
94
100
  # ASSIGNED block
95
101
  @property
@@ -72,6 +72,7 @@ class PythonCodeGenerator(CodeGenerator):
72
72
  'independent_var_name': ast.independent_var_name,
73
73
  'channel_params': ast.params,
74
74
  'range_params': ast.range_params,
75
+ 'current_available': ast.current_available,
75
76
  'state_vars': ast.state_vars,
76
77
  'functions': self._generate_functions(ast),
77
78
  'procedures': self._generate_procedures(ast),
@@ -296,10 +297,15 @@ class NMODLCodeGenerator(CodeGenerator):
296
297
  variables = {
297
298
  'suffix': channel.name,
298
299
  'ion': channel.ion,
299
- 'range_params': [
300
+ 'params': [
300
301
  (param, channel.params[param], get_unit(param))
301
302
  for param in channel.params
302
303
  ],
304
+ 'range_params': [
305
+ (param, channel.range_params[param], get_unit(param))
306
+ for param in channel.range_params
307
+ ],
308
+ 'has_tadj': ('q10' in channel.params and 'temp' in channel.params),
303
309
  'state_vars': {
304
310
  var: params['power'] for var, params in channel._state_powers.items()
305
311
  },
@@ -1,6 +1,6 @@
1
- from dendrotweaks.membrane.io.reader import MODFileReader
2
- from dendrotweaks.membrane.io.parser import MODFileParser
3
- from dendrotweaks.membrane.io.code_generators import PythonCodeGenerator
1
+ from dendrotweaks.biophys.io.reader import MODFileReader
2
+ from dendrotweaks.biophys.io.parser import MODFileParser
3
+ from dendrotweaks.biophys.io.code_generators import PythonCodeGenerator
4
4
 
5
5
  class MODFileConverter():
6
6
  """
@@ -3,9 +3,9 @@ import sys
3
3
  from typing import List, Tuple
4
4
 
5
5
 
6
- from dendrotweaks.membrane.io.converter import MODFileConverter
7
- from dendrotweaks.membrane.io.code_generators import NMODLCodeGenerator
8
- from dendrotweaks.membrane.mechanisms import Mechanism, IonChannel, StandardIonChannel
6
+ from dendrotweaks.biophys.io.converter import MODFileConverter
7
+ from dendrotweaks.biophys.io.code_generators import NMODLCodeGenerator
8
+ from dendrotweaks.biophys.mechanisms import Mechanism, IonChannel, StandardIonChannel
9
9
 
10
10
 
11
11
  def create_channel(path_to_mod_file: str,
@@ -86,10 +86,12 @@ def standardize_channel(channel: IonChannel,
86
86
  state_powers=channel._state_powers,
87
87
  ion=channel.ion)
88
88
 
89
- standard_channel.params.update({'q10': channel.params.get('q10'),
90
- 'temp': channel.params.get('temp')})
89
+ if 'q10' in channel.params:
90
+ standard_channel.params['q10'] = channel.params['q10']
91
+ if 'temp' in channel.params:
92
+ standard_channel.params['temp'] = channel.params['temp']
91
93
 
92
- fit_temperature = channel.params.get('temp') or 23
94
+ fit_temperature = channel.params.get('temp')
93
95
 
94
96
  standard_channel.set_tadj(fit_temperature)
95
97
  # Fit the standard channel to the data
@@ -0,0 +1,190 @@
1
+ import os
2
+ import sys
3
+ import shutil
4
+ import subprocess
5
+ import neuron
6
+ from neuron import h
7
+
8
+
9
+ class MODFileLoader():
10
+
11
+ def __init__(self):
12
+ self._loaded_mechanisms = set()
13
+ self.verbose = False
14
+
15
+ def _log(self, message):
16
+ """Print a message if verbose mode is enabled."""
17
+ if self.verbose:
18
+ print(message)
19
+
20
+ # LOADING METHODS
21
+
22
+ def _get_mechanism_dir(self, path_to_mod_file: str) -> str:
23
+ """
24
+ Get the subdirectory for the given mod file.
25
+
26
+ Parameters
27
+ ----------
28
+ path_to_mod_file : str
29
+ Path to the .mod file.
30
+
31
+ Returns
32
+ -------
33
+ str
34
+ Path to the subdirectory for the mechanism.
35
+ """
36
+ mechanism_name = os.path.basename(path_to_mod_file).replace('.mod', '')
37
+ parent_dir = os.path.dirname(path_to_mod_file)
38
+ if sys.platform.startswith('win'):
39
+ return os.path.join(parent_dir, mechanism_name, mechanism_name)
40
+ else:
41
+ return os.path.join(parent_dir, mechanism_name)
42
+
43
+ def _clean_mechanism_dir(self, mechanism_dir: str) -> None:
44
+
45
+ if sys.platform.startswith('win'):
46
+ parent_dir = os.path.dirname(mechanism_dir)
47
+ shutil.rmtree(parent_dir)
48
+ else:
49
+ shutil.rmtree(mechanism_dir)
50
+
51
+
52
+ def load_mechanism(self, path_to_mod_file: str,
53
+ recompile: bool = False) -> None:
54
+ """
55
+ Load a mechanism from the specified mod file.
56
+ Uses the NEURON neuron.load_mechanisms method to make
57
+ the mechanism available in the hoc interpreter.
58
+ Creates a temporary directory for the mechanism files
59
+ to be able to dynamically load mechanisms.
60
+
61
+ Parameters
62
+ ----------
63
+ path_to_mod_file : str
64
+ Path to the .mod file.
65
+ recompile : bool
66
+ Force recompilation even if already compiled.
67
+ """
68
+ mechanism_name = os.path.basename(path_to_mod_file).replace('.mod', '')
69
+ mechanism_dir = self._get_mechanism_dir(path_to_mod_file)
70
+
71
+ if self.verbose: print(f"{'=' * 60}\nLoading mechanism {mechanism_name} to NEURON...")
72
+
73
+ # Check if the mechanism is already loaded
74
+ if mechanism_name in self._loaded_mechanisms:
75
+ self._log(f'Mechanism "{mechanism_name}" already loaded')
76
+ return
77
+
78
+ if recompile and os.path.exists(mechanism_dir):
79
+ self._clean_mechanism_dir(mechanism_dir)
80
+
81
+ self._separate_and_compile(mechanism_name, mechanism_dir, path_to_mod_file)
82
+
83
+ # Load the mechanism
84
+ self._load_mechanism(mechanism_name, mechanism_dir)
85
+
86
+
87
+ # HELPER METHODS
88
+
89
+ def _separate_and_compile(self, mechanism_name, mechanism_dir, path_to_mod_file):
90
+ """
91
+ Separate the mechanism files into their own directory and compile them.
92
+ Separation is done to enable dynamic loading of mechanisms.
93
+ Compilation is done using the appropriate command based on the platform.
94
+
95
+ Parameters
96
+ ----------
97
+ mechanism_name : str
98
+ Name of the mechanism.
99
+ mechanism_dir : str
100
+ Directory to store the mechanism files.
101
+ path_to_mod_file : str
102
+ Path to the .mod file.
103
+ """
104
+
105
+ if sys.platform.startswith('win'):
106
+ dll_file = os.path.join(os.path.dirname(mechanism_dir), 'nrnmech.dll')
107
+ if not os.path.exists(dll_file):
108
+ self._log(f'Compiling mechanism "{mechanism_name}"...')
109
+ os.makedirs(mechanism_dir, exist_ok=True)
110
+ shutil.copy(path_to_mod_file, mechanism_dir)
111
+ self._compile_files(mechanism_dir, ["mknrndll"], shell=True)
112
+ else:
113
+ x86_64_dir = os.path.join(mechanism_dir, 'x86_64')
114
+ if not os.path.exists(x86_64_dir):
115
+ self._log(f'Compiling mechanism "{mechanism_name}"...')
116
+ os.makedirs(mechanism_dir, exist_ok=True)
117
+ shutil.copy(path_to_mod_file, mechanism_dir)
118
+ self._compile_files(mechanism_dir, ["nrnivmodl"])
119
+
120
+
121
+ def _load_mechanism(self, mechanism_name: str, mechanism_dir: str) -> None:
122
+ """
123
+ Load the mechanism into NEURON using neuron.load_mechanisms.
124
+ This method checks if the mechanism is already loaded
125
+ and only loads it if not.
126
+ Parameters
127
+ ----------
128
+ mechanism_name : str
129
+ Name of the mechanism.
130
+ mechanism_dir : str
131
+ Directory containing the compiled mechanism files.
132
+ """
133
+
134
+ if hasattr(h, mechanism_name):
135
+ self._log(f'Mechanism "{mechanism_name}" already exists in hoc')
136
+ else:
137
+ try:
138
+ neuron.load_mechanisms(mechanism_dir)
139
+ except Exception as e:
140
+ print(f"Failed to load mechanism {mechanism_name}: {e}")
141
+ return
142
+ self._loaded_mechanisms.add(mechanism_name)
143
+ self._log(f'Loaded mechanism "{mechanism_name}"')
144
+
145
+
146
+
147
+ def _compile_files(self, path, command, shell=False):
148
+ """
149
+ Compile the MOD files in the specified directory.
150
+
151
+ Parameters
152
+ ----------
153
+ path : str or Path
154
+ Directory containing MOD files to compile.
155
+ command : list
156
+ Compilation command to execute. Either "mknrndll" or "nrnivmodl".
157
+ shell : bool
158
+ Whether to use shell=True for subprocess.run
159
+ (Windows compatibility).
160
+
161
+ Returns
162
+ -------
163
+ bool
164
+ True if compilation succeeded, False otherwise.
165
+ """
166
+ path_str = str(path)
167
+
168
+ try:
169
+ result = subprocess.run(
170
+ command,
171
+ cwd=path_str,
172
+ check=True,
173
+ capture_output=True,
174
+ text=True,
175
+ shell=shell
176
+ )
177
+
178
+ self._log("Compilation successful.")
179
+ if self.verbose and result.stdout:
180
+ print(result.stdout)
181
+ return
182
+
183
+ except subprocess.CalledProcessError as e:
184
+ print(f"Compilation failed with return code {e.returncode}")
185
+ if self.verbose:
186
+ if e.stdout:
187
+ print("Compiler output:\n", e.stdout)
188
+ if e.stderr:
189
+ print("Compiler errors:\n", e.stderr)
190
+ return
@@ -2,14 +2,14 @@ import re
2
2
  import pprint
3
3
  from typing import List, Dict, Union, Any
4
4
 
5
- from dendrotweaks.membrane.io.grammar import title, comment_block
6
- from dendrotweaks.membrane.io.grammar import neuron_block
7
- from dendrotweaks.membrane.io.grammar import units_block, parameter_block, assigned_block
8
- from dendrotweaks.membrane.io.grammar import state_block
9
- from dendrotweaks.membrane.io.grammar import breakpoint_block, derivative_block, initial_block
10
- from dendrotweaks.membrane.io.grammar import function_block, procedure_block
11
-
12
- from dendrotweaks.membrane.io.ast import AbstracSyntaxTree
5
+ from dendrotweaks.biophys.io.grammar import title, comment_block
6
+ from dendrotweaks.biophys.io.grammar import neuron_block
7
+ from dendrotweaks.biophys.io.grammar import units_block, parameter_block, assigned_block
8
+ from dendrotweaks.biophys.io.grammar import state_block
9
+ from dendrotweaks.biophys.io.grammar import breakpoint_block, derivative_block, initial_block
10
+ from dendrotweaks.biophys.io.grammar import function_block, procedure_block
11
+
12
+ from dendrotweaks.biophys.io.ast import AbstracSyntaxTree
13
13
 
14
14
 
15
15
  class MODFileParser():
@@ -32,6 +32,7 @@ class Mechanism():
32
32
  self.name = name
33
33
  self.params = {}
34
34
  self.range_params = {}
35
+ self.current_available = False
35
36
 
36
37
  @property
37
38
  def params_with_suffix(self):
@@ -119,9 +120,12 @@ class IonChannel(Mechanism):
119
120
  where q10 is the temperature coefficient and reference_temp is the
120
121
  temperature at which the channel kinetics were measured.
121
122
  """
122
- q10 = self.params.get("q10", 2.3)
123
- reference_temp = self.params.get("temp", temperature)
124
- self.tadj = q10 ** ((temperature - reference_temp) / 10)
123
+ q10 = self.params.get("q10")
124
+ reference_temp = self.params.get("temp")
125
+ if q10 is None or reference_temp is None:
126
+ self.tadj = 1
127
+ else:
128
+ self.tadj = q10 ** ((temperature - reference_temp) / 10)
125
129
 
126
130
  def get_data(self, x=None, temperature: float = 37, verbose=True) -> Dict[str, Dict[str, float]]:
127
131
  """
@@ -367,14 +371,14 @@ class StandardIonChannel(IonChannel):
367
371
  # for param in self.STANDARD_PARAMS]
368
372
 
369
373
  self.params = {
374
+ 'gbar': 0.0,
375
+ **{
370
376
  f'{param}_{state}': None
371
377
  for state in state_powers
372
378
  for param in self.STANDARD_PARAMS
379
+ }
373
380
  }
374
- self.params.update({
375
- 'gbar': 0.0,
376
- })
377
- self.range_params = self.params.copy()
381
+ self.range_params = {k:v for k, v in self.params.items()}
378
382
 
379
383
  self.temperature = 37
380
384
 
@@ -474,9 +478,9 @@ class StandardIonChannel(IonChannel):
474
478
  fit_result.params = {key: round(value, round_params) for key, value in fit_result.params.items()}
475
479
 
476
480
  for param in ['k', 'delta', 'tau0', 'vhalf', 'sigma']:
477
- self.params[f'{param}_{state}'] = fit_result.params[param]
478
-
479
- self.range_params = self.params.copy()
481
+ value = fit_result.params[param]
482
+ self.params[f'{param}_{state}'] = value
483
+ self.range_params[f'{param}_{state}'] = value
480
484
 
481
485
 
482
486
  def to_dict(self):