1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
use clap::{Parser, Subcommand};
use nml2::{acc, bundle, error::Result, get_runtime_types, lems, nmodl};
#[derive(Parser)]
#[clap(name = "nmlcc")]
#[clap(version = "0.4.1-dev", author = "t.hater@fz-juelich.de")]
struct Cli {
/// Verbosity level, defaults to 'WARN'.
#[clap(short, long, default_value="0", action = clap::ArgAction::Count)]
verbose: u8,
/// Comma separated list of ion species to consider as given. The default is
/// _Arbor's_ list of ions Calcium Ca 2+, Sodium Na 1+, and Potassium K 1+.
/// NeuroML2 defaults to just Ca and Na, so if you are trying to port an
/// NML2 model 1:1 pass --ions='na,ca'. All ion names will be turned into
/// lowercase. Note that this gives the simulator's built-in, but does not
/// allow for adding new species.
#[clap(short, long, default_value = "ca, na, k")]
ions: String,
#[clap(subcommand)]
cmd: Cmd,
}
#[derive(Subcommand)]
enum Cmd {
/// Export to NMODL
Nmodl {
/// NeuroML2 compliant XML files
nml: Vec<String>,
/// Parameters to be retained/removed from NMODL; prefix with `-` to
/// remove or `+` to retain, `*` matches all suffices, cannot be given
/// as infix/prefix; eg --parameter='-*,+foo_*,-foo_bar_*' will retain
/// only those starting with `foo_`, unless followed by `bar_`. NOTE:
/// Must be given in order of specificity and follow our internal naming
/// scheme (sorry, but this is for fine-tuning).
#[clap(short, long, default_value = "+*")]
parameter: String,
/// Write mechanisms under this prefix
#[clap(short, long, default_value = ".")]
dir: String,
},
/// Export to Arbor Cable Cell format (.acc)
Acc {
/// NeuroML2 compliant XML files
nml: Vec<String>,
/// Write ouput under this prefix
#[clap(short, long, default_value = ".")]
dir: String,
},
/// DWIM creation of an Arbor simulation template
Bundle {
/// NeuroML2 compliant XML files
nml: String,
/// Try to combine channels per segment group
#[clap(short, long)]
super_mechanisms: bool,
/// Export a C++ simulation file
#[clap(long)]
cxx: bool,
/// Export a Python simulation file
#[clap(long, default_value = "true")]
py: bool,
/// Change catalogue prefix.
/// Set to empty string if mechanisms do not collide with internal mechanisms
#[clap(short, long, default_value = "local_")]
cat_prefix: String,
/// Prefix to put bundle
dir: String,
},
}
fn set_collector(v: usize) -> std::result::Result<(), tracing::dispatcher::SetGlobalDefaultError> {
let lvl = match v {
0 => tracing::Level::WARN,
1 => tracing::Level::INFO,
_ => tracing::Level::TRACE,
};
let collector = tracing_subscriber::fmt()
.with_max_level(lvl)
.with_target(false)
.compact()
.finish();
tracing::subscriber::set_global_default(collector)
}
fn main() -> Result<()> {
let opts = Cli::parse();
let _g = set_collector(opts.verbose as usize);
let mut lems = lems::file::LemsFile::core();
let ions = opts
.ions
.split(',')
.map(|s| s.trim().to_lowercase())
.collect::<Vec<_>>();
match opts.cmd {
Cmd::Nmodl {
nml,
parameter,
dir,
} => {
get_runtime_types(&mut lems, &nml)?;
nmodl::export(&lems, &nml, ¶meter, &dir, &ions[..])?;
}
Cmd::Acc { nml, dir } => {
get_runtime_types(&mut lems, &nml)?;
acc::export(&lems, &nml, &dir, &ions[..], "")?;
}
Cmd::Bundle {
nml,
dir,
super_mechanisms,
cat_prefix,
cxx,
py,
} => {
get_runtime_types(&mut lems, &[nml.to_string()])?;
bundle::export(
&lems,
&[nml],
&ions[..],
bundle::Bundle {
dir,
cxx,
py,
super_mechanisms,
cat_prefix,
},
)?;
}
}
Ok(())
}