Page 1 of 1
Filter Mechanism params by NMODL PARAMETER
Posted: Thu Sep 19, 2019 7:25 am
by vogdb
Hello! I'm collecting all cell's mechanisms in Python like this:
Code: Select all
soma = h.Section(name='soma')
// soma.insert( lots of mechanisms )
for seg in soma:
for mech in seg:
print(mech)
mech contains parameters like 'gbar', 'g', 'ica' and so on. How can I filter them to get only those that are in 'PARAMETER' block of their corresponding `.mod` file?
Code: Select all
NEURON {
...
RANGE gbar, g, ica
}
PARAMETER {
gbar = 0.00001 (S/cm2)
}
Considering this example I would like to get `gbar` but leave out `g`. Would it be possible to do?
Re: Filter Mechanism params by NMODL PARAMETER
Posted: Thu Sep 19, 2019 10:27 am
by ted
mech contains parameters like 'gbar', 'g', 'ica' and so on.
Not what I see. Given
Code: Select all
soma = h.Section(name='soma')
soma.insert('hh')
then
Code: Select all
for seg in soma:
for mech in seg:
print(mech)
returns
but no mention of gnabar, gkbar, gl. or el, which are declared in hh.mod's PARAMETER block.
Re: Filter Mechanism params by NMODL PARAMETER
Posted: Thu Sep 19, 2019 12:27 pm
by vogdb
If to be that precise, lets take this example:
Code: Select all
soma = h.Section(name='soma')
soma.insert('hh')
for seg in soma:
for mech in seg:
if mech.name() == 'hh':
filtered = []
for n in dir(mech):
v = getattr(mech, n)
if n.startswith('__') or n in ('next', 'name', 'is_ion', 'segment',):
continue
filtered.append(n)
print(filtered)
# ['el', 'gk', 'gkbar', 'gl', 'gna', 'gnabar', 'h', 'il', 'm', 'n']
How can I make `filtered` to contain `['el', 'gkbar', 'gl', 'gnabar']` that are in `PARAMETER` block of `hh.mod`?
Code: Select all
PARAMETER {
gnabar = .12 (S/cm2) <0,1e9>
gkbar = .036 (S/cm2) <0,1e9>
gl = .0003 (S/cm2) <0,1e9>
el = -54.3 (mV)
Re: Filter Mechanism params by NMODL PARAMETER
Posted: Thu Sep 19, 2019 1:41 pm
by ramcdougal
As long as you're using NEURON 7.7+, mod file code is available for introspection from Python, so it can be parsed manually with a handful of lines of Python. Here's a function that seems to work to get parameters:
Code: Select all
from neuron import h
import re
def get_parameters(mech_name):
mech = h.MechanismType(0)
mech.select(mech_name)
parameters = {}
code = mech.code().split('\n')
inside_comment = False
inside_parameter = False
for line in code:
line = line.strip()
lineupper = line.upper()
if not line:
continue
if line[0] in ('?', ':'):
continue
if lineupper.startswith('COMMENT'):
inside_comment = True
elif lineupper.startswith('ENDCOMMENT'):
if not inside_comment:
raise('Parse error')
inside_comment = False
elif not inside_comment:
if lineupper.startswith('PARAMETER'):
inside_parameter = True
elif lineupper.startswith('}') and inside_parameter:
inside_parameter = False
elif inside_parameter:
# discard any comments
# NB: colon can also appear as part of a CURIE in other parts of a mod file
# but not in the PARAMETERS block
line = line.split(':')[0].strip()
if not line:
continue
varname, value, metadata = re.match('(\w+)\s*=\s*(-?[0-9\.]+)\s*(.*)', line).groups()
parameters[varname] = {'value': value}
if metadata:
parsed_metadata = re.match(r'(\((([\w/])+)\))?\s*(.*)', metadata).groups()
if parsed_metadata[1] is not None:
parameters[varname]['units'] = parsed_metadata[1]
if parsed_metadata[-1]:
parameters[varname]['bounds'] = parsed_metadata[-1]
return parameters
For example, if you call it with:
Code: Select all
import pprint
pprint.pprint(get_parameters('hh'))
Then it will display:
Code: Select all
{'el': {'units': 'mV', 'value': '-54.3'},
'gkbar': {'bounds': '<0,1e9>', 'units': 'S/cm2', 'value': '.036'},
'gl': {'bounds': '<0,1e9>', 'units': 'S/cm2', 'value': '.0003'},
'gnabar': {'bounds': '<0,1e9>', 'units': 'S/cm2', 'value': '.12'}}
There is also a proper Python NMODL parser available at
https://bluebrain.github.io/nmodl/ that could be used to generate the same data, but the above solution works without installing any additional packages.
Re: Filter Mechanism params by NMODL PARAMETER
Posted: Thu Sep 19, 2019 2:24 pm
by vogdb
That is brilliant! Thank you!
Re: Filter Mechanism params by NMODL PARAMETER
Posted: Fri Sep 20, 2019 10:39 am
by ted
Brilliant up to a point. The NMODL source code will tell you the default values of parameters. However, it won't tell you the actual value of any parameter used in a particular model implementation, because those can be changed by hoc or Python assignment statements. Also, if mechanism X's PARAMETER is also a range variable, every instance of X can have a different value for that parameter.
Finally, remember that some NMODL code (mis)declares some variables to be PARAMETERs and (mistakenly) assigns values to them even though those variables will actually get their values at runtime from code outside of the NMODL file. The most obvious example is celsius, but there are others. Such variables should really be declared in the ASSIGNED block.
Bottom line: although NEURON's new ability to introspect NMODL source code from compiled mechanisms can be truly useful, you still need to be careful about interpreting code written by yourself and others.
Re: Filter Mechanism params by NMODL PARAMETER
Posted: Fri Sep 20, 2019 1:47 pm
by hines
An old way of getting the PARAMETER names of a mechanism is
Code: Select all
from neuron import h
ms = h.MechanismStandard("hh", 1)
parm_name = h.ref("")
for i in range(ms.count()):
ms.name(parm_name, i)
print(parm_name[0])
https://www.neuron.yale.edu/neuron/stat ... ndard.name
Re: Filter Mechanism params by NMODL PARAMETER
Posted: Fri Sep 20, 2019 3:22 pm
by vogdb
Thank you so much for so many options. I will try the old way tomorrow as it looks very neat. Today I've ended up with this solution:
Code: Select all
from neuron import h
from nmodl import dsl
mech_type = h.MechanismType(0)
mech_type.select('hh')
code = mech_type.code()
driver = dsl.NmodlDriver()
modast = driver.parse_string(code)
lookup_visitor = dsl.visitor.AstLookupVisitor()
param_block = lookup_visitor.lookup(modast, dsl.ast.AstNodeType.PARAM_ASSIGN)
params = {}
for param in param_block:
name = param.name.value.value
value = None
if param.value is not None:
value = param.value.value
params[name] = value
return params
If someone would try the solution by
ramcdougal then it would be better to replace
Code: Select all
varname, value, metadata = re.match('(\w+)\s*=\s*(-?[0-9\.]+)\s*(.*)', line).groups()
with
Code: Select all
varname, value, metadata = re.match(r'(\w+)\s*(?:=\s*(-?[0-9.]+)\s*)?(.*)', line).groups()
otherwise you would have problems when
value is not presented.
I completely agree that this method is not reliable for values extraction. That is why I'm using it only for parameters names extraction.
Re: Filter Mechanism params by NMODL PARAMETER
Posted: Sat Sep 21, 2019 10:02 am
by vogdb
Here is the today's solution. Thank you again!
Code: Select all
ms = h.MechanismStandard(mech_name, 1)
param_name = h.ref('')
param_names = []
for i in range(ms.count()):
ms.name(param_name, i)
param_names.append(param_name[0])
param_names = [name.split('_' + mech_name)[0] for name in param_names]