Skip to content
This repository was archived by the owner on Mar 20, 2023. It is now read-only.

Commit d0b1171

Browse files
authored
Add summation reports (#514)
* Support i_membrane in summation * Clang format nitpicks * Error when trying to use summation report on soma target
1 parent 625becd commit d0b1171

File tree

8 files changed

+243
-60
lines changed

8 files changed

+243
-60
lines changed

coreneuron/io/nrn_setup.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include "coreneuron/io/mech_report.h"
3737
#include "coreneuron/apps/corenrn_parameters.hpp"
3838
#include "coreneuron/io/nrn_setup.hpp"
39+
#include "coreneuron/io/reports/nrnreport.hpp"
3940

4041
// callbacks into nrn/src/nrniv/nrnbbcore_write.cpp
4142
#include "coreneuron/sim/fast_imem.hpp"
@@ -951,6 +952,7 @@ void read_phase3(NrnThread& nt, UserParams& userParams) {
951952

952953
// set pointer in NrnThread
953954
nt.mapping = (void*) ntmapping;
955+
nt.summation_report_handler_ = std::make_unique<SummationReportMapping>();
954956
}
955957

956958
static size_t memb_list_size(NrnThreadMembList* tml) {

coreneuron/io/reports/nrnreport.hpp

Lines changed: 58 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -17,44 +17,82 @@
1717
#include <string>
1818
#include <vector>
1919
#include <set>
20+
#include <unordered_map>
2021

2122
#define REPORT_MAX_NAME_LEN 256
2223
#define REPORT_MAX_FILEPATH_LEN 4096
2324

2425
namespace coreneuron {
26+
27+
struct SummationReport {
28+
// Contains the values of the summation with index == segment_id
29+
std::vector<double> summation_ = {};
30+
// Map containing the pointers of the currents and its scaling factor for every segment_id
31+
std::unordered_map<int, std::vector<std::pair<double*, int>>> currents_;
32+
};
33+
34+
struct SummationReportMapping {
35+
// Map containing an SummationReport object per report
36+
std::unordered_map<std::string, SummationReport> summation_reports_;
37+
};
38+
2539
// name of the variable in mod file that is used to indicate which synapse
2640
// is enabled or disable for reporting
2741
#define SELECTED_VAR_MOD_NAME "selected_for_report"
2842

2943
/// name of the variable in mod file used for setting synapse id
3044
#define SYNAPSE_ID_MOD_NAME "synapseID"
3145

46+
/*
47+
* Defines the type of target, as per the following syntax:
48+
* 0=Compartment, 1=Cell/Soma, Section { 2=Axon, 3=Dendrite, 4=Apical }
49+
* The "Comp" variations are compartment-based (all segments, not middle only)
50+
*/
51+
enum class TargetType {
52+
Compartment = 0,
53+
Soma = 1,
54+
Axon = 2,
55+
Dendrite = 3,
56+
Apical = 4,
57+
AxonComp = 5,
58+
DendriteComp = 6,
59+
ApicalComp = 7,
60+
};
61+
3262
// enumerate that defines the type of target report requested
33-
enum ReportType { SomaReport, CompartmentReport, SynapseReport, IMembraneReport, SectionReport };
63+
enum ReportType {
64+
SomaReport,
65+
CompartmentReport,
66+
SynapseReport,
67+
IMembraneReport,
68+
SectionReport,
69+
SummationReport
70+
};
3471

3572
// enumerate that defines the section type for a Section report
3673
enum SectionType { Axon, Dendrite, Apical };
3774

3875
struct ReportConfiguration {
39-
std::string name; // name of the report
40-
std::string output_path; // full path of the report
41-
std::string target_name; // target of the report
42-
std::string mech_name; // mechanism name
43-
std::string var_name; // variable name
44-
std::string unit; // unit of the report
45-
std::string format; // format of the report (Bin, hdf5, SONATA)
46-
std::string type_str; // type of report string
47-
std::string population_name; // population name of the report
48-
ReportType type; // type of the report
49-
SectionType section_type; // type of section report
50-
bool section_all_compartments; // flag for section report (all values)
51-
int mech_id; // mechanism
52-
double report_dt; // reporting timestep
53-
double start; // start time of report
54-
double stop; // stop time of report
55-
int num_gids; // total number of gids
56-
int buffer_size; // hint on buffer size used for this report
57-
std::set<int> target; // list of gids for this report
76+
std::string name; // name of the report
77+
std::string output_path; // full path of the report
78+
std::string target_name; // target of the report
79+
std::vector<std::string> mech_names; // mechanism names
80+
std::vector<std::string> var_names; // variable names
81+
std::vector<int> mech_ids; // mechanisms
82+
std::string unit; // unit of the report
83+
std::string format; // format of the report (Bin, hdf5, SONATA)
84+
std::string type_str; // type of report string
85+
std::string population_name; // population name of the report
86+
TargetType target_type; // type of the target
87+
ReportType type; // type of the report
88+
SectionType section_type; // type of section report
89+
bool section_all_compartments; // flag for section report (all values)
90+
double report_dt; // reporting timestep
91+
double start; // start time of report
92+
double stop; // stop time of report
93+
int num_gids; // total number of gids
94+
int buffer_size; // hint on buffer size used for this report
95+
std::set<int> target; // list of gids for this report
5896
};
5997

6098
void setup_report_engine(double dt_report, double mindelay);

coreneuron/io/reports/report_configuration_parser.cpp

Lines changed: 30 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -23,52 +23,54 @@
2323

2424
namespace coreneuron {
2525

26-
/*
27-
* Defines the type of target, as per the following syntax:
28-
* 0=Compartment, 1=Cell/Soma, Section { 2=Axon, 3=Dendrite, 4=Apical }
29-
* The "Comp" variations are compartment-based (all segments, not middle only)
30-
*/
31-
enum class TargetType {
32-
Compartment = 0,
33-
Soma = 1,
34-
Axon = 2,
35-
Dendrite = 3,
36-
Apical = 4,
37-
AxonComp = 5,
38-
DendriteComp = 6,
39-
ApicalComp = 7,
40-
};
4126

4227
/*
43-
* Split filter string ("mech.var_name") into mech_id and var_name
28+
* Split filter comma separated strings ("mech.var_name") into mech_name and var_name
4429
*/
4530
void parse_filter_string(const std::string& filter, ReportConfiguration& config) {
46-
std::istringstream iss(filter);
47-
std::string token;
48-
std::getline(iss, config.mech_name, '.');
49-
std::getline(iss, config.var_name, '.');
31+
std::vector<std::string> mechanisms;
32+
std::stringstream ss(filter);
33+
std::string mechanism;
34+
// Multiple report variables are separated by `,`
35+
while (getline(ss, mechanism, ',')) {
36+
mechanisms.push_back(mechanism);
37+
38+
// Split mechanism name and corresponding reporting variable
39+
std::string mech_name;
40+
std::string var_name;
41+
std::istringstream iss(mechanism);
42+
std::getline(iss, mech_name, '.');
43+
std::getline(iss, var_name, '.');
44+
if (var_name.empty()) {
45+
var_name = "i";
46+
}
47+
config.mech_names.emplace_back(mech_name);
48+
config.var_names.emplace_back(var_name);
49+
if (mech_name == "i_membrane") {
50+
nrn_use_fast_imem = true;
51+
}
52+
}
5053
}
5154

5255
std::vector<ReportConfiguration> create_report_configurations(const std::string& conf_file,
5356
const std::string& output_dir,
5457
std::string& spikes_population_name) {
5558
std::vector<ReportConfiguration> reports;
5659
std::string report_on;
57-
int target_type;
60+
int target;
5861
std::ifstream report_conf(conf_file);
5962

6063
int num_reports = 0;
6164
report_conf >> num_reports;
6265
for (int i = 0; i < num_reports; i++) {
6366
ReportConfiguration report;
64-
// mechansim id registered in coreneuron
65-
report.mech_id = -1;
6667
report.buffer_size = 4; // default size to 4 Mb
6768

6869
report_conf >> report.name >> report.target_name >> report.type_str >> report_on >>
69-
report.unit >> report.format >> target_type >> report.report_dt >> report.start >>
70+
report.unit >> report.format >> target >> report.report_dt >> report.start >>
7071
report.stop >> report.num_gids >> report.buffer_size >> report.population_name;
7172

73+
report.target_type = static_cast<TargetType>(target);
7274
std::transform(report.type_str.begin(),
7375
report.type_str.end(),
7476
report.type_str.begin(),
@@ -79,7 +81,7 @@ std::vector<ReportConfiguration> create_report_configurations(const std::string&
7981
nrn_use_fast_imem = true;
8082
report.type = IMembraneReport;
8183
} else {
82-
switch (static_cast<TargetType>(target_type)) {
84+
switch (report.target_type) {
8385
case TargetType::Soma:
8486
report.type = SomaReport;
8587
break;
@@ -123,11 +125,13 @@ std::vector<ReportConfiguration> create_report_configurations(const std::string&
123125
}
124126
} else if (report.type_str == "synapse") {
125127
report.type = SynapseReport;
128+
} else if (report.type_str == "summation") {
129+
report.type = SummationReport;
126130
} else {
127131
std::cerr << "Report error: unsupported type " << report.type_str << std::endl;
128132
nrn_abort(1);
129133
}
130-
if (report.type == SynapseReport) {
134+
if (report.type == SynapseReport || report.type == SummationReport) {
131135
parse_filter_string(report_on, report);
132136
}
133137
if (report.num_gids) {

coreneuron/io/reports/report_event.cpp

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include "report_event.hpp"
1010
#include "coreneuron/sim/multicore.hpp"
11+
#include "coreneuron/io/reports/nrnreport.hpp"
1112
#include "coreneuron/utils/nrn_assert.h"
1213
#ifdef ENABLE_BIN_REPORTS
1314
#include "reportinglib/Records.h"
@@ -22,25 +23,48 @@ namespace coreneuron {
2223
ReportEvent::ReportEvent(double dt,
2324
double tstart,
2425
const VarsToReport& filtered_gids,
25-
const char* name)
26+
const char* name,
27+
double report_dt)
2628
: dt(dt)
2729
, tstart(tstart)
28-
, report_path(name) {
30+
, report_path(name)
31+
, report_dt(report_dt) {
2932
VarsToReport::iterator it;
3033
nrn_assert(filtered_gids.size());
3134
step = tstart / dt;
35+
reporting_period = static_cast<int>(report_dt / dt);
3236
gids_to_report.reserve(filtered_gids.size());
3337
for (const auto& gid: filtered_gids) {
3438
gids_to_report.push_back(gid.first);
3539
}
3640
std::sort(gids_to_report.begin(), gids_to_report.end());
3741
}
3842

43+
void ReportEvent::summation_alu(NrnThread* nt) {
44+
// Sum currents only on reporting steps
45+
if (static_cast<int>(step) % reporting_period == 0) {
46+
auto& summation_report = nt->summation_report_handler_->summation_reports_[report_path];
47+
// Add currents of all variables in each segment
48+
double sum = 0.0;
49+
for (const auto& kv: summation_report.currents_) {
50+
int segment_id = kv.first;
51+
for (const auto& value: kv.second) {
52+
double current_value = *value.first;
53+
int scale = value.second;
54+
sum += current_value * scale;
55+
}
56+
summation_report.summation_[segment_id] = sum;
57+
sum = 0.0;
58+
}
59+
}
60+
}
61+
3962
/** on deliver, call ReportingLib and setup next event */
4063
void ReportEvent::deliver(double t, NetCvode* nc, NrnThread* nt) {
4164
/* reportinglib is not thread safe */
4265
#pragma omp critical
4366
{
67+
summation_alu(nt);
4468
// each thread needs to know its own step
4569
#ifdef ENABLE_BIN_REPORTS
4670
records_nrec(step, gids_to_report.size(), gids_to_report.data(), report_path.data());

coreneuron/io/reports/report_event.hpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,23 @@ using VarsToReport = std::unordered_map<int, std::vector<VarWithMapping>>;
3232

3333
class ReportEvent: public DiscreteEvent {
3434
public:
35-
ReportEvent(double dt, double tstart, const VarsToReport& filtered_gids, const char* name);
35+
ReportEvent(double dt,
36+
double tstart,
37+
const VarsToReport& filtered_gids,
38+
const char* name,
39+
double report_dt);
3640

3741
/** on deliver, call ReportingLib and setup next event */
3842
void deliver(double t, NetCvode* nc, NrnThread* nt) override;
3943
bool require_checkpoint() override;
44+
void summation_alu(NrnThread* nt);
4045

4146
private:
4247
double dt;
4348
double step;
4449
std::string report_path;
50+
double report_dt;
51+
int reporting_period;
4552
std::vector<int> gids_to_report;
4653
double tstart;
4754
};

0 commit comments

Comments
 (0)