bmtool 0.7.0.6.4__py3-none-any.whl → 0.7.1.1__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.
- bmtool/SLURM.py +162 -109
- bmtool/__init__.py +1 -1
- bmtool/__main__.py +8 -7
- bmtool/analysis/entrainment.py +290 -147
- bmtool/analysis/lfp.py +279 -134
- bmtool/analysis/netcon_reports.py +41 -44
- bmtool/analysis/spikes.py +114 -73
- bmtool/bmplot/connections.py +658 -325
- bmtool/bmplot/entrainment.py +17 -18
- bmtool/bmplot/lfp.py +24 -17
- bmtool/bmplot/netcon_reports.py +0 -4
- bmtool/bmplot/spikes.py +97 -48
- bmtool/connectors.py +394 -251
- bmtool/debug/commands.py +13 -7
- bmtool/debug/debug.py +2 -2
- bmtool/graphs.py +26 -19
- bmtool/manage.py +6 -11
- bmtool/plot_commands.py +350 -151
- bmtool/singlecell.py +357 -195
- bmtool/synapses.py +564 -470
- bmtool/util/commands.py +1079 -627
- bmtool/util/neuron/celltuner.py +989 -609
- bmtool/util/util.py +992 -588
- {bmtool-0.7.0.6.4.dist-info → bmtool-0.7.1.1.dist-info}/METADATA +40 -2
- bmtool-0.7.1.1.dist-info/RECORD +34 -0
- {bmtool-0.7.0.6.4.dist-info → bmtool-0.7.1.1.dist-info}/WHEEL +1 -1
- bmtool-0.7.0.6.4.dist-info/RECORD +0 -34
- {bmtool-0.7.0.6.4.dist-info → bmtool-0.7.1.1.dist-info}/entry_points.txt +0 -0
- {bmtool-0.7.0.6.4.dist-info → bmtool-0.7.1.1.dist-info}/licenses/LICENSE +0 -0
- {bmtool-0.7.0.6.4.dist-info → bmtool-0.7.1.1.dist-info}/top_level.txt +0 -0
bmtool/util/neuron/celltuner.py
CHANGED
@@ -1,13 +1,14 @@
|
|
1
|
-
from neuron import h
|
2
|
-
import neuron
|
3
|
-
import os
|
4
1
|
import glob
|
5
|
-
import
|
6
|
-
from datetime import datetime
|
2
|
+
import os
|
7
3
|
import re
|
4
|
+
from datetime import datetime
|
5
|
+
|
8
6
|
import click
|
9
|
-
|
10
|
-
|
7
|
+
import neuron
|
8
|
+
import numpy as np
|
9
|
+
from clint.textui import colored
|
10
|
+
from neuron import h
|
11
|
+
|
11
12
|
|
12
13
|
class Widget:
|
13
14
|
def __init__(self):
|
@@ -16,15 +17,15 @@ class Widget:
|
|
16
17
|
def execute(self):
|
17
18
|
raise NotImplementedError
|
18
19
|
|
19
|
-
def hoc_declaration_str_list(self
|
20
|
+
def hoc_declaration_str_list(self, **kwargs):
|
20
21
|
return []
|
21
22
|
|
22
|
-
def hoc_display_str_list(self
|
23
|
+
def hoc_display_str_list(self, **kwargs):
|
23
24
|
return []
|
24
25
|
|
25
|
-
class ValuePanel:
|
26
26
|
|
27
|
-
|
27
|
+
class ValuePanel:
|
28
|
+
def __init__(self, init_val=0, label="", lower_limit=-100, upper_limit=100, slider=True):
|
28
29
|
self._val = h.ref(init_val)
|
29
30
|
h.xvalue(label, self._val, True, self._bounds_check)
|
30
31
|
self.__lower_limit = lower_limit
|
@@ -44,61 +45,71 @@ class ValuePanel:
|
|
44
45
|
new_val = max(self.__lower_limit, new_val)
|
45
46
|
self._val[0] = min(new_val, self.__upper_limit)
|
46
47
|
|
47
|
-
class SameCellValuePanel:
|
48
48
|
|
49
|
-
|
49
|
+
class SameCellValuePanel:
|
50
|
+
def __init__(
|
51
|
+
self,
|
52
|
+
original_cell,
|
53
|
+
other_cells,
|
54
|
+
section,
|
55
|
+
prop,
|
56
|
+
init_val=0,
|
57
|
+
label="",
|
58
|
+
lower_limit=-1e15,
|
59
|
+
upper_limit=1e15,
|
60
|
+
all_sec=False,
|
61
|
+
):
|
50
62
|
self.original_cell = original_cell
|
51
63
|
self.other_cells = other_cells
|
52
64
|
self.prop = prop
|
53
|
-
#import pdb;pdb.set_trace()
|
54
|
-
#self._val = h.ref(init_val)
|
55
|
-
|
65
|
+
# import pdb;pdb.set_trace()
|
66
|
+
# self._val = h.ref(init_val)
|
67
|
+
|
56
68
|
try:
|
57
|
-
self._val_obj = getattr(eval("original_cell."+section)(0.5),"_ref_"+prop)
|
69
|
+
self._val_obj = getattr(eval("original_cell." + section)(0.5), "_ref_" + prop)
|
58
70
|
except AttributeError as e:
|
59
|
-
self._val_obj = getattr(eval("original_cell."+section),"_ref_"+prop)
|
60
|
-
|
61
|
-
|
71
|
+
self._val_obj = getattr(eval("original_cell." + section), "_ref_" + prop)
|
62
72
|
|
63
73
|
try:
|
64
|
-
self._val =
|
74
|
+
self._val = h.Pointer(self._val_obj)
|
65
75
|
except Exception as e:
|
66
|
-
|
76
|
+
# Debug statement removed
|
77
|
+
pass
|
67
78
|
self._vals = []
|
68
79
|
|
69
80
|
all_sections = [sec for sec in h.allsec()]
|
70
|
-
primary_section = eval("original_cell."+section)
|
81
|
+
primary_section = eval("original_cell." + section)
|
71
82
|
|
72
83
|
if all_sec:
|
73
84
|
for osection in all_sections:
|
74
85
|
if not osection == primary_section:
|
75
86
|
try:
|
76
|
-
attrptr = getattr(osection(0.5),"_ref_"+prop)
|
87
|
+
attrptr = getattr(osection(0.5), "_ref_" + prop)
|
77
88
|
self._vals.append(h.Pointer(attrptr))
|
78
89
|
except AttributeError as e:
|
79
90
|
print(e)
|
80
91
|
|
81
92
|
else:
|
82
93
|
for cell in other_cells:
|
83
|
-
self._vals.append(h.Pointer(getattr(eval("cell."+section)(0.5),"_ref_"+prop)))
|
84
|
-
#print(self._vals[-1].val)
|
85
|
-
#import pdb;pdb.set_trace()
|
94
|
+
self._vals.append(h.Pointer(getattr(eval("cell." + section)(0.5), "_ref_" + prop)))
|
95
|
+
# print(self._vals[-1].val)
|
96
|
+
# import pdb;pdb.set_trace()
|
86
97
|
h.xvalue(label, self._val_obj, True, self._bounds_check)
|
87
98
|
self.__lower_limit = lower_limit
|
88
99
|
self.__upper_limit = upper_limit
|
89
|
-
#h.xslider(self._val, self.__lower_limit, self.__upper_limit)
|
100
|
+
# h.xslider(self._val, self.__lower_limit, self.__upper_limit)
|
90
101
|
|
91
102
|
def _bounds_check(self):
|
92
|
-
#self.val = self.val
|
103
|
+
# self.val = self.val
|
93
104
|
new_val = max(self.__lower_limit, self.val)
|
94
|
-
#self._val[0] = min(new_val, self.__upper_limit)
|
105
|
+
# self._val[0] = min(new_val, self.__upper_limit)
|
95
106
|
self._val.assign(min(new_val, self.__upper_limit))
|
96
|
-
#print(self._val.val)
|
107
|
+
# print(self._val.val)
|
97
108
|
for _val in self._vals:
|
98
109
|
_val.assign(min(new_val, self.__upper_limit))
|
99
|
-
#print(_val.val)
|
100
|
-
#print("bounds check called")
|
101
|
-
#pass
|
110
|
+
# print(_val.val)
|
111
|
+
# print("bounds check called")
|
112
|
+
# pass
|
102
113
|
|
103
114
|
@property
|
104
115
|
def val(self):
|
@@ -107,17 +118,19 @@ class SameCellValuePanel:
|
|
107
118
|
@val.setter
|
108
119
|
def val(self, new_val):
|
109
120
|
new_val = max(self.__lower_limit, new_val)
|
110
|
-
#self._val[0] = min(new_val, self.__upper_limit)
|
121
|
+
# self._val[0] = min(new_val, self.__upper_limit)
|
111
122
|
self._val.assign(min(new_val, self.__upper_limit))
|
112
|
-
#print(self._val.val)
|
123
|
+
# print(self._val.val)
|
113
124
|
for _val in self._vals:
|
114
125
|
_val.assign(min(new_val, self.__upper_limit))
|
115
|
-
#print(_val.val)
|
126
|
+
# print(_val.val)
|
127
|
+
|
116
128
|
|
117
129
|
# 1WQ2E -- Morgan 1/20/2020 @ ~9:30pm
|
118
130
|
|
131
|
+
|
119
132
|
class SingleButtonWidget(Widget):
|
120
|
-
def __init__(self,text,on_press):
|
133
|
+
def __init__(self, text, on_press):
|
121
134
|
self.text = text
|
122
135
|
self.on_press = on_press
|
123
136
|
|
@@ -126,8 +139,9 @@ class SingleButtonWidget(Widget):
|
|
126
139
|
h.xbutton(self.text, self.on_press)
|
127
140
|
h.xpanel()
|
128
141
|
|
142
|
+
|
129
143
|
class MultiSecMenuWidget(Widget):
|
130
|
-
def __init__(self,cell,other_cells,section,md,label="",x="0.5",vartype=1):
|
144
|
+
def __init__(self, cell, other_cells, section, md, label="", x="0.5", vartype=1):
|
131
145
|
super(MultiSecMenuWidget, self).__init__()
|
132
146
|
self.cell = cell
|
133
147
|
self.other_cells = other_cells
|
@@ -144,43 +158,47 @@ class MultiSecMenuWidget(Widget):
|
|
144
158
|
self.variables = self.get_variables()
|
145
159
|
|
146
160
|
def get_variables(self):
|
147
|
-
variables = [("diam","diam (um)"),("cm", "cm (uF/cm2)")]
|
148
|
-
cellsec = eval(
|
161
|
+
variables = [("diam", "diam (um)"), ("cm", "cm (uF/cm2)")]
|
162
|
+
cellsec = eval("self.cell." + self.section)
|
149
163
|
mechs = [mech.name() for mech in cellsec(0.5) if not mech.name().endswith("_ion")]
|
150
|
-
#ctg.mechanism_dict["kdr"]["NEURON"]["USEION"]["READ"]
|
151
|
-
#['eleak']
|
152
|
-
# if they're in the useion read then ignore as
|
153
|
-
#ctg.mechanism_dict["leak"]["PARAMETER"]
|
154
|
-
#[('gbar', '(siemens/cm2)'), ('eleak', '(mV)')]
|
164
|
+
# ctg.mechanism_dict["kdr"]["NEURON"]["USEION"]["READ"]
|
165
|
+
# ['eleak']
|
166
|
+
# if they're in the useion read then ignore as
|
167
|
+
# ctg.mechanism_dict["leak"]["PARAMETER"]
|
168
|
+
# [('gbar', '(siemens/cm2)'), ('eleak', '(mV)')]
|
155
169
|
md = self.md
|
156
170
|
for mech in mechs:
|
157
|
-
if
|
158
|
-
md
|
159
|
-
md[mech]
|
160
|
-
md[mech]["NEURON"]
|
161
|
-
|
162
|
-
|
163
|
-
|
171
|
+
if (
|
172
|
+
md.get(mech)
|
173
|
+
and md[mech].get("NEURON")
|
174
|
+
and md[mech]["NEURON"].get("USEION")
|
175
|
+
and md[mech]["NEURON"]["USEION"].get("READ")
|
176
|
+
):
|
177
|
+
ri = md[mech]["NEURON"]["USEION"]["READ"]
|
178
|
+
for v in ri:
|
179
|
+
variables.append((v, v))
|
164
180
|
if md.get(mech) and md[mech].get("PARAMETER"):
|
165
181
|
params = md[mech]["PARAMETER"]
|
166
182
|
ions = [v[0] for v in variables]
|
167
183
|
for param in params:
|
168
184
|
if param[0] not in ions:
|
169
|
-
v = param[0]+"_"+mech
|
185
|
+
v = param[0] + "_" + mech
|
170
186
|
units = ""
|
171
187
|
if param[1]:
|
172
188
|
units = param[1]
|
173
|
-
t = v +
|
174
|
-
variables.append((v,t))
|
189
|
+
t = v + " " + units
|
190
|
+
variables.append((v, t))
|
175
191
|
return variables
|
176
|
-
|
192
|
+
|
177
193
|
def execute(self):
|
178
|
-
h.xpanel(
|
194
|
+
h.xpanel("xvarlabel")
|
179
195
|
h.xlabel(self.label)
|
180
196
|
for var in self.variables:
|
181
197
|
if var[1] not in self.defined_vars:
|
182
198
|
try:
|
183
|
-
panel=SameCellValuePanel(
|
199
|
+
panel = SameCellValuePanel(
|
200
|
+
self.cell, self.other_cells, self.section, var[0], label=var[1]
|
201
|
+
)
|
184
202
|
self.panels.append(panel)
|
185
203
|
self.defined_vars.append(var[1])
|
186
204
|
except AttributeError as e:
|
@@ -191,16 +209,19 @@ class MultiSecMenuWidget(Widget):
|
|
191
209
|
def add_var(self):
|
192
210
|
pass
|
193
211
|
|
194
|
-
def hoc_display_str_list(self
|
212
|
+
def hoc_display_str_list(self, **kwargs):
|
195
213
|
ctg = kwargs["ctg"]
|
196
214
|
ret = []
|
197
|
-
#ret.append("$o2.soma nrnsecmenu(.5,1)")
|
215
|
+
# ret.append("$o2.soma nrnsecmenu(.5,1)")
|
198
216
|
cell = ctg.hoc_ref(self.cell)
|
199
|
-
ret.append(
|
217
|
+
ret.append(
|
218
|
+
cell + "." + self.section + " nrnsecmenu(" + str(self.x) + "," + str(self.vartype) + ")"
|
219
|
+
)
|
200
220
|
return ret
|
201
221
|
|
222
|
+
|
202
223
|
class SegregationSelectorWidget(Widget):
|
203
|
-
def __init__(self,cell, other_cells, section, mechanism_dict, all_sec=False, variables=None):
|
224
|
+
def __init__(self, cell, other_cells, section, mechanism_dict, all_sec=False, variables=None):
|
204
225
|
super(SegregationSelectorWidget, self).__init__()
|
205
226
|
if all_sec:
|
206
227
|
self.label = "Segregation Selection (All Segments)"
|
@@ -212,11 +233,10 @@ class SegregationSelectorWidget(Widget):
|
|
212
233
|
self.mechanism_dict = mechanism_dict
|
213
234
|
self.all_sec = all_sec
|
214
235
|
|
215
|
-
self.vps=[]#ValuePanels
|
216
|
-
self.labels=[]
|
217
|
-
cellsec = eval("cell."+section)
|
236
|
+
self.vps = [] # ValuePanels
|
237
|
+
self.labels = []
|
238
|
+
cellsec = eval("cell." + section)
|
218
239
|
self.mechs = [mech.name() for mech in cellsec(0.5) if not mech.name().endswith("_ion")]
|
219
|
-
|
220
240
|
|
221
241
|
self.variables = variables
|
222
242
|
|
@@ -228,15 +248,23 @@ class SegregationSelectorWidget(Widget):
|
|
228
248
|
def a(n):
|
229
249
|
"""function to be called when a radio button is toggled"""
|
230
250
|
print(n)
|
231
|
-
|
251
|
+
|
252
|
+
h.xpanel("xvarlabel")
|
232
253
|
h.xlabel(self.label)
|
233
254
|
if self.variables:
|
234
255
|
for variable in self.variables:
|
235
|
-
label = variable
|
256
|
+
label = variable # + ' Segregation (mV)'
|
236
257
|
ref = variable
|
237
258
|
try:
|
238
|
-
if not
|
239
|
-
vp = SameCellValuePanel(
|
259
|
+
if label not in self.labels:
|
260
|
+
vp = SameCellValuePanel(
|
261
|
+
self.cell,
|
262
|
+
self.other_cells,
|
263
|
+
self.section,
|
264
|
+
ref,
|
265
|
+
label=label,
|
266
|
+
all_sec=self.all_sec,
|
267
|
+
)
|
240
268
|
self.vps.append(vp)
|
241
269
|
self.labels.append(label)
|
242
270
|
except AttributeError as e:
|
@@ -245,33 +273,47 @@ class SegregationSelectorWidget(Widget):
|
|
245
273
|
for mech in self.mechs:
|
246
274
|
if not self.mechanism_dict[mech].get("DERIVATIVE"):
|
247
275
|
continue
|
248
|
-
actvars = [
|
249
|
-
|
250
|
-
|
251
|
-
if
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
276
|
+
actvars = [
|
277
|
+
line["variable"]
|
278
|
+
for line in self.mechanism_dict[mech]["DERIVATIVE"]
|
279
|
+
if line["is_likely_activation"]
|
280
|
+
]
|
281
|
+
|
282
|
+
for var in self.mechanism_dict[mech]["state_activation_vars"]:
|
283
|
+
if var["var"] in actvars:
|
284
|
+
# {'var': 'n', 'var_inf': 'inf', 'vh': 'nvhalf', 'k': 'nk', 'procedure_set': 'rate', 'line_set': 'inf = 1.0 / (1.0 + (exp((v + nvhalf) / (nk))))'}
|
285
|
+
label = var["var"] + " (" + mech + ") " + "Segregation (mV)"
|
286
|
+
# vp = ValuePanel(label=label)
|
287
|
+
ref = var["var"] + "seg_" + mech
|
256
288
|
try:
|
257
|
-
if not
|
258
|
-
vp = SameCellValuePanel(
|
289
|
+
if label not in self.labels:
|
290
|
+
vp = SameCellValuePanel(
|
291
|
+
self.cell,
|
292
|
+
self.other_cells,
|
293
|
+
self.section,
|
294
|
+
ref,
|
295
|
+
label=label,
|
296
|
+
all_sec=self.all_sec,
|
297
|
+
)
|
259
298
|
self.vps.append(vp)
|
260
299
|
self.labels.append(label)
|
261
300
|
except AttributeError as e:
|
262
301
|
pass
|
263
|
-
h.xbutton(
|
264
|
-
|
265
|
-
#menu = h.xmenu('menu')
|
266
|
-
#import pdb;pdb.set_trace()
|
267
|
-
#for i in range(1, 11):
|
302
|
+
h.xbutton("Segregation (Run)", calculate)
|
303
|
+
|
304
|
+
# menu = h.xmenu('menu')
|
305
|
+
# import pdb;pdb.set_trace()
|
306
|
+
# for i in range(1, 11):
|
268
307
|
# h.xradiobutton('item %d' % i, (a, i))
|
269
308
|
|
270
|
-
#h.xmenu()
|
309
|
+
# h.xmenu()
|
271
310
|
h.xpanel()
|
272
|
-
|
311
|
+
|
312
|
+
|
273
313
|
class SegregationPassiveWidget(Widget):
|
274
|
-
def __init__(
|
314
|
+
def __init__(
|
315
|
+
self, fir_widget, cell, other_cells, section, mechanism_dict, gleak_var=None, eleak_var=None
|
316
|
+
):
|
275
317
|
super(SegregationPassiveWidget, self).__init__()
|
276
318
|
self.label = "Segregation Passive Fitting"
|
277
319
|
self.fir_widget = fir_widget
|
@@ -284,50 +326,49 @@ class SegregationPassiveWidget(Widget):
|
|
284
326
|
self.other_cells = other_cells
|
285
327
|
self.section = section
|
286
328
|
self.mechanism_dict = mechanism_dict
|
287
|
-
|
288
|
-
self.segment = eval("cell."+section+"(0.5)")
|
329
|
+
|
330
|
+
self.segment = eval("cell." + section + "(0.5)") # getattr(cell,section)(0.5)
|
289
331
|
self.mechs = [mech.name() for mech in self.segment if not mech.name().endswith("_ion")]
|
290
332
|
|
291
|
-
|
292
333
|
self.eleak_var = ""
|
293
334
|
self.gleak_var = ""
|
294
335
|
self.eleak_not_found = False
|
295
336
|
self.gleak_not_found = False
|
296
337
|
if not gleak_var:
|
297
|
-
if hasattr(self.segment,"gbar_leak"):
|
338
|
+
if hasattr(self.segment, "gbar_leak"):
|
298
339
|
self.gleak_var = "gbar_leak"
|
299
|
-
elif hasattr(self.segment,"g_bar_leak"):
|
340
|
+
elif hasattr(self.segment, "g_bar_leak"):
|
300
341
|
self.gleak_var = "g_bar_leak"
|
301
342
|
else:
|
302
|
-
#raise AttributeError("Leak channel gbar not found, specify gleak_var in SegregationPassiveWidget")
|
343
|
+
# raise AttributeError("Leak channel gbar not found, specify gleak_var in SegregationPassiveWidget")
|
303
344
|
self.gleak_not_found = True
|
304
345
|
else:
|
305
346
|
self.gleak_var = gleak_var
|
306
|
-
|
347
|
+
|
307
348
|
if not eleak_var:
|
308
|
-
if hasattr(self.segment,"eleak"):
|
349
|
+
if hasattr(self.segment, "eleak"):
|
309
350
|
self.eleak_var = "eleak"
|
310
|
-
elif hasattr(self.segment,"e_leak"):
|
351
|
+
elif hasattr(self.segment, "e_leak"):
|
311
352
|
self.eleak_var = "e_leak"
|
312
353
|
else:
|
313
|
-
#raise AttributeError("Leak channel reversal not found, specify eleak_var in SegregationPassiveWidget")
|
354
|
+
# raise AttributeError("Leak channel reversal not found, specify eleak_var in SegregationPassiveWidget")
|
314
355
|
self.eleak_not_found = True
|
315
356
|
else:
|
316
357
|
self.eleak_var = eleak_var
|
317
|
-
|
318
|
-
#import pdb;pdb.set_trace()
|
358
|
+
|
359
|
+
# import pdb;pdb.set_trace()
|
319
360
|
|
320
361
|
def execute(self):
|
321
362
|
def calculate():
|
322
363
|
if not self.is_calculating:
|
323
364
|
self.is_calculating = True
|
324
|
-
|
365
|
+
|
325
366
|
area = self.segment.area()
|
326
|
-
g_bar_leak = getattr(self.segment,self.gleak_var)
|
367
|
+
g_bar_leak = getattr(self.segment, self.gleak_var)
|
327
368
|
|
328
|
-
v_rest = self.v_rest.val
|
329
|
-
r_in = self.r_in.val
|
330
|
-
tau = self.tau.val
|
369
|
+
v_rest = self.v_rest.val # mV
|
370
|
+
r_in = self.r_in.val # Ohms
|
371
|
+
tau = self.tau.val # ms
|
331
372
|
|
332
373
|
# Assuming Vrest is within the range for ELeak
|
333
374
|
# ELeak = Vrest
|
@@ -340,23 +381,25 @@ class SegregationPassiveWidget(Widget):
|
|
340
381
|
# cm/cm2 = (tau*g_bar_leak*Area)/Area = tau*g_bar_leak
|
341
382
|
|
342
383
|
eleak = v_rest
|
343
|
-
setattr(self.segment,self.eleak_var,eleak)
|
384
|
+
setattr(self.segment, self.eleak_var, eleak)
|
344
385
|
|
345
|
-
g_bar_leak = 1/(r_in*area)*1e2
|
346
|
-
setattr(self.segment,self.gleak_var,g_bar_leak)
|
386
|
+
g_bar_leak = 1 / (r_in * area) * 1e2 # area m to cm?
|
387
|
+
setattr(self.segment, self.gleak_var, g_bar_leak)
|
347
388
|
|
348
|
-
cm = tau*g_bar_leak*1e3
|
349
|
-
setattr(self.segment,"cm",cm)
|
389
|
+
cm = tau * g_bar_leak * 1e3 # tau ms->s
|
390
|
+
setattr(self.segment, "cm", cm)
|
350
391
|
|
351
392
|
for cell in self.other_cells:
|
352
|
-
segment = eval(
|
353
|
-
|
354
|
-
|
355
|
-
setattr(segment,
|
393
|
+
segment = eval(
|
394
|
+
"cell." + self.section + "(0.5)"
|
395
|
+
) # getattr(cell,self.section)(0.5)
|
396
|
+
setattr(segment, self.eleak_var, eleak)
|
397
|
+
setattr(segment, self.gleak_var, g_bar_leak)
|
398
|
+
setattr(segment, "cm", cm)
|
356
399
|
|
357
400
|
h.stdinit()
|
358
401
|
h.run()
|
359
|
-
|
402
|
+
|
360
403
|
spw = self
|
361
404
|
ctstop = self.fir_widget.tstop
|
362
405
|
cvode = h.CVode()
|
@@ -364,26 +407,32 @@ class SegregationPassiveWidget(Widget):
|
|
364
407
|
def commands():
|
365
408
|
def start_event():
|
366
409
|
return
|
367
|
-
|
410
|
+
|
411
|
+
cvode.event(0, start_event)
|
368
412
|
|
369
413
|
def stop_event():
|
370
414
|
nonlocal spw
|
371
415
|
if not spw.is_calculating:
|
372
416
|
if self.gleak_var and self.eleak_var:
|
373
|
-
spw.v_rest.val = round(self.fir_widget.v_rest,4)
|
374
|
-
spw.r_in.val = round(float(self.fir_widget.r_in/1e6),4)
|
375
|
-
spw.tau.val = round(self.fir_widget.tau,4)
|
417
|
+
spw.v_rest.val = round(self.fir_widget.v_rest, 4)
|
418
|
+
spw.r_in.val = round(float(self.fir_widget.r_in / 1e6), 4)
|
419
|
+
spw.tau.val = round(self.fir_widget.tau, 4)
|
376
420
|
else:
|
377
|
-
spw.is_calculating = False
|
378
|
-
cvode.event(ctstop, stop_event)
|
421
|
+
spw.is_calculating = False
|
379
422
|
|
380
|
-
|
423
|
+
cvode.event(ctstop, stop_event)
|
424
|
+
|
425
|
+
h.xpanel("xvarlabel")
|
381
426
|
h.xlabel(self.label)
|
382
427
|
if self.gleak_var and self.eleak_var:
|
383
|
-
self.v_rest=ValuePanel(
|
384
|
-
|
385
|
-
|
386
|
-
|
428
|
+
self.v_rest = ValuePanel(
|
429
|
+
label="V Rest (mV)", slider=False, lower_limit=-1000, upper_limit=1000
|
430
|
+
)
|
431
|
+
self.r_in = ValuePanel(
|
432
|
+
label="R in (MOhm)", slider=False, lower_limit=0, upper_limit=100000
|
433
|
+
)
|
434
|
+
self.tau = ValuePanel(label="Tau (ms)", slider=False, lower_limit=-100, upper_limit=100)
|
435
|
+
h.xbutton("Fit Passive Properties (Run)", calculate)
|
387
436
|
else:
|
388
437
|
if self.gleak_not_found:
|
389
438
|
h.xlabel("Leak conductance (gleak) not found")
|
@@ -393,6 +442,7 @@ class SegregationPassiveWidget(Widget):
|
|
393
442
|
|
394
443
|
return commands
|
395
444
|
|
445
|
+
|
396
446
|
class SegregationFIRFitWidget(Widget):
|
397
447
|
def __init__(self, fir_widget):
|
398
448
|
super(SegregationFIRFitWidget, self).__init__()
|
@@ -416,38 +466,45 @@ class SegregationFIRFitWidget(Widget):
|
|
416
466
|
def commands():
|
417
467
|
def start_event():
|
418
468
|
vals = [v.val for v in self.vps]
|
419
|
-
any_nonzero = next((value for index,value in enumerate(vals) if value != 0), None)
|
469
|
+
any_nonzero = next((value for index, value in enumerate(vals) if value != 0), None)
|
420
470
|
if any_nonzero:
|
421
471
|
self.valvec = h.Vector(vals)
|
422
472
|
self.fir_widget.graph.color(3)
|
423
473
|
self.fir_widget.graph.label("User FI Curve")
|
424
|
-
self.plot = self.valvec.plot(
|
474
|
+
self.plot = self.valvec.plot(
|
475
|
+
self.fir_widget.graph, self.fir_widget.ampvec, 3, 1
|
476
|
+
)
|
425
477
|
return
|
426
|
-
|
478
|
+
|
479
|
+
cvode.event(1, start_event)
|
427
480
|
|
428
481
|
def stop_event():
|
429
482
|
nonlocal spw
|
430
483
|
if not spw.is_calculating:
|
431
|
-
pass
|
484
|
+
pass
|
432
485
|
else:
|
433
|
-
spw.is_calculating = False
|
434
|
-
cvode.event(ctstop, stop_event)
|
486
|
+
spw.is_calculating = False
|
435
487
|
|
436
|
-
|
488
|
+
cvode.event(ctstop, stop_event)
|
489
|
+
|
490
|
+
h.xpanel("xvarlabel")
|
437
491
|
h.xlabel(self.label)
|
438
492
|
for amp in self.fir_widget.amps:
|
439
|
-
vp = ValuePanel(
|
493
|
+
vp = ValuePanel(
|
494
|
+
label=str(int(amp * 1000)) + " (pA)", slider=False, lower_limit=0, upper_limit=1000
|
495
|
+
)
|
440
496
|
self.vps.append(vp)
|
441
|
-
h.xbutton(
|
497
|
+
h.xbutton("Fit FIR Curve (Run) [Plots User FIR]", calculate)
|
442
498
|
h.xpanel()
|
443
499
|
|
444
500
|
return commands
|
445
501
|
|
502
|
+
|
446
503
|
class AutoVInitWidget(Widget):
|
447
|
-
def __init__(self,fir_widget):
|
504
|
+
def __init__(self, fir_widget):
|
448
505
|
self.fir_widget = fir_widget
|
449
506
|
self.vinitcheckbox = 1
|
450
|
-
|
507
|
+
|
451
508
|
def execute(self):
|
452
509
|
spw = self
|
453
510
|
ctstop = self.fir_widget.tstop
|
@@ -456,22 +513,27 @@ class AutoVInitWidget(Widget):
|
|
456
513
|
def commands():
|
457
514
|
def start_event():
|
458
515
|
return
|
459
|
-
|
516
|
+
|
517
|
+
cvode.event(0, start_event)
|
460
518
|
|
461
519
|
def stop_event():
|
462
520
|
nonlocal spw
|
463
521
|
if spw.vinitcheckbox:
|
464
|
-
h.v_init = spw.fir_widget.v_rest
|
465
|
-
|
522
|
+
h.v_init = spw.fir_widget.v_rest
|
523
|
+
|
524
|
+
cvode.event(ctstop, stop_event)
|
466
525
|
|
467
|
-
h.xpanel(
|
468
|
-
h.xcheckbox(
|
526
|
+
h.xpanel("xvarlabel")
|
527
|
+
h.xcheckbox(
|
528
|
+
"Auto-set v_init to v_rest at end of simulation", (self, "vinitcheckbox")
|
529
|
+
) # , self.vinitcheckboxpressed)
|
469
530
|
h.xpanel()
|
470
531
|
|
471
532
|
return commands
|
472
533
|
|
534
|
+
|
473
535
|
class TextWidget(Widget):
|
474
|
-
def __init__(self,label=""):
|
536
|
+
def __init__(self, label=""):
|
475
537
|
super(TextWidget, self).__init__()
|
476
538
|
self.label = label
|
477
539
|
self.mystrs = []
|
@@ -480,14 +542,14 @@ class TextWidget(Widget):
|
|
480
542
|
self.fir_print_calc = False
|
481
543
|
self.fir_print_fi = False
|
482
544
|
return
|
483
|
-
|
545
|
+
|
484
546
|
def add_text(self, text):
|
485
547
|
"""
|
486
548
|
Returns the index for the string you want to set
|
487
549
|
Easier way to do newlines
|
488
550
|
"""
|
489
|
-
self.mystrs.append(h.ref(
|
490
|
-
i = len(self.mystrs)-1
|
551
|
+
self.mystrs.append(h.ref(""))
|
552
|
+
i = len(self.mystrs) - 1
|
491
553
|
self.mystrs[i][0] = text
|
492
554
|
return i
|
493
555
|
|
@@ -496,18 +558,18 @@ class TextWidget(Widget):
|
|
496
558
|
return
|
497
559
|
|
498
560
|
def execute(self):
|
499
|
-
h.xpanel(
|
561
|
+
h.xpanel("xvarlabel")
|
500
562
|
h.xlabel(self.label)
|
501
563
|
for mystr in self.mystrs:
|
502
564
|
h.xvarlabel(mystr)
|
503
565
|
h.xpanel()
|
504
566
|
return
|
505
|
-
|
567
|
+
|
506
568
|
def set_to_fir_passive(self, fir_widget, print_calc=True, print_fi=True):
|
507
569
|
self.fir_widget = fir_widget
|
508
570
|
self.fir_print_calc = print_calc
|
509
571
|
self.fir_print_fi = print_fi
|
510
|
-
self.label=
|
572
|
+
self.label = "PASSIVE PROPERTIES:\n"
|
511
573
|
self.add_text("V_rest: ")
|
512
574
|
self.add_text("R_in: ")
|
513
575
|
self.add_text("Tau: ")
|
@@ -523,38 +585,102 @@ class TextWidget(Widget):
|
|
523
585
|
self.add_text("FICurve ([nA]:Hz): ")
|
524
586
|
self.add_text("")
|
525
587
|
return
|
526
|
-
|
588
|
+
|
527
589
|
def update_fir_passive(self):
|
528
|
-
|
529
590
|
if self.fir_widget:
|
530
|
-
self.set_text(0,"V_rest: " + str(round(self.fir_widget.v_rest,2)) + " (mV) ")
|
531
|
-
self.set_text(1,"R_in: " + str(round(self.fir_widget.r_in/1e6,2)) + " (MOhms) ")
|
532
|
-
self.set_text(2,"Tau: " + str(round(self.fir_widget.tau,4)) + " (ms) ")
|
591
|
+
self.set_text(0, "V_rest: " + str(round(self.fir_widget.v_rest, 2)) + " (mV) ")
|
592
|
+
self.set_text(1, "R_in: " + str(round(self.fir_widget.r_in / 1e6, 2)) + " (MOhms) ")
|
593
|
+
self.set_text(2, "Tau: " + str(round(self.fir_widget.tau, 4)) + " (ms) ")
|
533
594
|
|
534
595
|
if self.fir_print_calc:
|
535
|
-
v_rest_calc =
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
596
|
+
v_rest_calc = (
|
597
|
+
"V_rest Calculation: Taken at time "
|
598
|
+
+ str(self.fir_widget.v_rest_time)
|
599
|
+
+ "(ms) on negative injection cell"
|
600
|
+
)
|
601
|
+
rin_calc = (
|
602
|
+
"R_in Calculation: [(dV/dI)] = (v_start-v_final)/(i_start-i_final) = "
|
603
|
+
+ str(round(self.fir_widget.v_rest, 2))
|
604
|
+
+ "-("
|
605
|
+
+ str(round(self.fir_widget.passive_v_final, 2))
|
606
|
+
+ "))/(0-("
|
607
|
+
+ str(self.fir_widget.passive_amp)
|
608
|
+
+ "))"
|
609
|
+
+ " = ("
|
610
|
+
+ str(round(self.fir_widget.v_rest - self.fir_widget.passive_v_final, 2))
|
611
|
+
+ " (mV) /"
|
612
|
+
+ str(0 - self.fir_widget.passive_amp)
|
613
|
+
+ " (nA))"
|
614
|
+
+ " = ("
|
615
|
+
+ str(
|
616
|
+
round(
|
617
|
+
(
|
618
|
+
(self.fir_widget.v_rest - self.fir_widget.passive_v_final)
|
619
|
+
/ (0 - self.fir_widget.passive_amp)
|
620
|
+
),
|
621
|
+
2,
|
622
|
+
)
|
623
|
+
)
|
624
|
+
+ " (MOhms))"
|
625
|
+
)
|
626
|
+
tau_calc = (
|
627
|
+
"Tau Calculation: [(s) until 63.2% change in mV] = "
|
628
|
+
+ "(mV at inj_start_time ("
|
629
|
+
+ str(self.fir_widget.tstart)
|
630
|
+
+ ")) - ((mV at inj_time - mV at inj_final ("
|
631
|
+
+ str(self.fir_widget.tstart + self.fir_widget.passive_delay)
|
632
|
+
+ ")) * 0.632) = "
|
633
|
+
+ "("
|
634
|
+
+ str(round(self.fir_widget.v_rest, 2))
|
635
|
+
+ ") - ("
|
636
|
+
+ str(round(self.fir_widget.v_rest, 2))
|
637
|
+
+ "-"
|
638
|
+
+ str(round(self.fir_widget.passive_v_final, 2))
|
639
|
+
+ ")*0.632 = "
|
640
|
+
+ str(
|
641
|
+
round(
|
642
|
+
self.fir_widget.v_rest
|
643
|
+
- ((self.fir_widget.v_rest - self.fir_widget.passive_v_final) * 0.632),
|
644
|
+
2,
|
645
|
+
)
|
646
|
+
)
|
647
|
+
)
|
648
|
+
tau_calc2 = (
|
649
|
+
"Time where mV == "
|
650
|
+
+ str(round(self.fir_widget.v_t_const, 2))
|
651
|
+
+ " = "
|
652
|
+
+ str(self.fir_widget.tstart + self.fir_widget.tau)
|
653
|
+
+ "(ms) | ("
|
654
|
+
+ str(self.fir_widget.tstart + self.fir_widget.tau * 1000)
|
655
|
+
+ " - v_start_time ("
|
656
|
+
+ str(self.fir_widget.tstart)
|
657
|
+
+ "))/1000 = "
|
658
|
+
+ str(round(self.fir_widget.tau, 4))
|
659
|
+
)
|
660
|
+
|
661
|
+
self.set_text(4, v_rest_calc)
|
662
|
+
self.set_text(5, rin_calc)
|
663
|
+
self.set_text(
|
664
|
+
6,
|
665
|
+
"v_start time: "
|
666
|
+
+ str(self.fir_widget.v_rest_time)
|
667
|
+
+ "(ms) | v_final time: "
|
668
|
+
+ str(self.fir_widget.v_final_time)
|
669
|
+
+ "(ms)",
|
670
|
+
)
|
671
|
+
self.set_text(7, tau_calc)
|
672
|
+
self.set_text(8, tau_calc2)
|
550
673
|
if self.fir_print_fi:
|
551
|
-
spikes = [str(round(i,0)) for i in self.fir_widget.plenvec]
|
674
|
+
spikes = [str(round(i, 0)) for i in self.fir_widget.plenvec]
|
552
675
|
amps = self.fir_widget.amps
|
553
|
-
self.set_text(
|
676
|
+
self.set_text(
|
677
|
+
11, " | ".join("[" + str(round(a, 2)) + "]:" + n for a, n in zip(amps, spikes))
|
678
|
+
)
|
554
679
|
return
|
555
|
-
|
680
|
+
|
681
|
+
|
556
682
|
class PointMenuWidget(Widget):
|
557
|
-
def __init__(self,pointprocess):
|
683
|
+
def __init__(self, pointprocess):
|
558
684
|
super(PointMenuWidget, self).__init__()
|
559
685
|
self.pointprocess = pointprocess
|
560
686
|
|
@@ -571,7 +697,7 @@ class PointMenuWidget(Widget):
|
|
571
697
|
self.netstim_interval = 0
|
572
698
|
self.netstim_number = 0
|
573
699
|
self.netstim_start = 0
|
574
|
-
self.netstim_noise = 0
|
700
|
+
self.netstim_noise = 0
|
575
701
|
self.netstim_synapse = None
|
576
702
|
self.netstim_netcon = None
|
577
703
|
self.netstim_netcon_weight = 1
|
@@ -583,7 +709,7 @@ class PointMenuWidget(Widget):
|
|
583
709
|
self.synapse_location = 0.5
|
584
710
|
|
585
711
|
return
|
586
|
-
|
712
|
+
|
587
713
|
def iclamp(self, sec, dur, amp, delay):
|
588
714
|
self.is_iclamp = True
|
589
715
|
self.iclamp_sec = sec
|
@@ -602,26 +728,28 @@ class PointMenuWidget(Widget):
|
|
602
728
|
|
603
729
|
return self.iclamp_obj
|
604
730
|
|
605
|
-
def netstim(self,interval,number,start,noise,target=None,weight=1,location=0.5):
|
731
|
+
def netstim(self, interval, number, start, noise, target=None, weight=1, location=0.5):
|
606
732
|
self.is_netstim = True
|
607
733
|
|
608
734
|
self.netstim_obj = h.NetStim(location)
|
609
|
-
self.netstim_obj.interval = interval
|
610
|
-
self.netstim_obj.number = number
|
611
|
-
self.netstim_obj.start = start
|
612
|
-
self.netstim_obj.noise = noise
|
613
|
-
|
735
|
+
self.netstim_obj.interval = interval # ms (mean) time between spikes
|
736
|
+
self.netstim_obj.number = number # (average) number of spikes
|
737
|
+
self.netstim_obj.start = start # ms (most likely) start time of first spike
|
738
|
+
self.netstim_obj.noise = noise # range 0 to 1. Fractional randomness.
|
739
|
+
|
614
740
|
self.netstim_location = location
|
615
741
|
self.netstim_interval = interval
|
616
742
|
self.netstim_number = number
|
617
743
|
self.netstim_start = start
|
618
|
-
self.netstim_noise = noise
|
744
|
+
self.netstim_noise = noise
|
619
745
|
|
620
746
|
self.netstim_netcon_weight = weight
|
621
747
|
|
622
748
|
if target:
|
623
749
|
self.netstim_synapse = target
|
624
|
-
self.netstim_netcon = h.NetCon(
|
750
|
+
self.netstim_netcon = h.NetCon(
|
751
|
+
self.netstim_obj, target, 0, 0, self.netstim_netcon_weight
|
752
|
+
)
|
625
753
|
|
626
754
|
self.pointprocess = self.netstim_obj
|
627
755
|
|
@@ -629,20 +757,20 @@ class PointMenuWidget(Widget):
|
|
629
757
|
|
630
758
|
def synapse(self, sec, location, synapse_name):
|
631
759
|
self.is_synapse = True
|
632
|
-
#syn = h.AlphaSynapse(soma(0.5))
|
760
|
+
# syn = h.AlphaSynapse(soma(0.5))
|
633
761
|
self.synapse_sec = sec(float(location))
|
634
762
|
self.synapse_name = synapse_name
|
635
|
-
self.synapse_obj = getattr(h,synapse_name)(float(location),sec=sec)
|
763
|
+
self.synapse_obj = getattr(h, synapse_name)(float(location), sec=sec)
|
636
764
|
self.pointprocess = self.synapse_obj
|
637
765
|
self.synapse_location = location
|
638
|
-
|
766
|
+
|
639
767
|
return self.synapse_obj
|
640
768
|
|
641
769
|
def execute(self):
|
642
770
|
h.nrnpointmenu(self.pointprocess)
|
643
771
|
return
|
644
772
|
|
645
|
-
def hoc_declaration_str_list(self
|
773
|
+
def hoc_declaration_str_list(self, **kwargs):
|
646
774
|
ctg = kwargs["ctg"]
|
647
775
|
ret = []
|
648
776
|
|
@@ -653,8 +781,10 @@ class PointMenuWidget(Widget):
|
|
653
781
|
clamp_loc = self.iclamp_sec.x
|
654
782
|
|
655
783
|
ret.append("// current clamp current injection")
|
656
|
-
#ret.append("objref " + clamp_ref)
|
657
|
-
ret.append(
|
784
|
+
# ret.append("objref " + clamp_ref)
|
785
|
+
ret.append(
|
786
|
+
cell_ref + "." + sec_ref + " " + clamp_ref + " = new IClamp(" + str(clamp_loc) + ")"
|
787
|
+
)
|
658
788
|
ret.append(clamp_ref + ".del = " + str(self.iclamp_delay))
|
659
789
|
ret.append(clamp_ref + ".dur = " + str(self.iclamp_dur))
|
660
790
|
ret.append(clamp_ref + ".amp = " + str(self.iclamp_amp))
|
@@ -665,29 +795,69 @@ class PointMenuWidget(Widget):
|
|
665
795
|
netcon_ref = ctg.hoc_ref(self.netstim_netcon)
|
666
796
|
netstim_syn_ref = ctg.hoc_ref(self.netstim_synapse)
|
667
797
|
|
668
|
-
#ret.append("objref " + netstim_ref + "// the code below provides the cell with a spike train")
|
669
|
-
#ret.append("objref " + netcon_ref + "// the code below provides the cell with a spike train")
|
798
|
+
# ret.append("objref " + netstim_ref + "// the code below provides the cell with a spike train")
|
799
|
+
# ret.append("objref " + netcon_ref + "// the code below provides the cell with a spike train")
|
670
800
|
|
671
801
|
ret.append(netstim_ref + "=new NetStim(" + str(netstim_loc) + ")")
|
672
|
-
ret.append(
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
802
|
+
ret.append(
|
803
|
+
netstim_ref
|
804
|
+
+ ".interval="
|
805
|
+
+ str(self.netstim_interval)
|
806
|
+
+ " // ms (mean) time between spikes"
|
807
|
+
)
|
808
|
+
ret.append(
|
809
|
+
netstim_ref
|
810
|
+
+ ".number="
|
811
|
+
+ str(self.netstim_number)
|
812
|
+
+ " //(average) number of spikes"
|
813
|
+
)
|
814
|
+
ret.append(
|
815
|
+
netstim_ref
|
816
|
+
+ ".start="
|
817
|
+
+ str(self.netstim_start)
|
818
|
+
+ " // ms (most likely) start time of first spike"
|
819
|
+
)
|
820
|
+
ret.append(
|
821
|
+
netstim_ref
|
822
|
+
+ ".noise="
|
823
|
+
+ str(self.netstim_noise)
|
824
|
+
+ " // range 0 to 1. Fractional randomness."
|
825
|
+
)
|
826
|
+
ret.append(
|
827
|
+
netcon_ref
|
828
|
+
+ "=new NetCon("
|
829
|
+
+ netstim_ref
|
830
|
+
+ ","
|
831
|
+
+ netstim_syn_ref
|
832
|
+
+ ",0,0,"
|
833
|
+
+ str(self.netstim_netcon_weight)
|
834
|
+
+ ")"
|
835
|
+
)
|
677
836
|
|
678
837
|
elif self.is_synapse:
|
679
838
|
cell_ref = ctg.hoc_ref(self.synapse_sec.sec.cell())
|
680
839
|
sec_ref = self.synapse_sec.sec.hname().split(".")[-1]
|
681
840
|
syn_ref = ctg.hoc_ref(self.synapse_obj)
|
682
841
|
syn_loc = self.synapse_location
|
683
|
-
|
684
|
-
#ret.append("objref " + syn_ref)
|
685
|
-
ret.append(
|
686
|
-
|
687
|
-
|
842
|
+
|
843
|
+
# ret.append("objref " + syn_ref)
|
844
|
+
ret.append(
|
845
|
+
cell_ref
|
846
|
+
+ "."
|
847
|
+
+ sec_ref
|
848
|
+
+ " "
|
849
|
+
+ syn_ref
|
850
|
+
+ " = new "
|
851
|
+
+ self.synapse_name
|
852
|
+
+ "("
|
853
|
+
+ str(syn_loc)
|
854
|
+
+ ") // build a synapse input into "
|
855
|
+
+ cell_ref
|
856
|
+
)
|
857
|
+
|
688
858
|
return ret
|
689
859
|
|
690
|
-
def hoc_display_str_list(self
|
860
|
+
def hoc_display_str_list(self, **kwargs):
|
691
861
|
ctg = kwargs["ctg"]
|
692
862
|
ret = []
|
693
863
|
|
@@ -704,9 +874,9 @@ class PointMenuWidget(Widget):
|
|
704
874
|
pass
|
705
875
|
return ret
|
706
876
|
|
877
|
+
|
707
878
|
class VoltagePlotWidget(Widget):
|
708
|
-
|
709
|
-
def __init__(self,cell,section="soma",tstop=1150,minx=-80,maxx=50,miny=0,maxy=1):
|
879
|
+
def __init__(self, cell, section="soma", tstop=1150, minx=-80, maxx=50, miny=0, maxy=1):
|
710
880
|
super(VoltagePlotWidget, self).__init__()
|
711
881
|
self.cell = cell
|
712
882
|
self.section = section
|
@@ -714,7 +884,7 @@ class VoltagePlotWidget(Widget):
|
|
714
884
|
self.graph = None
|
715
885
|
self.color = 1
|
716
886
|
self.expressions = {}
|
717
|
-
self.segment = eval("self.cell."+section)
|
887
|
+
self.segment = eval("self.cell." + section) # getattr(self.cell,section)
|
718
888
|
self.minx = minx
|
719
889
|
self.maxx = maxx
|
720
890
|
self.miny = miny
|
@@ -725,16 +895,15 @@ class VoltagePlotWidget(Widget):
|
|
725
895
|
return
|
726
896
|
|
727
897
|
def advance_color(self):
|
728
|
-
#https://www.neuron.yale.edu/neuron/static/py_doc/visualization/graph.html#Graph.color
|
898
|
+
# https://www.neuron.yale.edu/neuron/static/py_doc/visualization/graph.html#Graph.color
|
729
899
|
self.color = self.color + 1
|
730
900
|
if self.color == 10:
|
731
901
|
self.color = 1
|
732
|
-
|
733
902
|
|
734
903
|
def reset_color(self):
|
735
904
|
self.color = 1
|
736
905
|
|
737
|
-
def add_var(self,variable,text):
|
906
|
+
def add_var(self, variable, text):
|
738
907
|
self.expressions[text] = variable
|
739
908
|
return
|
740
909
|
|
@@ -744,78 +913,91 @@ class VoltagePlotWidget(Widget):
|
|
744
913
|
for mech in mechs:
|
745
914
|
if not mech_dict[mech].get("DERIVATIVE"):
|
746
915
|
continue
|
747
|
-
actvars = [
|
748
|
-
|
749
|
-
|
750
|
-
if
|
751
|
-
|
752
|
-
|
753
|
-
|
754
|
-
|
755
|
-
|
756
|
-
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
|
916
|
+
actvars = [
|
917
|
+
line["variable"]
|
918
|
+
for line in mech_dict[mech]["DERIVATIVE"]
|
919
|
+
if line["is_likely_activation"]
|
920
|
+
]
|
921
|
+
|
922
|
+
for var in mech_dict[mech]["state_activation_vars"]:
|
923
|
+
if var["var"] in actvars:
|
924
|
+
# {'var': 'n', 'var_inf': 'inf', 'vh': 'nvhalf', 'k': 'nk', 'procedure_set': 'rate', 'line_set': 'inf = 1.0 / (1.0 + (exp((v + nvhalf) / (nk))))'}
|
925
|
+
# label = var['var'] + ' (' + mech + ') ' + 'Segregation (mV)'
|
926
|
+
# vp = ValuePanel(label=label)
|
927
|
+
# ref = var['var']+'seg_'+mech
|
928
|
+
|
929
|
+
variable = "_ref_" + var["var_inf"] + "_" + mech
|
930
|
+
text = "(" + var["var"] + ") " + var["var_inf"] + "_" + mech
|
931
|
+
|
932
|
+
if (
|
933
|
+
var["k"]
|
934
|
+
in [
|
935
|
+
m[0]
|
936
|
+
for m in mech_dict[mech]["PARAMETER"]
|
937
|
+
if m[2] and float(m[2]) < 0
|
938
|
+
]
|
939
|
+
or not var["k"]
|
940
|
+
):
|
941
|
+
self.add_var(variable, text)
|
761
942
|
if variables:
|
762
943
|
for variable in variables:
|
763
|
-
variable_ref = "_ref_"+variable
|
764
|
-
self.add_var(variable_ref,variable)
|
944
|
+
variable_ref = "_ref_" + variable
|
945
|
+
self.add_var(variable_ref, variable)
|
765
946
|
|
766
|
-
#self.add_var("_ref_inf_kdrseg","n inf kdr")
|
767
|
-
#self.add_var("_ref_minf_naseg","m inf na")
|
947
|
+
# self.add_var("_ref_inf_kdrseg","n inf kdr")
|
948
|
+
# self.add_var("_ref_minf_naseg","m inf na")
|
768
949
|
return
|
769
|
-
|
950
|
+
|
770
951
|
def execute(self):
|
771
|
-
variable = getattr(self.segment(0.5),"_ref_v")
|
952
|
+
variable = getattr(self.segment(0.5), "_ref_v")
|
772
953
|
self.v_vector = h.Vector()
|
773
954
|
self.v_vector.record(variable)
|
774
955
|
|
775
|
-
#Recording
|
956
|
+
# Recording
|
776
957
|
for text, var in self.expressions.items():
|
777
958
|
try:
|
778
|
-
variable = getattr(self.segment(0.5),var)
|
959
|
+
variable = getattr(self.segment(0.5), var)
|
779
960
|
except AttributeError as e:
|
780
|
-
variable = getattr(h,var)
|
961
|
+
variable = getattr(h, var) # Perhaps it's a global?
|
781
962
|
spvec = h.Vector()
|
782
963
|
spvec.record(variable)
|
783
|
-
self.vectors.append((spvec,text))
|
964
|
+
self.vectors.append((spvec, text))
|
784
965
|
|
785
966
|
cvode = h.CVode()
|
786
|
-
|
967
|
+
|
787
968
|
self.graph = h.Graph()
|
788
|
-
|
789
|
-
#self.graph.size(self.tstart,self.tstop,self.miny,self.maxy)
|
969
|
+
|
970
|
+
# self.graph.size(self.tstart,self.tstop,self.miny,self.maxy)
|
790
971
|
h.graphList[0].append(self.graph)
|
791
972
|
|
792
973
|
def commands():
|
793
974
|
def start_event():
|
794
975
|
self.graph.erase_all()
|
795
976
|
return
|
796
|
-
|
977
|
+
|
978
|
+
cvode.event(0, start_event)
|
797
979
|
|
798
980
|
def stop_event():
|
799
981
|
for color, v in enumerate(self.vectors):
|
800
982
|
vec = v[0]
|
801
983
|
text = v[1]
|
802
|
-
#self.graph.addvar(text,variable)
|
803
|
-
self.graph.color(color+1)
|
984
|
+
# self.graph.addvar(text,variable)
|
985
|
+
self.graph.color(color + 1)
|
804
986
|
self.graph.label(text)
|
805
|
-
vec.plot(self.graph,self.v_vector, color+1,1)
|
806
|
-
|
807
|
-
#self.advance_color()
|
808
|
-
|
987
|
+
vec.plot(self.graph, self.v_vector, color + 1, 1)
|
988
|
+
|
989
|
+
# self.advance_color()
|
990
|
+
|
809
991
|
return
|
810
|
-
|
811
|
-
cvode.event(self.tstop, stop_event)
|
812
|
-
|
992
|
+
|
993
|
+
cvode.event(self.tstop, stop_event)
|
994
|
+
|
995
|
+
self.graph.size(self.minx, self.maxx, self.miny, self.maxy)
|
813
996
|
return commands
|
814
|
-
|
815
997
|
|
816
|
-
class PlotWidget(Widget):
|
817
998
|
|
818
|
-
|
999
|
+
class PlotWidget(Widget):
|
1000
|
+
def __init__(self, tstart=0, tstop=50, miny=-80, maxy=50):
|
819
1001
|
super(PlotWidget, self).__init__()
|
820
1002
|
self.tstart = tstart
|
821
1003
|
self.tstop = tstop
|
@@ -829,66 +1011,86 @@ class PlotWidget(Widget):
|
|
829
1011
|
return
|
830
1012
|
|
831
1013
|
def advance_color(self):
|
832
|
-
#https://www.neuron.yale.edu/neuron/static/py_doc/visualization/graph.html#Graph.color
|
1014
|
+
# https://www.neuron.yale.edu/neuron/static/py_doc/visualization/graph.html#Graph.color
|
833
1015
|
self.color = self.color + 1
|
834
1016
|
if self.color == 10:
|
835
1017
|
self.color = 1
|
836
|
-
|
837
1018
|
|
838
1019
|
def reset_color(self):
|
839
1020
|
self.color = 1
|
840
1021
|
|
841
|
-
def add_expr(self,variable,text,hoc_text="",hoc_text_obj=None):
|
1022
|
+
def add_expr(self, variable, text, hoc_text="", hoc_text_obj=None):
|
842
1023
|
self.expressions[text] = variable
|
843
1024
|
if hoc_text != "":
|
844
|
-
self.hoc_expressions[text] = (hoc_text,hoc_text_obj)
|
1025
|
+
self.hoc_expressions[text] = (hoc_text, hoc_text_obj)
|
845
1026
|
return
|
846
|
-
|
1027
|
+
|
847
1028
|
def execute(self):
|
848
1029
|
self.graph = h.Graph()
|
849
1030
|
for text, variable in self.expressions.items():
|
850
|
-
#self.graph.addvar('soma(0.5).v', my_cell.soma(0.5)._ref_v)
|
851
|
-
self.graph.addvar(text,variable)
|
1031
|
+
# self.graph.addvar('soma(0.5).v', my_cell.soma(0.5)._ref_v)
|
1032
|
+
self.graph.addvar(text, variable)
|
852
1033
|
self.advance_color()
|
853
1034
|
self.graph.color(self.color)
|
854
|
-
self.graph.size(self.tstart,self.tstop,self.miny,self.maxy)
|
1035
|
+
self.graph.size(self.tstart, self.tstop, self.miny, self.maxy)
|
855
1036
|
h.graphList[0].append(self.graph)
|
856
1037
|
return
|
857
1038
|
|
858
|
-
def hoc_display_str_list(self
|
1039
|
+
def hoc_display_str_list(self, **kwargs):
|
859
1040
|
ret = []
|
860
1041
|
ctg = kwargs["ctg"]
|
861
|
-
#newPlot(0,tstop,-80,60)
|
862
|
-
#graphItem.save_name("graphList[0].")
|
863
|
-
#graphList[0].append(graphItem)
|
864
|
-
#sprint(tstr1,"%s.soma.v(.5)",$s1)
|
865
|
-
#graphItem.addexpr(tstr1,3,1)
|
866
|
-
ret.append(
|
867
|
-
|
868
|
-
|
1042
|
+
# newPlot(0,tstop,-80,60)
|
1043
|
+
# graphItem.save_name("graphList[0].")
|
1044
|
+
# graphList[0].append(graphItem)
|
1045
|
+
# sprint(tstr1,"%s.soma.v(.5)",$s1)
|
1046
|
+
# graphItem.addexpr(tstr1,3,1)
|
1047
|
+
ret.append(
|
1048
|
+
"newPlot("
|
1049
|
+
+ str(self.tstart)
|
1050
|
+
+ ","
|
1051
|
+
+ str(self.tstop)
|
1052
|
+
+ ","
|
1053
|
+
+ str(self.miny)
|
1054
|
+
+ ","
|
1055
|
+
+ str(self.maxy)
|
1056
|
+
+ ")"
|
1057
|
+
)
|
1058
|
+
ret.append('graphItem.save_name("graphList[0].")')
|
869
1059
|
ret.append("graphList[0].append(graphItem)")
|
870
1060
|
for text, hoc_expression in self.hoc_expressions.items():
|
871
|
-
#ret.append("sprint(tstr1,\"%s.soma.v(.5)\",$s1)
|
872
|
-
|
873
|
-
hoc_ref_str = ctg.hoc_ref(hoc_expression[1])
|
874
|
-
ret.append(
|
875
|
-
ret.append("graphItem.addexpr(tstr1,"+str(self.color)+",1)")
|
1061
|
+
# ret.append("sprint(tstr1,\"%s.soma.v(.5)\",$s1)
|
1062
|
+
|
1063
|
+
hoc_ref_str = ctg.hoc_ref(hoc_expression[1]) # Get the hoc equivilent of this object
|
1064
|
+
ret.append('sprint(tstr1,"' + hoc_expression[0] + '","' + hoc_ref_str + '")')
|
1065
|
+
ret.append("graphItem.addexpr(tstr1," + str(self.color) + ",1)")
|
876
1066
|
self.advance_color()
|
877
1067
|
ret.append("")
|
878
1068
|
|
879
1069
|
return ret
|
880
1070
|
|
1071
|
+
|
881
1072
|
class FICurveWidget(Widget):
|
882
|
-
def __init__(
|
883
|
-
|
884
|
-
|
885
|
-
|
886
|
-
|
1073
|
+
def __init__(
|
1074
|
+
self,
|
1075
|
+
template_name,
|
1076
|
+
i_increment=100,
|
1077
|
+
i_start=0,
|
1078
|
+
i_stop=1000,
|
1079
|
+
tstart=50,
|
1080
|
+
tdur=1000,
|
1081
|
+
passive_amp=-100,
|
1082
|
+
passive_delay=200,
|
1083
|
+
record_sec="soma",
|
1084
|
+
record_loc="0.5",
|
1085
|
+
inj_sec="soma",
|
1086
|
+
inj_loc="0.5",
|
1087
|
+
):
|
1088
|
+
"""Takes in values of pA"""
|
887
1089
|
super(FICurveWidget, self).__init__()
|
888
1090
|
self.template_name = template_name
|
889
|
-
self.i_increment = float(i_increment)/1e3
|
890
|
-
self.i_start = float(i_start)/1e3
|
891
|
-
self.i_stop = float(i_stop)/1e3
|
1091
|
+
self.i_increment = float(i_increment) / 1e3
|
1092
|
+
self.i_start = float(i_start) / 1e3
|
1093
|
+
self.i_stop = float(i_stop) / 1e3
|
892
1094
|
self.tstart = tstart
|
893
1095
|
self.tdur = tdur
|
894
1096
|
|
@@ -897,7 +1099,7 @@ class FICurveWidget(Widget):
|
|
897
1099
|
self.inj_sec = inj_sec
|
898
1100
|
self.inj_loc = inj_loc
|
899
1101
|
|
900
|
-
self.tstop = tstart+tdur
|
1102
|
+
self.tstop = tstart + tdur
|
901
1103
|
self.graph = None
|
902
1104
|
self.cells = []
|
903
1105
|
self.sources = []
|
@@ -906,20 +1108,20 @@ class FICurveWidget(Widget):
|
|
906
1108
|
self.t_vec = h.Vector()
|
907
1109
|
self.plenvec = []
|
908
1110
|
|
909
|
-
self.amps = np.arange(self.i_start,self.i_stop,self.i_increment)
|
1111
|
+
self.amps = np.arange(self.i_start, self.i_stop, self.i_increment)
|
910
1112
|
for _ in self.amps:
|
911
|
-
#Cell definition
|
912
|
-
cell = eval(
|
1113
|
+
# Cell definition
|
1114
|
+
cell = eval("h." + self.template_name + "()")
|
913
1115
|
self.cells.append(cell)
|
914
1116
|
|
915
1117
|
self.lenvec = None
|
916
|
-
self.ampvec = h.Vector([i*1e3 for i in self.amps])
|
1118
|
+
self.ampvec = h.Vector([i * 1e3 for i in self.amps])
|
917
1119
|
|
918
|
-
self.passive_amp = passive_amp/1e3
|
919
|
-
self.passive_cell = eval(
|
1120
|
+
self.passive_amp = passive_amp / 1e3
|
1121
|
+
self.passive_cell = eval("h." + self.template_name + "()")
|
920
1122
|
self.passive_src = None
|
921
1123
|
self.passive_vec = None
|
922
|
-
self.passive_delay = passive_delay
|
1124
|
+
self.passive_delay = passive_delay # use x ms after start of inj to calculate r_in, etc
|
923
1125
|
self.passive_v_final = 0
|
924
1126
|
self.v_t_const = 0
|
925
1127
|
|
@@ -934,19 +1136,23 @@ class FICurveWidget(Widget):
|
|
934
1136
|
self.graph = h.Graph()
|
935
1137
|
self.t_vec.record(h._ref_t)
|
936
1138
|
|
937
|
-
self.passive_src = h.IClamp(
|
1139
|
+
self.passive_src = h.IClamp(
|
1140
|
+
eval("self.passive_cell." + self.inj_sec + "(" + self.inj_loc + ")")
|
1141
|
+
)
|
938
1142
|
self.passive_src.delay = self.tstart
|
939
1143
|
self.passive_src.dur = self.tdur
|
940
1144
|
self.passive_src.amp = self.passive_amp
|
941
|
-
|
1145
|
+
|
942
1146
|
rec_str = "self.passive_cell." + self.record_sec + "(" + self.record_loc + ")._ref_v"
|
943
|
-
self.passive_nc = h.NetCon(
|
1147
|
+
self.passive_nc = h.NetCon(
|
1148
|
+
eval(rec_str), None, sec=eval("self.passive_cell." + self.record_sec)
|
1149
|
+
)
|
944
1150
|
self.passive_nc.threshold = 0
|
945
1151
|
self.passive_vec = h.Vector()
|
946
1152
|
self.passive_vec.record(eval(rec_str))
|
947
1153
|
|
948
1154
|
for i, amp in enumerate(self.amps):
|
949
|
-
#Injection
|
1155
|
+
# Injection
|
950
1156
|
cell = self.cells[i]
|
951
1157
|
|
952
1158
|
inj_str = "cell." + self.inj_sec + "(" + self.inj_loc + ")"
|
@@ -956,16 +1162,16 @@ class FICurveWidget(Widget):
|
|
956
1162
|
src.amp = amp
|
957
1163
|
self.sources.append(src)
|
958
1164
|
|
959
|
-
#Recording
|
1165
|
+
# Recording
|
960
1166
|
rec_str = "cell." + self.record_sec + "(" + self.record_loc + ")._ref_v"
|
961
|
-
nc = h.NetCon(eval(rec_str),None,sec=eval("cell."+self.record_sec))
|
1167
|
+
nc = h.NetCon(eval(rec_str), None, sec=eval("cell." + self.record_sec))
|
962
1168
|
nc.threshold = 0
|
963
1169
|
spvec = h.Vector()
|
964
1170
|
nc.record(spvec)
|
965
1171
|
self.ncs.append(nc)
|
966
1172
|
self.vectors.append(spvec)
|
967
1173
|
|
968
|
-
ctstop = self.tstart+self.tdur
|
1174
|
+
ctstop = self.tstart + self.tdur
|
969
1175
|
cvgraph = self.graph
|
970
1176
|
cvectors = self.vectors
|
971
1177
|
ctemplate_name = self.template_name
|
@@ -976,61 +1182,72 @@ class FICurveWidget(Widget):
|
|
976
1182
|
cdur = self.tdur
|
977
1183
|
cfir_widget = self
|
978
1184
|
cvode = h.CVode()
|
1185
|
+
|
979
1186
|
def commands():
|
980
1187
|
def start_event():
|
981
1188
|
nonlocal cfir_widget, cvgraph
|
982
1189
|
cvgraph.erase_all()
|
983
1190
|
cfir_widget.plenvec.clear()
|
984
|
-
#print(cfir_widget.vectors[4].as_numpy())
|
1191
|
+
# print(cfir_widget.vectors[4].as_numpy())
|
985
1192
|
return
|
986
|
-
|
1193
|
+
|
1194
|
+
cvode.event(0, start_event)
|
987
1195
|
|
988
1196
|
def stop_event():
|
989
|
-
nonlocal ctstop, cvectors, cvgraph, ctemplate_name, ampvec, lenvec,camps,plenvec
|
1197
|
+
nonlocal ctstop, cvectors, cvgraph, ctemplate_name, ampvec, lenvec, camps, plenvec
|
990
1198
|
nonlocal cfir_widget
|
991
|
-
#print(cfir_widget.vectors[4].as_numpy())
|
992
|
-
#print(cfir_widget.cells[0].soma(0.5)._ref_cm)
|
1199
|
+
# print(cfir_widget.vectors[4].as_numpy())
|
1200
|
+
# print(cfir_widget.cells[0].soma(0.5)._ref_cm)
|
993
1201
|
tplenvec = [len(cvec) for cvec in cvectors]
|
994
|
-
hzlenvec = [i * (1000/cdur) for i in tplenvec]
|
1202
|
+
hzlenvec = [i * (1000 / cdur) for i in tplenvec]
|
995
1203
|
for vec in hzlenvec:
|
996
1204
|
plenvec.append(vec)
|
997
1205
|
lenvec = h.Vector(plenvec)
|
998
|
-
#print(lenvec.as_numpy())
|
999
|
-
#cvgraph.erase_all()
|
1206
|
+
# print(lenvec.as_numpy())
|
1207
|
+
# cvgraph.erase_all()
|
1000
1208
|
cvgraph.color(1)
|
1001
1209
|
cvgraph.label(ctemplate_name + " FI Curve")
|
1002
|
-
plot = lenvec.plot(cvgraph,ampvec,1,1)
|
1003
|
-
cvgraph.size(0,max([i*1e3 for i in camps]),0,max(lenvec)+1)
|
1004
|
-
|
1005
|
-
#cfir_widget.passive_vec[int(cfir_widget.tstop)-20]
|
1006
|
-
index_v_rest = int(((1000/h.dt)/1000 * cfir_widget.tstart))
|
1007
|
-
index_v_final = int(
|
1008
|
-
|
1210
|
+
plot = lenvec.plot(cvgraph, ampvec, 1, 1)
|
1211
|
+
cvgraph.size(0, max([i * 1e3 for i in camps]), 0, max(lenvec) + 1)
|
1212
|
+
|
1213
|
+
# cfir_widget.passive_vec[int(cfir_widget.tstop)-20]
|
1214
|
+
index_v_rest = int(((1000 / h.dt) / 1000 * cfir_widget.tstart))
|
1215
|
+
index_v_final = int(
|
1216
|
+
((1000 / h.dt) / 1000 * (cfir_widget.tstart + cfir_widget.passive_delay))
|
1217
|
+
)
|
1218
|
+
|
1009
1219
|
cfir_widget.v_rest = cfir_widget.passive_vec[index_v_rest]
|
1010
|
-
cfir_widget.v_rest_time = index_v_rest / (1/h.dt)
|
1220
|
+
cfir_widget.v_rest_time = index_v_rest / (1 / h.dt)
|
1011
1221
|
|
1012
1222
|
cfir_widget.passive_v_final = cfir_widget.passive_vec[index_v_final]
|
1013
|
-
cfir_widget.v_final_time = index_v_final / (1/h.dt)
|
1223
|
+
cfir_widget.v_final_time = index_v_final / (1 / h.dt)
|
1014
1224
|
|
1015
1225
|
v_diff = cfir_widget.v_rest - cfir_widget.passive_v_final
|
1016
1226
|
|
1017
|
-
cfir_widget.v_t_const = cfir_widget.v_rest - (v_diff
|
1018
|
-
#Find index of first occurance where
|
1019
|
-
#index_v_tau = list(filter(lambda i: i < v_t_const, cfir_widget.passive_vec))[0]
|
1020
|
-
index_v_tau = next(
|
1021
|
-
|
1022
|
-
|
1023
|
-
|
1024
|
-
|
1227
|
+
cfir_widget.v_t_const = cfir_widget.v_rest - (v_diff * 0.632)
|
1228
|
+
# Find index of first occurance where
|
1229
|
+
# index_v_tau = list(filter(lambda i: i < v_t_const, cfir_widget.passive_vec))[0]
|
1230
|
+
index_v_tau = next(
|
1231
|
+
x
|
1232
|
+
for x, val in enumerate(list(cfir_widget.passive_vec))
|
1233
|
+
if val < cfir_widget.v_t_const
|
1234
|
+
)
|
1235
|
+
time_tau = (index_v_tau / ((1000 / h.dt) / 1000)) - cfir_widget.tstart
|
1236
|
+
cfir_widget.tau = time_tau # / 1000 (in ms)
|
1237
|
+
cfir_widget.r_in = (
|
1238
|
+
(v_diff) / (0 - cfir_widget.passive_amp) * 1e6
|
1239
|
+
) # MegaOhms -> Ohms
|
1240
|
+
|
1025
1241
|
cvode.event(ctstop, stop_event)
|
1026
|
-
|
1242
|
+
|
1027
1243
|
h.graphList[0].append(self.graph)
|
1028
1244
|
|
1029
1245
|
return commands
|
1030
1246
|
|
1031
|
-
def hoc_display_str_list(self
|
1247
|
+
def hoc_display_str_list(self, **kwargs):
|
1032
1248
|
return []
|
1033
1249
|
|
1250
|
+
|
1034
1251
|
class SecMenuWidget(Widget):
|
1035
1252
|
def __init__(self, sec, x=0.5, vartype=1):
|
1036
1253
|
"""
|
@@ -1044,38 +1261,37 @@ class SecMenuWidget(Widget):
|
|
1044
1261
|
return
|
1045
1262
|
|
1046
1263
|
def execute(self):
|
1047
|
-
h.nrnsecmenu(self.x,self.vartype,sec=self.sec)
|
1264
|
+
h.nrnsecmenu(self.x, self.vartype, sec=self.sec)
|
1048
1265
|
return
|
1049
1266
|
|
1050
|
-
def hoc_display_str_list(self
|
1267
|
+
def hoc_display_str_list(self, **kwargs):
|
1051
1268
|
ctg = kwargs["ctg"]
|
1052
1269
|
ret = []
|
1053
|
-
#ret.append("$o2.soma nrnsecmenu(.5,1)")
|
1270
|
+
# ret.append("$o2.soma nrnsecmenu(.5,1)")
|
1054
1271
|
cell = ctg.hoc_ref(self.sec.cell())
|
1055
1272
|
sec = self.sec.hname().split(".")[-1]
|
1056
|
-
ret.append(cell + "."+ sec + " nrnsecmenu("+str(self.x)+","+str(self.vartype)+")")
|
1273
|
+
ret.append(cell + "." + sec + " nrnsecmenu(" + str(self.x) + "," + str(self.vartype) + ")")
|
1057
1274
|
return ret
|
1058
1275
|
|
1059
|
-
class ControlMenuWidget(Widget):
|
1060
1276
|
|
1277
|
+
class ControlMenuWidget(Widget):
|
1061
1278
|
def __init__(self):
|
1062
1279
|
super(ControlMenuWidget, self).__init__()
|
1063
1280
|
return
|
1064
1281
|
|
1065
1282
|
def add_expr(self):
|
1066
1283
|
return
|
1067
|
-
|
1284
|
+
|
1068
1285
|
def execute(self):
|
1069
1286
|
h.nrncontrolmenu()
|
1070
1287
|
return
|
1071
1288
|
|
1072
|
-
def hoc_display_str_list(self
|
1289
|
+
def hoc_display_str_list(self, **kwargs):
|
1073
1290
|
ret = []
|
1074
1291
|
ret.append("nrncontrolmenu()")
|
1075
1292
|
return ret
|
1076
1293
|
|
1077
1294
|
|
1078
|
-
|
1079
1295
|
class CellTunerGUI:
|
1080
1296
|
"""
|
1081
1297
|
Notes:
|
@@ -1114,7 +1330,7 @@ class CellTunerGUI:
|
|
1114
1330
|
print(sec) #is an object
|
1115
1331
|
dir(sec)
|
1116
1332
|
s = sec
|
1117
|
-
|
1333
|
+
|
1118
1334
|
#https://www.neuron.yale.edu/neuron/static/new_doc/programming/python.html#neuron.h.Section
|
1119
1335
|
for seg in s:
|
1120
1336
|
for mech in seg:
|
@@ -1124,7 +1340,18 @@ class CellTunerGUI:
|
|
1124
1340
|
https://github.com/tjbanks/two-cell-hco/blob/master/graphic_library.hoc
|
1125
1341
|
|
1126
1342
|
"""
|
1127
|
-
|
1343
|
+
|
1344
|
+
def __init__(
|
1345
|
+
self,
|
1346
|
+
template_dir,
|
1347
|
+
mechanism_dir,
|
1348
|
+
title="NEURON GUI",
|
1349
|
+
tstop=250,
|
1350
|
+
dt=0.1,
|
1351
|
+
print_debug=False,
|
1352
|
+
skip_load_mod=False,
|
1353
|
+
v_init=-65,
|
1354
|
+
):
|
1128
1355
|
self.template_dir = template_dir
|
1129
1356
|
self.mechanism_dir = mechanism_dir
|
1130
1357
|
self.title = title
|
@@ -1135,30 +1362,28 @@ class CellTunerGUI:
|
|
1135
1362
|
self.h = h
|
1136
1363
|
self.hboxes = []
|
1137
1364
|
self.fih = []
|
1138
|
-
|
1365
|
+
|
1139
1366
|
self.clamps = []
|
1140
1367
|
self.netstims = []
|
1141
1368
|
self.netcons = []
|
1142
1369
|
self.synapses = []
|
1143
1370
|
self.other_templates = []
|
1144
|
-
|
1145
1371
|
|
1146
|
-
self.display = []
|
1372
|
+
self.display = [] # Don't feel like dealing with classes
|
1147
1373
|
|
1148
|
-
self.template = None
|
1374
|
+
self.template = None # Template file used for GUI
|
1149
1375
|
self.root_sec = None
|
1150
1376
|
self.sections = []
|
1151
1377
|
|
1152
1378
|
self.setup_hoc_text = []
|
1153
|
-
|
1379
|
+
|
1154
1380
|
self.tstop = tstop
|
1155
1381
|
self.v_init = v_init
|
1156
1382
|
|
1157
1383
|
h.dt = dt
|
1158
1384
|
self.print_debug = print_debug
|
1159
|
-
|
1160
|
-
|
1161
|
-
#I'm not entirely pleased with how messy this solution is but it works
|
1385
|
+
|
1386
|
+
# I'm not entirely pleased with how messy this solution is but it works
|
1162
1387
|
# - in regards to mechanism reading, surely NEURON has an easier/clean way builtin
|
1163
1388
|
self.mechanism_files = []
|
1164
1389
|
self.mechanism_parse = {}
|
@@ -1173,19 +1398,20 @@ class CellTunerGUI:
|
|
1173
1398
|
self.hoc_ref_netcons = "nc"
|
1174
1399
|
self.hoc_ref_syns = "syn"
|
1175
1400
|
self.hoc_ref_other_templates = "auxcell"
|
1176
|
-
return
|
1401
|
+
return
|
1177
1402
|
|
1178
1403
|
def get_all_h_hocobjects(self):
|
1179
1404
|
ret = []
|
1180
1405
|
for i in dir(h):
|
1181
1406
|
try:
|
1182
|
-
|
1407
|
+
# update to use is and is not comparison
|
1408
|
+
if isinstance(getattr(neuron.h, i), neuron.hoc.HocObject):
|
1183
1409
|
ret.append(i)
|
1184
1410
|
except Exception as e:
|
1185
1411
|
pass
|
1186
1412
|
return ret
|
1187
1413
|
|
1188
|
-
def hoc_ref(self,hobject):
|
1414
|
+
def hoc_ref(self, hobject):
|
1189
1415
|
found = False
|
1190
1416
|
if hobject == self.template or hobject == self.template.hname():
|
1191
1417
|
return self.hoc_ref_template
|
@@ -1197,83 +1423,83 @@ class CellTunerGUI:
|
|
1197
1423
|
|
1198
1424
|
if hobject in self.clamps:
|
1199
1425
|
found = True
|
1200
|
-
return
|
1426
|
+
return self.hoc_ref_clamps + "[" + str(self.clamps.index(hobject)) + "]"
|
1201
1427
|
if hobject in clamps_name:
|
1202
1428
|
found = True
|
1203
1429
|
return self.hoc_ref_clamps + "[" + str(clamps_name.index(hobject)) + "]"
|
1204
1430
|
|
1205
1431
|
if hobject in self.netstims:
|
1206
1432
|
found = True
|
1207
|
-
return
|
1433
|
+
return self.hoc_ref_netstims + "[" + str(self.netstims.index(hobject)) + "]"
|
1208
1434
|
if hobject in netstims_name:
|
1209
1435
|
found = True
|
1210
1436
|
return self.hoc_ref_netstims + "[" + str(netstims_name.index(hobject)) + "]"
|
1211
1437
|
|
1212
1438
|
if hobject in self.netcons:
|
1213
1439
|
found = True
|
1214
|
-
return
|
1440
|
+
return self.hoc_ref_netcons + "[" + str(self.netcons.index(hobject)) + "]"
|
1215
1441
|
if hobject in netcons_name:
|
1216
1442
|
found = True
|
1217
1443
|
return self.hoc_ref_netcons + "[" + str(netcons_name.index(hobject)) + "]"
|
1218
1444
|
|
1219
1445
|
if hobject in self.synapses:
|
1220
1446
|
found = True
|
1221
|
-
return
|
1447
|
+
return self.hoc_ref_syns + "[" + str(self.synapses.index(hobject)) + "]"
|
1222
1448
|
if hobject in synapses_name:
|
1223
1449
|
found = True
|
1224
1450
|
return self.hoc_ref_syns + "[" + str(synapses_name.index(hobject)) + "]"
|
1225
1451
|
|
1226
1452
|
if not found:
|
1227
|
-
|
1228
|
-
|
1229
|
-
return
|
1453
|
+
# Debug statement removed
|
1454
|
+
pass
|
1230
1455
|
|
1231
|
-
|
1456
|
+
return
|
1457
|
+
|
1458
|
+
def register_iclamp(self, iclamp):
|
1232
1459
|
self.clamps.append(iclamp)
|
1233
1460
|
|
1234
|
-
def register_netstim(self,netstim):
|
1461
|
+
def register_netstim(self, netstim):
|
1235
1462
|
self.netstims.append(netstim)
|
1236
1463
|
|
1237
|
-
def register_netcon(self,netcon):
|
1464
|
+
def register_netcon(self, netcon):
|
1238
1465
|
self.netcons.append(netcon)
|
1239
1466
|
|
1240
|
-
def register_synapse(self,synapse):
|
1467
|
+
def register_synapse(self, synapse):
|
1241
1468
|
self.synapses.append(synapse)
|
1242
1469
|
|
1243
|
-
def set_title(self,window_index,title):
|
1244
|
-
self.display[window_index][
|
1245
|
-
|
1246
|
-
|
1470
|
+
def set_title(self, window_index, title):
|
1471
|
+
self.display[window_index]["title"] = title
|
1472
|
+
|
1473
|
+
def get_title(self, window_index):
|
1474
|
+
return self.display[window_index]["title"]
|
1247
1475
|
|
1248
|
-
def add_window(self,title=None,width=1100,height=600):
|
1476
|
+
def add_window(self, title=None, width=1100, height=600):
|
1249
1477
|
if title is None:
|
1250
1478
|
title = self.template_name + " - BMTool Single Cell Tuner"
|
1251
1479
|
|
1252
1480
|
window = {
|
1253
|
-
|
1254
|
-
|
1255
|
-
|
1256
|
-
|
1257
|
-
|
1258
|
-
|
1481
|
+
"title": title,
|
1482
|
+
"width": width,
|
1483
|
+
"height": height,
|
1484
|
+
"columns": [],
|
1485
|
+
"_column_objs": [],
|
1486
|
+
}
|
1259
1487
|
self.display.append(window)
|
1260
1488
|
|
1261
1489
|
window_index = len(self.display) - 1
|
1262
1490
|
return window_index
|
1263
1491
|
|
1264
|
-
def add_column(self,window_index):
|
1265
|
-
column = {
|
1266
|
-
|
1267
|
-
|
1268
|
-
self.display[window_index]['columns'].append(column)
|
1269
|
-
column_index = len(self.display[window_index]['columns']) - 1
|
1492
|
+
def add_column(self, window_index):
|
1493
|
+
column = {"widgets": []}
|
1494
|
+
self.display[window_index]["columns"].append(column)
|
1495
|
+
column_index = len(self.display[window_index]["columns"]) - 1
|
1270
1496
|
return column_index
|
1271
1497
|
|
1272
|
-
def add_widget(self,window_index,column_index,widget):
|
1273
|
-
self.display[window_index][
|
1274
|
-
return len(self.display[window_index][
|
1498
|
+
def add_widget(self, window_index, column_index, widget):
|
1499
|
+
self.display[window_index]["columns"][column_index]["widgets"].append(widget)
|
1500
|
+
return len(self.display[window_index]["columns"][column_index]["widgets"])
|
1275
1501
|
|
1276
|
-
def new_IClamp_Widget(self,sec,dur,amp,delay):
|
1502
|
+
def new_IClamp_Widget(self, sec, dur, amp, delay):
|
1277
1503
|
"""
|
1278
1504
|
Safely handles hoc output
|
1279
1505
|
"""
|
@@ -1284,57 +1510,58 @@ class CellTunerGUI:
|
|
1284
1510
|
self.setup_hoc_text.append("")
|
1285
1511
|
return PointMenuWidget(iclamp), iclamp
|
1286
1512
|
|
1287
|
-
def show(self,auto_run=False, on_complete=None,on_complete_fih=None,run_count=1):
|
1288
|
-
from neuron import gui
|
1513
|
+
def show(self, auto_run=False, on_complete=None, on_complete_fih=None, run_count=1):
|
1289
1514
|
fih_commands = []
|
1290
1515
|
h.tstop = int(self.tstop)
|
1291
1516
|
h.v_init = int(self.v_init)
|
1292
1517
|
self.hboxes = []
|
1293
|
-
for window_index,window in enumerate(self.display):
|
1518
|
+
for window_index, window in enumerate(self.display):
|
1294
1519
|
self.hboxes.append(h.HBox())
|
1295
1520
|
# Instance for each column
|
1296
|
-
window[
|
1521
|
+
window["_column_objs"] = [h.VBox() for _ in range(len(window["columns"]))]
|
1297
1522
|
|
1298
|
-
for column_index, col_vbox_obj in enumerate(window[
|
1523
|
+
for column_index, col_vbox_obj in enumerate(window["_column_objs"]):
|
1299
1524
|
col_vbox_obj.intercept(True)
|
1300
|
-
column = window[
|
1301
|
-
for widget in column[
|
1525
|
+
column = window["columns"][column_index]
|
1526
|
+
for widget in column["widgets"]:
|
1302
1527
|
ret = widget.execute()
|
1303
1528
|
if ret:
|
1304
1529
|
fih_commands.append(ret)
|
1305
1530
|
col_vbox_obj.intercept(False)
|
1306
1531
|
|
1307
1532
|
self.hboxes[window_index].intercept(True)
|
1308
|
-
for col in window[
|
1533
|
+
for col in window["_column_objs"]:
|
1309
1534
|
col.map()
|
1310
1535
|
self.hboxes[window_index].intercept(False)
|
1311
|
-
x = window_index * 35
|
1536
|
+
x = window_index * 35 # Degree of separation, will be 35 pixels apart on popup
|
1312
1537
|
y = x
|
1313
|
-
self.hboxes[window_index].map(window[
|
1538
|
+
self.hboxes[window_index].map(window["title"], x, y, window["width"], window["height"])
|
1314
1539
|
|
1315
|
-
|
1316
|
-
#https://www.neuron.yale.edu/phpbb/viewtopic.php?f=2&t=2236
|
1540
|
+
# https://www.neuron.yale.edu/phpbb/viewtopic.php?f=2&t=2236
|
1317
1541
|
self.fih = []
|
1318
1542
|
for commands in fih_commands:
|
1319
1543
|
self.fih.append(h.FInitializeHandler(0, commands))
|
1320
1544
|
if on_complete_fih:
|
1321
1545
|
tstop = self.tstop
|
1322
1546
|
cvode = h.CVode()
|
1547
|
+
|
1323
1548
|
def commands_complete():
|
1324
1549
|
nonlocal tstop, self
|
1550
|
+
|
1325
1551
|
def pdbtest():
|
1326
1552
|
nonlocal tstop, self
|
1327
|
-
#import pdb;pdb.set_trace()
|
1553
|
+
# import pdb;pdb.set_trace()
|
1328
1554
|
pass
|
1329
|
-
|
1330
|
-
cvode.event(tstop,
|
1331
|
-
|
1555
|
+
|
1556
|
+
cvode.event(tstop, on_complete_fih)
|
1557
|
+
cvode.event(tstop, pdbtest)
|
1558
|
+
|
1332
1559
|
self.fih.append(h.FInitializeHandler(0, commands_complete))
|
1333
1560
|
|
1334
1561
|
if auto_run:
|
1335
1562
|
for _ in range(run_count):
|
1336
1563
|
h.stdinit()
|
1337
|
-
h.run()
|
1564
|
+
h.run()
|
1338
1565
|
if on_complete:
|
1339
1566
|
on_complete()
|
1340
1567
|
print("Press enter to close the GUI window and continue...")
|
@@ -1342,10 +1569,9 @@ class CellTunerGUI:
|
|
1342
1569
|
return
|
1343
1570
|
|
1344
1571
|
def get_mech_variables(self, sec):
|
1345
|
-
|
1346
1572
|
return
|
1347
1573
|
|
1348
|
-
def write_hoc(self, filename,mechanism_dir=None,template_dir=None,val_set=None):
|
1574
|
+
def write_hoc(self, filename, mechanism_dir=None, template_dir=None, val_set=None):
|
1349
1575
|
if not mechanism_dir:
|
1350
1576
|
mechanism_dir = self.mechanism_dir
|
1351
1577
|
if not template_dir:
|
@@ -1357,38 +1583,46 @@ class CellTunerGUI:
|
|
1357
1583
|
os.remove(filename)
|
1358
1584
|
except Exception as e:
|
1359
1585
|
print("Error removing " + filename + ". Continuing but issues may arrise.")
|
1360
|
-
with open(filename,
|
1586
|
+
with open(filename, "a+") as f:
|
1361
1587
|
now = datetime.now()
|
1362
1588
|
now_str = now.strftime("%m/%d/%Y %H:%M:%S")
|
1363
|
-
extra_sp = 49-len(now_str)
|
1589
|
+
extra_sp = 49 - len(now_str)
|
1364
1590
|
f.write("//################################################################//\n")
|
1365
1591
|
f.write("//# GUI Built using BMTool (https://github.com/tjbanks/bmtool) #//\n")
|
1366
1592
|
f.write("//# Tyler Banks (tyler@tylerbanks.net) #//\n")
|
1367
1593
|
f.write("//# Neural Engineering Laboratory (Prof. Satish Nair) #//\n")
|
1368
1594
|
f.write("//# University of Missouri, Columbia #//\n")
|
1369
|
-
f.write("//# Build time: " + now_str +
|
1595
|
+
f.write("//# Build time: " + now_str + " " * extra_sp + "#//\n")
|
1370
1596
|
f.write("//################################################################//\n")
|
1371
1597
|
f.write("\n")
|
1372
|
-
#IMPORT STATEMENTS
|
1373
|
-
f.write(
|
1374
|
-
f.write(
|
1598
|
+
# IMPORT STATEMENTS
|
1599
|
+
f.write('{load_file("stdrun.hoc")}\n')
|
1600
|
+
f.write('{load_file("nrngui.hoc")}\n')
|
1375
1601
|
f.write("\n")
|
1376
|
-
|
1377
|
-
#LOAD MECHANISMS
|
1378
|
-
if mechanism_dir !=
|
1602
|
+
|
1603
|
+
# LOAD MECHANISMS
|
1604
|
+
if mechanism_dir != "./" and mechanism_dir != ".":
|
1379
1605
|
f.write("//Loading mechanisms in other folder\n")
|
1380
|
-
f.write(
|
1381
|
-
|
1606
|
+
f.write(
|
1607
|
+
'nrn_load_dll("' + mechanism_dir + '/x86_64/.libs/libnrnmech.so")\n'
|
1608
|
+
) # UNIX
|
1609
|
+
f.write('nrn_load_dll("' + mechanism_dir + '/nrnmech.dll")\n') # WINDOWS
|
1382
1610
|
f.write("\n")
|
1383
1611
|
|
1384
|
-
#LOAD TEMPLATES
|
1612
|
+
# LOAD TEMPLATES
|
1385
1613
|
cwd = os.getcwd()
|
1386
|
-
f.write(
|
1387
|
-
|
1388
|
-
|
1389
|
-
#os.chdir(
|
1614
|
+
f.write(
|
1615
|
+
"// Load Template(s) (some may not be needed if a folder was specified and may cause problems, remove as needed)\n"
|
1616
|
+
)
|
1617
|
+
# os.chdir(self.template_dir)
|
1618
|
+
# hoc_templates = glob.glob("*.hoc")
|
1619
|
+
# os.chdir(cwd)
|
1390
1620
|
for hoc_template in self.hoc_templates:
|
1391
|
-
f.write(
|
1621
|
+
f.write(
|
1622
|
+
'{load_file("'
|
1623
|
+
+ os.path.join(template_dir, hoc_template).replace("\\", "/")
|
1624
|
+
+ '")}\n'
|
1625
|
+
)
|
1392
1626
|
|
1393
1627
|
f.write("\n")
|
1394
1628
|
f.write("tstop = " + str(self.tstop) + "\n")
|
@@ -1406,47 +1640,55 @@ class CellTunerGUI:
|
|
1406
1640
|
|
1407
1641
|
st = "objref " + self.hoc_ref_clamps + "[NumClamps]\n"
|
1408
1642
|
if len(self.clamps) == 0:
|
1409
|
-
st = "//"+st
|
1643
|
+
st = "//" + st
|
1410
1644
|
f.write(st)
|
1411
1645
|
|
1412
1646
|
st = "objref " + self.hoc_ref_netstims + "[NumStims]\n"
|
1413
1647
|
if len(self.netstims) == 0:
|
1414
|
-
st = "//"+st
|
1648
|
+
st = "//" + st
|
1415
1649
|
f.write(st)
|
1416
1650
|
|
1417
1651
|
st = "objref " + self.hoc_ref_netcons + "[NumNetcons]\n"
|
1418
1652
|
if len(self.netcons) == 0:
|
1419
|
-
st = "//"+st
|
1653
|
+
st = "//" + st
|
1420
1654
|
f.write(st)
|
1421
1655
|
|
1422
1656
|
st = "objref " + self.hoc_ref_syns + "[NumSynapses]\n"
|
1423
1657
|
if len(self.synapses) == 0:
|
1424
|
-
st = "//"+st
|
1658
|
+
st = "//" + st
|
1425
1659
|
f.write(st)
|
1426
1660
|
|
1427
1661
|
st = "objref " + self.hoc_ref_other_templates + "[NumOtherCells]\n"
|
1428
1662
|
if len(self.other_templates) == 0:
|
1429
|
-
st = "//"+st
|
1663
|
+
st = "//" + st
|
1430
1664
|
f.write(st)
|
1431
1665
|
|
1432
1666
|
f.write("\n")
|
1433
1667
|
|
1434
1668
|
for text in self.setup_hoc_text:
|
1435
1669
|
f.write(text + "\n")
|
1436
|
-
|
1437
|
-
#f.write("\n\n")
|
1670
|
+
|
1671
|
+
# f.write("\n\n")
|
1438
1672
|
f.write("strdef tstr0, tstr1,tstr2,tstr3\n")
|
1439
1673
|
f.write("\n")
|
1440
1674
|
for window_index, window in enumerate(self.display):
|
1441
|
-
f.write("//Window " + str(window_index+1) + " variables\n")
|
1442
|
-
var_prefix = "Window"+str(window_index+1)
|
1443
|
-
|
1444
|
-
f.write("strdef "+var_prefix+"BoxTitle\n")
|
1445
|
-
f.write(var_prefix+"SubVBoxNum = " + str(len(window["columns"])) + "\n")
|
1446
|
-
f.write(
|
1675
|
+
f.write("//Window " + str(window_index + 1) + " variables\n")
|
1676
|
+
var_prefix = "Window" + str(window_index + 1)
|
1677
|
+
|
1678
|
+
f.write("strdef " + var_prefix + "BoxTitle\n")
|
1679
|
+
f.write(var_prefix + "SubVBoxNum = " + str(len(window["columns"])) + "\n")
|
1680
|
+
f.write(
|
1681
|
+
"objref "
|
1682
|
+
+ var_prefix
|
1683
|
+
+ "HBoxObj,"
|
1684
|
+
+ var_prefix
|
1685
|
+
+ "SubVBoxObj["
|
1686
|
+
+ var_prefix
|
1687
|
+
+ "SubVBoxNum]\n"
|
1688
|
+
)
|
1447
1689
|
|
1448
1690
|
f.write("\n")
|
1449
|
-
|
1691
|
+
|
1450
1692
|
f.write("\n")
|
1451
1693
|
|
1452
1694
|
for window_index, window in enumerate(self.display):
|
@@ -1454,71 +1696,114 @@ class CellTunerGUI:
|
|
1454
1696
|
for widget_index, widget in enumerate(column["widgets"]):
|
1455
1697
|
newline = False
|
1456
1698
|
for widget_line in widget.hoc_declaration_str_list(ctg=self):
|
1457
|
-
f.write(widget_line +"\n")
|
1699
|
+
f.write(widget_line + "\n")
|
1458
1700
|
newline = True
|
1459
1701
|
if newline:
|
1460
1702
|
f.write("\n")
|
1461
|
-
|
1703
|
+
|
1462
1704
|
# Define custom cell parameters here if present
|
1463
1705
|
if val_set:
|
1464
|
-
for cell,section in val_set.items():
|
1706
|
+
for cell, section in val_set.items():
|
1465
1707
|
cell_prefix = self.hoc_ref(cell)
|
1466
|
-
for section,values in section.items():
|
1467
|
-
for param,val in values.items():
|
1468
|
-
f.write(
|
1708
|
+
for section, values in section.items():
|
1709
|
+
for param, val in values.items():
|
1710
|
+
f.write(
|
1711
|
+
cell_prefix
|
1712
|
+
+ "."
|
1713
|
+
+ section
|
1714
|
+
+ "."
|
1715
|
+
+ param
|
1716
|
+
+ " = "
|
1717
|
+
+ str(round(val, 12))
|
1718
|
+
+ "\n"
|
1719
|
+
)
|
1469
1720
|
f.write("\n")
|
1470
|
-
|
1721
|
+
|
1471
1722
|
for window_index, window in enumerate(self.display):
|
1472
1723
|
window_method_prefix = "DisplayWindow"
|
1473
|
-
f.write("proc " + window_method_prefix + str(window_index+1) + "() { local i\n")
|
1474
|
-
f.write("\n")
|
1475
|
-
var_prefix = "Window"+str(window_index+1)
|
1476
|
-
f.write(" "+var_prefix+
|
1477
|
-
f.write(" "+var_prefix+"HBoxObj = new HBox()\n")
|
1478
|
-
f.write(
|
1724
|
+
f.write("proc " + window_method_prefix + str(window_index + 1) + "() { local i\n")
|
1725
|
+
f.write("\n")
|
1726
|
+
var_prefix = "Window" + str(window_index + 1)
|
1727
|
+
f.write(" " + var_prefix + 'BoxTitle = "' + window["title"] + '"\n')
|
1728
|
+
f.write(" " + var_prefix + "HBoxObj = new HBox()\n")
|
1729
|
+
f.write(
|
1730
|
+
" for i=0,"
|
1731
|
+
+ var_prefix
|
1732
|
+
+ "SubVBoxNum-1 "
|
1733
|
+
+ var_prefix
|
1734
|
+
+ "SubVBoxObj[i] = new VBox()\n"
|
1735
|
+
)
|
1479
1736
|
f.write("\n")
|
1480
|
-
|
1481
|
-
|
1482
|
-
var_prefix = "Window"+str(window_index+1)
|
1483
|
-
#f.write(" // " + var_prefix + "\n")
|
1737
|
+
# f.write("\n")
|
1738
|
+
# for window_index, window in enumerate(self.display):
|
1739
|
+
var_prefix = "Window" + str(window_index + 1)
|
1740
|
+
# f.write(" // " + var_prefix + "\n")
|
1484
1741
|
for column_index, column in enumerate(window["columns"]):
|
1485
|
-
f.write(" // Column" + str(column_index+1) + "\n")
|
1486
|
-
f.write(
|
1742
|
+
f.write(" // Column" + str(column_index + 1) + "\n")
|
1743
|
+
f.write(
|
1744
|
+
" " + var_prefix + "SubVBoxObj[" + str(column_index) + "].intercept(1)\n"
|
1745
|
+
)
|
1487
1746
|
for widget_index, widget in enumerate(column["widgets"]):
|
1488
|
-
f.write(" // Widget"+str(widget_index+1) + "\n")
|
1747
|
+
f.write(" // Widget" + str(widget_index + 1) + "\n")
|
1489
1748
|
for widget_line in widget.hoc_display_str_list(ctg=self):
|
1490
|
-
f.write(" " + widget_line +"\n")
|
1491
|
-
f.write(
|
1749
|
+
f.write(" " + widget_line + "\n")
|
1750
|
+
f.write(
|
1751
|
+
" " + var_prefix + "SubVBoxObj[" + str(column_index) + "].intercept(0)\n"
|
1752
|
+
)
|
1492
1753
|
f.write("\n")
|
1493
|
-
f.write(" "+var_prefix+"HBoxObj.intercept(1)\n")
|
1494
|
-
f.write(
|
1495
|
-
|
1496
|
-
|
1754
|
+
f.write(" " + var_prefix + "HBoxObj.intercept(1)\n")
|
1755
|
+
f.write(
|
1756
|
+
" for i=0,"
|
1757
|
+
+ var_prefix
|
1758
|
+
+ "SubVBoxNum-1 "
|
1759
|
+
+ var_prefix
|
1760
|
+
+ "SubVBoxObj[i].map()\n"
|
1761
|
+
)
|
1762
|
+
f.write(" " + var_prefix + "HBoxObj.intercept(0)\n")
|
1763
|
+
x = str(
|
1764
|
+
window_index * 35
|
1765
|
+
) # Degree of separation 35 pixels apart for each window so you can see them on popup
|
1497
1766
|
y = x
|
1498
|
-
f.write(
|
1767
|
+
f.write(
|
1768
|
+
" "
|
1769
|
+
+ var_prefix
|
1770
|
+
+ "HBoxObj.map("
|
1771
|
+
+ var_prefix
|
1772
|
+
+ "BoxTitle,"
|
1773
|
+
+ x
|
1774
|
+
+ ","
|
1775
|
+
+ y
|
1776
|
+
+ ","
|
1777
|
+
+ str(window["width"])
|
1778
|
+
+ ","
|
1779
|
+
+ str(window["height"])
|
1780
|
+
+ ")\n"
|
1781
|
+
)
|
1499
1782
|
|
1500
1783
|
f.write("\n")
|
1501
|
-
f.write("}// end " + window_method_prefix + str(window_index+1) + "()\n")
|
1784
|
+
f.write("}// end " + window_method_prefix + str(window_index + 1) + "()\n")
|
1502
1785
|
f.write("\n")
|
1503
1786
|
|
1504
1787
|
f.write("\n")
|
1505
1788
|
for window_index, window in enumerate(self.display):
|
1506
|
-
f.write(window_method_prefix + str(window_index+1) + "()\n")
|
1789
|
+
f.write(window_method_prefix + str(window_index + 1) + "()\n")
|
1507
1790
|
|
1508
1791
|
return
|
1509
1792
|
|
1510
|
-
def load_template(self,template_name,hoc_template_file=None):
|
1793
|
+
def load_template(self, template_name, hoc_template_file=None):
|
1511
1794
|
for sec in h.allsec():
|
1512
|
-
h("%s{delete_section()}"%sec.name())
|
1795
|
+
h("%s{delete_section()}" % sec.name())
|
1513
1796
|
self.template_name = template_name
|
1514
|
-
templates = self.get_templates(
|
1797
|
+
templates = self.get_templates(
|
1798
|
+
hoc_template_file=hoc_template_file
|
1799
|
+
) # also serves to load templates
|
1515
1800
|
if template_name not in templates:
|
1516
1801
|
raise Exception("NEURON template not found")
|
1517
|
-
|
1518
|
-
self.template = eval(
|
1802
|
+
|
1803
|
+
self.template = eval("h." + template_name + "()")
|
1519
1804
|
self.sections = [sec for sec in h.allsec()]
|
1520
1805
|
root_sec = [sec for sec in h.allsec() if sec.parentseg() is None]
|
1521
|
-
assert len(root_sec)
|
1806
|
+
assert len(root_sec) == 1
|
1522
1807
|
self.root_sec = root_sec[0]
|
1523
1808
|
self.other_sec = [sec for sec in h.allsec() if sec.parentseg() is not None]
|
1524
1809
|
return
|
@@ -1533,13 +1818,12 @@ class CellTunerGUI:
|
|
1533
1818
|
return [sec.name() for sec in self.get_sections()]
|
1534
1819
|
|
1535
1820
|
def parse_mechs(self):
|
1536
|
-
from pynmodl.lems import mod2lems
|
1537
1821
|
from pynmodl.nmodl import ValidationException
|
1538
|
-
from textx import TextXSyntaxError,TextXSemanticError
|
1539
1822
|
from pynmodl.unparser import Unparser
|
1540
|
-
import
|
1823
|
+
from textx import TextXSemanticError, TextXSyntaxError
|
1824
|
+
|
1541
1825
|
cwd = os.getcwd()
|
1542
|
-
mods_path = os.path.join(self.mechanism_dir,
|
1826
|
+
mods_path = os.path.join(self.mechanism_dir, "modfiles")
|
1543
1827
|
if not os.path.exists(mods_path):
|
1544
1828
|
mods_path = os.path.join(self.mechanism_dir)
|
1545
1829
|
os.chdir(mods_path)
|
@@ -1550,19 +1834,23 @@ class CellTunerGUI:
|
|
1550
1834
|
# Or any file that uses builtin t or dt or v variables
|
1551
1835
|
# Manually search for those words and make a manual list
|
1552
1836
|
# of these possible point processes
|
1553
|
-
mech_suffix = ".".join(mech.split(".")[:-1])
|
1837
|
+
mech_suffix = ".".join(mech.split(".")[:-1]) # Regex it?
|
1554
1838
|
if self.print_debug:
|
1555
1839
|
print("Loading mech: " + mech)
|
1556
|
-
with open(os.path.join(mods_path,mech)) as f:
|
1840
|
+
with open(os.path.join(mods_path, mech)) as f:
|
1557
1841
|
mod_file = f.read()
|
1558
1842
|
if "POINT_PROCESS" in mod_file:
|
1559
1843
|
try:
|
1560
|
-
pp =
|
1844
|
+
pp = (
|
1845
|
+
re.search("POINT_PROCESS [A-Za-z0-9 ]*", mod_file)
|
1846
|
+
.group()
|
1847
|
+
.split(" ")[-1]
|
1848
|
+
)
|
1561
1849
|
self.mechanism_point_processes.append(pp)
|
1562
1850
|
except Exception as e:
|
1563
1851
|
pass
|
1564
1852
|
try:
|
1565
|
-
#parse = mod2lems(mod_file)
|
1853
|
+
# parse = mod2lems(mod_file)
|
1566
1854
|
parse = Unparser().mm.model_from_str(mod_file)
|
1567
1855
|
self.mechanism_parse[mech_suffix] = parse
|
1568
1856
|
suffix = mech_suffix
|
@@ -1575,7 +1863,9 @@ class CellTunerGUI:
|
|
1575
1863
|
suffix = statement.suffix
|
1576
1864
|
elif statement.__class__.__name__ == "Range":
|
1577
1865
|
ranges = ranges + [rng.name for rng in statement.ranges]
|
1578
|
-
ranges = [
|
1866
|
+
ranges = [
|
1867
|
+
r for r in ranges if r not in read_ions
|
1868
|
+
] # Remove any external ions read in
|
1579
1869
|
self.mechanism_dict[suffix] = {}
|
1580
1870
|
self.mechanism_dict[suffix]["filename"] = mech
|
1581
1871
|
self.mechanism_dict[suffix]["NEURON"] = {}
|
@@ -1585,23 +1875,29 @@ class CellTunerGUI:
|
|
1585
1875
|
|
1586
1876
|
self.mechanism_dict[suffix]["STATE"] = {}
|
1587
1877
|
self.mechanism_dict[suffix]["STATE"]["variables"] = []
|
1588
|
-
if hasattr(parse,
|
1589
|
-
self.mechanism_dict[suffix]["STATE"]["variables"] = [
|
1590
|
-
|
1591
|
-
|
1592
|
-
|
1878
|
+
if hasattr(parse, "state"):
|
1879
|
+
self.mechanism_dict[suffix]["STATE"]["variables"] = [
|
1880
|
+
var.name for var in parse.state.state_vars
|
1881
|
+
]
|
1882
|
+
|
1883
|
+
self.mechanism_dict[suffix]["PARAMETER"] = [
|
1884
|
+
(p.name, p.unit, p.value) for p in parse.parameter.parameters
|
1885
|
+
]
|
1886
|
+
|
1593
1887
|
self.mechanism_dict[suffix]["DERIVATIVE"] = []
|
1594
1888
|
|
1595
|
-
parse_funcs = [
|
1889
|
+
parse_funcs = [
|
1890
|
+
func for func in parse.blocks if func.__class__.__name__ == "FuncDef"
|
1891
|
+
]
|
1596
1892
|
|
1597
1893
|
# Should extract vhalf and slope
|
1598
1894
|
boltzmann_reg = r"[A-Za-z0-9\*\/+\.\-\(\)]*\s*\/\s*\([A-Za-z0-9\*\/+\.\-\(\)]*\s*\+\s*\(\s*exp\s*\(\s*\(v\s*[\+\-]\s*([A-Za-z0-9\*\/+\.\-\(\)]*)\s*\)\s*\/\s*\(\s*(\-*[A-Za-z0-9\*\/+\.\-\(\)]*)\s*\)\s*\)\s*\)\s*\)\s*"
|
1599
1895
|
boltzmann_activation_reg = r"[A-Za-z0-9\*\/+\.\-\(\)]*\s*\/\s*\([A-Za-z0-9\*\/+\.\-\(\)]*\s*\+\s*\(\s*exp\s*\(\s*\(v\s*[\-]\s*([A-Za-z0-9\*\/+\.\-\(\)]*)\s*\)\s*\/\s*\(\s*(\-*[A-Za-z0-9\*\/+\.\-\(\)]*)\s*\)\s*\)\s*\)\s*\)\s*"
|
1600
1896
|
boltzmann_inactivation_reg = r"[A-Za-z0-9\*\/+\.\-\(\)]*\s*\/\s*\([A-Za-z0-9\*\/+\.\-\(\)]*\s*\+\s*\(\s*exp\s*\(\s*\(v\s*[\+]\s*([A-Za-z0-9\*\/+\.\-\(\)]*)\s*\)\s*\/\s*\(\s*(\-*[A-Za-z0-9\*\/+\.\-\(\)]*)\s*\)\s*\)\s*\)\s*\)\s*"
|
1601
|
-
|
1897
|
+
|
1602
1898
|
func_extract_reg = r"([A-Za-z0-9]*)\("
|
1603
1899
|
|
1604
|
-
if hasattr(parse,
|
1900
|
+
if hasattr(parse, "derivative"):
|
1605
1901
|
for statement in parse.derivative.b.stmts:
|
1606
1902
|
line = {}
|
1607
1903
|
line["unparsed"] = statement.unparsed
|
@@ -1619,35 +1915,54 @@ class CellTunerGUI:
|
|
1619
1915
|
line["expression"] = statement.expression.unparsed
|
1620
1916
|
except:
|
1621
1917
|
pass
|
1622
|
-
if statement.__class__.__name__ == "Assignment":
|
1918
|
+
if statement.__class__.__name__ == "Assignment": # ex: method(v)
|
1623
1919
|
if not statement.variable:
|
1624
1920
|
line["procedure_call"] = True
|
1625
1921
|
try:
|
1626
|
-
line["procedure"] = re.search(
|
1627
|
-
|
1922
|
+
line["procedure"] = re.search(
|
1923
|
+
func_extract_reg, statement.expression.unparsed
|
1924
|
+
).group(1)
|
1925
|
+
# process_procedure(line["procedure"])
|
1628
1926
|
except AttributeError:
|
1629
1927
|
# procedure not found in the string
|
1630
1928
|
pass
|
1631
|
-
else:
|
1929
|
+
else:
|
1632
1930
|
line["variable_assignment"] = True
|
1633
1931
|
line["variable"] = statement.variable
|
1634
|
-
|
1635
|
-
if statement.__class__.__name__ == "Primed":
|
1636
|
-
if
|
1932
|
+
|
1933
|
+
if statement.__class__.__name__ == "Primed": # ex: m' = ...
|
1934
|
+
if (
|
1935
|
+
statement.variable
|
1936
|
+
in self.mechanism_dict[suffix]["STATE"]["variables"]
|
1937
|
+
):
|
1637
1938
|
var = statement.variable
|
1638
1939
|
line["variable"] = var
|
1639
|
-
inf_reg =
|
1940
|
+
inf_reg = (
|
1941
|
+
var
|
1942
|
+
+ r"'\s*=\s*\(([A-Za-z0-9\*\/+\.\-\(\)]*)\s*-\s*"
|
1943
|
+
+ var
|
1944
|
+
+ "\)\s*\/\s[A-Za-z]*"
|
1945
|
+
)
|
1640
1946
|
line["primed"] = True
|
1641
|
-
try:
|
1642
|
-
line["inf"] = re.search(inf_reg, statement.unparsed).group(
|
1947
|
+
try:
|
1948
|
+
line["inf"] = re.search(inf_reg, statement.unparsed).group(
|
1949
|
+
1
|
1950
|
+
)
|
1643
1951
|
line["is_likely_activation"] = True
|
1644
1952
|
except AttributeError:
|
1645
1953
|
# inf_reg not found in the original string
|
1646
1954
|
pass
|
1647
1955
|
if line["inf"]:
|
1648
|
-
if
|
1956
|
+
if (
|
1957
|
+
line["inf"] in ranges
|
1958
|
+
): # the inf expression is a defined variable in RANGES section
|
1649
1959
|
line["inf_in_range"] = True
|
1650
|
-
elif line["inf"] in [
|
1960
|
+
elif line["inf"] in [
|
1961
|
+
line_item["inf"]
|
1962
|
+
for line_item in self.mechanism_dict[suffix][
|
1963
|
+
"DERIVATIVE"
|
1964
|
+
]
|
1965
|
+
]:
|
1651
1966
|
line["inf_in_derivative_block"] = True
|
1652
1967
|
|
1653
1968
|
self.mechanism_dict[suffix]["DERIVATIVE"].append(line)
|
@@ -1658,9 +1973,11 @@ class CellTunerGUI:
|
|
1658
1973
|
return True
|
1659
1974
|
except ValueError:
|
1660
1975
|
return False
|
1661
|
-
|
1662
|
-
def get_vh_slope(inf_var,procedure):
|
1663
|
-
func = [f for f in parse_funcs if f.name==procedure][
|
1976
|
+
|
1977
|
+
def get_vh_slope(inf_var, procedure):
|
1978
|
+
func = [f for f in parse_funcs if f.name == procedure][
|
1979
|
+
0
|
1980
|
+
] # May be a crash point if not found, other issues
|
1664
1981
|
stmts = [s for s in func.b.stmts]
|
1665
1982
|
for statement in stmts:
|
1666
1983
|
if statement.__class__.__name__ == "Assignment":
|
@@ -1671,23 +1988,25 @@ class CellTunerGUI:
|
|
1671
1988
|
expression = statement.expression.unparsed
|
1672
1989
|
try:
|
1673
1990
|
vh = re.search(boltzmann_reg, expression).group(1)
|
1674
|
-
slope = re.search(boltzmann_reg, expression).group(
|
1675
|
-
|
1991
|
+
slope = re.search(boltzmann_reg, expression).group(
|
1992
|
+
2
|
1993
|
+
)
|
1994
|
+
return vh, slope, statement.unparsed
|
1676
1995
|
except AttributeError:
|
1677
1996
|
# inf_reg not found in the original string
|
1678
1997
|
pass
|
1679
1998
|
|
1680
|
-
return None,None,None
|
1681
|
-
#print(mech)
|
1682
|
-
|
1999
|
+
return None, None, None
|
1683
2000
|
|
1684
|
-
#
|
1685
|
-
|
2001
|
+
# print(mech)
|
2002
|
+
|
2003
|
+
# activation to vhalf and slope matching
|
2004
|
+
# state_activation_vars = []
|
1686
2005
|
self.mechanism_dict[suffix]["state_activation_vars"] = []
|
1687
2006
|
procedures_called = []
|
1688
|
-
#Look at each state variable
|
2007
|
+
# Look at each state variable
|
1689
2008
|
for state_var in self.mechanism_dict[suffix]["STATE"]["variables"]:
|
1690
|
-
#Look through each line of the derivative block
|
2009
|
+
# Look through each line of the derivative block
|
1691
2010
|
for derivative_line in self.mechanism_dict[suffix]["DERIVATIVE"]:
|
1692
2011
|
if derivative_line["procedure_call"]:
|
1693
2012
|
procedures_called.append(derivative_line["procedure"])
|
@@ -1695,92 +2014,101 @@ class CellTunerGUI:
|
|
1695
2014
|
# There may be a case where the inf var is set right before calculating the derivative
|
1696
2015
|
# TODO handle this case
|
1697
2016
|
pass
|
1698
|
-
if state_var == derivative_line["variable"]:
|
2017
|
+
if state_var == derivative_line["variable"]:
|
1699
2018
|
if derivative_line["is_likely_activation"]:
|
1700
2019
|
inf_var = derivative_line["inf"]
|
1701
2020
|
if not procedures_called:
|
1702
2021
|
vardef = {}
|
1703
|
-
vardef[
|
1704
|
-
vardef[
|
1705
|
-
vardef[
|
1706
|
-
vardef[
|
1707
|
-
vardef[
|
1708
|
-
vardef[
|
1709
|
-
self.mechanism_dict[suffix]["state_activation_vars"].append(
|
2022
|
+
vardef["var"] = state_var
|
2023
|
+
vardef["var_inf"] = inf_var
|
2024
|
+
vardef["vh"] = None
|
2025
|
+
vardef["k"] = None
|
2026
|
+
vardef["procedure_set"] = None
|
2027
|
+
vardef["line_set"] = line
|
2028
|
+
self.mechanism_dict[suffix]["state_activation_vars"].append(
|
2029
|
+
vardef
|
2030
|
+
)
|
1710
2031
|
|
1711
2032
|
for procedure in procedures_called:
|
1712
|
-
vh,slope,line = get_vh_slope(inf_var, procedure)
|
2033
|
+
vh, slope, line = get_vh_slope(inf_var, procedure)
|
1713
2034
|
if vh and slope:
|
1714
2035
|
vardef = {}
|
1715
|
-
vardef[
|
1716
|
-
vardef[
|
1717
|
-
vardef[
|
1718
|
-
vardef[
|
1719
|
-
vardef[
|
1720
|
-
vardef[
|
1721
|
-
self.mechanism_dict[suffix][
|
2036
|
+
vardef["var"] = state_var
|
2037
|
+
vardef["var_inf"] = inf_var
|
2038
|
+
vardef["vh"] = vh
|
2039
|
+
vardef["k"] = slope
|
2040
|
+
vardef["procedure_set"] = procedure
|
2041
|
+
vardef["line_set"] = line
|
2042
|
+
self.mechanism_dict[suffix][
|
2043
|
+
"state_activation_vars"
|
2044
|
+
].append(vardef)
|
1722
2045
|
else:
|
1723
2046
|
vardef = {}
|
1724
|
-
vardef[
|
1725
|
-
vardef[
|
1726
|
-
vardef[
|
1727
|
-
vardef[
|
1728
|
-
vardef[
|
1729
|
-
vardef[
|
1730
|
-
self.mechanism_dict[suffix][
|
2047
|
+
vardef["var"] = state_var
|
2048
|
+
vardef["var_inf"] = inf_var
|
2049
|
+
vardef["vh"] = vh
|
2050
|
+
vardef["k"] = slope
|
2051
|
+
vardef["procedure_set"] = procedure
|
2052
|
+
vardef["line_set"] = line
|
2053
|
+
self.mechanism_dict[suffix][
|
2054
|
+
"state_activation_vars"
|
2055
|
+
].append(vardef)
|
1731
2056
|
break
|
1732
|
-
#if not is_number(vh):
|
2057
|
+
# if not is_number(vh):
|
1733
2058
|
# vh_var = True
|
1734
|
-
#if not is_number(slope):
|
2059
|
+
# if not is_number(slope):
|
1735
2060
|
# slope_var = True
|
1736
2061
|
|
1737
2062
|
except ValidationException as e:
|
1738
2063
|
if self.print_debug or True:
|
1739
2064
|
print("ValidationException: Unable to parse " + mech)
|
1740
2065
|
print(e)
|
1741
|
-
#import pdb;pdb.set_trace()
|
2066
|
+
# import pdb;pdb.set_trace()
|
1742
2067
|
except TextXSyntaxError as e:
|
1743
2068
|
if self.print_debug or True:
|
1744
2069
|
print("TextXSyntaxError: Unable to parse " + mech)
|
1745
2070
|
print(e)
|
1746
|
-
#import pdb;pdb.set_trace()
|
2071
|
+
# import pdb;pdb.set_trace()
|
1747
2072
|
except TextXSemanticError as e:
|
1748
2073
|
if self.print_debug or True:
|
1749
2074
|
print("TextXSemanticError: Unable to parse " + mech)
|
1750
2075
|
print(e)
|
1751
|
-
#import pdb;pdb.set_trace()
|
1752
|
-
#except AttributeError as e:
|
2076
|
+
# import pdb;pdb.set_trace()
|
2077
|
+
# except AttributeError as e:
|
1753
2078
|
# if self.print_debug or True:
|
1754
2079
|
# print("AttributeError: Unable to parse " + mech)
|
1755
2080
|
# print(e)
|
1756
2081
|
# import pdb;pdb.set_trace()
|
1757
|
-
#import pdb;pdb.set_trace()
|
2082
|
+
# import pdb;pdb.set_trace()
|
1758
2083
|
return
|
1759
2084
|
|
1760
2085
|
def seg_mechs(self, folder=None):
|
1761
|
-
|
1762
2086
|
cwd = os.getcwd()
|
1763
2087
|
|
1764
2088
|
if folder:
|
1765
2089
|
os.chdir(os.path.abspath(folder))
|
1766
2090
|
|
1767
2091
|
mechs = [mech.name() for mech in self.root_sec() if not mech.name().endswith("_ion")]
|
1768
|
-
|
2092
|
+
|
1769
2093
|
valid_mechs = []
|
1770
2094
|
for mech in mechs:
|
1771
2095
|
if not self.mechanism_dict.get(mech):
|
1772
2096
|
if self.print_debug:
|
1773
|
-
click.echo(
|
2097
|
+
click.echo(
|
2098
|
+
'Skipping "'
|
2099
|
+
+ colored.green(mech)
|
2100
|
+
+ '" mechanism (mod file not originally parsed)'
|
2101
|
+
)
|
1774
2102
|
else:
|
1775
2103
|
if self.print_debug:
|
1776
|
-
print(
|
2104
|
+
print('Adding mechanism "' + mech + '" to queue')
|
1777
2105
|
valid_mechs.append(mech)
|
1778
2106
|
if self.print_debug:
|
1779
2107
|
print("")
|
1780
2108
|
mechs_processed = []
|
1781
2109
|
for mech in valid_mechs:
|
1782
2110
|
if self.print_debug:
|
1783
|
-
click.echo(
|
2111
|
+
click.echo('Processing "' + mech + '"')
|
1784
2112
|
|
1785
2113
|
parameters = [p[0] for p in self.mechanism_dict[mech]["PARAMETER"]]
|
1786
2114
|
ranges = []
|
@@ -1790,11 +2118,23 @@ class CellTunerGUI:
|
|
1790
2118
|
act_vars = []
|
1791
2119
|
if self.mechanism_dict[mech].get("state_activation_vars"):
|
1792
2120
|
avars = self.mechanism_dict[mech]["state_activation_vars"]
|
1793
|
-
|
2121
|
+
|
1794
2122
|
# If the values are already variables we don't need to process the mech further
|
1795
|
-
act_vars = [
|
2123
|
+
act_vars = [
|
2124
|
+
v
|
2125
|
+
for v in avars
|
2126
|
+
if v["vh"] not in parameters
|
2127
|
+
and v["k"] not in parameters
|
2128
|
+
and (v["k"] is None or float(v["k"]) < 0)
|
2129
|
+
]
|
1796
2130
|
act_vars_names = [v["var"] for v in act_vars]
|
1797
|
-
inact_vars = [
|
2131
|
+
inact_vars = [
|
2132
|
+
v
|
2133
|
+
for v in avars
|
2134
|
+
if v["vh"] not in parameters
|
2135
|
+
and v["k"] not in parameters
|
2136
|
+
and (v["k"] is None or float(v["k"]) > 0)
|
2137
|
+
]
|
1798
2138
|
inact_vars_names = [v["var"] for v in inact_vars]
|
1799
2139
|
|
1800
2140
|
if act_vars:
|
@@ -1802,28 +2142,38 @@ class CellTunerGUI:
|
|
1802
2142
|
|
1803
2143
|
if len(act_vars):
|
1804
2144
|
if self.print_debug:
|
1805
|
-
click.echo(
|
2145
|
+
click.echo(
|
2146
|
+
"Activation variables to process: "
|
2147
|
+
+ colored.green(", ".join(act_vars_names))
|
2148
|
+
)
|
1806
2149
|
if len(inact_vars):
|
1807
2150
|
if self.print_debug:
|
1808
|
-
click.echo(
|
2151
|
+
click.echo(
|
2152
|
+
"Inactivation variables to process: "
|
2153
|
+
+ colored.red(", ".join(inact_vars_names))
|
2154
|
+
)
|
1809
2155
|
else:
|
1810
2156
|
if self.print_debug:
|
1811
2157
|
print("No activation/inactivation variables")
|
1812
2158
|
print("")
|
1813
2159
|
continue
|
1814
|
-
|
1815
|
-
filename = mech +
|
1816
|
-
|
1817
|
-
with open(filename,
|
2160
|
+
|
2161
|
+
filename = mech + "seg.mod" if not mech.endswith("seg") else mech + ".mod"
|
2162
|
+
|
2163
|
+
with open(filename, "w+") as f:
|
1818
2164
|
if self.print_debug:
|
1819
2165
|
click.echo("Writing " + colored.green(filename))
|
1820
|
-
f.write(
|
1821
|
-
|
1822
|
-
|
2166
|
+
f.write(
|
2167
|
+
": Ion channel activation segregation -- Generated by BMTool (https://github.com/tjbanks/bmtool)\n"
|
2168
|
+
)
|
2169
|
+
f.write(
|
2170
|
+
': based on the paper "Distinct Current Modules Shape Cellular Dynamics in Model Neurons" (2016)\n\n'
|
2171
|
+
)
|
2172
|
+
|
1823
2173
|
if mech in self.mechanism_parse:
|
1824
2174
|
code_blocks = self.mechanism_parse[mech].blocks
|
1825
|
-
else:
|
1826
|
-
mech_name = self.mechanism_dict[mech]["filename"].replace(".mod","")
|
2175
|
+
else: # it may be possible that the filename is different from the actual mechanism suffix
|
2176
|
+
mech_name = self.mechanism_dict[mech]["filename"].replace(".mod", "")
|
1827
2177
|
code_blocks = self.mechanism_parse[mech_name].blocks
|
1828
2178
|
|
1829
2179
|
for block in code_blocks:
|
@@ -1835,29 +2185,37 @@ class CellTunerGUI:
|
|
1835
2185
|
if not statement.suffix.endswith("seg"):
|
1836
2186
|
st = st + "seg"
|
1837
2187
|
if statement.__class__.__name__ == "UseIon":
|
1838
|
-
st = st.replace(
|
1839
|
-
|
2188
|
+
st = st.replace(
|
2189
|
+
"VALENCE +", "VALENCE "
|
2190
|
+
) # This is a bit of a hack, as NEURON doesn't like `+2`, prefer `2`
|
2191
|
+
f.write("\t" + st + "\n")
|
1840
2192
|
rngvars = []
|
1841
2193
|
for act_var in act_vars:
|
1842
2194
|
if act_var["vh"]:
|
1843
|
-
rngvars.append(act_var[
|
2195
|
+
rngvars.append(act_var["var"] + "vhalf")
|
1844
2196
|
if act_var["k"]:
|
1845
|
-
rngvars.append(act_var[
|
1846
|
-
rngvars.append(act_var[
|
2197
|
+
rngvars.append(act_var["var"] + "k")
|
2198
|
+
rngvars.append(act_var["var"] + "seg")
|
1847
2199
|
if rngvars:
|
1848
2200
|
f.write("\t" + "RANGE " + ", ".join(rngvars) + "\n")
|
1849
2201
|
f.write("} \n")
|
1850
2202
|
elif block.__class__.__name__ == "Parameter":
|
1851
2203
|
f.write("PARAMETER {\n")
|
1852
2204
|
for parameter in block.parameters:
|
1853
|
-
f.write(
|
2205
|
+
f.write("\t" + parameter.unparsed + "\n")
|
1854
2206
|
for act_var in act_vars:
|
1855
|
-
act = [
|
2207
|
+
act = [
|
2208
|
+
v
|
2209
|
+
for v in self.mechanism_dict[mech]["state_activation_vars"]
|
2210
|
+
if v["var"] == act_var["var"]
|
2211
|
+
][0]
|
1856
2212
|
if act["vh"]:
|
1857
|
-
f.write(
|
2213
|
+
f.write("\t" + act_var["var"] + "vhalf = " + act["vh"] + "\n")
|
1858
2214
|
if act["k"]:
|
1859
|
-
f.write(
|
1860
|
-
f.write(
|
2215
|
+
f.write("\t" + act_var["var"] + "k = " + act["k"] + "\n")
|
2216
|
+
f.write(
|
2217
|
+
"\t" + act_var["var"] + "seg = " + "-99" + "\n"
|
2218
|
+
) # TODO CHANGE THIS TO USER DEFINED VARIABLE
|
1861
2219
|
f.write("}\n")
|
1862
2220
|
|
1863
2221
|
elif block.__class__.__name__ == "Derivative":
|
@@ -1869,14 +2227,17 @@ class CellTunerGUI:
|
|
1869
2227
|
pass
|
1870
2228
|
if statement.__class__.__name__ == "Primed":
|
1871
2229
|
for act_var in act_vars:
|
1872
|
-
if
|
1873
|
-
|
2230
|
+
if (
|
2231
|
+
statement.variable == act_var["var"]
|
2232
|
+
and act_var["var_inf"] in statement.unparsed
|
2233
|
+
):
|
2234
|
+
f.write("\t" + act_var["var"] + "segment(v)" + "\n")
|
1874
2235
|
f.write("\t" + statement_str + "\n")
|
1875
2236
|
f.write("}\n")
|
1876
2237
|
|
1877
2238
|
elif block.__class__.__name__ == "FuncDef":
|
1878
2239
|
func_name = block.name
|
1879
|
-
#{'var': 'n', 'var_inf': 'inf', 'vh': '12.3', 'k': '-11.8', 'procedure_set': 'rate', 'line_set': 'inf = 1.0 / (1.0 + (exp((v + 12.3) / (-11.8))))'}
|
2240
|
+
# {'var': 'n', 'var_inf': 'inf', 'vh': '12.3', 'k': '-11.8', 'procedure_set': 'rate', 'line_set': 'inf = 1.0 / (1.0 + (exp((v + 12.3) / (-11.8))))'}
|
1880
2241
|
pars_arr = [p.unparsed for p in block.pars]
|
1881
2242
|
pars = ", ".join(pars_arr)
|
1882
2243
|
ftype = "PROCEDURE" if block.is_procedure else "FUNCTION"
|
@@ -1885,46 +2246,55 @@ class CellTunerGUI:
|
|
1885
2246
|
statement_str = statement.unparsed
|
1886
2247
|
if statement.__class__.__name__ == "Assignment":
|
1887
2248
|
for act_var in act_vars:
|
1888
|
-
if
|
2249
|
+
if (
|
2250
|
+
func_name == act_var["procedure_set"]
|
2251
|
+
and statement_str == act_var["line_set"]
|
2252
|
+
):
|
1889
2253
|
if act["vh"]:
|
1890
|
-
statement_str = statement_str.replace(
|
2254
|
+
statement_str = statement_str.replace(
|
2255
|
+
act_var["vh"], act_var["var"] + "vhalf", 1
|
2256
|
+
)
|
1891
2257
|
if act["k"]:
|
1892
|
-
statement_str = statement_str.replace(
|
1893
|
-
|
2258
|
+
statement_str = statement_str.replace(
|
2259
|
+
act_var["k"], act_var["var"] + "k", 1
|
2260
|
+
)
|
2261
|
+
f.write("\t" + statement_str + "\n")
|
1894
2262
|
|
1895
2263
|
f.write("}\n")
|
1896
2264
|
|
1897
2265
|
else:
|
1898
2266
|
f.write(block.unparsed)
|
1899
|
-
f.write(
|
2267
|
+
f.write("\n")
|
1900
2268
|
|
1901
2269
|
if act_vars:
|
1902
2270
|
f.write(": Segmentation functions\n\n")
|
1903
2271
|
|
1904
2272
|
for act_var in act_vars:
|
1905
|
-
#Create a xsegment(v) function for each variable
|
2273
|
+
# Create a xsegment(v) function for each variable
|
1906
2274
|
f.write("PROCEDURE " + act_var["var"] + "segment(v){\n")
|
1907
2275
|
f.write("\tif (v < " + act_var["var"] + "seg){\n")
|
1908
|
-
f.write("\t\t" + act_var[
|
2276
|
+
f.write("\t\t" + act_var["var_inf"] + " = 0\n")
|
1909
2277
|
f.write("\t}\n")
|
1910
2278
|
f.write("}\n")
|
1911
2279
|
if self.print_debug:
|
1912
2280
|
print("")
|
1913
|
-
|
2281
|
+
|
1914
2282
|
if folder:
|
1915
2283
|
os.chdir(cwd)
|
1916
|
-
|
2284
|
+
|
1917
2285
|
return mechs_processed
|
1918
2286
|
|
1919
|
-
def seg_template(
|
1920
|
-
|
2287
|
+
def seg_template(
|
2288
|
+
self, outhoc, mechs_processed, hoc_template_file=None, outappend=False, returnnameonly=False
|
2289
|
+
):
|
2290
|
+
# open hoc template file
|
1921
2291
|
# scan through each line for template selected begintemplate
|
1922
2292
|
# copy all lines until ^endtemplate TEMPL\s*$
|
1923
2293
|
# go through all copied lines, replace "insert x" with "insert xseg" && "_x" with "_xseg"
|
1924
2294
|
# write to outhoc and append if outappend set
|
1925
|
-
|
2295
|
+
|
1926
2296
|
if mechs_processed:
|
1927
|
-
new_template_name = self.template_name+"Seg"
|
2297
|
+
new_template_name = self.template_name + "Seg"
|
1928
2298
|
else:
|
1929
2299
|
new_template_name = self.template_name
|
1930
2300
|
|
@@ -1942,7 +2312,7 @@ class CellTunerGUI:
|
|
1942
2312
|
for hoc_file in hoc_files:
|
1943
2313
|
if found:
|
1944
2314
|
break
|
1945
|
-
with open(hoc_file,
|
2315
|
+
with open(hoc_file, "r") as f:
|
1946
2316
|
lines = f.readlines()
|
1947
2317
|
readon = False
|
1948
2318
|
for line in lines:
|
@@ -1955,25 +2325,35 @@ class CellTunerGUI:
|
|
1955
2325
|
readon = False
|
1956
2326
|
if found:
|
1957
2327
|
mode = "a+" if outappend else "w+"
|
1958
|
-
#ins_mechs = ["insert " + mech for mech in mechs_processed]
|
1959
|
-
#ref_mechs = ["_ " + mech for mech in mechs_processed]
|
1960
|
-
with open(outhoc,mode) as f:
|
1961
|
-
click.echo(
|
2328
|
+
# ins_mechs = ["insert " + mech for mech in mechs_processed]
|
2329
|
+
# ref_mechs = ["_ " + mech for mech in mechs_processed]
|
2330
|
+
with open(outhoc, mode) as f:
|
2331
|
+
click.echo(
|
2332
|
+
"Writing segregated template to "
|
2333
|
+
+ colored.green(outhoc)
|
2334
|
+
+ " in "
|
2335
|
+
+ mode
|
2336
|
+
+ " mode."
|
2337
|
+
)
|
1962
2338
|
for line in template_text:
|
1963
|
-
line = line.replace
|
2339
|
+
line = line.replace(self.template_name, new_template_name)
|
1964
2340
|
for mech in mechs_processed:
|
1965
2341
|
line = line.replace("insert " + mech, "insert " + mech + "seg")
|
1966
|
-
line = line.replace("_"+mech, "_"+mech+"seg")
|
2342
|
+
line = line.replace("_" + mech, "_" + mech + "seg")
|
1967
2343
|
f.write(line)
|
1968
2344
|
else:
|
1969
|
-
print("Template "+ self.template_name +"not found in a hoc file, no file written.")
|
2345
|
+
print("Template " + self.template_name + "not found in a hoc file, no file written.")
|
1970
2346
|
|
1971
2347
|
return new_template_name
|
1972
2348
|
|
1973
|
-
def get_templates(self,hoc_template_file=None):
|
1974
|
-
if self.templates is None:
|
2349
|
+
def get_templates(self, hoc_template_file=None):
|
2350
|
+
if self.templates is None: # Can really only do this once
|
1975
2351
|
##import pdb;pdb.set_trace()
|
1976
|
-
if
|
2352
|
+
if (
|
2353
|
+
self.mechanism_dir != "./"
|
2354
|
+
and self.mechanism_dir != "."
|
2355
|
+
and self.mechanism_dir != "././"
|
2356
|
+
):
|
1977
2357
|
neuron.load_mechanisms(self.mechanism_dir)
|
1978
2358
|
h_base = dir(h)
|
1979
2359
|
|
@@ -1989,54 +2369,54 @@ class CellTunerGUI:
|
|
1989
2369
|
|
1990
2370
|
os.chdir(cwd)
|
1991
2371
|
|
1992
|
-
#h.load_file('biophys_components/hoc_templates/Template.hoc')
|
2372
|
+
# h.load_file('biophys_components/hoc_templates/Template.hoc')
|
1993
2373
|
h_loaded = dir(h)
|
1994
2374
|
|
1995
2375
|
self.templates = [x for x in h_loaded if x not in h_base]
|
1996
2376
|
|
1997
2377
|
return self.templates
|
1998
2378
|
|
1999
|
-
def get_current_cell_values(self,cell=None,change_dict=None):
|
2379
|
+
def get_current_cell_values(self, cell=None, change_dict=None):
|
2000
2380
|
if not cell:
|
2001
|
-
cell = self.template
|
2002
|
-
|
2003
|
-
#change_dict={'soma': {'g_kdrseg': 0.0, 'gbar_kdrseg': 0.3, 'ik_kdrseg': 0.0, 'inf_kdrseg': 0.0, 'n_kdrseg': 0.0, 'nk_kdrseg': -11.8, 'nseg_kdrseg': -999.0, 'nvhalf_kdrseg': 12.3, 'tau_kdrseg': 0.0, 'g_naseg': 0.0, 'gbar_naseg': 0.3, 'h_naseg': 0.0, 'hinf_naseg': 0.0, 'htau_naseg': 0.0, 'ina_naseg': 0.0, 'm_naseg': 0.0, 'minf_naseg': 0.0, 'mk_naseg': -5.29, 'mseg_naseg': -999.0, 'mtau_naseg': 0.0, 'mvhalf_naseg': 25.5, 'gbar_leak': 3e-05, 'ileak_leak': 0.0, 'dik_dv_': 0.0, 'ek': -80.0, 'ik': 0.0, 'ki': 54.4, 'ko': 2.5, 'dina_dv_': 0.0, 'ena': 50.0, 'ina': 0.0, 'nai': 10.0, 'nao': 140.0, 'dileak_dv_': 0.0, 'eleak': -60.0, 'ileak': 0.0, 'leaki': 1.0, 'leako': 1.0}}
|
2381
|
+
cell = self.template
|
2382
|
+
|
2383
|
+
# change_dict={'soma': {'g_kdrseg': 0.0, 'gbar_kdrseg': 0.3, 'ik_kdrseg': 0.0, 'inf_kdrseg': 0.0, 'n_kdrseg': 0.0, 'nk_kdrseg': -11.8, 'nseg_kdrseg': -999.0, 'nvhalf_kdrseg': 12.3, 'tau_kdrseg': 0.0, 'g_naseg': 0.0, 'gbar_naseg': 0.3, 'h_naseg': 0.0, 'hinf_naseg': 0.0, 'htau_naseg': 0.0, 'ina_naseg': 0.0, 'm_naseg': 0.0, 'minf_naseg': 0.0, 'mk_naseg': -5.29, 'mseg_naseg': -999.0, 'mtau_naseg': 0.0, 'mvhalf_naseg': 25.5, 'gbar_leak': 3e-05, 'ileak_leak': 0.0, 'dik_dv_': 0.0, 'ek': -80.0, 'ik': 0.0, 'ki': 54.4, 'ko': 2.5, 'dina_dv_': 0.0, 'ena': 50.0, 'ina': 0.0, 'nai': 10.0, 'nao': 140.0, 'dileak_dv_': 0.0, 'eleak': -60.0, 'ileak': 0.0, 'leaki': 1.0, 'leako': 1.0}}
|
2004
2384
|
allsec = [a for a in h.allsec()]
|
2005
2385
|
primary_cell_secs = []
|
2006
2386
|
for s in allsec:
|
2007
2387
|
if s.cell() == cell:
|
2008
2388
|
primary_cell_secs.append(s)
|
2009
|
-
|
2389
|
+
|
2010
2390
|
sections = {}
|
2011
2391
|
|
2012
2392
|
for cellsec in primary_cell_secs:
|
2013
2393
|
mechs = [mech.name() for mech in cellsec(0.5) if not mech.name().endswith("_ion")]
|
2014
2394
|
ions = [mech.name() for mech in cellsec(0.5) if mech.name().endswith("_ion")]
|
2015
|
-
cellmechvars = ["cm","diam"]
|
2016
|
-
|
2395
|
+
cellmechvars = ["cm", "diam"]
|
2396
|
+
|
2017
2397
|
for mech in mechs:
|
2018
|
-
if hasattr(cellsec(0.5),mech):
|
2019
|
-
mechobj = getattr(cellsec(0.5),mech)
|
2398
|
+
if hasattr(cellsec(0.5), mech):
|
2399
|
+
mechobj = getattr(cellsec(0.5), mech)
|
2020
2400
|
else:
|
2021
2401
|
print(mech + " not found on " + cellsec.name())
|
2022
2402
|
continue
|
2023
|
-
|
2024
|
-
attribs = [at for at in dir(mechobj) if not at.startswith("__") and at !="name"]
|
2403
|
+
|
2404
|
+
attribs = [at for at in dir(mechobj) if not at.startswith("__") and at != "name"]
|
2025
2405
|
for attrib in attribs:
|
2026
|
-
ref = attrib+"_"+mech
|
2027
|
-
if hasattr(cellsec(0.5),ref):
|
2406
|
+
ref = attrib + "_" + mech
|
2407
|
+
if hasattr(cellsec(0.5), ref):
|
2028
2408
|
cellmechvars.append(ref)
|
2029
2409
|
|
2030
2410
|
for ion in ions:
|
2031
|
-
if hasattr(cellsec(0.5),ion):
|
2032
|
-
ionobj = getattr(cellsec(0.5),ion)
|
2411
|
+
if hasattr(cellsec(0.5), ion):
|
2412
|
+
ionobj = getattr(cellsec(0.5), ion)
|
2033
2413
|
else:
|
2034
2414
|
print(ion + " not found on " + cellsec.name())
|
2035
2415
|
continue
|
2036
|
-
attribs = [at for at in dir(ionobj) if not at.startswith("__") and at !="name"]
|
2416
|
+
attribs = [at for at in dir(ionobj) if not at.startswith("__") and at != "name"]
|
2037
2417
|
for attrib in attribs:
|
2038
2418
|
ref = attrib
|
2039
|
-
if hasattr(cellsec(0.5),ref):
|
2419
|
+
if hasattr(cellsec(0.5), ref):
|
2040
2420
|
cellmechvars.append(ref)
|
2041
2421
|
|
2042
2422
|
secname = cellsec.hname().split(".")[-1]
|
@@ -2050,17 +2430,17 @@ class CellTunerGUI:
|
|
2050
2430
|
compared = change_dict.get(secname)
|
2051
2431
|
|
2052
2432
|
for v in values:
|
2053
|
-
if hasattr(eval("cell."+secname),v):
|
2433
|
+
if hasattr(eval("cell." + secname), v):
|
2054
2434
|
key = v
|
2055
|
-
value = eval("cell."+secname+"."+v)
|
2435
|
+
value = eval("cell." + secname + "." + v)
|
2056
2436
|
add = True
|
2057
2437
|
if compared and (compared.get(key) or (compared.get(key) == 0 and value == 0)):
|
2058
2438
|
if compared.get(key) == value:
|
2059
2439
|
add = False
|
2060
2440
|
if add:
|
2061
|
-
valpairs[key]=value
|
2441
|
+
valpairs[key] = value
|
2062
2442
|
|
2063
2443
|
ret[secname] = valpairs
|
2064
|
-
#import pdb;pdb.set_trace()
|
2444
|
+
# import pdb;pdb.set_trace()
|
2065
2445
|
|
2066
|
-
return ret
|
2446
|
+
return ret
|