20 double dx2(
dot(dx, dx));
21 double dxn(std::sqrt(dx2));
22 if (dxn < std::numeric_limits<double>::epsilon()) {
25 double de2(
dot(de, de));
26 double mu(
dot(dx, de) / dx2);
28 double de_star2(
dot(de_star, de_star));
29 double q2(de_star2 / dx2);
31 double delta(mu * mu - (de2 - radius * radius) / dx2);
32 double one_m_mu(1.0 - mu);
33 auto log_integral = [&q2, &dxn](
double a,
double b) {
34 if (q2 < std::numeric_limits<double>::epsilon()) {
37 s <<
"Log integral: invalid arguments " << b <<
" " << a
38 <<
". Likely electrode exactly on the segment and "
39 <<
"no flooring is present.";
40 throw std::invalid_argument(s.str());
42 return std::abs(std::log(b / a)) / dxn;
44 return std::log((b + std::sqrt(b * b + q2)) / (a + std::sqrt(a * a + q2))) / dxn;
48 return f * log_integral(-mu, one_m_mu);
50 double sqr_delta(std::sqrt(delta));
51 double d1(mu - sqr_delta);
52 double d2(mu + sqr_delta);
55 double b(std::min(d1, 1.0) - mu);
56 parts += log_integral(-mu, b);
59 double b(std::max(d2, 0.0) - mu);
60 parts += log_integral(b, one_m_mu);
63 double maxd1_0(std::max(d1, 0.0)), mind2_1(std::min(d2, 1.0));
64 if (maxd1_0 < mind2_1) {
65 parts += 1.0 / radius * (mind2_1 - maxd1_0);
72 using namespace lfputils;
74 template <LFPCalculatorType Type,
typename SegmentIdTy>
77 const std::vector<double>& radius,
78 const std::vector<SegmentIdTy>& segment_ids,
80 double extra_cellular_conductivity)
81 : segment_ids_(segment_ids) {
82 if (seg_start.size() != seg_end.size()) {
83 throw std::invalid_argument(
"Different number of segment starts and ends.");
85 if (seg_start.size() != radius.size()) {
86 throw std::invalid_argument(
"Different number of segments and radii.");
88 double f(1.0 / (extra_cellular_conductivity * 4.0 *
pi));
90 m.resize(electrodes.size());
91 for (
size_t k = 0; k < electrodes.size(); ++k) {
93 ms.resize(seg_start.size());
94 for (
size_t l = 0; l < seg_start.size(); l++) {
95 ms[l] =
getFactor(electrodes[k], seg_start[l], seg_end[l], radius[l], f);
100 template <LFPCalculatorType Type,
typename SegmentIdTy>
101 template <
typename Vector>
103 std::vector<double> res(m.size());
104 for (
size_t k = 0; k < m.size(); ++k) {
107 for (
size_t l = 0; l < ms.size(); l++) {
108 res[k] += ms[l] * membrane_current[segment_ids_[l]];
113 lfp_values_.resize(res.size());
119 std::swap(res, lfp_values_);
126 const std::vector<double>& radius,
127 const std::vector<int>& segment_ids,
129 double extra_cellular_conductivity);
132 const std::vector<double>& radius,
133 const std::vector<int>& segment_ids,
135 double extra_cellular_conductivity);