From 16ab91d69d812173a227cc9569329e3c529e3a94 Mon Sep 17 00:00:00 2001 From: Pramod Kumbhar Date: Wed, 25 Sep 2024 19:34:08 +0200 Subject: [PATCH] Backport #3093 - We were commenting TABLE statement from hh.mod as TABLE statement was not supported in mod2c. - NMODL on CoreNEURON side supports TABLE statements also on GPU side. - Hence, we can remove the CMake toggling logic for TABLE. - Also update the references for tests in ringtest and testcorenrn repos fixes #1764 --- CMakeLists.txt | 9 +- src/coreneuron/mechanism/mech/modfile/hh.mod | 125 +++++++++++ src/nrnoc/hh.mod | 2 +- test/CMakeLists.txt | 6 +- test/api/hh_sim.cpp | 84 ++++++++ test/api/netcon.cpp | 94 ++++++++ test/external/CMakeLists.txt | 4 +- .../connect_dend/cell3soma.core.dat.ref | 203 ------------------ 8 files changed, 309 insertions(+), 218 deletions(-) create mode 100644 src/coreneuron/mechanism/mech/modfile/hh.mod create mode 100644 test/api/hh_sim.cpp create mode 100644 test/api/netcon.cpp delete mode 100644 test/hoc_tests/connect_dend/cell3soma.core.dat.ref diff --git a/CMakeLists.txt b/CMakeLists.txt index 4e8000623f..66cb970ff6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -713,22 +713,17 @@ endif() # ============================================================================= if(NRN_ENABLE_CORENEURON OR NRN_ENABLE_MOD_COMPATIBILITY) set(GLOBAL_VAR_TOGGLE_COMMAND "'s/ GLOBAL minf/ RANGE minf/'") - set(TABLE_VAR_TOGGLE_COMMAND "'s/ TABLE minf/ :TABLE minf/'") else() set(GLOBAL_VAR_TOGGLE_COMMAND "'s/ RANGE minf/ GLOBAL minf/'") - set(TABLE_VAR_TOGGLE_COMMAND "'s/ :TABLE minf/ TABLE minf/'") endif() separate_arguments(GLOBAL_VAR_TOGGLE_COMMAND UNIX_COMMAND "${GLOBAL_VAR_TOGGLE_COMMAND}") -separate_arguments(TABLE_VAR_TOGGLE_COMMAND UNIX_COMMAND "${TABLE_VAR_TOGGLE_COMMAND}") add_custom_target( hh_update COMMAND sed ${GLOBAL_VAR_TOGGLE_COMMAND} ${CMAKE_SOURCE_DIR}/src/nrnoc/hh.mod > ${CMAKE_BINARY_DIR}/hh.mod.1 - COMMAND sed ${TABLE_VAR_TOGGLE_COMMAND} ${CMAKE_BINARY_DIR}/hh.mod.1 > - ${CMAKE_BINARY_DIR}/hh.mod.2 - COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_BINARY_DIR}/hh.mod.2 + COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_BINARY_DIR}/hh.mod.1 ${CMAKE_SOURCE_DIR}/src/nrnoc/hh.mod - COMMAND ${CMAKE_COMMAND} -E remove ${CMAKE_BINARY_DIR}/hh.mod.1 ${CMAKE_BINARY_DIR}/hh.mod.2 + COMMAND ${CMAKE_COMMAND} -E remove ${CMAKE_BINARY_DIR}/hh.mod.1 COMMENT "Update hh.mod for CoreNEURON compatibility" VERBATIM) add_dependencies(nrniv_lib hh_update) diff --git a/src/coreneuron/mechanism/mech/modfile/hh.mod b/src/coreneuron/mechanism/mech/modfile/hh.mod new file mode 100644 index 0000000000..bbb336197c --- /dev/null +++ b/src/coreneuron/mechanism/mech/modfile/hh.mod @@ -0,0 +1,125 @@ +TITLE hh.mod squid sodium, potassium, and leak channels + +COMMENT + This is the original Hodgkin-Huxley treatment for the set of sodium, + potassium, and leakage channels found in the squid giant axon membrane. + ("A quantitative description of membrane current and its application + conduction and excitation in nerve" J.Physiol. (Lond.) 117:500-544 (1952).) + Membrane voltage is in absolute mV and has been reversed in polarity + from the original HH convention and shifted to reflect a resting potential + of -65 mV. + Remember to set celsius=6.3 (or whatever) in your HOC file. + See squid.hoc for an example of a simulation using this model. + SW Jaslove 6 March, 1992 +ENDCOMMENT + +UNITS { + (mA) = (milliamp) + (mV) = (millivolt) + (S) = (siemens) +} + +? interface +NEURON { + SUFFIX hh + USEION na READ ena WRITE ina + USEION k READ ek WRITE ik + NONSPECIFIC_CURRENT il + RANGE gnabar, gkbar, gl, el, gna, gk + :GLOBAL minf, hinf, ninf, mtau, htau, ntau + RANGE minf, hinf, ninf, mtau, htau, ntau + THREADSAFE : assigned GLOBALs will be per thread +} + +PARAMETER { + gnabar = .12 (S/cm2) <0,1e9> + gkbar = .036 (S/cm2) <0,1e9> + gl = .0003 (S/cm2) <0,1e9> + el = -54.3 (mV) +} + +STATE { + m h n +} + +ASSIGNED { + v (mV) + celsius (degC) + ena (mV) + ek (mV) + + gna (S/cm2) + gk (S/cm2) + ina (mA/cm2) + ik (mA/cm2) + il (mA/cm2) + minf hinf ninf + mtau (ms) htau (ms) ntau (ms) +} + +? currents +BREAKPOINT { + SOLVE states METHOD cnexp + gna = gnabar*m*m*m*h + ina = gna*(v - ena) + gk = gkbar*n*n*n*n + ik = gk*(v - ek) + il = gl*(v - el) +} + + +INITIAL { + rates(v) + m = minf + h = hinf + n = ninf +} + +? states +DERIVATIVE states { + rates(v) + m' = (minf-m)/mtau + h' = (hinf-h)/htau + n' = (ninf-n)/ntau +} + +:LOCAL q10 + + +? rates +PROCEDURE rates(v(mV)) { :Computes rate and other constants at current v. + :Call once from HOC to initialize inf at resting v. + LOCAL alpha, beta, sum, q10 + TABLE minf, mtau, hinf, htau, ninf, ntau DEPEND celsius FROM -100 TO 100 WITH 200 + +UNITSOFF + q10 = 3^((celsius - 6.3)/10) + :"m" sodium activation system + alpha = .1 * vtrap(-(v+40),10) + beta = 4 * exp(-(v+65)/18) + sum = alpha + beta + mtau = 1/(q10*sum) + minf = alpha/sum + :"h" sodium inactivation system + alpha = .07 * exp(-(v+65)/20) + beta = 1 / (exp(-(v+35)/10) + 1) + sum = alpha + beta + htau = 1/(q10*sum) + hinf = alpha/sum + :"n" potassium activation system + alpha = .01*vtrap(-(v+55),10) + beta = .125*exp(-(v+65)/80) + sum = alpha + beta + ntau = 1/(q10*sum) + ninf = alpha/sum +} + +FUNCTION vtrap(x,y) { :Traps for 0 in denominator of rate eqns. + if (fabs(x/y) < 1e-6) { + vtrap = y*(1 - x/y/2) + }else{ + vtrap = x/(exp(x/y) - 1) + } +} + +UNITSON diff --git a/src/nrnoc/hh.mod b/src/nrnoc/hh.mod index 0c7305ee1b..d14818e46d 100644 --- a/src/nrnoc/hh.mod +++ b/src/nrnoc/hh.mod @@ -30,7 +30,7 @@ NEURON { NONSPECIFIC_CURRENT il RANGE gnabar, gkbar, gl, el, gna, gk : `GLOBAL minf` will be replaced with `RANGE minf` if CoreNEURON enabled - GLOBAL minf, hinf, ninf, mtau, htau, ntau + RANGE minf, hinf, ninf, mtau, htau, ntau THREADSAFE : assigned GLOBALs will be per thread } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index abf8c78c9d..db250feaa8 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -64,11 +64,7 @@ list(APPEND TESTS ringtest) # Add small hoc test # ============================================================================= set(HOCTEST_DIR ${PROJECT_SOURCE_DIR}/test/hoc_tests/connect_dend) -if(NRN_ENABLE_CORENEURON OR NRN_ENABLE_MOD_COMPATIBILITY) - set(REF_FILE cell3soma.core.dat.ref) -else() - set(REF_FILE cell3soma.dat.ref) -endif() +set(REF_FILE cell3soma.dat.ref) add_test( connect_dend ${CMAKE_COMMAND} diff --git a/test/api/hh_sim.cpp b/test/api/hh_sim.cpp new file mode 100644 index 0000000000..b0ab735ce0 --- /dev/null +++ b/test/api/hh_sim.cpp @@ -0,0 +1,84 @@ +// NOTE: this assumes neuronapi.h is on your CPLUS_INCLUDE_PATH +#include "neuronapi.h" +#include + +#include +#include +#include +#include +#include +#include + +#include "./test_common.h" + +using std::cout; +using std::endl; +using std::ofstream; + +constexpr std::array EXPECTED_V{ + -0x1.04p+6, + -0x1.b254ad82e20edp+5, + -0x1.24a52af1ab463p+6, +}; + +extern "C" void modl_reg(){/* No modl_reg */}; + +int main(void) { + static std::array argv = {"hh_sim", "-nogui", "-nopython", nullptr}; + nrn_init(3, argv.data()); + + // load the stdrun library + char* temp_str = strdup("stdrun.hoc"); + nrn_str_push(&temp_str); + nrn_function_call(nrn_symbol("load_file"), 1); + nrn_double_pop(); + free(temp_str); + + // topology + Section* soma = nrn_section_new("soma"); + nrn_nseg_set(soma, 3); + + // define soma morphology with two 3d points + nrn_section_push(soma); + for (double x: {0, 0, 0, 10}) { + nrn_double_push(x); + } + nrn_function_call(nrn_symbol("pt3dadd"), 4); + nrn_double_pop(); // pt3dadd returns a number + for (double x: {10, 0, 0, 10}) { + nrn_double_push(x); + } + nrn_function_call(nrn_symbol("pt3dadd"), 4); + nrn_double_pop(); // pt3dadd returns a number + + // ion channels + nrn_mechanism_insert(soma, nrn_symbol("hh")); + + // current clamp at soma(0.5) + nrn_double_push(0.5); + Object* iclamp = nrn_object_new(nrn_symbol("IClamp"), 1); + nrn_property_set(iclamp, "amp", 0.3); + nrn_property_set(iclamp, "del", 1); + nrn_property_set(iclamp, "dur", 0.1); + + // setup recording + Object* v = nrn_object_new(nrn_symbol("Vector"), 0); + nrn_rangevar_push(nrn_symbol("v"), soma, 0.5); + nrn_double_push(5.); + nrn_method_call(v, nrn_method_symbol(v, "record"), 2); + nrn_object_unref(nrn_object_pop()); // record returns the vector + + // finitialize(-65) + nrn_double_push(-65); + nrn_function_call(nrn_symbol("finitialize"), 1); + nrn_double_pop(); + + // continuerun(10) + nrn_double_push(10.5); + nrn_function_call(nrn_symbol("continuerun"), 1); + nrn_double_pop(); + + if (!approximate(EXPECTED_V, v)) { + return 1; + } +} diff --git a/test/api/netcon.cpp b/test/api/netcon.cpp new file mode 100644 index 0000000000..674ae6d0ec --- /dev/null +++ b/test/api/netcon.cpp @@ -0,0 +1,94 @@ +// NOTE: this assumes neuronapi.h is on your CPLUS_INCLUDE_PATH +#include +#include +#include +#include +#include +#include "neuronapi.h" +#include "./test_common.h" + +using std::cout; +using std::endl; +using std::ofstream; + +constexpr std::array EXPECTED_V{ + -0x1.04p+6, + -0x1.085a63d029bc3p+6, + -0x1.112a5e95eb67cp+6, + -0x1.1795abaec26c1p+6, + -0x1.0422351f3f9dcp+6, + -0x1.03e5317ac368cp+6, +}; + +extern "C" void modl_reg(){/* No modl_reg */}; + +int main(void) { + static std::array argv = {"netcon", "-nogui", "-nopython", nullptr}; + nrn_init(3, argv.data()); + + // load the stdrun library + char* temp_str = strdup("stdrun.hoc"); + nrn_str_push(&temp_str); + nrn_function_call(nrn_symbol("load_file"), 1); + nrn_double_pop(); + free(temp_str); + + // topology + auto soma = nrn_section_new("soma"); + + // ion channels + nrn_mechanism_insert(soma, nrn_symbol("hh")); + + // NetStim + auto ns = nrn_object_new(nrn_symbol("NetStim"), 0); + nrn_property_set(ns, "start", 5); + nrn_property_set(ns, "noise", 1); + nrn_property_set(ns, "interval", 5); + nrn_property_set(ns, "number", 10); + + nrn_double_push(1); + nrn_double_push(2); + nrn_double_push(3); + nrn_method_call(ns, nrn_method_symbol(ns, "noiseFromRandom123"), 3); + + // syn = h.ExpSyn(soma(0.5)) + nrn_double_push(0.5); + auto syn = nrn_object_new(nrn_symbol("ExpSyn"), 1); + nrn_property_set(syn, "tau", 3); // 3 ms timeconstant + nrn_property_set(syn, "e", 0); // 0 mV reversal potential (excitatory synapse) + + // nc = h.NetCon(ns, syn) + nrn_object_push(ns); + nrn_object_push(syn); + auto nc = nrn_object_new(nrn_symbol("NetCon"), 2); + nrn_property_array_set(nc, "weight", 0, 0.5); + nrn_property_set(nc, "delay", 0); + + auto vec = nrn_object_new(nrn_symbol("Vector"), 0); + + // nc.record(vec) + nrn_object_push(vec); + nrn_method_call(nc, nrn_method_symbol(nc, "record"), 1); + // TODO: record probably put something on the stack that should be removed + + // setup recording + Object* v = nrn_object_new(nrn_symbol("Vector"), 0); + nrn_rangevar_push(nrn_symbol("v"), soma, 0.5); + nrn_double_push(20); + nrn_method_call(v, nrn_method_symbol(v, "record"), 2); + nrn_object_unref(nrn_object_pop()); // record returns the vector + + // finitialize(-65) + nrn_double_push(-65); + nrn_function_call(nrn_symbol("finitialize"), 1); + nrn_double_pop(); + + // continuerun(100) + nrn_double_push(100.5); + nrn_function_call(nrn_symbol("continuerun"), 1); + nrn_double_pop(); + + if (!approximate(EXPECTED_V, v)) { + return 1; + } +} diff --git a/test/external/CMakeLists.txt b/test/external/CMakeLists.txt index a27aa1ae45..21e1056bee 100644 --- a/test/external/CMakeLists.txt +++ b/test/external/CMakeLists.txt @@ -7,13 +7,13 @@ include(FetchContent) FetchContent_Declare( ringtest GIT_REPOSITORY https://github.com/neuronsimulator/ringtest - GIT_TAG ee24c8 + GIT_TAG 7d1aee72939f6dfcb2a14db4c7b00725d9e485fa SOURCE_DIR ${PROJECT_SOURCE_DIR}/external/tests/ringtest) FetchContent_Declare( testcorenrn GIT_REPOSITORY https://github.com/neuronsimulator/testcorenrn - GIT_TAG 41a6d7ea47551559cc89a71544a746a5d3c2a6b8 + GIT_TAG e53831b3963af8be412e16807a85157e4413f307 SOURCE_DIR ${PROJECT_SOURCE_DIR}/external/tests/testcorenrn) FetchContent_Declare( diff --git a/test/hoc_tests/connect_dend/cell3soma.core.dat.ref b/test/hoc_tests/connect_dend/cell3soma.core.dat.ref deleted file mode 100644 index b0d38144b5..0000000000 --- a/test/hoc_tests/connect_dend/cell3soma.core.dat.ref +++ /dev/null @@ -1,203 +0,0 @@ -t soma.v(0.5) -201 2 - 0 -65 - 0.025 -65.025 - 0.05 -65.0671 - 0.075 -65.1203 - 0.1 -65.1809 - 0.125 -65.2462 - 0.15 -65.3146 - 0.175 -65.3848 - 0.2 -65.4561 - 0.225 -65.5279 - 0.25 -65.5998 - 0.275 -65.6714 - 0.3 -65.7427 - 0.325 -65.8134 - 0.35 -65.8835 - 0.375 -65.9528 - 0.4 -66.0213 - 0.425 -66.0889 - 0.45 -66.1555 - 0.475 -66.2213 - 0.5 -66.286 - 0.525 -66.3497 - 0.55 -66.4124 - 0.575 -66.4741 - 0.6 -66.5348 - 0.625 -66.5944 - 0.65 -66.6529 - 0.675 -66.7104 - 0.7 -66.7669 - 0.725 -66.8223 - 0.75 -66.8766 - 0.775 -66.93 - 0.8 -66.9823 - 0.825 -67.0335 - 0.85 -67.0838 - 0.875 -67.1331 - 0.9 -67.1813 - 0.925 -67.2286 - 0.95 -67.2749 - 0.975 -67.3203 - 1 -67.3647 - 1.025 -67.4081 - 1.05 -67.4507 - 1.075 -67.4923 - 1.1 -67.5331 - 1.125 -67.573 - 1.15 -67.612 - 1.175 -67.6502 - 1.2 -67.6875 - 1.225 -67.724 - 1.25 -67.7597 - 1.275 -67.7946 - 1.3 -67.8287 - 1.325 -67.8621 - 1.35 -67.8947 - 1.375 -67.9265 - 1.4 -67.9577 - 1.425 -67.9881 - 1.45 -68.0178 - 1.475 -68.0469 - 1.5 -68.0753 - 1.525 -68.103 - 1.55 -68.1301 - 1.575 -68.1565 - 1.6 -68.1823 - 1.625 -68.2076 - 1.65 -68.2322 - 1.675 -68.2563 - 1.7 -68.2797 - 1.725 -68.3027 - 1.75 -68.325 - 1.775 -68.3469 - 1.8 -68.3682 - 1.825 -68.389 - 1.85 -68.4093 - 1.875 -68.4291 - 1.9 -68.4485 - 1.925 -68.4673 - 1.95 -68.4858 - 1.975 -68.5037 - 2 -68.5212 - 2.025 -68.5383 - 2.05 -68.555 - 2.075 -68.5712 - 2.1 -68.5871 - 2.125 -68.6026 - 2.15 -68.6176 - 2.175 -68.6323 - 2.2 -68.6467 - 2.225 -68.6606 - 2.25 -68.6743 - 2.275 -68.6875 - 2.3 -68.7005 - 2.325 -68.7131 - 2.35 -68.7254 - 2.375 -68.7374 - 2.4 -68.749 - 2.425 -68.7604 - 2.45 -68.7715 - 2.475 -68.7823 - 2.5 -68.7928 - 2.525 -68.803 - 2.55 -68.813 - 2.575 -68.8227 - 2.6 -68.8321 - 2.625 -68.8413 - 2.65 -68.8503 - 2.675 -68.859 - 2.7 -68.8675 - 2.725 -68.8758 - 2.75 -68.8838 - 2.775 -68.8916 - 2.8 -68.8992 - 2.825 -68.9066 - 2.85 -68.9139 - 2.875 -68.9209 - 2.9 -68.9277 - 2.925 -68.9343 - 2.95 -68.9407 - 2.975 -68.947 - 3 -68.9531 - 3.025 -68.959 - 3.05 -68.9648 - 3.075 -68.9703 - 3.1 -68.9758 - 3.125 -68.981 - 3.15 -68.9862 - 3.175 -68.9911 - 3.2 -68.996 - 3.225 -69.0007 - 3.25 -69.0052 - 3.275 -69.0096 - 3.3 -69.0139 - 3.325 -69.0181 - 3.35 -69.0221 - 3.375 -69.026 - 3.4 -69.0298 - 3.425 -69.0335 - 3.45 -69.037 - 3.475 -69.0405 - 3.5 -69.0438 - 3.525 -69.0471 - 3.55 -69.0502 - 3.575 -69.0532 - 3.6 -69.0562 - 3.625 -69.059 - 3.65 -69.0617 - 3.675 -69.0644 - 3.7 -69.067 - 3.725 -69.0694 - 3.75 -69.0718 - 3.775 -69.0741 - 3.8 -69.0764 - 3.825 -69.0785 - 3.85 -69.0806 - 3.875 -69.0826 - 3.9 -69.0845 - 3.925 -69.0864 - 3.95 -69.0882 - 3.975 -69.0899 - 4 -69.0916 - 4.025 -69.0932 - 4.05 -69.0947 - 4.075 -69.0962 - 4.1 -69.0976 - 4.125 -69.0989 - 4.15 -69.1002 - 4.175 -69.1015 - 4.2 -69.1027 - 4.225 -69.1038 - 4.25 -69.1049 - 4.275 -69.1059 - 4.3 -69.1069 - 4.325 -69.1078 - 4.35 -69.1087 - 4.375 -69.1096 - 4.4 -69.1104 - 4.425 -69.1112 - 4.45 -69.1119 - 4.475 -69.1126 - 4.5 -69.1132 - 4.525 -69.1138 - 4.55 -69.1144 - 4.575 -69.1149 - 4.6 -69.1154 - 4.625 -69.1159 - 4.65 -69.1163 - 4.675 -69.1167 - 4.7 -69.117 - 4.725 -69.1174 - 4.75 -69.1177 - 4.775 -69.118 - 4.8 -69.1182 - 4.825 -69.1184 - 4.85 -69.1186 - 4.875 -69.1188 - 4.9 -69.1189 - 4.925 -69.119 - 4.95 -69.1191 - 4.975 -69.1192 - 5 -69.1192