Skip to content
This repository was archived by the owner on Feb 26, 2025. It is now read-only.

Commit 38ba649

Browse files
Merge pull request #441 from AurelienJaquier/nml-custom-mechs
Allow custom mechanism in neuroml conversion
2 parents a76041a + ddd68de commit 38ba649

File tree

3 files changed

+99
-7
lines changed

3 files changed

+99
-7
lines changed

bluepyopt/neuroml/biophys.py

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,42 @@ def add_nml_channel_to_nml_cell_file(
207207
included_channels.append(channel_nml2_file)
208208

209209

210+
def get_channel_ion(channel, custom_channel_ion=None):
211+
"""Get ion name given channel name.
212+
213+
Arguments:
214+
channel (str): ion channel (e.g. StochKv)
215+
custom_channel_ion (dict): dict mapping channel to ion
216+
"""
217+
ion = channel_ions.get(channel, None)
218+
if ion is None and custom_channel_ion is not None:
219+
ion = custom_channel_ion.get(channel, None)
220+
if ion is None:
221+
raise KeyError(
222+
f"Ion not found for channel {channel}."
223+
" Please set channel-ion mapping using custom_channel_ion."
224+
)
225+
return ion
226+
227+
228+
def get_erev(ion, custom_ion_erevs=None):
229+
"""Get reversal potential as str given ion name.
230+
231+
Arguments:
232+
ion (str): ion name (e.g. na)
233+
custom_ion_erevs (dict): dict mapping ion to erev (reversal potential)
234+
"""
235+
erev = ion_erevs.get(ion, None)
236+
if erev is None and custom_ion_erevs is not None:
237+
erev = custom_ion_erevs.get(ion, None)
238+
if erev is None:
239+
raise KeyError(
240+
f"Reversal potential not found for ion {ion}."
241+
" Please set ion-erev mapping using custom_ion_erevs."
242+
)
243+
return erev
244+
245+
210246
def get_arguments(
211247
params,
212248
parameter_name,
@@ -216,6 +252,8 @@ def get_arguments(
216252
variable_parameters,
217253
cond_density,
218254
release_params,
255+
custom_channel_ion=None,
256+
custom_ion_erevs=None,
219257
):
220258
"""Get arguments for channel density function.
221259
@@ -230,11 +268,13 @@ def get_arguments(
230268
parameters for non-uniform distributions
231269
cond_density (str): conductance density
232270
release_params (dict): optimized parameters
271+
custom_channel_ion (dict): dict mapping channel to ion
272+
custom_ion_erevs (dict): dict mapping ion to erev (reversal potential)
233273
"""
234274
arguments = {}
235275

236-
arguments["ion"] = channel_ions[channel]
237-
erev = ion_erevs[arguments["ion"]]
276+
arguments["ion"] = get_channel_ion(channel, custom_channel_ion)
277+
erev = get_erev(arguments["ion"], custom_ion_erevs)
238278

239279
channel_class = "ChannelDensity"
240280

@@ -331,6 +371,8 @@ def get_density(
331371
skip_non_uniform,
332372
release_params,
333373
skip_channels_copy,
374+
custom_channel_ion=None,
375+
custom_ion_erevs=None,
334376
):
335377
"""Return density.
336378
@@ -345,6 +387,8 @@ def get_density(
345387
release_params (dict): optimized parameters
346388
skip_channels_copy (bool): True to skip the copy pasting
347389
of the neuroml channel files
390+
custom_channel_ion (dict): dict mapping channel to ion
391+
custom_ion_erevs (dict): dict mapping ion to erev (reversal potential)
348392
"""
349393
channel = get_channel_from_param_name(parameter.param_name)
350394

@@ -375,6 +419,8 @@ def get_density(
375419
variable_parameters=variable_parameters,
376420
cond_density=cond_density,
377421
release_params=release_params,
422+
custom_channel_ion=custom_channel_ion,
423+
custom_ion_erevs=custom_ion_erevs,
378424
)
379425

380426
density = getattr(neuroml, channel_class)(**arguments)
@@ -413,6 +459,8 @@ def get_biophys(
413459
release_params,
414460
skip_non_uniform=False,
415461
skip_channels_copy=False,
462+
custom_channel_ion=None,
463+
custom_ion_erevs=None,
416464
):
417465
"""Get biophys in neuroml format.
418466
@@ -423,6 +471,8 @@ def get_biophys(
423471
skip_non_uniform (bool): True to skip non uniform distributions
424472
skip_channels_copy (bool): True to skip the copy pasting
425473
of the neuroml channel files
474+
custom_channel_ion (dict): dict mapping channel to ion
475+
custom_ion_erevs (dict): dict mapping ion to erev (reversal potential)
426476
"""
427477
concentrationModels = {}
428478

@@ -458,6 +508,8 @@ def get_biophys(
458508
skip_non_uniform,
459509
release_params,
460510
skip_channels_copy,
511+
custom_channel_ion,
512+
custom_ion_erevs,
461513
)
462514

463515
if density is not None:

bluepyopt/neuroml/cell.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,22 @@
2727
logger = logging.getLogger(__name__)
2828

2929

30-
def create_neuroml_cell(bpo_cell, release_params, skip_channels_copy=False):
30+
def create_neuroml_cell(
31+
bpo_cell,
32+
release_params,
33+
skip_channels_copy=False,
34+
custom_channel_ion=None,
35+
custom_ion_erevs=None,
36+
):
3137
"""Create the cell.
3238
3339
Arguments:
3440
bpo_cell (ephys.CellModel): bluepyopt cell
3541
release_params (dict): the optimized parameters
3642
skip_channels_copy (bool): True to skip the copy pasting
3743
of the neuroml channel files
44+
custom_channel_ion (dict): dict mapping channel to ion
45+
custom_ion_erevs (dict): dict mapping ion to erev (reversal potential)
3846
3947
:returns: name of the cell nml file
4048
"""
@@ -74,6 +82,8 @@ def create_neuroml_cell(bpo_cell, release_params, skip_channels_copy=False):
7482
release_params,
7583
skip_non_uniform=True,
7684
skip_channels_copy=skip_channels_copy,
85+
custom_channel_ion=custom_channel_ion,
86+
custom_ion_erevs=custom_ion_erevs,
7787
)
7888

7989
# Append biophys to cell

examples/neuroml/neuroml.ipynb

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,6 @@
5959
"import sys\n",
6060
"\n",
6161
"from pyneuroml import pynml\n",
62-
"from bluepyopt.ephys import models\n",
6362
"from bluepyopt.neuroml import cell\n",
6463
"from bluepyopt.neuroml import simulation"
6564
]
@@ -176,7 +175,7 @@
176175
"- a neuroml cell file named after the bluepyopt cell's name: Here, `l5pc_0_0.cell.nml`.\n",
177176
"- a neuroml network file containing the neuroml cell, named after the bluepyopt cell's name. Here, `l5pc.net.nml`.\n",
178177
"\n",
179-
"Note that the `create_neuroml_cell` function is designed to work with the mechanisms present in `bluepyopt/neuroml/NeuroML2_mechanisms/` and will likely crash if you try to use it with custom mechanisms."
178+
"Skip this step if you want to use custom mechanisms not present in `bluepyopt/neuroml/NeuroML2_mechanisms/`."
180179
]
181180
},
182181
{
@@ -187,7 +186,38 @@
187186
"outputs": [],
188187
"source": [
189188
"cell.create_neuroml_cell(\n",
190-
" l5pc_cell, release_params, skip_channels_copy=False\n",
189+
" l5pc_cell, release_params, skip_channels_copy=False,\n",
190+
")"
191+
]
192+
},
193+
{
194+
"attachments": {},
195+
"cell_type": "markdown",
196+
"id": "a0db4c6b",
197+
"metadata": {},
198+
"source": [
199+
"If you want to create a neuroml cell with custom mechanisms that are not present in `bluepyopt/neuroml/NeuroML2_mechanisms/`, you will have to:\n",
200+
"- copy your custom mechanisms in the `.nml` format in the `./channels` directory\n",
201+
"- give as argument `custom_channel_ion`, a dict mapping channel name to ion name, e.g. `custom_channel_ion = {\"NaCustom\": \"na\"}`\n",
202+
"- if one of the ion in `custom_channel_ion` is not in pre-registered ions (na, k, hcn, ca, pas), you'll also have to give as argument `custom_ion_erevs`, a dict mapping ions to their reversal potential\n",
203+
"\n",
204+
"Below is an example of how to use the `create_neuroml_cell` function with custom mechanisms.\n",
205+
"\n",
206+
"However, be aware that `create_neuroml_cell` might not be able to deal with any given custom mechanism, and some might break it."
207+
]
208+
},
209+
{
210+
"cell_type": "code",
211+
"execution_count": null,
212+
"id": "adf01098",
213+
"metadata": {},
214+
"outputs": [],
215+
"source": [
216+
"custom_channel_ion = {\"Cl_custom_mech_name\": \"cl\"}\n",
217+
"custom_ion_erevs = {\"cl\": \"-60.0 mV\"}\n",
218+
"\n",
219+
"cell.create_neuroml_cell(\n",
220+
" l5pc_cell, release_params, skip_channels_copy=False, custom_channel_ion=custom_channel_ion, custom_ion_erevs=custom_ion_erevs,\n",
191221
")"
192222
]
193223
},
@@ -387,7 +417,7 @@
387417
"name": "python",
388418
"nbconvert_exporter": "python",
389419
"pygments_lexer": "ipython3",
390-
"version": "3.10.8"
420+
"version": "3.10.8 (main, Oct 13 2022, 10:17:43) [Clang 14.0.0 (clang-1400.0.29.102)]"
391421
},
392422
"vscode": {
393423
"interpreter": {

0 commit comments

Comments
 (0)