NEURON
report_event.cpp
Go to the documentation of this file.
1 /*
2 # =============================================================================
3 # Copyright (c) 2016 - 2021 Blue Brain Project/EPFL
4 #
5 # See top-level LICENSE file for details.
6 # =============================================================================
7 */
8 
9 #include "report_event.hpp"
14 #ifdef ENABLE_SONATA_REPORTS
15 #include "bbp/sonata/reports.h"
16 #endif // ENABLE_SONATA_REPORTS
17 
18 namespace coreneuron {
19 
20 #ifdef ENABLE_SONATA_REPORTS
21 ReportEvent::ReportEvent(double dt,
22  double tstart,
23  const VarsToReport& filtered_gids,
24  const char* name,
25  double report_dt,
27  : dt(dt)
28  , tstart(tstart)
29  , report_path(name)
30  , report_dt(report_dt)
31  , report_type(type)
32  , vars_to_report(filtered_gids) {
33  nrn_assert(filtered_gids.size());
34  step = tstart / dt;
35  reporting_period = static_cast<int>(report_dt / dt);
36  gids_to_report.reserve(filtered_gids.size());
37  for (const auto& gid: filtered_gids) {
38  gids_to_report.push_back(gid.first);
39  }
40  std::sort(gids_to_report.begin(), gids_to_report.end());
41 }
42 
43 // Compute and store the weighted sum of currents for each segment,
44 // then compute the soma total as the sum of its segments' currents.
45 // This function assumes that nt->summation_report_handler_ and vars_to_report are properly
46 // populated.
47 
48 void ReportEvent::summation_alu(NrnThread* nt) {
49  auto& summation_report = nt->summation_report_handler_->summation_reports_[report_path];
50  const auto weighted_sum_accumulator = [](double acc, const auto& pair) {
51  // pair.first is a pointer to the current value,
52  // pair.second is the scaling factor
53  return acc + (*pair.first) * pair.second;
54  };
55 
56  // Calculate weighted sum of currents for each segment using std::accumulate
57  for (const auto& [segment_id, current_pairs]: summation_report.currents_) {
58  double sum = std::accumulate(current_pairs.begin(),
59  current_pairs.end(),
60  0.0,
61  weighted_sum_accumulator);
62 
63  summation_report.summation_[segment_id] = sum;
64  }
65 
66  // Calculate the soma total current by summing over its segments using std::accumulate
67  if (!summation_report.gid_segments_.empty()) {
68  const auto accumulator = [&summation_report](double acc, int segment_id) {
69  return acc + summation_report.summation_[segment_id];
70  };
71  for (const auto& [gid, segment_ids]: summation_report.gid_segments_) {
72  double sum_soma =
73  std::accumulate(segment_ids.begin(), segment_ids.end(), 0.0, accumulator);
74 
75  *(vars_to_report[gid].front().var_value) = sum_soma;
76  }
77  }
78 }
79 
80 void ReportEvent::lfp_calc(NrnThread* nt) {
81  auto* mapinfo = static_cast<NrnThreadMappingInfo*>(nt->mapping);
82  double* fast_imem_rhs = nt->nrn_fast_imem->nrn_sav_rhs;
83  auto& summation_report = nt->summation_report_handler_->summation_reports_[report_path];
84  for (const auto& kv: vars_to_report) {
85  int gid = kv.first;
86  const auto& to_report = kv.second;
87  const auto& cell_mapping = mapinfo->get_cell_mapping(gid);
88  int num_electrodes = cell_mapping->num_electrodes();
89  std::vector<double> lfp_values(num_electrodes, 0.0);
90  for (const auto& kv: cell_mapping->lfp_factors) {
91  int segment_id = kv.first;
92  const auto& factors = kv.second;
93  int electrode_id = 0;
94  for (const auto& factor: factors) {
95  double iclamp = 0.0;
96  for (const auto& value: summation_report.currents_[segment_id]) {
97  double current_value = *value.first;
98  int scale = value.second;
99  iclamp += current_value * scale;
100  }
101  lfp_values[electrode_id] += (fast_imem_rhs[segment_id] + iclamp) * factor;
102  electrode_id++;
103  }
104  }
105  for (int i = 0; i < to_report.size(); i++) {
106  *(to_report[i].var_value) = lfp_values[i];
107  }
108  }
109 }
110 
111 /** on deliver, call ReportingLib and setup next event */
112 void ReportEvent::deliver(double t, NetCvode* nc, NrnThread* nt) {
113 /* libsonata is not thread safe */
114 #pragma omp critical
115  {
116  // Sum currents and calculate lfp only on reporting steps
117  if ((static_cast<int>(step) % reporting_period) == 0) {
118  if (report_type == ReportType::Summation) {
119  summation_alu(nt);
120  } else if (report_type == ReportType::LFP) {
121  lfp_calc(nt);
122  }
123  }
124  // each thread needs to know its own step
125 #ifdef ENABLE_SONATA_REPORTS
126  sonata_record_node_data(step,
127  gids_to_report.size(),
128  gids_to_report.data(),
129  report_path.data());
130 #endif
131  send(t + dt, nc, nt);
132  step++;
133  }
134 }
135 
136 bool ReportEvent::require_checkpoint() {
137  return false;
138 }
139 #endif
140 
141 } // Namespace coreneuron
#define i
Definition: md1redef.h:19
step
Definition: extdef.h:7
const char * name
Definition: init.cpp:16
THIS FILE IS AUTO GENERATED DONT MODIFY IT.
#define nrn_assert(x)
assert()-like macro, independent of NDEBUG status
Definition: nrn_assert.h:33
NrnMappingInfo mapinfo
mapping information
short type
Definition: cabvars.h:10
static uint32_t value
Definition: scoprand.cpp:25
CellMapping * get_cell_mapping(int gid)
get cell mapping information for given gid if exist otherwise return NULL.
Represent main neuron object computed by single thread.
Definition: multicore.h:58