Skip to content
Snippets Groups Projects
Commit b3c4654b authored by Sam Yates's avatar Sam Yates
Browse files

Command-line support for limitting trace output.

New options:
 * -p, --probe-ratio      Attach probes to this proportion of cells
 * -X, --probe-soma-only  Don't probe dendrites
 * -P, --trace-prefix     Specify where to write traces
                          (default: 'trace_')
 * -T, --trace-max-gid    Don't trace cells with a larger gid than this.
parent 5719d261
No related branches found
No related tags found
No related merge requests found
#include <fstream>
#include <exception>
#include <fstream>
#include <istream>
#include <tclap/CmdLine.h>
#include <json/src/json.hpp>
#include <util/optional.hpp>
#include "io.hpp"
// Let TCLAP understand value arguments that are of an optional type.
template <typename V>
struct TCLAP::ArgTraits<nest::mc::util::optional<V>> {
using ValueCategory = ValueLike;
};
namespace nest {
namespace mc {
// Using static here because we do not want external linkage for this operator
namespace util {
template <typename V>
static std::istream& operator>>(std::istream& I, optional<V>& v) {
V u;
if (I >> u) {
v = u;
}
return I;
}
}
namespace io {
/// read simulation options from json file with name fname
......@@ -17,7 +41,8 @@ namespace io {
cl_options read_options(int argc, char** argv) {
// set default options
const cl_options defopts{"", 1000, 500, "expsyn", 100, 100., 0.025, false};
const cl_options defopts{"", 1000, 500, "expsyn", 100, 100., 0.025, false,
false, 1.0, "trace_", util::nothing};
cl_options options;
// parse command line arguments
......@@ -47,6 +72,17 @@ cl_options read_options(int argc, char** argv) {
false, defopts.dt, "positive real number", cmd);
TCLAP::SwitchArg all_to_all_arg(
"m","alltoall","all to all network", cmd, false);
TCLAP::ValueArg<double> probe_ratio_arg(
"p", "probe-ratio", "proportion of cells to probe",
false, defopts.probe_ratio, "real number in [0,1]", cmd);
TCLAP::SwitchArg probe_soma_only_arg(
"X", "probe-soma-only", "only probe cell somas, not dendrites", cmd, false);
TCLAP::ValueArg<std::string> trace_prefix_arg(
"P", "trace-prefix", "write traces to files with this prefix",
false, defopts.trace_prefix, "stringr", cmd);
TCLAP::ValueArg<util::optional<unsigned>> trace_max_gid_arg(
"T", "trace-max-gid", "only trace probes on cells up to this gid",
false, defopts.trace_max_gid, "unisgned integer", cmd);
cmd.parse(argc, argv);
......@@ -58,6 +94,10 @@ cl_options read_options(int argc, char** argv) {
options.tfinal = tfinal_arg.getValue();
options.dt = dt_arg.getValue();
options.all_to_all = all_to_all_arg.getValue();
options.probe_ratio = probe_ratio_arg.getValue();
options.probe_soma_only = probe_soma_only_arg.getValue();
options.trace_prefix = trace_prefix_arg.getValue();
options.trace_max_gid = trace_max_gid_arg.getValue();
}
// catch any exceptions in command line handling
catch (TCLAP::ArgException& e) {
......@@ -100,6 +140,14 @@ std::ostream& operator<<(std::ostream& o, const cl_options& options) {
o << " simulation time : " << options.tfinal << "\n";
o << " dt : " << options.dt << "\n";
o << " all to all network : " << (options.all_to_all ? "yes" : "no") << "\n";
o << " probe ratio : " << options.probe_ratio << "\n";
o << " probe soma only : " << (options.probe_soma_only ? "yes" : "no") << "\n";
o << " trace prefix : " << options.trace_prefix << "\n";
o << " trace max gid : ";
if (options.trace_max_gid) {
o << *options.trace_max_gid;
}
o << "\n";
o << " input file name : " << options.ifname << "\n";
return o;
......
......@@ -6,6 +6,8 @@
#include <stdexcept>
#include <utility>
#include <util/optional.hpp>
namespace nest {
namespace mc {
namespace io {
......@@ -20,6 +22,10 @@ struct cl_options {
double tfinal;
double dt;
bool all_to_all;
bool probe_soma_only;
double probe_ratio;
std::string trace_prefix;
util::optional<unsigned> trace_max_gid;
};
class usage_error: public std::runtime_error {
......
......@@ -32,7 +32,7 @@ using model_type = model<lowered_cell>;
using sample_trace_type = sample_trace<model_type::time_type, model_type::value_type>;
void banner();
std::unique_ptr<recipe> make_recipe(const io::cl_options&);
std::unique_ptr<recipe> make_recipe(const io::cl_options&, const probe_distribution&);
std::unique_ptr<sample_trace_type> make_trace(cell_member_type probe_id, probe_spec probe);
std::pair<cell_gid_type, cell_gid_type> distribute_cells(cell_size_type ncells);
......@@ -53,7 +53,12 @@ int main(int argc, char** argv) {
<< std::ceil(options.tfinal / options.dt) << " steps of "
<< options.dt << " ms" << std::endl;
auto recipe = make_recipe(options);
// determine what to attach probes to
probe_distribution pdist;
pdist.proportion = options.probe_ratio;
pdist.all_segments = !options.probe_soma_only;
auto recipe = make_recipe(options, pdist);
auto cell_range = distribute_cells(recipe->num_cells());
// build model from recipe
......@@ -69,6 +74,10 @@ int main(int argc, char** argv) {
std::vector<std::unique_ptr<sample_trace_type>> traces;
const model_type::time_type sample_dt = 0.1;
for (auto probe: m.probes()) {
if (options.trace_max_gid && probe.id.gid>*options.trace_max_gid) {
continue;
}
traces.push_back(make_trace(probe.id, probe.probe));
m.attach_sampler(probe.id, make_trace_sampler(traces.back().get(),sample_dt));
}
......@@ -81,7 +90,7 @@ int main(int argc, char** argv) {
// save traces
for (const auto& trace: traces) {
write_trace_json(*trace.get());
write_trace_json(*trace.get(), options.trace_prefix);
}
}
catch (io::usage_error& e) {
......@@ -119,7 +128,7 @@ void banner() {
std::cout << "====================\n";
}
std::unique_ptr<recipe> make_recipe(const io::cl_options& options) {
std::unique_ptr<recipe> make_recipe(const io::cl_options& options, const probe_distribution& pdist) {
basic_recipe_param p;
p.num_compartments = options.compartments_per_segment;
......@@ -127,17 +136,17 @@ std::unique_ptr<recipe> make_recipe(const io::cl_options& options) {
p.synapse_type = options.syn_type;
if (options.all_to_all) {
return make_basic_kgraph_recipe(options.cells, p);
return make_basic_kgraph_recipe(options.cells, p, pdist);
}
else {
return make_basic_rgraph_recipe(options.cells, p);
return make_basic_rgraph_recipe(options.cells, p, pdist);
}
}
std::unique_ptr<sample_trace_type> make_trace(cell_member_type probe_id, probe_spec probe) {
std::string name = "";
std::string units = "";
switch (probe.kind) {
case probeKind::membrane_voltage:
name = "v";
......
......@@ -76,13 +76,15 @@ public:
EXPECTS(cell.detectors().size()==cc.num_sources);
// add probes
unsigned n_probe_segs = pdist_.all_segments? basic_cell_segments: 1u;
for (unsigned i = 0; i<n_probe_segs; ++i) {
if (pdist_.membrane_voltage) {
cell.add_probe({{i, i? 0.5: 0.0}, mc::probeKind::membrane_voltage});
}
if (pdist_.membrane_current) {
cell.add_probe({{i, i? 0.5: 0.0}, mc::probeKind::membrane_current});
if (cc.num_probes) {
unsigned n_probe_segs = pdist_.all_segments? basic_cell_segments: 1u;
for (unsigned i = 0; i<n_probe_segs; ++i) {
if (pdist_.membrane_voltage) {
cell.add_probe({{i, i? 0.5: 0.0}, mc::probeKind::membrane_voltage});
}
if (pdist_.membrane_current) {
cell.add_probe({{i, i? 0.5: 0.0}, mc::probeKind::membrane_current});
}
}
}
EXPECTS(cell.probes().size()==cc.num_probes);
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment