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

Commit 33f7156

Browse files
Refactor reporting config file reading (#431)
* Refactor reporting config file reading * Use ifstream to read directly * Fix compilation issues in OSX Co-authored-by: Sergio <[email protected]>
1 parent 9c40afb commit 33f7156

File tree

6 files changed

+87
-107
lines changed

6 files changed

+87
-107
lines changed

coreneuron/apps/main1.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -407,14 +407,14 @@ static void trajectory_return() {
407407

408408
std::unique_ptr<ReportHandler> create_report_handler(ReportConfiguration& config) {
409409
std::unique_ptr<ReportHandler> report_handler;
410-
if (std::strcmp(config.format, "Bin") == 0) {
410+
if (config.format == "Bin") {
411411
report_handler = std::make_unique<BinaryReportHandler>(config);
412-
} else if (std::strcmp(config.format, "SONATA") == 0) {
412+
} else if (config.format == "SONATA") {
413413
report_handler = std::make_unique<SonataReportHandler>(config);
414414
}
415415
else {
416416
if (nrnmpi_myid == 0) {
417-
printf(" WARNING : Report name '%s' has unknown format: '%s'.\n", config.name, config.format);
417+
printf(" WARNING : Report name '%s' has unknown format: '%s'.\n", config.name.data(), config.format.data());
418418
}
419419
return nullptr;
420420
}
@@ -477,8 +477,8 @@ extern "C" int run_solve_core(int argc, char** argv) {
477477
}
478478

479479
if (!corenrn_param.reportfilepath.empty()) {
480-
configs = create_report_configurations(corenrn_param.reportfilepath.c_str(),
481-
corenrn_param.outpath.c_str(),
480+
configs = create_report_configurations(corenrn_param.reportfilepath,
481+
corenrn_param.outpath,
482482
spikes_population_name);
483483
reports_needs_finalize = configs.size();
484484
}

coreneuron/io/reports/binary_report_handler.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -74,15 +74,15 @@ void BinaryReportHandler::register_report(const NrnThread& nt,
7474
const CellMapping* m = mapinfo->get_cell_mapping(gid);
7575
extra[0] = vars.size();
7676
create_extra(*m, extra);
77-
records_add_report(config.output_path, gid, gid, gid, config.start, config.stop,
78-
config.report_dt, sizemapping, config.type_str, extramapping,
79-
config.unit);
77+
records_add_report(config.output_path.data(), gid, gid, gid, config.start, config.stop,
78+
config.report_dt, sizemapping, config.type_str.data(), extramapping,
79+
config.unit.data());
8080

81-
records_set_report_max_buffer_size_hint(config.output_path, config.buffer_size);
82-
records_extra_mapping(config.output_path, gid, 5, extra.data());
81+
records_set_report_max_buffer_size_hint(config.output_path.data(), config.buffer_size);
82+
records_extra_mapping(config.output_path.data(), gid, 5, extra.data());
8383
for (const auto& var : vars) {
8484
mapping[0] = var.id;
85-
records_add_var_with_mapping(config.output_path, gid, var.var_value, sizemapping,
85+
records_add_var_with_mapping(config.output_path.data(), gid, var.var_value, sizemapping,
8686
mapping.data());
8787
}
8888
}

coreneuron/io/reports/nrnreport.hpp

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -59,30 +59,30 @@ enum ReportType { SomaReport, CompartmentReport, SynapseReport,
5959
enum SectionType { Axon, Dendrite, Apical };
6060

6161
struct ReportConfiguration {
62-
char name[REPORT_MAX_NAME_LEN]; // name of the report
63-
char output_path[REPORT_MAX_FILEPATH_LEN]; // full path of the report
64-
char target_name[REPORT_MAX_NAME_LEN]; // target of the report
65-
char mech_name[REPORT_MAX_NAME_LEN]; // mechanism name
66-
char var_name[REPORT_MAX_NAME_LEN]; // variable name
67-
char unit[REPORT_MAX_NAME_LEN]; // unit of the report
68-
char format[REPORT_MAX_NAME_LEN]; // format of the report (Bin, hdf5, SONATA)
69-
char type_str[REPORT_MAX_NAME_LEN]; // type of report string
70-
char population_name[REPORT_MAX_NAME_LEN]; // population name of the report
71-
ReportType type; // type of the report
72-
SectionType section_type; // type of section report
73-
bool section_all_compartments; // flag for section report (all values)
74-
int mech_id; // mechanism
75-
double report_dt; // reporting timestep
76-
double start; // start time of report
77-
double stop; // stop time of report
78-
int num_gids; // total number of gids
79-
int buffer_size; // hint on buffer size used for this report
80-
std::set<int> target; // list of gids for this report
62+
std::string name; // name of the report
63+
std::string output_path; // full path of the report
64+
std::string target_name; // target of the report
65+
std::string mech_name; // mechanism name
66+
std::string var_name; // variable name
67+
std::string unit; // unit of the report
68+
std::string format; // format of the report (Bin, hdf5, SONATA)
69+
std::string type_str; // type of report string
70+
std::string population_name; // population name of the report
71+
ReportType type; // type of the report
72+
SectionType section_type; // type of section report
73+
bool section_all_compartments; // flag for section report (all values)
74+
int mech_id; // mechanism
75+
double report_dt; // reporting timestep
76+
double start; // start time of report
77+
double stop; // stop time of report
78+
int num_gids; // total number of gids
79+
int buffer_size; // hint on buffer size used for this report
80+
std::set<int> target; // list of gids for this report
8181
};
8282

8383
void setup_report_engine(double dt_report, double mindelay);
84-
std::vector<ReportConfiguration> create_report_configurations(const char* filename,
85-
const char* output_dir,
84+
std::vector<ReportConfiguration> create_report_configurations(const std::string& filename,
85+
const std::string& output_dir,
8686
std::string& spikes_population_name);
8787
void finalize_report();
8888
void nrn_flush_reports(double t);

coreneuron/io/reports/report_configuration_parser.cpp

Lines changed: 46 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -25,17 +25,20 @@
2525
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
2626
THE POSSIBILITY OF SUCH DAMAGE.
2727
*/
28+
#include <algorithm>
2829
#include <cstdio>
2930
#include <cstdlib>
3031
#include <cstring>
32+
#include <fstream>
3133
#include <iostream>
34+
#include <sstream>
3235
#include <string>
3336
#include <vector>
3437

35-
#include "coreneuron/utils/nrn_assert.h"
3638
#include "coreneuron/io/reports/nrnreport.hpp"
37-
#include "coreneuron/sim/fast_imem.hpp"
3839
#include "coreneuron/mechanism/mech_mapping.hpp"
40+
#include "coreneuron/sim/fast_imem.hpp"
41+
#include "coreneuron/utils/nrn_assert.h"
3942

4043
namespace coreneuron {
4144

@@ -44,8 +47,7 @@ namespace coreneuron {
4447
* 0=Compartment, 1=Cell/Soma, Section { 2=Axon, 3=Dendrite, 4=Apical }
4548
* The "Comp" variations are compartment-based (all segments, not middle only)
4649
*/
47-
enum class TargetType
48-
{
50+
enum class TargetType {
4951
Compartment = 0,
5052
Soma = 1,
5153
Axon = 2,
@@ -59,62 +61,44 @@ enum class TargetType
5961
/*
6062
* Split filter string ("mech.var_name") into mech_id and var_name
6163
*/
62-
void parse_filter_string(char* filter, ReportConfiguration& config) {
63-
char* token = strtok(filter, ".");
64-
if (!token) {
65-
std::cerr << "Error : Invalid report variable, should be mch_name.var_name" << std::endl;
66-
nrn_abort(1);
67-
}
68-
strcpy(config.mech_name, token);
69-
token = strtok(nullptr, "\n");
70-
if (!token) {
71-
std::cerr << "Error : Invalid report variable, should be mch_name.var_name" << std::endl;
72-
nrn_abort(1);
73-
}
74-
strcpy(config.var_name, token);
64+
void parse_filter_string(const std::string &filter, ReportConfiguration &config) {
65+
std::istringstream iss(filter);
66+
std::string token;
67+
std::getline(iss, config.mech_name, '.');
68+
std::getline(iss, config.var_name, '.');
7569
}
7670

77-
std::vector<ReportConfiguration> create_report_configurations(const char* conf_file,
78-
const char* output_dir,
79-
std::string& spikes_population_name) {
71+
std::vector<ReportConfiguration> create_report_configurations(const std::string &conf_file,
72+
const std::string &output_dir,
73+
std::string &spikes_population_name) {
8074
std::vector<ReportConfiguration> reports;
81-
int num_reports = 0;
82-
char report_on[REPORT_MAX_NAME_LEN] = "";
83-
char raw_line[REPORT_MAX_FILEPATH_LEN] = "";
84-
char spikes_population[REPORT_MAX_NAME_LEN] = "";
85-
TargetType target_type;
86-
int* gids;
87-
88-
FILE* fp = fopen(conf_file, "r");
89-
if (!fp) {
90-
std::cerr << "Cannot open configuration file: " << conf_file << ", aborting execution"
91-
<< std::endl;
92-
nrn_abort(1);
93-
}
75+
std::string report_on;
76+
int target_type;
77+
std::ifstream report_conf(conf_file);
9478

95-
fgets(raw_line, REPORT_MAX_FILEPATH_LEN, fp);
96-
sscanf(raw_line, "%d\n", &num_reports);
79+
int num_reports = 0;
80+
report_conf >> num_reports;
9781
for (int i = 0; i < num_reports; i++) {
98-
reports.push_back(ReportConfiguration());
99-
ReportConfiguration& report = reports[reports.size() - 1];
82+
ReportConfiguration report;
10083
// mechansim id registered in coreneuron
10184
report.mech_id = -1;
102-
report.buffer_size = 4; // default size to 4 Mb
103-
fgets(raw_line, REPORT_MAX_FILEPATH_LEN, fp);
104-
sscanf(raw_line, "\n%s %s %s %s %s %s %d %lf %lf %lf %d %d %s\n", report.name,
105-
report.target_name, report.type_str, report_on, report.unit, report.format, &target_type,
106-
&report.report_dt, &report.start, &report.stop, &report.num_gids,
107-
&report.buffer_size, report.population_name);
108-
for (int i = 0; i < REPORT_MAX_NAME_LEN; i++) {
109-
report.type_str[i] = tolower(report.type_str[i]);
110-
}
111-
sprintf(report.output_path, "%s/%s", output_dir, report.name);
112-
if (strcmp(report.type_str, "compartment") == 0) {
113-
if (strcmp(report_on, "i_membrane") == 0) {
85+
report.buffer_size = 4; // default size to 4 Mb
86+
87+
report_conf >> report.name >> report.target_name >> report.type_str >> report_on >>
88+
report.unit >> report.format >> target_type >> report.report_dt >>
89+
report.start >> report.stop >> report.num_gids >> report.buffer_size >>
90+
report.population_name;
91+
92+
std::transform(report.type_str.begin(), report.type_str.end(),
93+
report.type_str.begin(),
94+
[](unsigned char c) { return std::tolower(c); });
95+
report.output_path = output_dir + "/" + report.name;
96+
if (report.type_str == "compartment") {
97+
if (report_on == "i_membrane") {
11498
nrn_use_fast_imem = true;
11599
report.type = IMembraneReport;
116100
} else {
117-
switch (target_type) {
101+
switch (static_cast<TargetType>(target_type)) {
118102
case TargetType::Soma:
119103
report.type = SomaReport;
120104
break;
@@ -156,31 +140,27 @@ std::vector<ReportConfiguration> create_report_configurations(const char* conf_f
156140
nrn_abort(1);
157141
}
158142
}
159-
} else if (strcmp(report.type_str, "synapse") == 0) {
143+
} else if (report.type_str == "synapse") {
160144
report.type = SynapseReport;
161145
} else {
162146
std::cerr << "Report error: unsupported type " << report.type_str << std::endl;
163147
nrn_abort(1);
164148
}
165-
166-
if (report.type == SynapseReport)
149+
if (report.type == SynapseReport) {
167150
parse_filter_string(report_on, report);
168-
151+
}
169152
if (report.num_gids) {
170-
gids = (int*)calloc(report.num_gids, sizeof(int));
171-
fread(gids, sizeof(int), report.num_gids, fp);
172-
// extra new line
173-
fgets(raw_line, REPORT_MAX_FILEPATH_LEN, fp);
174-
for (int i = 0; i < report.num_gids; i++) {
175-
report.target.insert(gids[i]);
176-
}
177-
free(gids);
153+
std::vector<int> new_gids(report.num_gids);
154+
report_conf.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
155+
report_conf.read(reinterpret_cast<char *>(new_gids.data()), report.num_gids * sizeof(int));
156+
report.target = std::set<int>(new_gids.begin(), new_gids.end());
157+
// extra new line: skip
158+
report_conf.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
178159
}
160+
reports.push_back(report);
179161
}
180-
fgets(raw_line, REPORT_MAX_NAME_LEN, fp);
181-
sscanf(raw_line, "%s\n", spikes_population);
182-
spikes_population_name = spikes_population;
183-
fclose(fp);
162+
163+
report_conf >> spikes_population_name;
184164
return reports;
185165
}
186166
} // namespace coreneuron

coreneuron/io/reports/report_handler.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ void ReportHandler::create_report(double dt, double tstop, double delay) {
1111
}
1212
m_report_config.stop = std::min(m_report_config.stop, tstop);
1313

14-
m_report_config.mech_id = nrn_get_mechtype(m_report_config.mech_name);
14+
m_report_config.mech_id = nrn_get_mechtype(m_report_config.mech_name.data());
1515
if (m_report_config.type == SynapseReport && m_report_config.mech_id == -1) {
1616
std::cerr << "[ERROR] mechanism to report: " << m_report_config.mech_name
1717
<< " is not mapped in this simulation, cannot report on it \n";
@@ -51,7 +51,7 @@ void ReportHandler::create_report(double dt, double tstop, double delay) {
5151
}
5252
if (!vars_to_report.empty()) {
5353
auto report_event =
54-
std::make_unique<ReportEvent>(dt, t, vars_to_report, m_report_config.output_path);
54+
std::make_unique<ReportEvent>(dt, t, vars_to_report, m_report_config.output_path.data());
5555
report_event->send(t, net_cvode_instance, &nt);
5656
m_report_events.push_back(std::move(report_event));
5757
}
@@ -263,7 +263,7 @@ VarsToReport ReportHandler::get_custom_vars_to_report(const NrnThread& nt,
263263
}
264264
if ((nodes_to_gids[ml->nodeindices[j]] == gid) && report_variable) {
265265
double* var_value =
266-
get_var_location_from_var_name(report.mech_id, report.var_name, ml, j);
266+
get_var_location_from_var_name(report.mech_id, report.var_name.data(), ml, j);
267267
const auto synapse_id = static_cast<int>(
268268
*get_var_location_from_var_name(report.mech_id, SYNAPSE_ID_MOD_NAME, ml, j));
269269
nrn_assert(synapse_id && var_value);

coreneuron/io/reports/sonata_report_handler.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,20 +38,20 @@ void SonataReportHandler::register_custom_report(const NrnThread& nt,
3838
void SonataReportHandler::register_report(const NrnThread& nt,
3939
ReportConfiguration& config,
4040
const VarsToReport& vars_to_report) {
41-
sonata_create_report(config.output_path, config.start, config.stop, config.report_dt,
42-
config.type_str);
43-
sonata_set_report_max_buffer_size_hint(config.output_path, config.buffer_size);
41+
sonata_create_report(config.output_path.data(), config.start, config.stop, config.report_dt,
42+
config.type_str.data());
43+
sonata_set_report_max_buffer_size_hint(config.output_path.data(), config.buffer_size);
4444

4545
for (const auto& kv : vars_to_report) {
4646
int gid = kv.first;
4747
const std::vector<VarWithMapping>& vars = kv.second;
4848
if (!vars.size())
4949
continue;
5050

51-
sonata_add_node(config.output_path, config.population_name, gid);
52-
sonata_set_report_max_buffer_size_hint(config.output_path, config.buffer_size);
51+
sonata_add_node(config.output_path.data(), config.population_name.data(), gid);
52+
sonata_set_report_max_buffer_size_hint(config.output_path.data(), config.buffer_size);
5353
for (const auto& variable : vars) {
54-
sonata_add_element(config.output_path, config.population_name, gid, variable.id, variable.var_value);
54+
sonata_add_element(config.output_path.data(), config.population_name.data(), gid, variable.id, variable.var_value);
5555
}
5656
}
5757
}

0 commit comments

Comments
 (0)