13double Sensor::m_signalConversion = ElementaryCharge;
23 m_hasTransferFunction(false),
25 m_hasNoiseFunction(false),
27 m_nThresholdCrossings(0),
37 m_className =
"Sensor";
41 m_thresholdCrossings.clear();
45 double& ex,
double& ey,
double& ez,
double& v,
46 Medium*& medium,
int& status) {
48 ex = ey = ez = v = 0.;
55 for (
int i = m_nComponents; i--;) {
56 m_components[i].comp->ElectricField(x, y, z, fx, fy, fz, p, med, stat);
71 double& ex,
double& ey,
double& ez,
Medium*& medium,
81 for (
int i = m_nComponents; i--;) {
82 m_components[i].comp->ElectricField(x, y, z, fx, fy, fz, med, stat);
96 double& bx,
double& by,
double& bz,
int& status) {
101 for (
int i = m_nComponents; i--;) {
102 m_components[i].comp->MagneticField(x, y, z, fx, fy, fz, status);
103 if (status != 0)
continue;
111 double& wx,
double& wy,
double& wz,
112 const std::string label) {
115 double fx = 0., fy = 0., fz = 0.;
117 for (
int i = m_nElectrodes; i--;) {
118 if (m_electrodes[i].label == label) {
120 m_electrodes[i].comp->WeightingField(x, y, z, fx, fy, fz, label);
129 const double z,
const std::string label) {
133 for (
int i = m_nElectrodes; i--;) {
134 if (m_electrodes[i].label == label) {
135 v += m_electrodes[i].comp->WeightingPotential(x, y, z, label);
147 if (m_lastComponent < 0)
return false;
150 m = m_components[m_lastComponent].comp->GetMedium(x, y, z);
154 for (
int i = m_nComponents; i--;) {
155 m = m_components[i].comp->GetMedium(x, y, z);
167 if (!GetBoundingBox(m_xMinUser, m_yMinUser, m_zMinUser, m_xMaxUser,
168 m_yMaxUser, m_zMaxUser)) {
169 std::cerr << m_className <<
"::SetArea:\n";
170 std::cerr <<
" Bounding box is not known.\n";
174 std::cout << m_className <<
"::SetArea:\n";
175 std::cout <<
" " << m_xMinUser <<
" < x [cm] < " << m_xMaxUser <<
"\n";
176 std::cout <<
" " << m_yMinUser <<
" < y [cm] < " << m_yMaxUser <<
"\n";
177 std::cout <<
" " << m_zMinUser <<
" < z [cm] < " << m_zMaxUser <<
"\n";
178 if (std::isinf(m_xMinUser) || std::isinf(m_xMaxUser)) {
179 std::cerr << m_className <<
"::SetArea:\n";
180 std::cerr <<
" Warning: infinite x-range\n";
182 if (std::isinf(m_yMinUser) || std::isinf(m_yMaxUser)) {
183 std::cerr << m_className <<
"::SetArea:\n";
184 std::cerr <<
" Warning: infinite x-range\n";
186 if (std::isinf(m_zMinUser) || std::isinf(m_zMaxUser)) {
187 std::cerr << m_className <<
"::SetArea:\n";
188 std::cerr <<
" Warning: infinite x-range\n";
190 m_hasUserArea =
true;
195 const double xmax,
const double ymax,
const double zmax) {
197 if (
fabs(xmax - xmin) < Small ||
fabs(ymax - ymin) < Small ||
198 fabs(zmax - zmin) < Small) {
199 std::cerr << m_className <<
"::SetArea:\n";
200 std::cerr <<
" Invalid range.\n";
223 m_hasUserArea =
true;
228 double& ymax,
double& zmax) {
256 if (!m_hasUserArea) {
258 std::cerr << m_className <<
"::IsInArea:\n";
259 std::cerr <<
" User area cannot be established.\n";
262 m_hasUserArea =
true;
265 if (x >= m_xMinUser && x <= m_xMaxUser && y >= m_yMinUser &&
266 y <= m_yMaxUser && z >= m_zMinUser && z <= m_zMaxUser) {
271 std::cout << m_className <<
"::IsInArea:\n" << std::endl;
272 std::cout <<
" (" << x <<
", " << y <<
", " << z <<
") "
279 const double x1,
const double y1,
const double z1,
280 double& xc,
double& yc,
double& zc) {
282 for (
int i = m_nComponents; i--;) {
283 if (m_components[i].comp->IsWireCrossed(x0, y0, z0,
284 x1, y1, z1, xc, yc, zc)) {
292 double& yw,
double& rw) {
294 for (
int i = m_nComponents; i--;) {
295 if (m_components[i].comp->IsInTrapRadius(x0, y0, z0, xw, yw, rw)) {
305 std::cerr << m_className <<
"::AddComponent:\n";
306 std::cerr <<
" Component pointer is null.\n";
310 component newComponent;
311 newComponent.comp = comp;
312 m_components.push_back(newComponent);
314 if (m_nComponents == 1) m_lastComponent = 0;
320 std::cerr << m_className <<
"::AddElectrode:\n";
321 std::cerr <<
" Component pointer is null.\n";
325 for (
int i = m_nElectrodes; i--;) {
326 if (m_electrodes[i].label == label) {
327 std::cout << m_className <<
"::AddElectrode:\n";
328 std::cout <<
" Warning: An electrode with label \"" << label
329 <<
"\" exists already.\n";
330 std::cout <<
" Weighting fields will be summed up.\n";
335 electrode newElectrode;
336 newElectrode.comp = comp;
337 newElectrode.label = label;
338 m_electrodes.push_back(newElectrode);
340 m_electrodes[m_nElectrodes - 1].signal.resize(m_nTimeBins);
341 m_electrodes[m_nElectrodes - 1].electronsignal.resize(m_nTimeBins);
342 m_electrodes[m_nElectrodes - 1].ionsignal.resize(m_nTimeBins);
343 std::cout << m_className <<
"::AddElectrode:\n";
344 std::cout <<
" Added readout electrode \"" << label <<
"\".\n";
345 std::cout <<
" All signals are reset.\n";
351 m_components.clear();
353 m_lastComponent = -1;
354 m_electrodes.clear();
360 m_hasUserArea =
false;
369 for (
int i = 0; i < m_nComponents; ++i) {
370 if (!m_components[i].comp->GetVoltageRange(umin, umax))
continue;
372 if (umin < vmin) vmin = umin;
373 if (umax > vmax) vmax = umax;
383 std::cerr << m_className <<
"::GetVoltageRange:\n";
384 std::cerr <<
" Sensor voltage range not known.\n";
390 std::cout << m_className <<
"::GetVoltageRange:\n";
391 std::cout <<
" Voltage range " << vmin <<
" < V < " << vmax <<
".\n";
398 for (
int i = m_nElectrodes; i--;) {
399 m_electrodes[i].charge = 0.;
400 for (
int j = m_nTimeBins; j--;) {
401 m_electrodes[i].signal[j] = 0.;
402 m_electrodes[i].electronsignal[j] = 0.;
403 m_electrodes[i].ionsignal[j] = 0.;
410 const double& x,
const double& y,
const double& z,
411 const double& vx,
const double& vy,
const double& vz) {
414 if (t < m_tStart || dt <= 0.) {
416 std::cerr << m_className <<
"::AddSignal:\n";
417 if (t < m_tStart) std::cerr <<
" Time " << t <<
" out of range.\n";
418 if (dt <= 0.) std::cerr <<
" Time step < 0.\n";
422 const int bin = int((t - m_tStart) / m_tStep);
424 if (bin < 0 || bin >= m_nTimeBins) {
426 std::cerr << m_className <<
"::AddSignal:\n";
427 std::cerr <<
" Bin " << bin <<
" out of range.\n";
431 if (m_nEvents <= 0) m_nEvents = 1;
433 double wx = 0., wy = 0., wz = 0.;
435 std::cout << m_className <<
"::AddSignal:\n";
436 std::cout <<
" Time: " << t <<
"\n";
437 std::cout <<
" Step: " << dt <<
"\n";
438 std::cout <<
" Charge: " << q <<
"\n";
439 std::cout <<
" Velocity: (" << vx <<
", " << vy <<
", " << vz <<
")\n";
441 for (
int i = m_nElectrodes; i--;) {
443 m_electrodes[i].comp->WeightingField(x, y, z, wx, wy, wz,
444 m_electrodes[i].label);
446 const double cur = -q * (wx * vx + wy * vy + wz * vz);
448 std::cout <<
" Electrode " << m_electrodes[i].label <<
":\n";
449 std::cout <<
" Weighting field: (" << wx <<
", " << wy <<
", " << wz
451 std::cout <<
" Induced charge: " << cur* dt <<
"\n";
453 double delta = m_tStart + (bin + 1) * m_tStep - t;
456 m_electrodes[i].signal[bin] += cur * delta;
458 m_electrodes[i].electronsignal[bin] += cur * delta;
460 m_electrodes[i].ionsignal[bin] += cur * delta;
464 while (delta > m_tStep && bin + j < m_nTimeBins) {
465 m_electrodes[i].signal[bin + j] += cur * m_tStep;
467 m_electrodes[i].electronsignal[bin + j] += cur * m_tStep;
469 m_electrodes[i].ionsignal[bin + j] += cur * m_tStep;
474 if (bin + j < m_nTimeBins) {
475 m_electrodes[i].signal[bin + j] += cur * delta;
477 m_electrodes[i].electronsignal[bin + j] += cur * delta;
479 m_electrodes[i].ionsignal[bin + j] += cur * delta;
483 m_electrodes[i].signal[bin] += cur * dt;
485 m_electrodes[i].electronsignal[bin] += cur * dt;
487 m_electrodes[i].ionsignal[bin] += cur * dt;
494 const double z0,
const double x1,
const double y1,
497 if (m_debug) std::cout << m_className <<
"::AddInducedCharge:\n";
498 double w0 = 0., w1 = 0.;
499 for (
int i = m_nElectrodes; i--;) {
502 .comp->WeightingPotential(x0, y0, z0, m_electrodes[i].label);
505 .comp->WeightingPotential(x1, y1, z1, m_electrodes[i].label);
506 m_electrodes[i].charge += q * (w1 - w0);
508 std::cout <<
" Electrode " << m_electrodes[i].label <<
":\n";
509 std::cout <<
" Weighting potential at (" << x0 <<
", " << y0 <<
", "
510 << z0 <<
"): " << w0 <<
"\n";
511 std::cout <<
" Weighting potential at (" << x1 <<
", " << y1 <<
", "
512 << z1 <<
"): " << w1 <<
"\n";
513 std::cout <<
" Induced charge: " << m_electrodes[i].charge <<
"\n";
523 std::cerr << m_className <<
"::SetTimeWindow:\n";
524 std::cerr <<
" Starting time out of range.\n";
530 std::cerr << m_className <<
"::SetTimeWindow:\n";
531 std::cerr <<
" Number of time bins out of range.\n";
533 m_nTimeBins = nsteps;
537 std::cout << m_className <<
"::SetTimeWindow:\n";
538 std::cout <<
" " << m_tStart <<
" < t [ns] < "
539 << m_tStart + m_nTimeBins* m_tStep <<
"\n";
540 std::cout <<
" Step size: " << m_tStep <<
" ns\n";
543 std::cout << m_className <<
"::SetTimeWindow:\n";
544 std::cout <<
" Resetting all signals.\n";
545 for (
int i = m_nElectrodes; i--;) {
546 m_electrodes[i].signal.clear();
547 m_electrodes[i].signal.resize(m_nTimeBins);
548 m_electrodes[i].electronsignal.clear();
549 m_electrodes[i].electronsignal.resize(m_nTimeBins);
550 m_electrodes[i].ionsignal.clear();
551 m_electrodes[i].ionsignal.resize(m_nTimeBins);
558 if (m_nEvents <= 0)
return 0.;
559 if (bin < 0 || bin >= m_nTimeBins)
return 0.;
561 for (
int i = m_nElectrodes; i--;) {
562 if (m_electrodes[i].label == label)
563 sig += m_electrodes[i].electronsignal[bin];
566 std::cout << m_className <<
"::GetElectronSignal:\n";
567 std::cout <<
" Electrode: " << label <<
"\n";
568 std::cout <<
" Bin: " << bin <<
"\n";
569 std::cout <<
" ElectronSignal: " << sig / m_tStep <<
"\n";
571 return m_signalConversion * sig / (m_nEvents * m_tStep);
576 if (m_nEvents <= 0)
return 0.;
577 if (bin < 0 || bin >= m_nTimeBins)
return 0.;
579 for (
int i = m_nElectrodes; i--;) {
580 if (m_electrodes[i].label == label) sig += m_electrodes[i].ionsignal[bin];
583 std::cout << m_className <<
"::GetIonSignal:\n";
584 std::cout <<
" Electrode: " << label <<
"\n";
585 std::cout <<
" Bin: " << bin <<
"\n";
586 std::cout <<
" IonSignal: " << sig / m_tStep <<
"\n";
588 return m_signalConversion * sig / (m_nEvents * m_tStep);
593 if (m_nEvents <= 0)
return 0.;
594 if (bin < 0 || bin >= m_nTimeBins)
return 0.;
596 for (
int i = m_nElectrodes; i--;) {
597 if (m_electrodes[i].label == label) sig += m_electrodes[i].signal[bin];
600 std::cout << m_className <<
"::GetSignal:\n";
601 std::cout <<
" Electrode: " << label <<
"\n";
602 std::cout <<
" Bin: " << bin <<
"\n";
603 std::cout <<
" Signal: " << sig / m_tStep <<
"\n";
605 return m_signalConversion * sig / (m_nEvents * m_tStep);
610 if (m_nEvents <= 0)
return 0.;
612 for (
int i = m_nElectrodes; i--;) {
613 if (m_electrodes[i].label == label) charge += m_electrodes[i].charge;
616 std::cout << m_className <<
"::GetInducedCharge:\n";
617 std::cout <<
" Electrode: " << label <<
"\n";
618 std::cout <<
" Charge: " << charge / m_tStep <<
"\n";
621 return charge / m_nEvents;
627 std::cerr << m_className <<
"::SetTransferFunction:\n";
628 std::cerr <<
" Function pointer is null.\n";
632 m_hasTransferFunction =
true;
633 m_transferFunctionTimes.clear();
634 m_transferFunctionValues.clear();
638 std::vector<double> values) {
640 if (times.empty() || values.empty()) {
641 std::cerr << m_className <<
"::SetTransferFunction:\n";
642 std::cerr <<
" Time and value vectors must not be empty.\n";
644 }
else if (times.size() != values.size()) {
645 std::cerr << m_className <<
"::SetTransferFunction:\n";
646 std::cerr <<
" Time and value vectors must have same size.\n";
649 m_transferFunctionTimes = times;
650 m_transferFunctionValues = values;
652 m_hasTransferFunction =
true;
655double Sensor::InterpolateTransferFunctionTable(
double t) {
657 if (m_transferFunctionTimes.empty() || m_transferFunctionValues.empty()) {
661 if (t < m_transferFunctionTimes.front() ||
662 t > m_transferFunctionTimes.back()) {
667 int iUp = m_transferFunctionTimes.size() - 1;
669 while (iUp - iLow > 1) {
670 iM = (iUp + iLow) >> 1;
671 if (t >= m_transferFunctionTimes[iM]) {
678 return m_transferFunctionValues[iLow] +
679 (t - m_transferFunctionTimes[iLow]) *
680 (m_transferFunctionValues[iUp] - m_transferFunctionValues[iLow]) /
681 (m_transferFunctionTimes[iUp] - m_transferFunctionTimes[iLow]);
686 if (!m_hasTransferFunction)
return 0.;
687 if (m_fTransfer)
return m_fTransfer(t);
688 return InterpolateTransferFunctionTable(t);
693 if (!m_hasTransferFunction) {
694 std::cerr << m_className <<
"::ConvoluteSignal:\n";
695 std::cerr <<
" No transfer function available.\n";
698 if (m_nEvents <= 0) {
699 std::cerr << m_className <<
"::ConvoluteSignal:\n";
700 std::cerr <<
" No signals present.\n";
706 double cnvMax = 1.e10;
708 std::vector<double> cnvTab;
709 cnvTab.resize(2 * m_nTimeBins);
710 int iOffset = m_nTimeBins;
712 for (
int i = 0; i < m_nTimeBins; ++i) {
714 double t = -i * m_tStep;
715 if (t < cnvMin || t > cnvMax) {
716 cnvTab[iOffset - i] = 0.;
717 }
else if (m_fTransfer) {
718 cnvTab[iOffset - i] = m_fTransfer(t);
720 cnvTab[iOffset - i] = InterpolateTransferFunctionTable(t);
725 if (t < cnvMin || t > cnvMax) {
726 cnvTab[iOffset + i] = 0.;
727 }
else if (m_fTransfer) {
728 cnvTab[iOffset + i] = m_fTransfer(t);
730 cnvTab[iOffset + i] = InterpolateTransferFunctionTable(t);
734 std::vector<double> tmpSignal;
735 tmpSignal.resize(m_nTimeBins);
737 for (
int i = 0; i < m_nElectrodes; ++i) {
738 for (
int j = 0; j < m_nTimeBins; ++j) {
740 for (
int k = 0; k < m_nTimeBins; ++k) {
742 m_tStep * cnvTab[iOffset + j - k] * m_electrodes[i].signal[k];
745 for (
int j = 0; j < m_nTimeBins; ++j) {
746 m_electrodes[i].signal[j] = tmpSignal[j];
754 if (m_nEvents <= 0) {
755 std::cerr << m_className <<
"::IntegrateSignal:\n";
756 std::cerr <<
" No signals present.\n";
760 for (
int i = 0; i < m_nElectrodes; ++i) {
761 for (
int j = 0; j < m_nTimeBins; ++j) {
762 m_electrodes[i].signal[j] *= m_tStep;
763 m_electrodes[i].electronsignal[j] *= m_tStep;
764 m_electrodes[i].ionsignal[j] *= m_tStep;
766 m_electrodes[i].signal[j] += m_electrodes[i].signal[j - 1];
767 m_electrodes[i].electronsignal[j] +=
768 m_electrodes[i].electronsignal[j - 1];
769 m_electrodes[i].ionsignal[j] += m_electrodes[i].ionsignal[j - 1];
779 std::cerr << m_className <<
"::SetNoiseFunction:\n";
780 std::cerr <<
" Function pointer is null.\n";
784 m_hasNoiseFunction =
true;
789 if (!m_hasNoiseFunction) {
790 std::cerr << m_className <<
"::AddNoise:\n";
791 std::cerr <<
" Noise function is not defined.\n";
794 if (m_nEvents <= 0) m_nEvents = 1;
796 for (
int i = m_nElectrodes; i--;) {
797 for (
int j = m_nTimeBins; j--;) {
798 const double t = m_tStart + (j + 0.5) * m_tStep;
799 m_electrodes[i].signal[j] += m_fNoise(t);
803 m_electrodes[i].electronsignal[j] += m_fNoise(t);
804 m_electrodes[i].ionsignal[j] += m_fNoise(t);
810 const std::string label,
int& n) {
813 m_thresholdCrossings.clear();
814 m_nThresholdCrossings = n = 0;
815 m_thresholdLevel = thr;
820 if (m_nEvents <= 0) {
821 std::cerr << m_className <<
"::ComputeThresholdCrossings:\n";
822 std::cerr <<
" No signals present.\n";
827 std::vector<double> signal;
828 signal.resize(m_nTimeBins);
829 for (
int i = m_nTimeBins; i--;) signal[i] = 0.;
831 bool foundLabel =
false;
832 for (
int j = m_nElectrodes; j--;) {
833 if (m_electrodes[j].label == label) {
835 for (
int i = m_nTimeBins; i--;) {
836 signal[i] += m_electrodes[j].signal[i];
841 std::cerr << m_className <<
"::ComputeThresholdCrossings:\n";
842 std::cerr <<
" Electrode " << label <<
" not found.\n";
845 for (
int i = m_nTimeBins; i--;) {
846 signal[i] *= m_signalConversion / (m_nEvents * m_tStep);
850 double vMin = signal[0];
851 double vMax = signal[0];
852 for (
int i = m_nTimeBins; i--;) {
853 if (signal[i] < vMin) vMin = signal[i];
854 if (signal[i] > vMax) vMax = signal[i];
856 if (thr < vMin && thr > vMax) {
858 std::cout << m_className <<
"::ComputeThresholdCrossings:\n";
859 std::cout <<
" Threshold outside the range [" << vMin <<
", " << vMax
869 while (rise || fall) {
872 std::cout << m_className <<
"::ComputeThresholdCrossings:\n";
873 std::cout <<
" Hunting for rising edges.\n";
875 std::cout << m_className <<
"::ComputeThresholdCrossings:\n";
876 std::cout <<
" Hunting for falling edges.\n";
880 std::vector<double> times;
881 std::vector<double> values;
884 times.push_back(m_tStart);
885 values.push_back(signal[0]);
888 for (
int i = 1; i < m_nTimeBins; ++i) {
890 const double tNew = m_tStart + i * m_tStep;
891 const double vNew = signal[i];
893 if ((rise && vNew > values.back()) || (fall && vNew < values.back())) {
894 times.push_back(tNew);
895 values.push_back(vNew);
898 }
else if ((values[0] - thr) * (thr - values.back()) >= 0. &&
899 nValues > 1 && ((rise && values.back() > values[0]) ||
900 (fall && values.back() < values[0]))) {
903 thresholdCrossing newCrossing;
904 newCrossing.time = tcr;
905 newCrossing.rise = rise;
906 m_thresholdCrossings.push_back(newCrossing);
907 ++m_nThresholdCrossings;
910 times.push_back(tNew);
911 values.push_back(vNew);
917 times.push_back(tNew);
918 values.push_back(vNew);
923 if ((values[0] - thr) * (thr - values.back()) >= 0. && nValues > 1 &&
924 ((rise && values.back() > values[0]) ||
925 (fall && values.back() < values[0]))) {
927 thresholdCrossing newCrossing;
928 newCrossing.time = tcr;
929 newCrossing.rise = rise;
930 m_thresholdCrossings.push_back(newCrossing);
931 ++m_nThresholdCrossings;
940 n = m_nThresholdCrossings;
943 std::cout << m_className <<
"::ComputeThresholdCrossings:\n";
944 std::cout <<
" Found " << m_nThresholdCrossings <<
" crossings.\n";
945 if (m_nThresholdCrossings > 0) {
946 std::cout <<
" Time [ns] Direction\n";
948 for (
int i = 0; i < m_nThresholdCrossings; ++i) {
949 std::cout <<
" " << m_thresholdCrossings[i].time <<
" ";
950 if (m_thresholdCrossings[i].rise) {
951 std::cout <<
"rising\n";
953 std::cout <<
"falling\n";
964 level = m_thresholdLevel;
966 if (i < 0 || i >= m_nThresholdCrossings) {
967 std::cerr << m_className <<
"::GetThresholdCrossing:\n";
968 std::cerr <<
" Index (" << i <<
") out of range.\n";
969 time = m_tStart + m_nTimeBins * m_tStep;
973 time = m_thresholdCrossings[i].time;
974 rise = m_thresholdCrossings[i].rise;
978bool Sensor::GetBoundingBox(
double& xmin,
double& ymin,
double& zmin,
979 double& xmax,
double& ymax,
double& zmax) {
984 double x0, y0, z0, x1, y1, z1;
985 for (
int i = m_nComponents; i--;) {
986 if (!m_components[i].comp->GetBoundingBox(x0, y0, z0, x1, y1, z1))
continue;
988 if (x0 < xmin) xmin = x0;
989 if (y0 < ymin) ymin = y0;
990 if (z0 < zmin) zmin = z0;
991 if (x1 > xmax) xmax = x1;
992 if (y1 > ymax) ymax = y1;
993 if (z1 > zmax) zmax = z1;
1007 std::cerr << m_className <<
"::GetBoundingBox:\n";
1008 std::cerr <<
" Sensor bounding box not known.\n";
1019 std::cout << m_className <<
"::GetBoundingBox:\n";
1020 std::cout <<
" " << xmin <<
" < x [cm] < " << xmax <<
"\n";
1021 std::cout <<
" " << ymin <<
" < y [cm] < " << ymax <<
"\n";
1022 std::cout <<
" " << zmin <<
" < z [cm] < " << zmax <<
"\n";
DoubleAc fabs(const DoubleAc &f)
void MagneticField(const double x, const double y, const double z, double &bx, double &by, double &bz, int &status)
bool GetVoltageRange(double &vmin, double &vmax)
bool ComputeThresholdCrossings(const double thr, const std::string label, int &n)
void AddElectrode(ComponentBase *comp, std::string label)
bool GetThresholdCrossing(const int i, double &time, double &level, bool &rise)
double GetTransferFunction(const double t)
void AddSignal(const double &q, const double &t, const double &dt, const double &x, const double &y, const double &z, const double &vx, const double &vy, const double &vz)
double WeightingPotential(const double x, const double y, const double z, const std::string label)
void WeightingField(const double x, const double y, const double z, double &wx, double &wy, double &wz, const std::string label)
double GetInducedCharge(const std::string label)
void ElectricField(const double x, const double y, const double z, double &ex, double &ey, double &ez, double &v, Medium *&medium, int &status)
void SetNoiseFunction(double(*f)(double t))
bool IsInArea(const double x, const double y, const double z)
bool IsInTrapRadius(double x0, double y0, double z0, double &xw, double &yw, double &rw)
bool GetMedium(const double x, const double y, const double z, Medium *&medium)
double GetElectronSignal(const std::string label, const int bin)
void SetTransferFunction(double(*f)(double t))
bool IsWireCrossed(const double x0, const double y0, const double z0, const double x1, const double y1, const double z1, double &xc, double &yc, double &zc)
void AddComponent(ComponentBase *comp)
void SetTimeWindow(const double tstart, const double tstep, const int nsteps)
void AddInducedCharge(const double q, const double x0, const double y0, const double z0, const double x1, const double y1, const double z1)
double GetIonSignal(const std::string label, const int bin)
double GetSignal(const std::string label, const int bin)
bool GetArea(double &xmin, double &ymin, double &zmin, double &xmax, double &ymax, double &zmax)
double Divdif(const std::vector< double > &f, const std::vector< double > &a, int nn, double x, int mm)