use nml2::{
acc::{self, Decor, Sexp},
bundle::{build_super_mechanisms, Cell, CellData},
error::Result,
instance::Instance,
lems::file::LemsFile,
neuroml::{self, raw::BiophysicalProperties},
nmodl,
xml::XML,
Map,
};
use pretty_assertions::assert_eq;
use roxmltree::Document;
#[test]
fn acc_biophys() {
let known_ions = vec![String::from("ca"), String::from("k"), String::from("na")];
let lems = LemsFile::core();
let tree = Document::parse(
r#"
"#).unwrap();
let node = &tree
.descendants()
.find(|n| n.has_tag_name("biophysicalProperties"))
.unwrap();
let prop: neuroml::raw::BiophysicalProperties = XML::from_node(node);
let result = acc::biophys(&prop, &lems, &known_ions, &Default::default());
assert!(result.is_ok());
let mut result = result.unwrap();
result.decor.sort_by(|a, b| a.partial_cmp(b).unwrap());
let mut expect = vec![
Decor::mechanism(
"all",
"naChan",
&Map::from([(String::from("conductance"), String::from("0.12"))]),
),
Decor::mechanism(
"all",
"kChan",
&Map::from([(String::from("conductance"), String::from("0.036"))]),
),
Decor::mechanism(
"all",
"passiveChan",
&Map::from([
(String::from("conductance"), String::from("0.0003")),
(String::from("e"), String::from("-54.29999923706055")),
]),
),
Decor::er("all", "na", "50"),
Decor::er("all", "k", "-77"),
Decor::cm("all", "0.01"),
Decor::vm("all", "-65"),
Decor::ra("all", "29.999999329447746"),
];
expect.sort_by(|a, b| a.partial_cmp(b).unwrap());
assert_eq!(result.decor, expect);
}
#[test]
fn acc_super() {
let known_ions = vec![String::from("ca"), String::from("k"), String::from("na")];
let lems = LemsFile::core();
let tree = Document::parse(
r#"
|
"#).unwrap();
let node = &tree
.descendants()
.find(|n| n.has_tag_name("biophysicalProperties"))
.unwrap();
let props: Map =
Map::from([("cell".to_string(), XML::from_node(node))]);
let ins = tree
.descendants()
.filter(|n| lems.derived_from(n.tag_name().name(), "baseIonChannel"))
.map(|n| Instance::new(&lems, &n))
.collect::>>()
.unwrap();
assert_eq!(ins.len(), 3);
let data = CellData {
bio_phys: props,
density: ins,
synapse: vec![],
c_model: vec![],
i_param: Map::from([("cell".to_string(), Map::new())]),
};
let cells = build_super_mechanisms(&data, &lems, &known_ions[..]).unwrap();
assert_eq!(cells.len(), 1);
let Cell { decor, channels } = &cells["cell"];
assert_eq!(
decor.to_sexp(),
"(arbor-component
(meta-data (version \"0.9-dev\"))
(decor
(paint (region \"all\") (density (mechanism \"cell_all\" )))
(default (ion-reversal-potential \"na\" 50 (scalar 1)))
(default (ion-reversal-potential \"k\" -77 (scalar 1)))
(default (membrane-capacitance 0.01 (scalar 1)))
(default (membrane-potential -65 (scalar 1)))
(default (axial-resistivity 29.999999329447746 (scalar 1)))))
"
);
assert_eq!(channels.len(), 1);
let (rg, ch) = &channels[0];
assert_eq!(rg, "all");
let ch = nmodl::mk_nmodl(ch.clone()).unwrap();
assert_eq!(
ch,
r#"NEURON {
SUFFIX cell_all
USEION k WRITE ik READ ek
USEION na WRITE ina READ ena
NONSPECIFIC_CURRENT i
}
STATE { kChan_gates_n_q naChan_gates_h_q naChan_gates_m_q }
INITIAL {
LOCAL naChan_gates_m_reverseRate_r, naChan_gates_m_forwardRate_x, naChan_gates_m_forwardRate_r, naChan_gates_m_inf, naChan_gates_h_forwardRate_r, naChan_gates_h_reverseRate_r, naChan_gates_h_inf, kChan_gates_n_reverseRate_r, kChan_gates_n_forwardRate_x, kChan_gates_n_forwardRate_r, kChan_gates_n_inf
naChan_gates_m_reverseRate_r = 4 * exp(-0.05555555555555555 * (65 + v))
naChan_gates_m_forwardRate_x = 0.1 * (40 + v)
if (naChan_gates_m_forwardRate_x != 0) {
naChan_gates_m_forwardRate_r = naChan_gates_m_forwardRate_x * (1 + -1 * exp(-1 * naChan_gates_m_forwardRate_x))^-1
} else {
naChan_gates_m_forwardRate_r = 1
}
naChan_gates_m_inf = naChan_gates_m_forwardRate_r * (naChan_gates_m_forwardRate_r + naChan_gates_m_reverseRate_r)^-1
naChan_gates_h_forwardRate_r = 0.07000000029802322 * exp(-0.05 * (65 + v))
naChan_gates_h_reverseRate_r = (1 + exp(-0.1 * (35 + v)))^-1
naChan_gates_h_inf = naChan_gates_h_forwardRate_r * (naChan_gates_h_forwardRate_r + naChan_gates_h_reverseRate_r)^-1
kChan_gates_n_reverseRate_r = 0.125 * exp(-0.0125 * (65 + v))
kChan_gates_n_forwardRate_x = 0.1 * (55 + v)
if (kChan_gates_n_forwardRate_x != 0) {
kChan_gates_n_forwardRate_r = 0.10000000149011612 * kChan_gates_n_forwardRate_x * (1 + -1 * exp(-1 * kChan_gates_n_forwardRate_x))^-1
} else {
kChan_gates_n_forwardRate_r = 0.10000000149011612
}
kChan_gates_n_inf = kChan_gates_n_forwardRate_r * (kChan_gates_n_forwardRate_r + kChan_gates_n_reverseRate_r)^-1
kChan_gates_n_q = kChan_gates_n_inf
naChan_gates_h_q = naChan_gates_h_inf
naChan_gates_m_q = naChan_gates_m_inf
}
DERIVATIVE dstate {
LOCAL naChan_gates_m_reverseRate_r, naChan_gates_m_forwardRate_x, naChan_gates_m_forwardRate_r, naChan_gates_m_inf, naChan_gates_m_tau, naChan_gates_h_forwardRate_r, naChan_gates_h_reverseRate_r, naChan_gates_h_inf, naChan_gates_h_tau, kChan_gates_n_reverseRate_r, kChan_gates_n_forwardRate_x, kChan_gates_n_forwardRate_r, kChan_gates_n_inf, kChan_gates_n_tau
naChan_gates_m_reverseRate_r = 4 * exp(-0.05555555555555555 * (65 + v))
naChan_gates_m_forwardRate_x = 0.1 * (40 + v)
if (naChan_gates_m_forwardRate_x != 0) {
naChan_gates_m_forwardRate_r = naChan_gates_m_forwardRate_x * (1 + -1 * exp(-1 * naChan_gates_m_forwardRate_x))^-1
} else {
naChan_gates_m_forwardRate_r = 1
}
naChan_gates_m_inf = naChan_gates_m_forwardRate_r * (naChan_gates_m_forwardRate_r + naChan_gates_m_reverseRate_r)^-1
naChan_gates_m_tau = (naChan_gates_m_forwardRate_r + naChan_gates_m_reverseRate_r)^-1
naChan_gates_h_forwardRate_r = 0.07000000029802322 * exp(-0.05 * (65 + v))
naChan_gates_h_reverseRate_r = (1 + exp(-0.1 * (35 + v)))^-1
naChan_gates_h_inf = naChan_gates_h_forwardRate_r * (naChan_gates_h_forwardRate_r + naChan_gates_h_reverseRate_r)^-1
naChan_gates_h_tau = (naChan_gates_h_forwardRate_r + naChan_gates_h_reverseRate_r)^-1
kChan_gates_n_reverseRate_r = 0.125 * exp(-0.0125 * (65 + v))
kChan_gates_n_forwardRate_x = 0.1 * (55 + v)
if (kChan_gates_n_forwardRate_x != 0) {
kChan_gates_n_forwardRate_r = 0.10000000149011612 * kChan_gates_n_forwardRate_x * (1 + -1 * exp(-1 * kChan_gates_n_forwardRate_x))^-1
} else {
kChan_gates_n_forwardRate_r = 0.10000000149011612
}
kChan_gates_n_inf = kChan_gates_n_forwardRate_r * (kChan_gates_n_forwardRate_r + kChan_gates_n_reverseRate_r)^-1
kChan_gates_n_tau = (kChan_gates_n_forwardRate_r + kChan_gates_n_reverseRate_r)^-1
kChan_gates_n_q' = (kChan_gates_n_inf + -1 * kChan_gates_n_q) * kChan_gates_n_tau^-1
naChan_gates_h_q' = (naChan_gates_h_inf + -1 * naChan_gates_h_q) * naChan_gates_h_tau^-1
naChan_gates_m_q' = (naChan_gates_m_inf + -1 * naChan_gates_m_q) * naChan_gates_m_tau^-1
}
BREAKPOINT {
SOLVE dstate METHOD cnexp
LOCAL naChan_gates_m_fcond, naChan_fopen0, naChan_g, g_na, kChan_gates_n_fcond, kChan_g, g_k
naChan_gates_m_fcond = naChan_gates_m_q * naChan_gates_m_q * naChan_gates_m_q
naChan_fopen0 = naChan_gates_h_q * naChan_gates_m_fcond
naChan_g = 0.12 * naChan_fopen0
g_na = naChan_g
kChan_gates_n_fcond = kChan_gates_n_q * kChan_gates_n_q * kChan_gates_n_q * kChan_gates_n_q
kChan_g = 0.036 * kChan_gates_n_fcond
g_k = kChan_g
i = 0.0003 * (54.29999923706055 + v)
ik = g_k * (v + -1 * ek)
ina = g_na * (v + -1 * ena)
}
"#
);
}
#[test]
fn acc_super_non_specific() {
let known_ions = vec![String::from("ca"), String::from("k"), String::from("na")];
let lems = LemsFile::core();
let tree = Document::parse(
r#"
|
"#).unwrap();
let node = &tree
.descendants()
.find(|n| n.has_tag_name("biophysicalProperties"))
.unwrap();
let props: Map =
Map::from([("cell".to_string(), XML::from_node(node))]);
let ins = tree
.descendants()
.filter(|n| lems.derived_from(n.tag_name().name(), "baseIonChannel"))
.map(|n| Instance::new(&lems, &n))
.collect::>>()
.unwrap();
assert_eq!(ins.len(), 3);
let data = CellData {
bio_phys: props,
density: ins,
synapse: vec![],
c_model: vec![],
i_param: Map::from([("cell".to_string(), Map::new())]),
};
let cells = build_super_mechanisms(&data, &lems, &known_ions[..]).unwrap();
assert_eq!(cells.len(), 1);
let Cell { decor, channels } = &cells["cell"];
assert_eq!(
decor.to_sexp(),
"(arbor-component
(meta-data (version \"0.9-dev\"))
(decor
(paint (region \"all\") (density (mechanism \"cell_all\" )))
(default (ion-reversal-potential \"na\" 50 (scalar 1)))
(default (ion-reversal-potential \"k\" -77 (scalar 1)))
(default (membrane-capacitance 0.01 (scalar 1)))
(default (membrane-potential -65 (scalar 1)))
(default (axial-resistivity 29.999999329447746 (scalar 1)))))
"
);
assert_eq!(channels.len(), 1);
let (rg, ch) = &channels[0];
assert_eq!(rg, "all");
let ch = nmodl::mk_nmodl(ch.clone()).unwrap();
assert_eq!(
ch,
"NEURON {
SUFFIX cell_all
USEION k WRITE ik READ ek
NONSPECIFIC_CURRENT i
}
STATE { kChan_gates_n_q naChan_gates_h_q naChan_gates_m_q }
INITIAL {
LOCAL naChan_gates_m_reverseRate_r, naChan_gates_m_forwardRate_x, naChan_gates_m_forwardRate_r, naChan_gates_m_inf, naChan_gates_h_forwardRate_r, naChan_gates_h_reverseRate_r, naChan_gates_h_inf, kChan_gates_n_reverseRate_r, kChan_gates_n_forwardRate_x, kChan_gates_n_forwardRate_r, kChan_gates_n_inf
naChan_gates_m_reverseRate_r = 4 * exp(-0.05555555555555555 * (65 + v))
naChan_gates_m_forwardRate_x = 0.1 * (40 + v)
if (naChan_gates_m_forwardRate_x != 0) {
naChan_gates_m_forwardRate_r = naChan_gates_m_forwardRate_x * (1 + -1 * exp(-1 * naChan_gates_m_forwardRate_x))^-1
} else {
naChan_gates_m_forwardRate_r = 1
}
naChan_gates_m_inf = naChan_gates_m_forwardRate_r * (naChan_gates_m_forwardRate_r + naChan_gates_m_reverseRate_r)^-1
naChan_gates_h_forwardRate_r = 0.07000000029802322 * exp(-0.05 * (65 + v))
naChan_gates_h_reverseRate_r = (1 + exp(-0.1 * (35 + v)))^-1
naChan_gates_h_inf = naChan_gates_h_forwardRate_r * (naChan_gates_h_forwardRate_r + naChan_gates_h_reverseRate_r)^-1
kChan_gates_n_reverseRate_r = 0.125 * exp(-0.0125 * (65 + v))
kChan_gates_n_forwardRate_x = 0.1 * (55 + v)
if (kChan_gates_n_forwardRate_x != 0) {
kChan_gates_n_forwardRate_r = 0.10000000149011612 * kChan_gates_n_forwardRate_x * (1 + -1 * exp(-1 * kChan_gates_n_forwardRate_x))^-1
} else {
kChan_gates_n_forwardRate_r = 0.10000000149011612
}
kChan_gates_n_inf = kChan_gates_n_forwardRate_r * (kChan_gates_n_forwardRate_r + kChan_gates_n_reverseRate_r)^-1
kChan_gates_n_q = kChan_gates_n_inf
naChan_gates_h_q = naChan_gates_h_inf
naChan_gates_m_q = naChan_gates_m_inf
}
DERIVATIVE dstate {
LOCAL naChan_gates_m_reverseRate_r, naChan_gates_m_forwardRate_x, naChan_gates_m_forwardRate_r, naChan_gates_m_inf, naChan_gates_m_tau, naChan_gates_h_forwardRate_r, naChan_gates_h_reverseRate_r, naChan_gates_h_inf, naChan_gates_h_tau, kChan_gates_n_reverseRate_r, kChan_gates_n_forwardRate_x, kChan_gates_n_forwardRate_r, kChan_gates_n_inf, kChan_gates_n_tau
naChan_gates_m_reverseRate_r = 4 * exp(-0.05555555555555555 * (65 + v))
naChan_gates_m_forwardRate_x = 0.1 * (40 + v)
if (naChan_gates_m_forwardRate_x != 0) {
naChan_gates_m_forwardRate_r = naChan_gates_m_forwardRate_x * (1 + -1 * exp(-1 * naChan_gates_m_forwardRate_x))^-1
} else {
naChan_gates_m_forwardRate_r = 1
}
naChan_gates_m_inf = naChan_gates_m_forwardRate_r * (naChan_gates_m_forwardRate_r + naChan_gates_m_reverseRate_r)^-1
naChan_gates_m_tau = (naChan_gates_m_forwardRate_r + naChan_gates_m_reverseRate_r)^-1
naChan_gates_h_forwardRate_r = 0.07000000029802322 * exp(-0.05 * (65 + v))
naChan_gates_h_reverseRate_r = (1 + exp(-0.1 * (35 + v)))^-1
naChan_gates_h_inf = naChan_gates_h_forwardRate_r * (naChan_gates_h_forwardRate_r + naChan_gates_h_reverseRate_r)^-1
naChan_gates_h_tau = (naChan_gates_h_forwardRate_r + naChan_gates_h_reverseRate_r)^-1
kChan_gates_n_reverseRate_r = 0.125 * exp(-0.0125 * (65 + v))
kChan_gates_n_forwardRate_x = 0.1 * (55 + v)
if (kChan_gates_n_forwardRate_x != 0) {
kChan_gates_n_forwardRate_r = 0.10000000149011612 * kChan_gates_n_forwardRate_x * (1 + -1 * exp(-1 * kChan_gates_n_forwardRate_x))^-1
} else {
kChan_gates_n_forwardRate_r = 0.10000000149011612
}
kChan_gates_n_inf = kChan_gates_n_forwardRate_r * (kChan_gates_n_forwardRate_r + kChan_gates_n_reverseRate_r)^-1
kChan_gates_n_tau = (kChan_gates_n_forwardRate_r + kChan_gates_n_reverseRate_r)^-1
kChan_gates_n_q' = (kChan_gates_n_inf + -1 * kChan_gates_n_q) * kChan_gates_n_tau^-1
naChan_gates_h_q' = (naChan_gates_h_inf + -1 * naChan_gates_h_q) * naChan_gates_h_tau^-1
naChan_gates_m_q' = (naChan_gates_m_inf + -1 * naChan_gates_m_q) * naChan_gates_m_tau^-1
}
BREAKPOINT {
SOLVE dstate METHOD cnexp
LOCAL kChan_gates_n_fcond, kChan_g, g_k, naChan_gates_m_fcond, naChan_fopen0, naChan_g
kChan_gates_n_fcond = kChan_gates_n_q * kChan_gates_n_q * kChan_gates_n_q * kChan_gates_n_q
kChan_g = 0.036 * kChan_gates_n_fcond
g_k = kChan_g
naChan_gates_m_fcond = naChan_gates_m_q * naChan_gates_m_q * naChan_gates_m_q
naChan_fopen0 = naChan_gates_h_q * naChan_gates_m_fcond
naChan_g = 0.12 * naChan_fopen0
i = 0.0003 * (54.29999923706055 + v) + naChan_g * (-50 + v)
ik = g_k * (v + -1 * ek)
}
"
);
}
#[test]
fn acc_super_conc_model() {
let known_ions = vec![String::from("ca"), String::from("k"), String::from("na")];
let lems = LemsFile::core();
let tree = Document::parse(
r#"
|
"#).unwrap();
let node = &tree
.descendants()
.find(|n| n.has_tag_name("biophysicalProperties"))
.unwrap();
let props: Map =
Map::from([("cell".to_string(), XML::from_node(node))]);
let ich = tree
.descendants()
.filter(|n| lems.derived_from(n.tag_name().name(), "baseIonChannel"))
.map(|n| Instance::new(&lems, &n))
.collect::>>()
.unwrap();
assert_eq!(ich.len(), 3);
let ccm = tree
.descendants()
.filter(|n| lems.derived_from(n.tag_name().name(), "concentrationModel"))
.map(|n| Instance::new(&lems, &n))
.collect::>>()
.unwrap();
assert_eq!(ccm.len(), 1);
let data = CellData {
bio_phys: props,
density: ich,
synapse: vec![],
c_model: ccm,
i_param: Map::from([("cell".to_string(), Map::new())]),
};
let cells = build_super_mechanisms(&data, &lems, &known_ions[..]).unwrap();
assert_eq!(cells.len(), 1);
let Cell { decor, channels } = &cells["cell"];
assert_eq!(
decor.to_sexp(),
"(arbor-component
(meta-data (version \"0.9-dev\"))
(decor
(paint (region \"all\") (density (mechanism \"cell_all\" )))
(default (ion-reversal-potential \"na\" 50 (scalar 1)))
(default (ion-reversal-potential \"k\" -77 (scalar 1)))
(default (membrane-capacitance 0.01 (scalar 1)))
(default (membrane-potential -65 (scalar 1)))
(default (axial-resistivity 29.999999329447746 (scalar 1)))
(default (ion-internal-concentration \"ca\" 0.0000500000006675716 (scalar 1)))
(default (ion-external-concentration \"ca\" 1.9999999949504854 (scalar 1)))
(paint (region \"all\") (density (mechanism \"CaDynamics_E2_NML2\" (\"initialConcentration\" 0.0000500000006675716))))))
"
);
assert_eq!(channels.len(), 1);
let (rg, ch) = &channels[0];
assert_eq!(rg, "all");
let ch = nmodl::mk_nmodl(ch.clone()).unwrap();
assert_eq!(ch,
"NEURON {
SUFFIX cell_all
USEION k WRITE ik READ ek
NONSPECIFIC_CURRENT i
}
STATE { kChan_gates_n_q naChan_gates_h_q naChan_gates_m_q }
INITIAL {
LOCAL naChan_gates_m_reverseRate_r, naChan_gates_m_forwardRate_x, naChan_gates_m_forwardRate_r, naChan_gates_m_inf, naChan_gates_h_forwardRate_r, naChan_gates_h_reverseRate_r, naChan_gates_h_inf, kChan_gates_n_reverseRate_r, kChan_gates_n_forwardRate_x, kChan_gates_n_forwardRate_r, kChan_gates_n_inf
naChan_gates_m_reverseRate_r = 4 * exp(-0.05555555555555555 * (65 + v))
naChan_gates_m_forwardRate_x = 0.1 * (40 + v)
if (naChan_gates_m_forwardRate_x != 0) {
naChan_gates_m_forwardRate_r = naChan_gates_m_forwardRate_x * (1 + -1 * exp(-1 * naChan_gates_m_forwardRate_x))^-1
} else {
naChan_gates_m_forwardRate_r = 1
}
naChan_gates_m_inf = naChan_gates_m_forwardRate_r * (naChan_gates_m_forwardRate_r + naChan_gates_m_reverseRate_r)^-1
naChan_gates_h_forwardRate_r = 0.07000000029802322 * exp(-0.05 * (65 + v))
naChan_gates_h_reverseRate_r = (1 + exp(-0.1 * (35 + v)))^-1
naChan_gates_h_inf = naChan_gates_h_forwardRate_r * (naChan_gates_h_forwardRate_r + naChan_gates_h_reverseRate_r)^-1
kChan_gates_n_reverseRate_r = 0.125 * exp(-0.0125 * (65 + v))
kChan_gates_n_forwardRate_x = 0.1 * (55 + v)
if (kChan_gates_n_forwardRate_x != 0) {
kChan_gates_n_forwardRate_r = 0.10000000149011612 * kChan_gates_n_forwardRate_x * (1 + -1 * exp(-1 * kChan_gates_n_forwardRate_x))^-1
} else {
kChan_gates_n_forwardRate_r = 0.10000000149011612
}
kChan_gates_n_inf = kChan_gates_n_forwardRate_r * (kChan_gates_n_forwardRate_r + kChan_gates_n_reverseRate_r)^-1
kChan_gates_n_q = kChan_gates_n_inf
naChan_gates_h_q = naChan_gates_h_inf
naChan_gates_m_q = naChan_gates_m_inf
}
DERIVATIVE dstate {
LOCAL naChan_gates_m_reverseRate_r, naChan_gates_m_forwardRate_x, naChan_gates_m_forwardRate_r, naChan_gates_m_inf, naChan_gates_m_tau, naChan_gates_h_forwardRate_r, naChan_gates_h_reverseRate_r, naChan_gates_h_inf, naChan_gates_h_tau, kChan_gates_n_reverseRate_r, kChan_gates_n_forwardRate_x, kChan_gates_n_forwardRate_r, kChan_gates_n_inf, kChan_gates_n_tau
naChan_gates_m_reverseRate_r = 4 * exp(-0.05555555555555555 * (65 + v))
naChan_gates_m_forwardRate_x = 0.1 * (40 + v)
if (naChan_gates_m_forwardRate_x != 0) {
naChan_gates_m_forwardRate_r = naChan_gates_m_forwardRate_x * (1 + -1 * exp(-1 * naChan_gates_m_forwardRate_x))^-1
} else {
naChan_gates_m_forwardRate_r = 1
}
naChan_gates_m_inf = naChan_gates_m_forwardRate_r * (naChan_gates_m_forwardRate_r + naChan_gates_m_reverseRate_r)^-1
naChan_gates_m_tau = (naChan_gates_m_forwardRate_r + naChan_gates_m_reverseRate_r)^-1
naChan_gates_h_forwardRate_r = 0.07000000029802322 * exp(-0.05 * (65 + v))
naChan_gates_h_reverseRate_r = (1 + exp(-0.1 * (35 + v)))^-1
naChan_gates_h_inf = naChan_gates_h_forwardRate_r * (naChan_gates_h_forwardRate_r + naChan_gates_h_reverseRate_r)^-1
naChan_gates_h_tau = (naChan_gates_h_forwardRate_r + naChan_gates_h_reverseRate_r)^-1
kChan_gates_n_reverseRate_r = 0.125 * exp(-0.0125 * (65 + v))
kChan_gates_n_forwardRate_x = 0.1 * (55 + v)
if (kChan_gates_n_forwardRate_x != 0) {
kChan_gates_n_forwardRate_r = 0.10000000149011612 * kChan_gates_n_forwardRate_x * (1 + -1 * exp(-1 * kChan_gates_n_forwardRate_x))^-1
} else {
kChan_gates_n_forwardRate_r = 0.10000000149011612
}
kChan_gates_n_inf = kChan_gates_n_forwardRate_r * (kChan_gates_n_forwardRate_r + kChan_gates_n_reverseRate_r)^-1
kChan_gates_n_tau = (kChan_gates_n_forwardRate_r + kChan_gates_n_reverseRate_r)^-1
kChan_gates_n_q' = (kChan_gates_n_inf + -1 * kChan_gates_n_q) * kChan_gates_n_tau^-1
naChan_gates_h_q' = (naChan_gates_h_inf + -1 * naChan_gates_h_q) * naChan_gates_h_tau^-1
naChan_gates_m_q' = (naChan_gates_m_inf + -1 * naChan_gates_m_q) * naChan_gates_m_tau^-1
}
BREAKPOINT {
SOLVE dstate METHOD cnexp
LOCAL kChan_gates_n_fcond, kChan_g, g_k, naChan_gates_m_fcond, naChan_fopen0, naChan_g
kChan_gates_n_fcond = kChan_gates_n_q * kChan_gates_n_q * kChan_gates_n_q * kChan_gates_n_q
kChan_g = 0.036 * kChan_gates_n_fcond
g_k = kChan_g
naChan_gates_m_fcond = naChan_gates_m_q * naChan_gates_m_q * naChan_gates_m_q
naChan_fopen0 = naChan_gates_h_q * naChan_gates_m_fcond
naChan_g = 0.12 * naChan_fopen0
i = 0.0003 * (54.29999923706055 + v) + naChan_g * (-50 + v)
ik = g_k * (v + -1 * ek)
}
"
);
}
#[test]
fn acc_super_nernst() {
let known_ions = vec![String::from("ca"), String::from("k"), String::from("na")];
let lems = LemsFile::core();
let tree = Document::parse(
r#"
|
"#).unwrap();
let node = &tree
.descendants()
.find(|n| n.has_tag_name("biophysicalProperties"))
.unwrap();
let props: Map =
Map::from([("cell".to_string(), XML::from_node(node))]);
let ins = tree
.descendants()
.filter(|n| lems.derived_from(n.tag_name().name(), "baseIonChannel"))
.map(|n| Instance::new(&lems, &n))
.collect::>>()
.unwrap();
assert_eq!(ins.len(), 3);
let data = CellData {
bio_phys: props,
density: ins,
synapse: vec![],
c_model: vec![],
i_param: Map::from([("cell".to_string(), Map::new())]),
};
let cells = build_super_mechanisms(&data, &lems, &known_ions[..]).unwrap();
assert_eq!(cells.len(), 1);
let Cell { decor, channels } = &cells["cell"];
assert_eq!(
decor.to_sexp(),
"(arbor-component
(meta-data (version \"0.9-dev\"))
(decor
(paint (region \"all\") (density (mechanism \"cell_all\" )))
(default (ion-reversal-potential \"na\" 50 (scalar 1)))
(default (ion-reversal-potential-method \"k\" (mechanism \"nernst/k\")))
(default (membrane-capacitance 0.01 (scalar 1)))
(default (membrane-potential -65 (scalar 1)))
(default (axial-resistivity 29.999999329447746 (scalar 1)))))
"
);
assert_eq!(channels.len(), 1);
let (rg, ch) = &channels[0];
assert_eq!(rg, "all");
let ch = nmodl::mk_nmodl(ch.clone()).unwrap();
assert_eq!(
ch,
r#"NEURON {
SUFFIX cell_all
USEION k WRITE ik READ ek
USEION na WRITE ina READ ena
NONSPECIFIC_CURRENT i
}
STATE { kChan_gates_n_q naChan_gates_h_q naChan_gates_m_q }
INITIAL {
LOCAL naChan_gates_m_reverseRate_r, naChan_gates_m_forwardRate_x, naChan_gates_m_forwardRate_r, naChan_gates_m_inf, naChan_gates_h_forwardRate_r, naChan_gates_h_reverseRate_r, naChan_gates_h_inf, kChan_gates_n_reverseRate_r, kChan_gates_n_forwardRate_x, kChan_gates_n_forwardRate_r, kChan_gates_n_inf
naChan_gates_m_reverseRate_r = 4 * exp(-0.05555555555555555 * (65 + v))
naChan_gates_m_forwardRate_x = 0.1 * (40 + v)
if (naChan_gates_m_forwardRate_x != 0) {
naChan_gates_m_forwardRate_r = naChan_gates_m_forwardRate_x * (1 + -1 * exp(-1 * naChan_gates_m_forwardRate_x))^-1
} else {
naChan_gates_m_forwardRate_r = 1
}
naChan_gates_m_inf = naChan_gates_m_forwardRate_r * (naChan_gates_m_forwardRate_r + naChan_gates_m_reverseRate_r)^-1
naChan_gates_h_forwardRate_r = 0.07000000029802322 * exp(-0.05 * (65 + v))
naChan_gates_h_reverseRate_r = (1 + exp(-0.1 * (35 + v)))^-1
naChan_gates_h_inf = naChan_gates_h_forwardRate_r * (naChan_gates_h_forwardRate_r + naChan_gates_h_reverseRate_r)^-1
kChan_gates_n_reverseRate_r = 0.125 * exp(-0.0125 * (65 + v))
kChan_gates_n_forwardRate_x = 0.1 * (55 + v)
if (kChan_gates_n_forwardRate_x != 0) {
kChan_gates_n_forwardRate_r = 0.10000000149011612 * kChan_gates_n_forwardRate_x * (1 + -1 * exp(-1 * kChan_gates_n_forwardRate_x))^-1
} else {
kChan_gates_n_forwardRate_r = 0.10000000149011612
}
kChan_gates_n_inf = kChan_gates_n_forwardRate_r * (kChan_gates_n_forwardRate_r + kChan_gates_n_reverseRate_r)^-1
kChan_gates_n_q = kChan_gates_n_inf
naChan_gates_h_q = naChan_gates_h_inf
naChan_gates_m_q = naChan_gates_m_inf
}
DERIVATIVE dstate {
LOCAL naChan_gates_m_reverseRate_r, naChan_gates_m_forwardRate_x, naChan_gates_m_forwardRate_r, naChan_gates_m_inf, naChan_gates_m_tau, naChan_gates_h_forwardRate_r, naChan_gates_h_reverseRate_r, naChan_gates_h_inf, naChan_gates_h_tau, kChan_gates_n_reverseRate_r, kChan_gates_n_forwardRate_x, kChan_gates_n_forwardRate_r, kChan_gates_n_inf, kChan_gates_n_tau
naChan_gates_m_reverseRate_r = 4 * exp(-0.05555555555555555 * (65 + v))
naChan_gates_m_forwardRate_x = 0.1 * (40 + v)
if (naChan_gates_m_forwardRate_x != 0) {
naChan_gates_m_forwardRate_r = naChan_gates_m_forwardRate_x * (1 + -1 * exp(-1 * naChan_gates_m_forwardRate_x))^-1
} else {
naChan_gates_m_forwardRate_r = 1
}
naChan_gates_m_inf = naChan_gates_m_forwardRate_r * (naChan_gates_m_forwardRate_r + naChan_gates_m_reverseRate_r)^-1
naChan_gates_m_tau = (naChan_gates_m_forwardRate_r + naChan_gates_m_reverseRate_r)^-1
naChan_gates_h_forwardRate_r = 0.07000000029802322 * exp(-0.05 * (65 + v))
naChan_gates_h_reverseRate_r = (1 + exp(-0.1 * (35 + v)))^-1
naChan_gates_h_inf = naChan_gates_h_forwardRate_r * (naChan_gates_h_forwardRate_r + naChan_gates_h_reverseRate_r)^-1
naChan_gates_h_tau = (naChan_gates_h_forwardRate_r + naChan_gates_h_reverseRate_r)^-1
kChan_gates_n_reverseRate_r = 0.125 * exp(-0.0125 * (65 + v))
kChan_gates_n_forwardRate_x = 0.1 * (55 + v)
if (kChan_gates_n_forwardRate_x != 0) {
kChan_gates_n_forwardRate_r = 0.10000000149011612 * kChan_gates_n_forwardRate_x * (1 + -1 * exp(-1 * kChan_gates_n_forwardRate_x))^-1
} else {
kChan_gates_n_forwardRate_r = 0.10000000149011612
}
kChan_gates_n_inf = kChan_gates_n_forwardRate_r * (kChan_gates_n_forwardRate_r + kChan_gates_n_reverseRate_r)^-1
kChan_gates_n_tau = (kChan_gates_n_forwardRate_r + kChan_gates_n_reverseRate_r)^-1
kChan_gates_n_q' = (kChan_gates_n_inf + -1 * kChan_gates_n_q) * kChan_gates_n_tau^-1
naChan_gates_h_q' = (naChan_gates_h_inf + -1 * naChan_gates_h_q) * naChan_gates_h_tau^-1
naChan_gates_m_q' = (naChan_gates_m_inf + -1 * naChan_gates_m_q) * naChan_gates_m_tau^-1
}
BREAKPOINT {
SOLVE dstate METHOD cnexp
LOCAL naChan_gates_m_fcond, naChan_fopen0, naChan_g, g_na, kChan_gates_n_fcond, kChan_g, g_k
naChan_gates_m_fcond = naChan_gates_m_q * naChan_gates_m_q * naChan_gates_m_q
naChan_fopen0 = naChan_gates_h_q * naChan_gates_m_fcond
naChan_g = 0.12 * naChan_fopen0
g_na = naChan_g
kChan_gates_n_fcond = kChan_gates_n_q * kChan_gates_n_q * kChan_gates_n_q * kChan_gates_n_q
kChan_g = 0.036 * kChan_gates_n_fcond
g_k = kChan_g
i = 0.0003 * (54.29999923706055 + v)
ik = g_k * (v + -1 * ek)
ina = g_na * (v + -1 * ena)
}
"#
);
}