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

Commit 4dfaf2c

Browse files
committed
Record online LFP from multiple electrodes
1 parent 86e1d87 commit 4dfaf2c

File tree

4 files changed

+77
-29
lines changed

4 files changed

+77
-29
lines changed

coreneuron/io/nrn_filehandler.hpp

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -113,30 +113,38 @@ class FileHandler {
113113
template <typename T>
114114
int read_mapping_info(T* mapinfo, NrnThreadMappingInfo* ntmapping, CellMapping* cmap) {
115115
int nsec, nseg, n_scan;
116+
size_t total_lfp_factors;
116117
char line_buf[max_line_length], name[max_line_length];
117118

118119
F.getline(line_buf, sizeof(line_buf));
119-
n_scan = sscanf(line_buf, "%s %d %d", name, &nsec, &nseg);
120+
n_scan = sscanf(line_buf, "%s %d %d %zd", name, &nsec, &nseg, &total_lfp_factors);
120121

121-
nrn_assert(n_scan == 3);
122+
nrn_assert(n_scan == 4);
122123

123124
mapinfo->name = std::string(name);
124125

125126
if (nseg) {
126127
std::vector<int> sec, seg;
127128
std::vector<double> lfp_factors;
129+
128130
sec.reserve(nseg);
129131
seg.reserve(nseg);
130-
lfp_factors.reserve(nseg);
132+
lfp_factors.reserve(total_lfp_factors);
131133

132134
read_array<int>(&sec[0], nseg);
133135
read_array<int>(&seg[0], nseg);
134-
read_array<double>(&lfp_factors[0], nseg);
136+
read_array<double>(&lfp_factors[0], total_lfp_factors);
137+
int num_electrodes = read_int();
135138

139+
int factor_offset = 0;
136140
for (int i = 0; i < nseg; i++) {
137141
mapinfo->add_segment(sec[i], seg[i]);
138142
ntmapping->add_segment_id(seg[i]);
139-
cmap->add_segment_lfp_factor(seg[i], lfp_factors[i]);
143+
int factor_offset = i * num_electrodes;
144+
if (total_lfp_factors > 0) {
145+
std::vector<double> segment_factors(lfp_factors.begin() + factor_offset, lfp_factors.begin() + factor_offset + num_electrodes);
146+
cmap->add_segment_lfp_factor(seg[i], segment_factors);
147+
}
140148
}
141149
}
142150
return nseg;

coreneuron/io/nrnsection_mapping.hpp

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ struct CellMapping {
7575
std::vector<SecMapping*> secmapvec;
7676

7777
/** map containing segment ids an its respective lfp factors */
78-
std::unordered_map<int, double> lfp_factors;
78+
std::unordered_map<int, std::vector<double>> lfp_factors;
7979

8080
CellMapping(int g)
8181
: gid(g) {}
@@ -100,6 +100,15 @@ struct CellMapping {
100100
});
101101
}
102102

103+
/** @brief return the number of electrodes in the lfp_factors map **/
104+
int num_electrodes() const {
105+
int num_electrodes = 0;
106+
if (!lfp_factors.empty()) {
107+
num_electrodes = lfp_factors.begin()->second.size();
108+
}
109+
return num_electrodes;
110+
}
111+
103112
/** @brief number of section lists */
104113
size_t size() const noexcept {
105114
return secmapvec.size();
@@ -141,9 +150,9 @@ struct CellMapping {
141150
return count;
142151
}
143152

144-
/** @brief add the lfp factor of a segment_id */
145-
void add_segment_lfp_factor(const int segment_id, double factor) {
146-
lfp_factors.insert({segment_id, factor});
153+
/** @brief add the lfp electrode factors of a segment_id */
154+
void add_segment_lfp_factor(const int segment_id, std::vector<double> factors) {
155+
lfp_factors.insert({segment_id, factors});
147156
}
148157

149158
~CellMapping() {
@@ -200,5 +209,14 @@ struct NrnThreadMappingInfo {
200209
void add_segment_id(const int segment_id) {
201210
segment_ids.push_back(segment_id);
202211
}
212+
213+
/** @brief Resize the lfp vector */
214+
void prepare_lfp() {
215+
size_t lfp_size = 0;
216+
for (const auto& mapping: mappingvec) {
217+
lfp_size += mapping->num_electrodes();
218+
}
219+
_lfp.resize(lfp_size);
220+
}
203221
};
204222
} // namespace coreneuron

coreneuron/io/reports/report_event.cpp

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -85,25 +85,29 @@ void ReportEvent::lfp_calc(NrnThread* nt) {
8585
int gid = kv.first;
8686
const auto& to_report = kv.second;
8787
const auto& cell_mapping = mapinfo->get_cell_mapping(gid);
88-
89-
int count = 0;
90-
double sum = 0.0;
88+
int num_electrodes = cell_mapping->num_electrodes();
89+
std::vector<double> lfp_values (num_electrodes, 0.0);
9190
for (const auto& kv: cell_mapping->lfp_factors) {
9291
int segment_id = kv.first;
93-
double factor = kv.second;
94-
if (std::isnan(factor)) {
95-
factor = 0.0;
96-
}
97-
double iclamp = 0.0;
98-
for (const auto& value: summation_report.currents_[segment_id]) {
99-
double current_value = *value.first;
100-
int scale = value.second;
101-
iclamp += current_value * scale;
92+
std::vector<double> factors = kv.second;
93+
int electrode_id = 0;
94+
for (auto& factor: factors) {
95+
if (std::isnan(factor)) {
96+
factor = 0.0;
97+
}
98+
double iclamp = 0.0;
99+
for (const auto& value: summation_report.currents_[segment_id]) {
100+
double current_value = *value.first;
101+
int scale = value.second;
102+
iclamp += current_value * scale;
103+
}
104+
lfp_values[electrode_id] += (fast_imem_rhs[segment_id] + iclamp) * factor;
105+
electrode_id++;
102106
}
103-
sum += (fast_imem_rhs[segment_id] + iclamp) * factor;
104-
count++;
105107
}
106-
*(to_report.front().var_value) = sum;
108+
for(int i=0; i < to_report.size(); i++) {
109+
*(to_report[i].var_value) = lfp_values[i];
110+
}
107111
}
108112
}
109113
}

coreneuron/io/reports/report_handler.cpp

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,7 @@ void ReportHandler::create_report(double dt, double tstop, double delay) {
6060
register_custom_report(nt, m_report_config, vars_to_report);
6161
break;
6262
case LFPReport:
63-
// 1 lfp value per gid
64-
mapinfo->_lfp.resize(nt.ncell);
63+
mapinfo->prepare_lfp();
6564
vars_to_report =
6665
get_lfp_vars_to_report(nt, m_report_config, mapinfo->_lfp.data(), nodes_to_gid);
6766
is_soma_target = m_report_config.section_type == SectionType::Soma ||
@@ -356,8 +355,15 @@ VarsToReport ReportHandler::get_lfp_vars_to_report(const NrnThread& nt,
356355
ReportConfiguration& report,
357356
double* report_variable,
358357
const std::vector<int>& nodes_to_gids) const {
358+
const auto* mapinfo = static_cast<NrnThreadMappingInfo*>(nt.mapping);
359+
if (!mapinfo) {
360+
std::cerr << "[LFP] Error : mapping information is missing for a Cell group "
361+
<< nt.ncell << '\n';
362+
nrn_abort(1);
363+
}
359364
auto& summation_report = nt.summation_report_handler_->summation_reports_[report.output_path];
360365
VarsToReport vars_to_report;
366+
off_t offset_lfp = 0;
361367
for (int i = 0; i < nt.ncell; i++) {
362368
int gid = nt.presyns[i].gid_;
363369
if (report.target.find(gid) == report.target.end()) {
@@ -373,10 +379,22 @@ VarsToReport ReportHandler::get_lfp_vars_to_report(const NrnThread& nt,
373379
summation_report.currents_[segment_id].push_back(std::make_pair(var_value, -1));
374380
}
375381
}
382+
const auto& cell_mapping = mapinfo->get_cell_mapping(gid);
383+
if (cell_mapping == nullptr) {
384+
std::cerr
385+
<< "[LFP] Error : Compartment mapping information is missing for gid "
386+
<< gid << '\n';
387+
nrn_abort(1);
388+
}
376389
std::vector<VarWithMapping> to_report;
377-
double* variable = report_variable + i;
378-
to_report.push_back(VarWithMapping(i, variable));
379-
vars_to_report[gid] = to_report;
390+
int num_electrodes = cell_mapping->num_electrodes();
391+
for (int electrode_id = 0; electrode_id < num_electrodes; electrode_id++) {
392+
to_report.emplace_back(VarWithMapping(electrode_id, report_variable + offset_lfp));
393+
offset_lfp++;
394+
}
395+
if (!to_report.empty()) {
396+
vars_to_report[gid] = to_report;
397+
}
380398
}
381399
return vars_to_report;
382400
}

0 commit comments

Comments
 (0)