diff --git a/.github/workflows/omv-ci.yml b/.github/workflows/omv-ci.yml index 0c9270b..ccb4c6c 100644 --- a/.github/workflows/omv-ci.yml +++ b/.github/workflows/omv-ci.yml @@ -16,26 +16,26 @@ jobs: strategy: fail-fast: false matrix: - python-version: [ 3.8, "3.10" ] - engine: [ jNeuroML_validate ] + python-version: [ "3.8", "3.10"] + engine: [ jNeuroML_validate, jNeuroML_NEURON ] steps: - uses: actions/checkout@v4 - + - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - + - name: Install OMV run: | - pip install git+https://github.com/OpenSourceBrain/osb-model-validation + pip install OSBModelValidation pip install scipy sympy matplotlib cython pandas tables - + - name: Run OMV tests on engine ${{ matrix.engine }} run: | omv all -V --engine=${{ matrix.engine }} - + - name: OMV final version info run: | omv list -V # list installed engines diff --git a/.gitignore b/.gitignore index e2346ac..8a4e105 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,12 @@ *.dat x86_64/ +channels/*dat +NeuroML2/channels/LEMS* +NeuroML2/channels/*mod +NeuroML2/*mod +NeuroML2/*.hoc +NeuroML2/*.dat +NeuroML2/*_nrn.py +NeuroML2/*.spikes +.mypy_cache/ +*.npy diff --git a/NEURON/mb/test_cell/test_kc.py b/NEURON/mb/test_cell/test_kc.py index c9875ae..c64cb7b 100644 --- a/NEURON/mb/test_cell/test_kc.py +++ b/NEURON/mb/test_cell/test_kc.py @@ -31,6 +31,7 @@ kc = eval(f'h.{cellname}()') delay = Q_(100, 'ms') duration=Q_(500.0, 'ms') +postdelay=Q_(100.0, 'ms') inj_current = Q_(16, 'pA') clamp = ephys.setup_current_clamp(kc.soma, delay=delay, duration=duration, amplitude=inj_current) @@ -43,7 +44,13 @@ tvec = h.Vector() tvec.record(h._ref_t) -h.tstop = delay.to('ms').m + duration.to('ms').m +# record spikes +apcvec = h.Vector() +apc = h.APCount(0.5) +apc.thresh = -10 +apc.record(apcvec) + +h.tstop = delay.to('ms').m + duration.to('ms').m + postdelay.to('ms').m h.v_init = Em.to('mV').m h.init() h.run() @@ -59,6 +66,8 @@ data_file = 'kc_vm.npy' np.save(data_file, data) +print(list(apcvec)) + print(f'Simulated {cellname} from template file {filename}.') print(f'Settling time {delay} followed by {inj_current} current injection for {duration}') print(f'Saved Vm in {data_file}') diff --git a/NEURON/run-test-kc.sh b/NEURON/run-test-kc.sh new file mode 100755 index 0000000..363aae0 --- /dev/null +++ b/NEURON/run-test-kc.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +# Copyright 2024 Ankur Sinha +# Author: Ankur Sinha +# File : +# + +if [[ -z "${MODEL_DIR}" ]]; then + export MODEL_DIR=$(pwd) + echo "Setting model root directory to $MODEL_DIR" + echo "To use a custom path, set the MODEL_DIR environment variable to the desired path." +fi + +export PYTHONPATH="${MODEL_DIR}/mb:${MODEL_DIR}/nrn:${MODEL_DIR}/morphutils:${MODEL_DIR}/common" +nrnivmodl ./mb/mod/ +python ./mb/test_cell/test_kc.py diff --git a/NeuroML2/.test.kc.jnmlnrn.omt b/NeuroML2/.test.kc.jnmlnrn.omt new file mode 100644 index 0000000..71b0f4e --- /dev/null +++ b/NeuroML2/.test.kc.jnmlnrn.omt @@ -0,0 +1,15 @@ +target: LEMS_KC_step_test.xml +engine: jNeuroML_NEURON +mep: .test.kc.mep +experiments: + stepKC: + observables: + spike times: + file: + path: KC_step_test.KC_pop.v.dat + columns: [0,1] + scaling: [1000,1000] + spike detection: + method: threshold + threshold: -10. + tolerance: 0.005087969567027844 diff --git a/NeuroML2/.test.kc.mep b/NeuroML2/.test.kc.mep new file mode 100644 index 0000000..6443954 --- /dev/null +++ b/NeuroML2/.test.kc.mep @@ -0,0 +1,8 @@ +system: Testing a detailed cell + +experiments: + stepKC: + expected: + spike times: [144.45000000000556, 177.64999999997536, 210.29999999994567, 242.74999999991616, 275.0499999998868, 307.19999999985754, 339.2249999998284, 371.07499999979945, 402.74999999977064, 434.1499999997421, 465.2249999997138, 495.87499999968594, 525.9749999997221, 555.3499999998289, 583.8499999999326] + +# generated from test-kc.py diff --git a/NeuroML2/GGN.cell.nml b/NeuroML2/GGN.cell.nml index aa075d6..4b1069c 100644 --- a/NeuroML2/GGN.cell.nml +++ b/NeuroML2/GGN.cell.nml @@ -4,8 +4,60 @@ Yale University and UCL - - Cell: GGM exported from NEURON ModelView. Reference: Subhasis Ray Zane N Aldworth Mark A Stopfer (2020) Feedback inhibition and its control in an insect olfactory circuit eLife 9:e53281. + + Cell: GGN exported from NEURON ModelView. Reference: Subhasis Ray, Zane N Aldworth, Mark A Stopfer (2020) Feedback inhibition and its control in an insect olfactory circuit eLife 9:e53281. + + + + + Giant GABAergic Neuron model + Subhasis Ray, Zane N Aldworth, Mark A Stopfer (2020) Feedback inhibition and its control in an insect olfactory circuit eLife 9:e53281. + + + + + + + + + + + + + + + + + + + + + + + Subhasis Ray + https://orcid.org/0000-0003-2566-7146 + + + + + Ankur Sinha + https://orcid.org/0000-0001-7568-7167 + + + + + 2024-04-25 + + + + + + diff --git a/NeuroML2/KC.cell.nml b/NeuroML2/KC.cell.nml index 61f019f..293ef23 100644 --- a/NeuroML2/KC.cell.nml +++ b/NeuroML2/KC.cell.nml @@ -1,11 +1,69 @@ - - + + + + + + + Kenyon cell model + Subhasis Ray, Zane N Aldworth, Mark A Stopfer (2020) Feedback inhibition and its control in an insect olfactory circuit eLife 9:e53281. + + + + + + + + + + + + + + + + + + + + + + + + + + + + Subhasis Ray + https://orcid.org/0000-0003-2566-7146 + + + + + Ankur Sinha + https://orcid.org/0000-0001-7568-7167 + + + + + 2024-04-25 + + + + + + @@ -22,14 +80,15 @@ - - - + + + + - + diff --git a/NeuroML2/KC.net.nml b/NeuroML2/KC.net.nml new file mode 100644 index 0000000..bfd9f2b --- /dev/null +++ b/NeuroML2/KC.net.nml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + Default soma segment group for the cell + + + + Default segment group for all segments in the cell + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/NeuroML2/LEMS_KC_step_test.xml b/NeuroML2/LEMS_KC_step_test.xml new file mode 100644 index 0000000..9fcfbf8 --- /dev/null +++ b/NeuroML2/LEMS_KC_step_test.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/NeuroML2/channels/RaySigmoid.nml b/NeuroML2/channels/RaySigmoid.nml index 79e03d3..abe205d 100644 --- a/NeuroML2/channels/RaySigmoid.nml +++ b/NeuroML2/channels/RaySigmoid.nml @@ -5,38 +5,57 @@ + description="Inf parameter for Ray et al 2020" > - - + - - + + + description="Tau parameter for Ray et al 2020"> - - - - + + + - + - + + + + + + + + + + + + + + + + + + + + diff --git a/NeuroML2/channels/Steady_state(s)_of_activation_variables_of_kst_from_kst.channel.nml_at_6.3_degC.png b/NeuroML2/channels/Steady_state(s)_of_activation_variables_of_kst_from_kst.channel.nml_at_6.3_degC.png new file mode 100644 index 0000000..3924a98 Binary files /dev/null and b/NeuroML2/channels/Steady_state(s)_of_activation_variables_of_kst_from_kst.channel.nml_at_6.3_degC.png differ diff --git a/NeuroML2/channels/Time_Course(s)_of_activation_variables_of_Nas_from_nas.channel.nml_at_6.3_degC.png b/NeuroML2/channels/Time_Course(s)_of_activation_variables_of_Nas_from_nas.channel.nml_at_6.3_degC.png deleted file mode 100644 index b48932e..0000000 Binary files a/NeuroML2/channels/Time_Course(s)_of_activation_variables_of_Nas_from_nas.channel.nml_at_6.3_degC.png and /dev/null differ diff --git a/NeuroML2/channels/Time_Course(s)_of_activation_variables_of_ka_from_ka.channel.nml_at_6.3_degC.png b/NeuroML2/channels/Time_Course(s)_of_activation_variables_of_ka_from_ka.channel.nml_at_6.3_degC.png index 9155c66..4aabc77 100644 Binary files a/NeuroML2/channels/Time_Course(s)_of_activation_variables_of_ka_from_ka.channel.nml_at_6.3_degC.png and b/NeuroML2/channels/Time_Course(s)_of_activation_variables_of_ka_from_ka.channel.nml_at_6.3_degC.png differ diff --git a/NeuroML2/channels/Time_Course(s)_of_activation_variables_of_kst_from_kst.channel.nml_at_6.3_degC.png b/NeuroML2/channels/Time_Course(s)_of_activation_variables_of_kst_from_kst.channel.nml_at_6.3_degC.png new file mode 100644 index 0000000..9211c92 Binary files /dev/null and b/NeuroML2/channels/Time_Course(s)_of_activation_variables_of_kst_from_kst.channel.nml_at_6.3_degC.png differ diff --git a/NeuroML2/channels/Time_Course(s)_of_activation_variables_of_kv_from_kv.channel.nml_at_6.3_degC.png b/NeuroML2/channels/Time_Course(s)_of_activation_variables_of_kv_from_kv.channel.nml_at_6.3_degC.png index 4237759..689d8f5 100644 Binary files a/NeuroML2/channels/Time_Course(s)_of_activation_variables_of_kv_from_kv.channel.nml_at_6.3_degC.png and b/NeuroML2/channels/Time_Course(s)_of_activation_variables_of_kv_from_kv.channel.nml_at_6.3_degC.png differ diff --git a/NeuroML2/channels/Time_Course(s)_of_activation_variables_of_naf_from_naf.channel.nml_at_6.3_degC.png b/NeuroML2/channels/Time_Course(s)_of_activation_variables_of_naf_from_naf.channel.nml_at_6.3_degC.png index a11a01f..f2c9afd 100644 Binary files a/NeuroML2/channels/Time_Course(s)_of_activation_variables_of_naf_from_naf.channel.nml_at_6.3_degC.png and b/NeuroML2/channels/Time_Course(s)_of_activation_variables_of_naf_from_naf.channel.nml_at_6.3_degC.png differ diff --git a/NeuroML2/channels/Time_Course(s)_of_activation_variables_of_nas_from_nas.channel.nml_at_6.3_degC.png b/NeuroML2/channels/Time_Course(s)_of_activation_variables_of_nas_from_nas.channel.nml_at_6.3_degC.png new file mode 100644 index 0000000..f07373c Binary files /dev/null and b/NeuroML2/channels/Time_Course(s)_of_activation_variables_of_nas_from_nas.channel.nml_at_6.3_degC.png differ diff --git a/NeuroML2/channels/ka.channel.nml b/NeuroML2/channels/ka.channel.nml index 00bc71e..9954a29 100644 --- a/NeuroML2/channels/ka.channel.nml +++ b/NeuroML2/channels/ka.channel.nml @@ -5,7 +5,6 @@ - Implementation of A type K+ channel ( KA ) from Wustenberg DG, Boytcheva M, Grunewald B, Byrne JH, Menzel R, Baxter DA. This is transient A type K+ channel in Apis mellifera Kenyon cells (cultured). @@ -13,53 +12,13 @@ + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/NeuroML2/channels/kst.channel.nml b/NeuroML2/channels/kst.channel.nml index 17c45b6..4ad01ab 100644 --- a/NeuroML2/channels/kst.channel.nml +++ b/NeuroML2/channels/kst.channel.nml @@ -14,12 +14,12 @@ - + - + diff --git a/NeuroML2/channels/kv.channel.nml b/NeuroML2/channels/kv.channel.nml index 9c9ec36..bcd3011 100644 --- a/NeuroML2/channels/kv.channel.nml +++ b/NeuroML2/channels/kv.channel.nml @@ -14,7 +14,7 @@ - + diff --git a/NeuroML2/channels/naf.channel.nml b/NeuroML2/channels/naf.channel.nml index 15661ba..ea2633b 100644 --- a/NeuroML2/channels/naf.channel.nml +++ b/NeuroML2/channels/naf.channel.nml @@ -14,12 +14,12 @@ - + - + diff --git a/NeuroML2/channels/nas.channel.nml b/NeuroML2/channels/nas.channel.nml index 65f790c..3f916bf 100644 --- a/NeuroML2/channels/nas.channel.nml +++ b/NeuroML2/channels/nas.channel.nml @@ -14,12 +14,12 @@ - + - + diff --git a/NeuroML2/postprocess_cells.py b/NeuroML2/postprocess_cells.py index 129b5da..83586dd 100644 --- a/NeuroML2/postprocess_cells.py +++ b/NeuroML2/postprocess_cells.py @@ -13,10 +13,16 @@ import random +import yaml import neuroml from neuroml.loaders import read_neuroml2_file -from pyneuroml.pynml import write_neuroml2_file +from pyneuroml.pynml import write_neuroml2_file, run_lems_with_jneuroml_neuron +from pyneuroml.lems import generate_lems_file_for_neuroml +from pyneuroml.plot import generate_plot +from pyneuroml.neuron import morphinfo, getinfo, load_hoc_or_python_file +from pyneuroml.annotations import create_annotation from neuroml.utils import component_factory +from textwrap import indent random.seed(1412) @@ -71,6 +77,28 @@ def postprocess_GGN(): celldoc = load_and_setup_cell(cellname) cell = celldoc.cells[0] # type: neuroml.Cell + # TODO: add organism + annotation = create_annotation( + subject=cell.id, title="Giant GABAergic Neuron model", + description="Subhasis Ray, Zane N Aldworth, Mark A Stopfer (2020) Feedback inhibition and its control in an insect olfactory circuit eLife 9:e53281.", + annotation_style="miriam", + serialization_format="pretty-xml", + xml_header=False, + citations={"https://doi.org/10.7554/eLife.53281": "Subhasis Ray, Zane N Aldworth, Mark A Stopfer (2020) Feedback inhibition and its control in an insect olfactory circuit eLife 9:e53281."}, + sources={"https://modeldb.science/262670": "ModelDB", + "https://github.com/OpenSourceBrain/262670": "GitHub", + "https://v1.opensourcebrain.org/projects/locust-mushroom-body": + "Open Source Brain"}, + authors={"Subhasis Ray": + {"https://orcid.org/0000-0003-2566-7146": "orcid"}, + }, + contributors={ + "Ankur Sinha": {"https://orcid.org/0000-0001-7568-7167": "orcid"}, + }, + creation_date="2024-04-25" + ) + cell.annotation = neuroml.Annotation([annotation]) + # biophysics # all cell.add_channel_density( @@ -96,47 +124,56 @@ def postprocess_GGN(): def postprocess_KC(): """Manually create KC and add biophysics.""" - celldoc = component_factory("NeuroMLDocument", id="KC_doc") # type: neuroml.NeuroMLDocument + celldoc = component_factory( + "NeuroMLDocument", id="KC_doc" + ) # type: neuroml.NeuroMLDocument cell = celldoc.add("Cell", id="KC", validate=False) # type: neuroml.Cell cell.setup_nml_cell() + + # TODO: add organism + annotation = create_annotation( + subject=cell.id, title="Kenyon cell model", + description="Subhasis Ray, Zane N Aldworth, Mark A Stopfer (2020) Feedback inhibition and its control in an insect olfactory circuit eLife 9:e53281.", + annotation_style="miriam", + serialization_format="pretty-xml", + xml_header=False, + encodes_other_biology={"http://uri.neuinfo.org/nif/nifstd/nlx_147420": "cell"}, + citations={"https://doi.org/10.7554/eLife.53281": "Subhasis Ray, Zane N Aldworth, Mark A Stopfer (2020) Feedback inhibition and its control in an insect olfactory circuit eLife 9:e53281."}, + sources={"https://modeldb.science/262670": "ModelDB", + "https://github.com/OpenSourceBrain/262670": "GitHub", + "https://v1.opensourcebrain.org/projects/locust-mushroom-body": + "Open Source Brain"}, + authors={"Subhasis Ray": + {"https://orcid.org/0000-0003-2566-7146": "orcid"}, + }, + contributors={ + "Ankur Sinha": {"https://orcid.org/0000-0001-7568-7167": "orcid"}, + }, + creation_date="2024-04-25" + ) + cell.annotation = neuroml.Annotation([annotation]) + cell.add_segment([0, 0, 0, 20], [0, 0, 6.366, 20], seg_type="soma") # biophysics # all + cell.set_resistivity("35.4 ohm_cm", group_id="all") + cell.set_specific_capacitance("1 uF_per_cm2", group_id="all") + cell.set_init_memb_potential("-70mV") + cell.set_spike_thresh("-10mV") + cell.add_channel_density( nml_cell_doc=celldoc, cd_id="pas", ion_channel="pas", - cond_density=".0000975 S_per_cm2", + cond_density="9.75e-5 S_per_cm2", erev="-70 mV", group_id="all", ion="non_specific", ion_chan_def_file="channels/pas.channel.nml", ) - cell.set_resistivity("35.4 ohm_cm", group_id="all") - cell.set_specific_capacitance("1 uF_per_cm2", group_id="all") - cell.set_init_memb_potential("-80mV") - cell.add_channel_density( - nml_cell_doc=celldoc, - cd_id="nas", - ion_channel="nas", - cond_density="3e-3 S_per_cm2", - erev="-58 mV", - group_id="all", - ion="na", - ion_chan_def_file="channels/nas.channel.nml", - ) - cell.add_channel_density( - nml_cell_doc=celldoc, - cd_id="naf", - ion_channel="naf", - cond_density="3.5e-2 S_per_cm2", - erev="-58 mV", - group_id="all", - ion="na", - ion_chan_def_file="channels/naf.channel.nml", - ) + # K cell.add_channel_density( nml_cell_doc=celldoc, cd_id="kv", @@ -167,6 +204,27 @@ def postprocess_KC(): ion="k", ion_chan_def_file="channels/kst.channel.nml", ) + # Na + cell.add_channel_density( + nml_cell_doc=celldoc, + cd_id="naf", + ion_channel="naf", + cond_density="3.5e-2 S_per_cm2", + erev="58 mV", + group_id="all", + ion="na", + ion_chan_def_file="channels/naf.channel.nml", + ) + cell.add_channel_density( + nml_cell_doc=celldoc, + cd_id="nas", + ion_channel="nas", + cond_density="3e-3 S_per_cm2", + erev="58 mV", + group_id="all", + ion="na", + ion_chan_def_file="channels/nas.channel.nml", + ) # L1 validation # cell.validate(recursive=True) @@ -175,6 +233,89 @@ def postprocess_KC(): write_neuroml2_file(celldoc, "KC.cell.nml") +def step_current_omv_kc(): + """Create a step current simulation OMV LEMS file""" + # read the cell file, modify it, write a new one + netdoc = read_neuroml2_file("KC.cell.nml") + kc_cell = netdoc.cells[0] + net = netdoc.add(neuroml.Network, id="KC_net", validate=False) + pop = net.add(neuroml.Population, id="KC_pop", component=kc_cell.id, size=1) + + # should be same as test_kc.py + pg = netdoc.add( + neuroml.PulseGenerator( + id="pg", delay="100ms", duration="500ms", + amplitude="16pA" + ) + ) + + # Add these to cells + input_list = net.add( + neuroml.InputList(id="input_list", component=pg.id, populations=pop.id) + ) + aninput = input_list.add( + neuroml.Input( + id="0", + target="../%s[0]" % (pop.id), + destination="synapses", + segment_id="0", + ) + ) + write_neuroml2_file(netdoc, "KC.net.nml") + + generate_lems_file_for_neuroml( + sim_id="KC_step_test", + target=net.id, + neuroml_file="KC.net.nml", + duration="700ms", + dt="0.01ms", + lems_file_name="LEMS_KC_step_test.xml", + nml_doc=netdoc, + gen_spike_saves_for_all_somas=True, + target_dir=".", + gen_saves_for_quantities={ + "k.dat": ["KC_pop[0]/biophys/membraneProperties/kv/iDensity"] + }, + copy_neuroml=False + ) + + data = run_lems_with_jneuroml_neuron( + "LEMS_KC_step_test.xml", load_saved_data=True, compile_mods=True + ) + + print(data.keys()) + + # print(data) + generate_plot( + xvalues=[data["t"]], + yvalues=[data["KC_pop[0]/v"]], + title="Membrane potential: KC", + ) + + +def getcellinfo(cellname): + """Get info of cell from HOC + + Used to match NeuroML hoc against original NEURON hoc. + + :param cellname: TODO + :returns: TODO + + """ + from neuron import h + load_hoc_or_python_file(f"{cellname}.hoc") + h("celsius = 34") + h("objectvar mycell") + h("strdef reference") + h('reference = "acell"') + h(f'mycell = new {cellname}(reference, "{cellname}", "A cell")') + with open(f"NeuroML-info-{cellname}.yaml", "w") as f: + retval = getinfo(h.allsec()) + print(yaml.dump(retval, sort_keys=True, indent=4), file=f, flush=True) + + if __name__ == "__main__": postprocess_GGN() postprocess_KC() + # step_current_omv_kc() + # getcellinfo("KC")