From 4284780f9c2418cc1e475672404b6a6d973c339a Mon Sep 17 00:00:00 2001 From: Ben Cumming <bcumming@cscs.ch> Date: Mon, 4 Mar 2019 11:01:03 +0100 Subject: [PATCH] Remove miniapp (#710) Remove the miniapp example. * Remove the miniapp source from example/miniapp. * Remove references to miniapp from CMake files. * Remove miniapp from the travis tests. * Fix unused variable warning in brunel miniapp. --- CMakeLists.txt | 2 +- example/CMakeLists.txt | 1 - example/brunel/brunel_miniapp.cpp | 4 +- example/miniapp/CMakeLists.txt | 10 - example/miniapp/README.md | 90 ------- example/miniapp/io.cpp | 377 ---------------------------- example/miniapp/io.hpp | 86 ------- example/miniapp/miniapp.cpp | 283 --------------------- example/miniapp/miniapp_recipes.cpp | 350 -------------------------- example/miniapp/miniapp_recipes.hpp | 59 ----- example/miniapp/morphology_pool.cpp | 56 ----- example/miniapp/morphology_pool.hpp | 40 --- example/miniapp/plot.py | 22 -- example/miniapp/trace.cpp | 52 ---- example/miniapp/trace.hpp | 21 -- scripts/travis/build.sh | 4 - 16 files changed, 2 insertions(+), 1455 deletions(-) delete mode 100644 example/miniapp/CMakeLists.txt delete mode 100644 example/miniapp/README.md delete mode 100644 example/miniapp/io.cpp delete mode 100644 example/miniapp/io.hpp delete mode 100644 example/miniapp/miniapp.cpp delete mode 100644 example/miniapp/miniapp_recipes.cpp delete mode 100644 example/miniapp/miniapp_recipes.hpp delete mode 100644 example/miniapp/morphology_pool.cpp delete mode 100644 example/miniapp/morphology_pool.hpp delete mode 100644 example/miniapp/plot.py delete mode 100644 example/miniapp/trace.cpp delete mode 100644 example/miniapp/trace.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 2cb8256b..ddce9394 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -369,7 +369,7 @@ add_subdirectory(arborenv) # unit, unit-mpi, unit-local, unit-modcc, validate add_subdirectory(test) -# miniapp, brunel-minapp, event-gen: +# self contained examples: add_subdirectory(example) # lmorpho: diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index d1e68b39..aeed60d2 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -2,7 +2,6 @@ # Example executable targets should be added to the 'examples' target as dependencies. add_custom_target(examples DEPENDS) -add_subdirectory(miniapp) add_subdirectory(dryrun) add_subdirectory(generators) add_subdirectory(brunel) diff --git a/example/brunel/brunel_miniapp.cpp b/example/brunel/brunel_miniapp.cpp index 1c83d2bc..320bdcb5 100644 --- a/example/brunel/brunel_miniapp.cpp +++ b/example/brunel/brunel_miniapp.cpp @@ -187,7 +187,6 @@ private: int main(int argc, char** argv) { bool root = true; - int rank = 0; try { arb::proc_allocation resources; @@ -202,8 +201,7 @@ int main(int argc, char** argv) { arbenv::with_mpi guard(argc, argv, false); resources.gpu_id = arbenv::find_private_gpu(MPI_COMM_WORLD); auto context = arb::make_context(resources, MPI_COMM_WORLD); - rank = arb::rank(context); - root = rank==0; + root = arb::rank(context)==0; #else resources.gpu_id = arbenv::default_gpu(); auto context = arb::make_context(resources); diff --git a/example/miniapp/CMakeLists.txt b/example/miniapp/CMakeLists.txt deleted file mode 100644 index ad78e825..00000000 --- a/example/miniapp/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -add_executable(miniapp EXCLUDE_FROM_ALL - miniapp.cpp - io.cpp - miniapp_recipes.cpp - morphology_pool.cpp - trace.cpp -) -add_dependencies(examples miniapp) - -target_link_libraries(miniapp PRIVATE arbor arborenv arbor-sup ext-tclap ext-json) diff --git a/example/miniapp/README.md b/example/miniapp/README.md deleted file mode 100644 index 066daf12..00000000 --- a/example/miniapp/README.md +++ /dev/null @@ -1,90 +0,0 @@ -# Arbor miniapp - -The miniapp is a simple benchmark for the Arbor library. - -## the model - -The model is very simple, with three parameters that describe the network, and two for controlling time stepping. - -### network/model parameters - -The following parameters are used to describe the size, connectivity and resolution of the model: - -- `cells` is the total number of cells in the network. -- `synapses_per_cell` the number of synapses per cell, must be in the range `[0,cells-1]` -- `compartments` the number of compartments per segment. -- `all_to_all` toggle whether to make an all to all network - -All cells have identical morphology, a soma with a dendrite attached. The dendrite branches as illustrated (roughly) below - - -``` -s = soma -. = branching point of dendrite - - / - / -s------. - \ - \ -``` - -The disrcetization of each cell is controlled with the __compartments__ parameter. -For example, when `compartments=100`, the total number of compartments in each cell is 301: 1 for the soma, and 100 for each of the dendrite segments. - -The `synapses_per_cell` parameter is in the range `[0,cells-1]`. -If it is zero, then there are no connections between the cells (not much of a network). -By default, the source gid of each synapse is chosen at random from the global set of cells (excluding the cell of the synapse). -If the `all_to_all` flag is set, `synapses_per_cell` is set to `cells-1`, i.e. one connection for each cell (excluding the cell of the synapse) - -Note that the to avoid numerical instability, the number of synapses per cell should be greater than 200 (or zero!). -The number of synapses per cell required for stability is dependent on the number of compartments per segment (fewer compartments is more stable) and the time step size (smaller time step sizes increase stability). -If there are numeric instabilities the simulation will print a warning -``` -warning: solution out of bounds -``` - -### time stepping parameters - -The time stepping can be controlled via two parameters - -- `dt` the time step size in ms (default `dt=0.025`) -- `tfinal` the length of the simulation in ms (default `tfinal=200`) - -## configuration - -There are two ways to specify the model properties, i.e. the number of cells, connections per cell, etc. - -### command line arguments - -- `-n integer` : `ncells` -- `-s integer` : `synapses_per_cell` -- `-c integer` : `compartments` -- `-d float` : `dt` -- `-t float` : `tfinal` -- `-i filename` : name of json file with parameters - -For example - -``` -> ./miniapp.exe -n 1000 -s 500 -c 50 -t 100 -d 0.02 -``` - -will run a simulation with 1000 cells, with 500 synapses per cell, 50 compartments per segment for a total of 100 ms with 0.02 ms time steps. - -### input parameter file - -To run the same simulation that we ran with the command line arguments with an input file: - -``` -> cat input.json -{ - "cells": 1000, - "synapses": 500, - "compartments": 50, - "dt": 0.02, - "tfinal": 100.0, - "all_to_all": false -} -> ./miniapp.exe -i input.json -``` diff --git a/example/miniapp/io.cpp b/example/miniapp/io.cpp deleted file mode 100644 index 4d8b1970..00000000 --- a/example/miniapp/io.cpp +++ /dev/null @@ -1,377 +0,0 @@ -#include <algorithm> -#include <exception> -#include <fstream> -#include <iostream> -#include <istream> -#include <memory> -#include <sstream> -#include <string> -#include <type_traits> - -#include <tclap/CmdLine.h> -#include <nlohmann/json.hpp> - -#include <arbor/util/optional.hpp> - -#include "io.hpp" - -// Let TCLAP understand value arguments that are of an optional type. - -namespace TCLAP { - template <typename V> - struct ArgTraits<arb::util::optional<V>> { - using ValueCategory = ValueLike; - }; -} // namespace TCLAP - -namespace arb { - -namespace util { - // Using static here because we do not want external linkage for this operator. - template <typename V> - static std::istream& operator>>(std::istream& I, optional<V>& v) { - V u; - if (I >> u) { - v = u; - } - return I; - } -} - -namespace io { - -// Override annoying parameters listed back-to-front behaviour. -// -// TCLAP argument creation _prepends_ its arguments to the internal -// list (_argList), where standard options --help etc. are already -// pre-inserted. -// -// reorder_arguments() reverses the arguments to restore ordering, -// and moves the standard options to the end. -class CustomCmdLine: public TCLAP::CmdLine { -public: - CustomCmdLine(const std::string &message, const std::string &version = "none"): - TCLAP::CmdLine(message, ' ', version, true) - {} - - void reorder_arguments() { - _argList.reverse(); - for (auto opt: {"help", "version", "ignore_rest"}) { - auto i = std::find_if( - _argList.begin(), _argList.end(), - [&opt](TCLAP::Arg* a) { return a->getName()==opt; }); - - if (i!=_argList.end()) { - auto a = *i; - _argList.erase(i); - _argList.push_back(a); - } - } - } -}; - -// Update an option value from command line argument if set. -template < - typename T, - typename Arg, - typename = std::enable_if_t<std::is_base_of<TCLAP::Arg, Arg>::value> -> -static void update_option(T& opt, Arg& arg) { - if (arg.isSet()) { - opt = arg.getValue(); - } -} - -// Update an option value from json object if key present. -template <typename T> -static void update_option(T& opt, const nlohmann::json& j, const std::string& key) { - if (j.count(key)) { - opt = j[key]; - } -} - -// --- special case for string due to ambiguous overloading in json library. -static void update_option(std::string& opt, const nlohmann::json& j, const std::string& key) { - if (j.count(key)) { - opt = j[key].get<std::string>(); - } -} - -// --- special case for optional values. -template <typename T> -static void update_option(util::optional<T>& opt, const nlohmann::json& j, const std::string& key) { - if (j.count(key)) { - auto value = j[key]; - if (value.is_null()) { - opt = util::nullopt; - } - else { - opt = value.get<T>(); - } - } -} - -// Read options from (optional) json file and command line arguments. -cl_options read_options(int argc, char** argv, bool allow_write) { - cl_options options; - std::string save_file = ""; - - // Parse command line arguments. - try { - cl_options defopts; - - CustomCmdLine cmd("arbor miniapp harness", "0.1"); - - TCLAP::ValueArg<std::string> ifile_arg( - "i", "ifile", - "read parameters from json-formatted file <file name>", - false, "","file name", cmd); - TCLAP::ValueArg<std::string> ofile_arg( - "o", "ofile", - "save parameters to json-formatted file <file name>", - false, "","file name", cmd); - TCLAP::ValueArg<uint32_t> ncells_arg( - "n", "ncells", "total number of cells in the model", - false, defopts.cells, "integer", cmd); - TCLAP::ValueArg<uint32_t> nsynapses_arg( - "s", "nsynapses", "number of synapses per cell", - false, defopts.synapses_per_cell, "integer", cmd); - TCLAP::ValueArg<std::string> syntype_arg( - "S", "syntype", "specify synapse type: expsyn or exp2syn", - false, defopts.syn_type, "string", cmd); - TCLAP::ValueArg<uint32_t> ncompartments_arg( - "c", "ncompartments", "number of compartments per segment", - false, defopts.compartments_per_segment, "integer", cmd); - TCLAP::ValueArg<double> tfinal_arg( - "t", "tfinal", "run simulation to <time> ms", - false, defopts.tfinal, "time", cmd); - TCLAP::ValueArg<double> dt_arg( - "d", "dt", "set simulation time step to <time> ms", - false, defopts.dt, "time", cmd); - TCLAP::ValueArg<double> bin_dt_arg( - "", "bin-dt", "set event binning interval to <time> ms", - false, defopts.bin_dt, "time", cmd); - TCLAP::SwitchArg bin_regular_arg( - "","bin-regular","use 'regular' binning policy instead of 'following'", cmd, false); - TCLAP::SwitchArg all_to_all_arg( - "m","alltoall","all to all network", cmd, false); - TCLAP::SwitchArg ring_arg( - "r","ring","ring network", cmd, false); - TCLAP::ValueArg<double> sample_dt_arg( - "", "sample-dt", "set sampling interval to <time> ms", - false, defopts.bin_dt, "time", cmd); - TCLAP::ValueArg<double> probe_ratio_arg( - "p", "probe-ratio", "proportion between 0 and 1 of cells to probe", - false, defopts.probe_ratio, "proportion", 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", "prefix", "write traces to files with prefix <prefix>", - false, defopts.trace_prefix, "string", cmd); - TCLAP::ValueArg<util::optional<unsigned>> trace_max_gid_arg( - "T", "trace-max-gid", "only trace probes on cells up to and including <gid>", - false, defopts.trace_max_gid, "gid", cmd); - TCLAP::ValueArg<std::string> trace_format_arg( - "F", "trace-format", "select trace data format: csv or json", - false, defopts.trace_prefix, "string", cmd); - TCLAP::ValueArg<util::optional<std::string>> morphologies_arg( - "M", "morphologies", "load morphologies from SWC files matching <glob>", - false, defopts.morphologies, "glob", cmd); - TCLAP::SwitchArg morph_rr_arg( - "", "morph-rr", "Serial rather than random morphology selection from pool", cmd, false); - TCLAP::SwitchArg report_compartments_arg( - "", "report-compartments", "Count compartments in cells before simulation", cmd, false); - TCLAP::SwitchArg spike_output_arg( - "f","spike-file-output","save spikes to file", cmd, false); - TCLAP::ValueArg<unsigned> dry_run_ranks_arg( - "D","dry-run-ranks","number of ranks in dry run mode", - false, defopts.dry_run_ranks, "positive integer", cmd); - TCLAP::SwitchArg verbose_arg( - "v", "verbose", "Present more verbose information to stdout", cmd, false); - - - cmd.reorder_arguments(); - cmd.parse(argc, argv); - - // Handle verbosity separately from other options: it is not considered part - // of the saved option state. - options.verbose = verbose_arg.getValue(); - - std::string ifile_name = ifile_arg.getValue(); - if (ifile_name != "") { - // Read parameters from specified JSON file first, to allow - // overriding arguments on the command line. - std::ifstream fid(ifile_name); - if (fid) { - try { - nlohmann::json fopts; - fid >> fopts; - - update_option(options.cells, fopts, "cells"); - update_option(options.synapses_per_cell, fopts, "synapses"); - update_option(options.syn_type, fopts, "syn_type"); - update_option(options.compartments_per_segment, fopts, "compartments"); - update_option(options.dt, fopts, "dt"); - update_option(options.bin_dt, fopts, "bin_dt"); - update_option(options.bin_regular, fopts, "bin_regular"); - update_option(options.tfinal, fopts, "tfinal"); - update_option(options.all_to_all, fopts, "all_to_all"); - update_option(options.ring, fopts, "ring"); - update_option(options.sample_dt, fopts, "sample_dt"); - update_option(options.probe_ratio, fopts, "probe_ratio"); - update_option(options.probe_soma_only, fopts, "probe_soma_only"); - update_option(options.trace_prefix, fopts, "trace_prefix"); - update_option(options.trace_max_gid, fopts, "trace_max_gid"); - update_option(options.trace_format, fopts, "trace_format"); - update_option(options.morphologies, fopts, "morphologies"); - update_option(options.morph_rr, fopts, "morph_rr"); - update_option(options.report_compartments, fopts, "report_compartments"); - - // Parameters for spike output - update_option(options.spike_file_output, fopts, "spike_file_output"); - update_option(options.single_file_per_rank, fopts, "single_file_per_rank"); - update_option(options.over_write, fopts, "over_write"); - update_option(options.output_path, fopts, "output_path"); - update_option(options.file_name, fopts, "file_name"); - update_option(options.file_extension, fopts, "file_extension"); - - update_option(options.dry_run_ranks, fopts, "dry_run_ranks"); - } - catch (std::exception& e) { - throw model_description_error( - "unable to parse parameters in "+ifile_name+": "+e.what()); - } - } - else { - throw usage_error("unable to open model parameter file "+ifile_name); - } - } - - update_option(options.cells, ncells_arg); - update_option(options.synapses_per_cell, nsynapses_arg); - update_option(options.syn_type, syntype_arg); - update_option(options.compartments_per_segment, ncompartments_arg); - update_option(options.tfinal, tfinal_arg); - update_option(options.dt, dt_arg); - update_option(options.bin_dt, bin_dt_arg); - update_option(options.bin_regular, bin_regular_arg); - update_option(options.all_to_all, all_to_all_arg); - update_option(options.ring, ring_arg); - update_option(options.sample_dt, sample_dt_arg); - update_option(options.probe_ratio, probe_ratio_arg); - update_option(options.probe_soma_only, probe_soma_only_arg); - update_option(options.trace_prefix, trace_prefix_arg); - update_option(options.trace_max_gid, trace_max_gid_arg); - update_option(options.trace_format, trace_format_arg); - update_option(options.morphologies, morphologies_arg); - update_option(options.morph_rr, morph_rr_arg); - update_option(options.report_compartments, report_compartments_arg); - update_option(options.spike_file_output, spike_output_arg); - update_option(options.dry_run_ranks, dry_run_ranks_arg); - - if (options.trace_format!="csv" && options.trace_format!="json") { - throw usage_error("trace format must be one of: csv, json"); - } - - if (options.all_to_all && options.ring) { - throw usage_error("can specify at most one of --ring and --all-to-all"); - } - - save_file = ofile_arg.getValue(); - } - catch (TCLAP::ArgException& e) { - throw usage_error("error parsing command line argument "+e.argId()+": "+e.error()); - } - - // Save option values if requested. - if (save_file != "" && allow_write) { - std::ofstream fid(save_file); - if (fid) { - try { - nlohmann::json fopts; - - fopts["cells"] = options.cells; - fopts["synapses"] = options.synapses_per_cell; - fopts["syn_type"] = options.syn_type; - fopts["compartments"] = options.compartments_per_segment; - fopts["dt"] = options.dt; - fopts["bin_dt"] = options.bin_dt; - fopts["bin_regular"] = options.bin_regular; - fopts["tfinal"] = options.tfinal; - fopts["all_to_all"] = options.all_to_all; - fopts["ring"] = options.ring; - fopts["sample_dt"] = options.sample_dt; - fopts["probe_ratio"] = options.probe_ratio; - fopts["probe_soma_only"] = options.probe_soma_only; - fopts["trace_prefix"] = options.trace_prefix; - if (options.trace_max_gid) { - fopts["trace_max_gid"] = options.trace_max_gid.value(); - } - else { - fopts["trace_max_gid"] = nullptr; - } - fopts["trace_format"] = options.trace_format; - if (options.morphologies) { - fopts["morphologies"] = options.morphologies.value(); - } - else { - fopts["morphologies"] = nullptr; - } - fopts["morph_rr"] = options.morph_rr; - fopts["report_compartments"] = options.report_compartments; - fid << std::setw(3) << fopts << "\n"; - - } - catch (std::exception& e) { - throw model_description_error( - "unable to save parameters in "+save_file+": "+e.what()); - } - } - else { - throw usage_error("unable to write to model parameter file "+save_file); - } - } - - // If verbose output requested, emit option summary. - if (options.verbose) { - std::cout << options << "\n"; - } - - return options; -} - -std::ostream& operator<<(std::ostream& o, const cl_options& options) { - o << "simulation options:\n"; - o << " cells : " << options.cells << "\n"; - o << " compartments/segment : " << options.compartments_per_segment << "\n"; - o << " synapses/cell : " << options.synapses_per_cell << "\n"; - o << " simulation time : " << options.tfinal << "\n"; - o << " dt : " << options.dt << "\n"; - o << " binning dt : " << options.bin_dt << "\n"; - o << " binning policy : " << - (options.bin_dt==0? "none": options.bin_regular? "regular": "following") << "\n"; - o << " all to all network : " << (options.all_to_all ? "yes" : "no") << "\n"; - o << " ring network : " << (options.ring ? "yes" : "no") << "\n"; - o << " sample dt : " << options.sample_dt << "\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 << " trace format : " << options.trace_format << "\n"; - o << " morphologies : "; - if (options.morphologies) { - o << *options.morphologies; - } - o << "\n"; - o << " morphology r-r : " << (options.morph_rr ? "yes" : "no") << "\n"; - o << " report compartments : " << (options.report_compartments ? "yes" : "no") << "\n"; - - return o; -} - -} // namespace io -} // namespace arb diff --git a/example/miniapp/io.hpp b/example/miniapp/io.hpp deleted file mode 100644 index f19ee309..00000000 --- a/example/miniapp/io.hpp +++ /dev/null @@ -1,86 +0,0 @@ -#pragma once - -#include <cstdint> -#include <iosfwd> -#include <stdexcept> -#include <string> -#include <utility> -#include <vector> - -#include <arbor/common_types.hpp> -#include <arbor/util/optional.hpp> -#include <sup/path.hpp> - -// TODO: this shouldn't be in arb namespace -namespace arb { -namespace io { - -// Holds the options for a simulation run. -// Default constructor gives default options. - -struct cl_options { - // Cell parameters: - uint32_t cells = 1000; - uint32_t synapses_per_cell = 500; - std::string syn_type = "expsyn"; - uint32_t compartments_per_segment = 100; - util::optional<std::string> morphologies; - bool morph_rr = false; // False => pick morphologies randomly, true => pick morphologies round-robin. - - // Network type (default is rgraph): - bool all_to_all = false; - bool ring = false; - - // Simulation running parameters: - double tfinal = 100.; - double dt = 0.025; - bool bin_regular = false; // False => use 'following' instead of 'regular'. - double bin_dt = 0.0025; // 0 => no binning. - - // Probe/sampling specification. - double sample_dt = 0.1; - bool probe_soma_only = false; - double probe_ratio = 0; // Proportion of cells to probe. - std::string trace_prefix = "trace_"; - util::optional<unsigned> trace_max_gid; // Only make traces up to this gid. - std::string trace_format = "json"; // Support only 'json' and 'csv'. - - // Parameters for spike output. - bool spike_file_output = false; - bool single_file_per_rank = false; - bool over_write = true; - std::string output_path = "./"; - std::string file_name = "spikes"; - std::string file_extension = "gdf"; - - // Dry run parameters (pertinent only when built with 'dryrun' distrib model). - int dry_run_ranks = 1; - - // Turn on/off profiling output for all ranks. - bool profile_only_zero = false; - - // Report (inefficiently) on number of cell compartments in sim. - bool report_compartments = false; - - // Be more verbose with informational messages. - bool verbose = false; -}; - -class usage_error: public std::runtime_error { -public: - template <typename S> - usage_error(S&& whatmsg): std::runtime_error(std::forward<S>(whatmsg)) {} -}; - -class model_description_error: public std::runtime_error { -public: - template <typename S> - model_description_error(S&& whatmsg): std::runtime_error(std::forward<S>(whatmsg)) {} -}; - -std::ostream& operator<<(std::ostream& o, const cl_options& opt); - -cl_options read_options(int argc, char** argv, bool allow_write = true); - -} // namespace io -} // namespace arb diff --git a/example/miniapp/miniapp.cpp b/example/miniapp/miniapp.cpp deleted file mode 100644 index f4d74440..00000000 --- a/example/miniapp/miniapp.cpp +++ /dev/null @@ -1,283 +0,0 @@ -#include <cmath> -#include <exception> -#include <iomanip> -#include <iostream> -#include <fstream> -#include <memory> -#include <vector> - -#include <arbor/context.hpp> -#include <arbor/load_balance.hpp> -#include <arbor/mc_cell.hpp> -#include <arbor/profile/meter_manager.hpp> -#include <arbor/profile/profiler.hpp> -#include <arbor/sampling.hpp> -#include <arbor/schedule.hpp> -#include <arbor/simulation.hpp> -#include <arbor/util/any.hpp> -#include <arbor/version.hpp> - - -#include <arborenv/concurrency.hpp> -#include <arborenv/gpu_env.hpp> - -#include <sup/ioutil.hpp> -#include <sup/json_meter.hpp> -#include <sup/path.hpp> -#include <sup/strsub.hpp> - -#ifdef ARB_MPI_ENABLED -#include <mpi.h> -#include <arborenv/with_mpi.hpp> -#endif - -#include "io.hpp" -#include "miniapp_recipes.hpp" -#include "trace.hpp" - -using namespace arb; - -using util::any_cast; - -void banner(const context&); -std::unique_ptr<recipe> make_recipe(const io::cl_options&, const probe_distribution&); -sample_trace make_trace(const probe_info& probe); -std::fstream& open_or_throw(std::fstream& file, const sup::path& p, bool exclusive = false); -void report_compartment_stats(const recipe&); - -int main(int argc, char** argv) { - bool root = true; - int rank = 0; - - try { - arb::proc_allocation resources; - if (auto nt = arbenv::get_env_num_threads()) { - resources.num_threads = nt; - } - else { - resources.num_threads = arbenv::thread_concurrency(); - } - -#ifdef ARB_MPI_ENABLED - arbenv::with_mpi guard(argc, argv, false); - resources.gpu_id = arbenv::find_private_gpu(MPI_COMM_WORLD); - auto context = arb::make_context(resources, MPI_COMM_WORLD); - rank = arb::rank(context); - root = rank == 0; -#else - resources.gpu_id = arbenv::default_gpu(); - auto context = arb::make_context(resources); -#endif - -#ifdef ARB_PROFILE_ENABLED - profile::profiler_initialize(context); -#endif - profile::meter_manager meters; - meters.start(context); - - std::cout << sup::mask_stream(root); - - // read parameters - io::cl_options options = io::read_options(argc, argv, root); - - // TODO: add dry run mode - - // Use a node description that uses the number of threads used by the - // threading back end, and 1 gpu if available. - banner(context); - - // Set up spike output if requested. - std::fstream spike_out; - if (options.spike_file_output && (root || options.single_file_per_rank)) { - sup::path p = options.output_path; - p /= sup::strsub("%_%.%", options.file_name, rank, options.file_extension); - spike_out = sup::open_or_throw(p, std::ios_base::out, !options.over_write); - } - - meters.checkpoint("setup", context); - - // 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); - if (options.report_compartments) { - report_compartment_stats(*recipe); - } - - auto decomp = partition_load_balance(*recipe, context); - simulation sim(*recipe, decomp, context); - - // Set up samplers for probes on local cable cells, as requested - // by command line options. - std::vector<sample_trace> sample_traces; - for (const auto& g: decomp.groups) { - if (g.kind==cell_kind::cable1d_neuron) { - for (auto gid: g.gids) { - if (options.trace_max_gid && gid>*options.trace_max_gid) { - continue; - } - - for (cell_lid_type j = 0; j<recipe->num_probes(gid); ++j) { - sample_traces.push_back(make_trace(recipe->get_probe({gid, j}))); - } - } - } - } - - auto ssched = regular_schedule(options.sample_dt); - for (auto& trace: sample_traces) { - sim.add_sampler(one_probe(trace.probe_id), ssched, make_simple_sampler(trace.samples)); - } - - // Specify event binning/coalescing. - auto binning_policy = - options.bin_dt==0? binning_kind::none: - options.bin_regular? binning_kind::regular: - binning_kind::following; - - sim.set_binning_policy(binning_policy, options.bin_dt); - - // Set up spike recording. - std::vector<arb::spike> recorded_spikes; - if (spike_out) { - auto spike_callback = [&recorded_spikes](auto& spikes) { - recorded_spikes.insert(recorded_spikes.end(), spikes.begin(), spikes.end()); - }; - - if (options.single_file_per_rank) { - sim.set_local_spike_callback(spike_callback); - } - else { - sim.set_global_spike_callback(spike_callback); - } - } - - meters.checkpoint("model-init", context); - - // Run model. - sim.run(options.tfinal, options.dt); - - meters.checkpoint("model-simulate", context); - - // Output profile and diagnostic feedback. - auto profile = profile::profiler_summary(); - std::cout << profile << "\n"; - std::cout << "\nthere were " << sim.num_spikes() << " spikes\n"; - - // Save spikes. - if (spike_out) { - spike_out << std::fixed << std::setprecision(4); - for (auto& s: recorded_spikes) { - spike_out << s.source.gid << ' ' << s.time << '\n'; - } - } - - // Save traces. - auto write_trace = options.trace_format=="json"? write_trace_json: write_trace_csv; - for (const auto& trace: sample_traces) { - write_trace(trace, options.trace_prefix); - } - - auto report = profile::make_meter_report(meters, context); - std::cout << report; - if (root) { - std::ofstream fid; - fid.exceptions(std::ios_base::badbit | std::ios_base::failbit); - fid.open("meters.json"); - fid << std::setw(1) << sup::to_json(report) << "\n"; - } - } - catch (io::usage_error& e) { - // only print usage/startup errors on master - std::cerr << sup::mask_stream(root); - std::cerr << e.what() << "\n"; - return 1; - } - catch (std::exception& e) { - std::cerr << e.what() << "\n"; - return 2; - } - return 0; -} - -void banner(const context& ctx) { - std::cout << "==========================================\n"; - std::cout << " Arbor miniapp\n"; - std::cout << " - distributed : " << arb::num_ranks(ctx) - << (arb::has_mpi(ctx)? " (mpi)": " (serial)") << "\n"; - std::cout << " - threads : " << arb::num_threads(ctx) << "\n"; - std::cout << " - gpus : " << (arb::has_gpu(ctx)? "yes": "no") << "\n"; - std::cout << "==========================================\n"; -} - -std::unique_ptr<recipe> make_recipe(const io::cl_options& options, const probe_distribution& pdist) { - basic_recipe_param p; - - if (options.morphologies) { - std::cout << "loading morphologies...\n"; - p.morphologies.clear(); - load_swc_morphology_glob(p.morphologies, options.morphologies.value()); - std::cout << "loading morphologies: " << p.morphologies.size() << " loaded.\n"; - } - p.morphology_round_robin = options.morph_rr; - - p.num_compartments = options.compartments_per_segment; - - // TODO: Put all recipe parameters in the recipes file - p.num_synapses = options.all_to_all? options.cells-1: options.synapses_per_cell; - p.synapse_type = options.syn_type; - - if (options.all_to_all) { - return make_basic_kgraph_recipe(options.cells, p, pdist); - } - else if (options.ring) { - return make_basic_ring_recipe(options.cells, p, pdist); - } - else { - return make_basic_rgraph_recipe(options.cells, p, pdist); - } -} - -sample_trace make_trace(const probe_info& probe) { - std::string name = ""; - std::string units = ""; - - auto addr = any_cast<cell_probe_address>(probe.address); - switch (addr.kind) { - case cell_probe_address::membrane_voltage: - name = "v"; - units = "mV"; - break; - case cell_probe_address::membrane_current: - name = "i"; - units = "mA/cm²"; - break; - default: ; - } - name += addr.location.segment? "dend" : "soma"; - - return sample_trace{probe.id, name, units}; -} - -void report_compartment_stats(const recipe& rec) { - std::size_t ncell = rec.num_cells(); - std::size_t ncomp_total = 0; - std::size_t ncomp_min = std::numeric_limits<std::size_t>::max(); - std::size_t ncomp_max = 0; - - for (std::size_t i = 0; i<ncell; ++i) { - std::size_t ncomp = 0; - auto c = rec.get_cell_description(i); - if (auto ptr = any_cast<mc_cell>(&c)) { - ncomp = ptr->num_compartments(); - } - ncomp_total += ncomp; - ncomp_min = std::min(ncomp_min, ncomp); - ncomp_max = std::max(ncomp_max, ncomp); - } - - std::cout << "compartments/cell: min=" << ncomp_min <<"; max=" << ncomp_max << "; mean=" << (double)ncomp_total/ncell << "\n"; -} - diff --git a/example/miniapp/miniapp_recipes.cpp b/example/miniapp/miniapp_recipes.cpp deleted file mode 100644 index 62d0ac99..00000000 --- a/example/miniapp/miniapp_recipes.cpp +++ /dev/null @@ -1,350 +0,0 @@ -#include <cmath> -#include <random> -#include <vector> -#include <utility> - -#include <arbor/assert.hpp> -#include <arbor/event_generator.hpp> -#include <arbor/mc_cell.hpp> -#include <arbor/morphology.hpp> -#include <arbor/schedule.hpp> -#include <arbor/spike_source_cell.hpp> - - -#include "io.hpp" -#include "miniapp_recipes.hpp" -#include "morphology_pool.hpp" - -namespace arb { - -// TODO: split cell description into separate morphology, stimulus, mechanisms etc. -// description for greater data reuse. - -template <typename RNG> -mc_cell make_basic_cell( - const morphology& morph, - unsigned compartments_per_segment, - unsigned num_synapses, - const std::string& syn_type, - RNG& rng) -{ - mc_cell cell = make_mc_cell(morph, true); - - for (auto& segment: cell.segments()) { - if (compartments_per_segment!=0) { - if (cable_segment* cable = segment->as_cable()) { - cable->set_compartments(compartments_per_segment); - } - } - - if (segment->is_dendrite()) { - segment->add_mechanism("pas"); - segment->rL = 100; - } - } - - cell.soma()->add_mechanism("hh"); - cell.add_detector({0,0}, 20); - - auto distribution = std::uniform_real_distribution<float>(0.f, 1.0f); - - // Distribute the synapses at random locations the terminal dendrites in a - // round robin manner. - - morph.assert_valid(); - std::vector<unsigned> terminals; - for (const auto& section: morph.sections) { - // Note that morphology section ids should match up exactly with cell - // segment ids! - if (section.terminal) { - terminals.push_back(section.id); - } - } - - arb_assert(!terminals.empty()); - - arb::mechanism_desc syn_default(syn_type); - for (unsigned i=0; i<num_synapses; ++i) { - unsigned id = terminals[i%terminals.size()]; - cell.add_synapse({id, distribution(rng)}, syn_default); - } - - return cell; -} - -class basic_cell_recipe: public recipe { -public: - basic_cell_recipe(cell_gid_type ncell, basic_recipe_param param, probe_distribution pdist): - ncell_(ncell), param_(std::move(param)), pdist_(std::move(pdist)) - { - arb_assert(param_.morphologies.size()>0); - delay_distribution_param_ = exp_param{param_.mean_connection_delay_ms - - param_.min_connection_delay_ms}; - } - - cell_size_type num_cells() const override { - return ncell_ + 1; // We automatically add a fake cell to each recipe! - } - - util::unique_any get_cell_description(cell_gid_type i) const override { - // The last 'cell' is a spike source cell, producing one spike at t = 0. - if (i == ncell_) { - return util::unique_any(spike_source_cell{explicit_schedule({0.})}); - } - - auto gen = std::mt19937(i); // TODO: replace this with hashing generator... - - const auto& morph = get_morphology(i); - unsigned cell_segments = morph.components(); - - auto cell = make_basic_cell(morph, param_.num_compartments, param_.num_synapses, - param_.synapse_type, gen); - - arb_assert(cell.num_segments()==cell_segments); - arb_assert(cell.synapses().size()==num_targets(i)); - arb_assert(cell.detectors().size()==num_sources(i)); - - return util::unique_any(std::move(cell)); - } - - probe_info get_probe(cell_member_type probe_id) const override { - if (probe_id.index>=num_probes(probe_id.gid)) { - throw arb::bad_probe_id(probe_id); - } - - // if we have both voltage and current probes, then order them - // voltage compartment 0, current compartment 0, voltage compartment 1, ... - - cell_probe_address::probe_kind kind; - - int stride = pdist_.membrane_voltage+pdist_.membrane_current; - - if (stride==1) { - // Just one kind of probe. - kind = pdist_.membrane_voltage? - cell_probe_address::membrane_voltage: cell_probe_address::membrane_current; - } - else { - arb_assert(stride==2); - // Both kinds available. - kind = (probe_id.index%stride==0)? - cell_probe_address::membrane_voltage: cell_probe_address::membrane_current; - } - - cell_lid_type compartment = probe_id.index/stride; - segment_location loc{compartment, compartment? 0.5: 0.0}; - - // Use probe kind as the token to be passed to a sampler. - return {probe_id, (int)kind, cell_probe_address{loc, kind}}; - } - - cell_kind get_cell_kind(cell_gid_type i) const override { - // The last 'cell' is a regular spike source with one spike at t=0 - if (i == ncell_) { - return cell_kind::spike_source; - } - return cell_kind::cable1d_neuron; - } - - cell_size_type num_sources(cell_gid_type i) const override { - return 1; - } - - cell_size_type num_targets(cell_gid_type i) const override { - return param_.num_synapses; - } - - cell_size_type num_probes(cell_gid_type i) const override { - bool has_probe = (std::floor(i*pdist_.proportion)!=std::floor((i-1.0)*pdist_.proportion)); - - if (!has_probe) { - return 0; - } - else { - cell_size_type np = pdist_.all_segments? get_morphology(i).components(): 1; - return np*(pdist_.membrane_voltage+pdist_.membrane_current); - } - } - -protected: - template <typename RNG> - cell_connection draw_connection_params(RNG& rng) const { - std::exponential_distribution<float> delay_dist(delay_distribution_param_); - float delay = param_.min_connection_delay_ms + delay_dist(rng); - float weight = param_.syn_weight_per_cell/param_.num_synapses; - return cell_connection{{0, 0}, {0, 0}, weight, delay}; - } - - cell_gid_type ncell_; - basic_recipe_param param_; - probe_distribution pdist_; - - using exp_param = std::exponential_distribution<float>::param_type; - exp_param delay_distribution_param_; - - const morphology& get_morphology(cell_gid_type gid) const { - // Allocate to gids sequentially? - if (param_.morphology_round_robin) { - return param_.morphologies[gid%param_.morphologies.size()]; - } - - // Morphologies are otherwise selected deterministically pseudo-randomly from pool. - std::uniform_int_distribution<unsigned> morph_select_dist_(0, param_.morphologies.size()-1); - - // TODO: definitely replace this with a random hash! - auto gen = std::mt19937(gid+0xbad0cafe); - return param_.morphologies[morph_select_dist_(gen)]; - } -}; - -class basic_ring_recipe: public basic_cell_recipe { -public: - basic_ring_recipe(cell_gid_type ncell, - basic_recipe_param param, - probe_distribution pdist = probe_distribution{}): - basic_cell_recipe(ncell, std::move(param), std::move(pdist)) {} - - std::vector<cell_connection> connections_on(cell_gid_type i) const override { - std::vector<cell_connection> conns; - - // The rss_cell does not have inputs - if (i == ncell_) { - return conns; - } - - auto gen = std::mt19937(i); // TODO: replace this with hashing generator... - - cell_gid_type prev = i==0? ncell_-1: i-1; - for (unsigned t=0; t<param_.num_synapses; ++t) { - cell_connection cc = draw_connection_params(gen); - cc.source = {prev, 0}; - cc.dest = {i, t}; - conns.push_back(cc); - - // The rss_cell spikes at t=0, with these connections it looks like - // (source % 20) == 0 spikes at that moment. - if (prev % 20 == 0) { - cc.source = {ncell_, 0}; // also add connection from reg spiker! - conns.push_back(cc); - } - } - - return conns; - } -}; - -std::unique_ptr<recipe> make_basic_ring_recipe( - cell_gid_type ncell, - basic_recipe_param param, - probe_distribution pdist) -{ - return std::unique_ptr<recipe>(new basic_ring_recipe(ncell, param, pdist)); -} - - -class basic_rgraph_recipe: public basic_cell_recipe { -public: - basic_rgraph_recipe(cell_gid_type ncell, - basic_recipe_param param, - probe_distribution pdist = probe_distribution{}): - basic_cell_recipe(ncell, std::move(param), std::move(pdist)) - { - // Cells are not allowed to connect to themselves; hence there must be least two cells - // to build a connected network. - if (ncell<2) { - throw std::runtime_error("A randomly connected network must have at least 2 cells."); - } - } - - std::vector<cell_connection> connections_on(cell_gid_type i) const override { - std::vector<cell_connection> conns; - - // The regular spike cell does not have inputs - if (i == ncell_) { - return conns; - } - auto conn_param_gen = std::mt19937(i); // TODO: replace this with hashing generator... - auto source_gen = std::mt19937(i*123+457); // ditto - - std::uniform_int_distribution<cell_gid_type> source_distribution(0, ncell_-2); - - for (unsigned t=0; t<param_.num_synapses; ++t) { - auto source = source_distribution(source_gen); - if (source>=i) ++source; - - cell_connection cc = draw_connection_params(conn_param_gen); - cc.source = {source, 0}; - cc.dest = {i, t}; - conns.push_back(cc); - - // The regular spike source spikes at t=0, with these connections it looks like - // (source % 20) == 0 spikes at that moment. - if (source % 20 == 0) { - cc.source = {ncell_, 0}; - conns.push_back(cc); - } - } - - return conns; - } -}; - -std::unique_ptr<recipe> make_basic_rgraph_recipe( - cell_gid_type ncell, - basic_recipe_param param, - probe_distribution pdist) -{ - return std::unique_ptr<recipe>(new basic_rgraph_recipe(ncell, param, pdist)); -} - -class basic_kgraph_recipe: public basic_cell_recipe { -public: - basic_kgraph_recipe(cell_gid_type ncell, - basic_recipe_param param, - probe_distribution pdist = probe_distribution{}): - basic_cell_recipe(ncell, std::move(param), std::move(pdist)) - { - if (std::size_t(param.num_synapses) != ncell-1) { - throw std::runtime_error("number of synapses per cell must equal number " - "of cells minus one in complete graph model"); - } - } - - std::vector<cell_connection> connections_on(cell_gid_type i) const override { - std::vector<cell_connection> conns; - // The spike source does not have inputs - if (i == ncell_) { - return conns; - } - auto conn_param_gen = std::mt19937(i); // TODO: replace this with hashing generator... - - for (unsigned t=0; t<param_.num_synapses; ++t) { - cell_gid_type source = t>=i? t+1: t; - arb_assert(source<ncell_); - - cell_connection cc = draw_connection_params(conn_param_gen); - cc.source = {source, 0}; - cc.dest = {i, t}; - conns.push_back(cc); - - // The spike source spikes at t=0, with these connections it looks like - // (source % 20) == 0 spikes at that moment. - if (source % 20 == 0) { - cc.source = {ncell_, 0}; - conns.push_back(cc); - } - } - - return conns; - } -}; - -std::unique_ptr<recipe> make_basic_kgraph_recipe( - cell_gid_type ncell, - basic_recipe_param param, - probe_distribution pdist) -{ - return std::unique_ptr<recipe>(new basic_kgraph_recipe(ncell, param, pdist)); -} - -} // namespace arb diff --git a/example/miniapp/miniapp_recipes.hpp b/example/miniapp/miniapp_recipes.hpp deleted file mode 100644 index 94103c1f..00000000 --- a/example/miniapp/miniapp_recipes.hpp +++ /dev/null @@ -1,59 +0,0 @@ -#pragma once - -#include <cstddef> -#include <memory> -#include <stdexcept> - -#include <arbor/util/optional.hpp> -#include <arbor/recipe.hpp> - -#include "morphology_pool.hpp" - -// miniapp-specific recipes - -namespace arb { - -struct probe_distribution { - float proportion = 1.f; // what proportion of cells should get probes? - bool all_segments = true; // false => soma only - bool membrane_voltage = true; - bool membrane_current = true; -}; - -struct basic_recipe_param { - // `num_compartments` is the number of compartments to place in each - // unbranched section of the morphology, A value of zero indicates that - // the number of compartments should equal the number of piecewise - // linear segments in the morphology description of that branch. - unsigned num_compartments = 1; - - // Total number of synapses on each cell. - unsigned num_synapses = 1; - - std::string synapse_type = "expsyn"; - float min_connection_delay_ms = 20.0; - float mean_connection_delay_ms = 20.75; - float syn_weight_per_cell = 0.3; - - morphology_pool morphologies = default_morphology_pool; - - // If true, iterate through morphologies rather than select randomly. - bool morphology_round_robin = false; -}; - -std::unique_ptr<recipe> make_basic_ring_recipe( - cell_gid_type ncell, - basic_recipe_param param, - probe_distribution pdist = probe_distribution{}); - -std::unique_ptr<recipe> make_basic_kgraph_recipe( - cell_gid_type ncell, - basic_recipe_param param, - probe_distribution pdist = probe_distribution{}); - -std::unique_ptr<recipe> make_basic_rgraph_recipe( - cell_gid_type ncell, - basic_recipe_param param, - probe_distribution pdist = probe_distribution{}); - -} // namespace arb diff --git a/example/miniapp/morphology_pool.cpp b/example/miniapp/morphology_pool.cpp deleted file mode 100644 index 353913b1..00000000 --- a/example/miniapp/morphology_pool.cpp +++ /dev/null @@ -1,56 +0,0 @@ -#include <fstream> -#include <memory> -#include <vector> - -#include <arbor/morphology.hpp> -#include <arbor/swcio.hpp> - -#include <sup/glob.hpp> -#include <sup/path.hpp> - -#include "morphology_pool.hpp" - -namespace arb { - -static morphology make_basic_y_morphology() { - morphology morph; - - // soma of diameter 12.6157 microns. - // proximal section: 200 microns, radius 0.5 microns. - // two terminal branches, each: 100 microns, terminal radius 0.25 microns. - morph.soma.r = 12.6157/2; - double x = morph.soma.r; - morph.add_section({{x, 0, 0, 0.5}, {x+200, 0, 0, 0.5}}); - x += 200; - morph.add_section({{x, 0, 0, 0.5}, {x+100, 0, 0, 0.25}}, 1u); - morph.add_section({{x, 0, 0, 0.5}, {x+100, 0, 0, 0.25}}, 1u); - - morph.assert_valid(); - return morph; -} - -morphology_pool default_morphology_pool(make_basic_y_morphology()); - -void load_swc_morphology(morphology_pool& pool, const sup::path& swc_path) { - std::ifstream fi; - fi.exceptions(std::ifstream::failbit); - - fi.open(swc_path.c_str()); - pool.insert(swc_as_morphology(parse_swc_file(fi))); -} - -void load_swc_morphology_glob(morphology_pool& pool, const std::string& swc_pattern) { - std::ifstream fi; - fi.exceptions(std::ifstream::failbit); - - auto swc_paths = sup::glob(swc_pattern); - for (const auto& p: swc_paths) { - fi.open(p.c_str()); - pool.insert(swc_as_morphology(parse_swc_file(fi))); - pool[pool.size()-1].assert_valid(); - fi.close(); - } -} - - -} // namespace arb diff --git a/example/miniapp/morphology_pool.hpp b/example/miniapp/morphology_pool.hpp deleted file mode 100644 index 5212982f..00000000 --- a/example/miniapp/morphology_pool.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -// Maintain a pool of morphologies for use with miniapp recipes. -// The default pool comprises a single ball-and-stick morphology; -// sets of morphologies can be loaded from SWC files. - -#include <memory> -#include <string> -#include <vector> - -#include <arbor/morphology.hpp> -#include <sup/path.hpp> - -namespace arb { - -class morphology_pool { - std::shared_ptr<std::vector<morphology>> pool; - -public: - // Construct default empty pool. - morphology_pool(): pool(new std::vector<morphology>) {} - - // Construct pool with one starting morphology. - explicit morphology_pool(morphology m): pool(new std::vector<morphology>) { - insert(std::move(m)); - } - - std::size_t size() const { return pool->size(); } - const morphology& operator[](std::ptrdiff_t i) const { return (*pool)[i]; } - - void insert(morphology m) { (*pool).push_back(std::move(m)); } - void clear() { (*pool).clear(); } -}; - -extern morphology_pool default_morphology_pool; - -void load_swc_morphology(morphology_pool& pool, const sup::path& swc_path); -void load_swc_morphology_glob(morphology_pool& pool, const std::string& pattern); - -} // namespace arb diff --git a/example/miniapp/plot.py b/example/miniapp/plot.py deleted file mode 100644 index ced8f4f0..00000000 --- a/example/miniapp/plot.py +++ /dev/null @@ -1,22 +0,0 @@ -from matplotlib import pyplot -import numpy as np - -ncol = 3 - -raw = np.fromfile("cell0.txt", sep=" ") -n = raw.size/ncol -data = raw.reshape(n,ncol) - -t = data[:, 0] -soma = data[:, 1] -dend = data[:, 2] - -pyplot.plot(t, soma, 'k') -pyplot.plot(t, dend, 'r') - -pyplot.xlabel('time (ms)') -pyplot.ylabel('mV') -pyplot.xlim([t[0], t[n-1]]) -pyplot.grid() -pyplot.show() - diff --git a/example/miniapp/trace.cpp b/example/miniapp/trace.cpp deleted file mode 100644 index 39db7138..00000000 --- a/example/miniapp/trace.cpp +++ /dev/null @@ -1,52 +0,0 @@ -#include <fstream> -#include <iomanip> -#include <string> - -#include <nlohmann/json.hpp> - -#include <arbor/common_types.hpp> - -#include "trace.hpp" - -using namespace arb; - -static std::string to_string(cell_member_type m) { - return std::to_string(m.gid)+"."+std::to_string(m.index); -} - -void write_trace_csv(const sample_trace& trace, const std::string& prefix) { - auto path = prefix + to_string(trace.probe_id) + "_" + trace.name + ".csv"; - - std::ofstream file(path); - file << "# cell: " << trace.probe_id.gid << "\n"; - file << "# probe: " << trace.probe_id.index << "\n"; - file << "time_ms, " << trace.name << "_" << trace.units << "\n"; - - file.precision(15); - file << std::fixed; - for (const auto& sample: trace.samples) { - file << std::setw(20) << sample.t << ',' << std::setw(20) << sample.v << '\n'; - } -} - -void write_trace_json(const sample_trace& trace, const std::string& prefix) { - auto path = prefix + to_string(trace.probe_id) + "_" + trace.name + ".json"; - - nlohmann::json jrep; - jrep["name"] = trace.name; - jrep["units"] = trace.units; - jrep["cell"] = trace.probe_id.gid; - jrep["probe"] = trace.probe_id.index; - - auto& jt = jrep["data"]["time"]; - auto& jy = jrep["data"][trace.name]; - - for (const auto& sample: trace.samples) { - jt.push_back(sample.t); - jy.push_back(sample.v); - } - - std::ofstream file(path); - file << std::setw(1) << jrep << "\n"; -} - diff --git a/example/miniapp/trace.hpp b/example/miniapp/trace.hpp deleted file mode 100644 index 4cf2a29c..00000000 --- a/example/miniapp/trace.hpp +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -/* - * Store trace data from samplers with metadata. - */ - -#include <string> -#include <vector> - -#include <arbor/common_types.hpp> -#include <arbor/simple_sampler.hpp> - -struct sample_trace { - arb::cell_member_type probe_id; - std::string name; - std::string units; - arb::trace_data<double> samples; -}; - -void write_trace_csv(const sample_trace& trace, const std::string& prefix); -void write_trace_json(const sample_trace& trace, const std::string& prefix); diff --git a/scripts/travis/build.sh b/scripts/travis/build.sh index f36eda21..a0e406b9 100755 --- a/scripts/travis/build.sh +++ b/scripts/travis/build.sh @@ -74,8 +74,4 @@ if [[ "${WITH_DISTRIBUTED}" = "mpi" ]]; then ${launch} ./bin/unit-mpi || error "running MPI distributed unit tests" fi -progress "Miniapp spike comparison test" -make miniapp -j4 || error "building miniapp" -${launch} ./bin/miniapp -n 20 -t 100 || error "running miniapp" - cd $base_path -- GitLab