diff --git a/commit.msg b/commit.msg new file mode 100644 index 0000000000000000000000000000000000000000..3abb1935698a6efe63d5ea651d8c7d5c017541fe --- /dev/null +++ b/commit.msg @@ -0,0 +1,9 @@ +* change `probe_sort` enum to scoped enum + - renamed to `probeKind` + - refactored out of class + - updated coding guidelines wiki with enum rules +* refactor `std::pair` into structs with meaningfull name types in `cell.hpp` + - not just probes: stimulii and detectors too. +* add profiling region around sampling in `cell_group` +* change output data format for traces to json +* remove white space at end of lines (looking at you Sam) diff --git a/miniapp/miniapp.cpp b/miniapp/miniapp.cpp index 4a619cf9a087dc7fa151ee9613adc6d5ff6357c4..74b551ff4f07fe795514caafde901de1721108dc 100644 --- a/miniapp/miniapp.cpp +++ b/miniapp/miniapp.cpp @@ -100,7 +100,10 @@ struct model { // traces from probes struct trace_data { - using sample_type = std::pair<float,double>; + struct sample_type { + float time; + double value; + }; std::string name; index_type id; std::vector<sample_type> samples; @@ -120,7 +123,8 @@ struct model { float dt_ = 0; simple_sampler_functor(std::vector<trace_data> &traces, size_t index, float dt) : - traces_(traces), trace_index_(index), dt_(dt) {} + traces_(traces), trace_index_(index), dt_(dt) + {} optional<float> operator()(float t, double v) { traces_[trace_index_].samples.push_back({t,v}); @@ -128,8 +132,8 @@ struct model { } }; - mc::sampler make_simple_sampler(index_type probe_gid, const std::string name, - index_type id, float dt) + mc::sampler make_simple_sampler( + index_type probe_gid, const std::string name, index_type id, float dt) { traces.push_back(trace_data{name, id}); return {probe_gid, simple_sampler_functor(traces, traces.size()-1, dt)}; @@ -143,15 +147,17 @@ struct model { void dump_traces() { // do not call during simulation: thread-unsafe access to traces. for (const auto& trace: traces) { - std::stringstream path; - path << "trace_" << trace.id << "_" << trace.name << ".dat"; + auto path = "trace_" + std::to_string(trace.id) + + "_" + trace.name + ".json"; - std::ofstream file(path.str()); - file << "time\t" << trace.name << "\n"; + nlohmann::json json; + json["name"] = trace.name; for (const auto& sample: trace.samples) { - file << sample.first << "\t" << sample.second << "\n"; + json["time"].push_back(sample.time); + json["value"].push_back(sample.value); } - file.close(); + std::ofstream file(path); + file << std::setw(1) << json << std::endl; } } }; @@ -403,8 +409,8 @@ mc::cell make_cell(int compartments_per_segment, int num_synapses) { } // add probes: - auto probe_soma = cell.add_probe({0, 0}, mc::cell::membrane_voltage); - auto probe_dendrite = cell.add_probe({1, 0.5}, mc::cell::membrane_voltage); + auto probe_soma = cell.add_probe({0, 0}, mc::probeKind::membrane_voltage); + auto probe_dendrite = cell.add_probe({1, 0.5}, mc::probeKind::membrane_voltage); EXPECTS(probe_soma==0); EXPECTS(probe_dendrite==1); diff --git a/src/cell.hpp b/src/cell.hpp index f53fb0592c94d76c3dfcd7552814345fde28f874..1c047e18b2b90cba58a805f66f1579723dd0ccd5 100644 --- a/src/cell.hpp +++ b/src/cell.hpp @@ -38,6 +38,11 @@ int find_compartment_index( compartment_model const& graph ); +enum class probeKind { + membrane_voltage, + membrane_current +}; + /// high-level abstract representation of a cell and its segments class cell { public: @@ -46,8 +51,18 @@ public: using index_type = int; using value_type = double; using point_type = point<value_type>; - - enum probe_sort { membrane_voltage, membrane_current }; + struct probe_instance { + segment_location location; + probeKind kind; + }; + struct stimulus_instance { + segment_location location; + i_clamp clamp; + }; + struct detector_instance { + segment_location location; + double threshold; + }; // constructor cell(); @@ -109,12 +124,12 @@ public: ////////////////// void add_stimulus(segment_location loc, i_clamp stim); - std::vector<std::pair<segment_location, i_clamp>>& + std::vector<stimulus_instance>& stimulii() { return stimulii_; } - const std::vector<std::pair<segment_location, i_clamp>>& + const std::vector<stimulus_instance>& stimulii() const { return stimulii_; } @@ -131,12 +146,12 @@ public: ////////////////// void add_detector(segment_location loc, double threshold); - std::vector<std::pair<segment_location, double>>& + std::vector<detector_instance>& detectors() { return spike_detectors_; } - const std::vector<std::pair<segment_location, double>>& + const std::vector<detector_instance>& detectors() const { return spike_detectors_; } @@ -144,12 +159,12 @@ public: ////////////////// // probes ////////////////// - index_type add_probe(segment_location loc, enum probe_sort sort) { - probes_.push_back({loc, sort}); + index_type add_probe(segment_location loc, probeKind kind) { + probes_.push_back({loc, kind}); return probes_.size()-1; } - const std::vector<std::pair<segment_location, enum probe_sort>>& + const std::vector<probe_instance>& probes() const { return probes_; } private: @@ -161,16 +176,16 @@ private: std::vector<segment_ptr> segments_; // the stimulii - std::vector<std::pair<segment_location, i_clamp>> stimulii_; + std::vector<stimulus_instance> stimulii_; // the synapses std::vector<segment_location> synapses_; // the sensors - std::vector<std::pair<segment_location, double>> spike_detectors_; + std::vector<detector_instance> spike_detectors_; // the probes - std::vector<std::pair<segment_location, enum probe_sort>> probes_; + std::vector<probe_instance> probes_; }; // Checks that two cells have the same diff --git a/src/cell_group.hpp b/src/cell_group.hpp index 922b7b197091af6cf4ba7ecc345030bcff3e380e..70bfdeb13123c780744c5875ae125bf631bf6142 100644 --- a/src/cell_group.hpp +++ b/src/cell_group.hpp @@ -24,7 +24,7 @@ struct sampler { index_type probe_gid; // samplers are attached to probes std::function<util::optional<time_type>(time_type, value_type)> sample; }; - + template <typename Cell> class cell_group { public: @@ -49,7 +49,7 @@ public: for (auto& d : c.detectors()) { spike_sources_.push_back( { - 0u, spike_detector_type(cell_, d.first, d.second, 0.f) + 0u, spike_detector_type(cell_, d.location, d.threshold, 0.f) }); } } @@ -76,23 +76,14 @@ public: return { first_probe_gid_, first_probe_gid_+cell_.num_probes() }; } -#ifdef SPLAT - void splat(std::string fname) { - char buffer[128]; - std::ofstream fid(fname); - for (auto i=0u; i<tt.size(); ++i) { - sprintf(buffer, "%8.4f %16.8f %16.8f\n", tt[i], vs[i], vd[i]); - fid << buffer; - } - } -#endif - void advance(double tfinal, double dt) { while (cell_.time()<tfinal) { // take any pending samples float cell_time = cell_.time(); + + nest::mc::util::profiler_enter("sampling"); while (auto m = sample_events_.pop_if_before(cell_time)) { - auto &sampler = samplers_[m->sampler_index]; + auto& sampler = samplers_[m->sampler_index]; EXPECTS((bool)sampler.sample); index_type probe_index = sampler.probe_gid-first_probe_gid_; @@ -102,12 +93,8 @@ public: sample_events_.push(*m); } } + nest::mc::util::profiler_leave(); -#ifdef SPLAT - tt.push_back(cell_.time()); - vs.push_back(cell_.voltage({0,0.0})); - vd.push_back(cell_.voltage({1,0.5})); -#endif // look for events in the next time step auto tstep = std::min(tfinal, cell_.time()+dt); auto next = events_.pop_if_before(tstep); @@ -164,20 +151,14 @@ public: spikes_.clear(); } - void add_sampler(const sampler &s, float start_time = 0) { - unsigned sampler_index = samplers_.size(); + void add_sampler(const sampler& s, float start_time = 0) { + auto sampler_index = uint32_t(samplers_.size()); samplers_.push_back(s); sample_events_.push({sampler_index, start_time}); } - + private: -#ifdef SPLAT - // REMOVE as soon as we have a better way to probe cell state - std::vector<float> tt; - std::vector<float> vs; - std::vector<float> vd; -#endif /// the lowered cell state (e.g. FVM) of the cell cell_type cell_; diff --git a/src/fvm_cell.hpp b/src/fvm_cell.hpp index 947b7a7ba233340274f5113c12d075d7851a1ea1..90e7f7be0d373274aba0b4ff28b908465e674cb5 100644 --- a/src/fvm_cell.hpp +++ b/src/fvm_cell.hpp @@ -382,8 +382,8 @@ fvm_cell<T, I>::fvm_cell(nest::mc::cell const& cell) // add the stimulii for(const auto& stim : cell.stimulii()) { - auto idx = find_compartment_index(stim.first, graph); - stimulii_.push_back( {idx, stim.second} ); + auto idx = find_compartment_index(stim.location, graph); + stimulii_.push_back( {idx, stim.clamp} ); } // add the synapses @@ -406,16 +406,16 @@ fvm_cell<T, I>::fvm_cell(nest::mc::cell const& cell) // record probe locations by index into corresponding state vector for (auto probe : cell.probes()) { - uint32_t comp = find_compartment_index(probe.first, graph); - switch (probe.second) { - case nest::mc::cell::membrane_voltage: - probes_.push_back({&fvm_cell::voltage_, comp}); - break; - case nest::mc::cell::membrane_current: - probes_.push_back({&fvm_cell::current_, comp}); - break; - default: - throw std::logic_error("unrecognized probe sort"); + uint32_t comp = find_compartment_index(probe.location, graph); + switch (probe.kind) { + case probeKind::membrane_voltage: + probes_.push_back({&fvm_cell::voltage_, comp}); + break; + case probeKind::membrane_current: + probes_.push_back({&fvm_cell::current_, comp}); + break; + default: + throw std::logic_error("unrecognized probeKind"); } } }