67#include "TRestDetectorSignal.h"
71#include <TFitResult.h>
83TRestDetectorSignal::TRestDetectorSignal() {
88 fSignalCharge.clear();
90 fPointsOverThreshold.clear();
93TRestDetectorSignal::~TRestDetectorSignal() =
default;
95void TRestDetectorSignal::NewPoint(Double_t time, Double_t data) {
96 fSignalTime.push_back(time);
97 fSignalCharge.push_back(data);
115 Int_t index = GetTimeIndex(x);
118 fSignalTime[index] = x;
119 fSignalCharge[index] += y;
121 fSignalTime.push_back(x);
122 fSignalCharge.push_back(y);
134 Int_t index = GetTimeIndex(p.X());
139 fSignalTime[index] = x;
140 fSignalCharge[index] = y;
142 fSignalTime.push_back(x);
143 fSignalCharge.push_back(y);
164 fSignalTime[index] = t;
165 fSignalCharge[index] = d;
168Double_t TRestDetectorSignal::GetIntegral(Int_t startBin, Int_t endBin)
const {
172 if (endBin <= 0 || endBin > GetNumberOfPoints()) {
173 endBin = GetNumberOfPoints();
177 for (
int i = startBin; i < endBin; i++) {
184void TRestDetectorSignal::Normalize(Double_t scale) {
185 Double_t sum = GetIntegral();
186 for (
int i = 0; i < GetNumberOfPoints(); i++) {
187 fSignalCharge[i] = scale * GetData(i) / sum;
191Double_t TRestDetectorSignal::GetIntegralWithTime(Double_t startTime, Double_t endTime)
const {
193 for (
int i = 0; i < GetNumberOfPoints(); i++) {
194 const auto time = GetTime(i);
195 if (time >= startTime && time <= endTime) {
202Double_t TRestDetectorSignal::GetMaxPeakWithTime(Double_t startTime, Double_t endTime)
const {
203 Double_t max = std::numeric_limits<double>::min();
204 for (
int i = 0; i < GetNumberOfPoints(); i++) {
205 if (GetTime(i) >= startTime && GetTime(i) < endTime) {
206 if (this->GetData(i) > max) max = GetData(i);
272Double_t TRestDetectorSignal::GetAverage(Int_t start, Int_t end) {
275 if (end == 0) end = this->GetNumberOfPoints();
278 for (
int i = start; i <= end; i++) {
279 sum += this->GetData(i);
281 return sum / (end - start + 1);
284Int_t TRestDetectorSignal::GetMaxPeakWidth() {
287 Int_t mIndex = this->GetMaxIndex();
288 Double_t maxValue = this->GetData(mIndex);
290 Double_t value = maxValue;
291 Int_t rightIndex = mIndex;
292 while (value > maxValue / 2) {
293 value = this->GetData(rightIndex);
296 Int_t leftIndex = mIndex;
298 while (value > maxValue / 2) {
299 value = this->GetData(leftIndex);
303 return rightIndex - leftIndex;
306Double_t TRestDetectorSignal::GetMaxPeakValue() {
return GetData(GetMaxIndex()); }
308Int_t TRestDetectorSignal::GetMaxIndex(Int_t from, Int_t to) {
309 Double_t max = std::numeric_limits<double>::min();
315 if (to > GetNumberOfPoints()) {
316 to = GetNumberOfPoints();
320 to = GetNumberOfPoints();
323 for (
int i = from; i < to; i++) {
324 if (this->GetData(i) > max) {
335optional<pair<Double_t, Double_t>>
336TRestDetectorSignal::GetPeakGauss()
338 const auto indexMax =
339 std::distance(fSignalCharge.begin(), std::max_element(fSignalCharge.begin(), fSignalCharge.end()));
340 const auto timeMax = fSignalTime[indexMax];
341 const auto signalMax = fSignalCharge[indexMax];
344 Double_t threshold = signalMax * 0.9;
346 Double_t lowerLimit = timeMax, upperLimit = timeMax;
349 for (
auto i = indexMax; i >= 0; --i) {
350 if (fSignalCharge[i] <= threshold) {
351 lowerLimit = fSignalTime[i];
356 for (
auto i = indexMax; i < GetNumberOfPoints(); ++i) {
357 if (fSignalCharge[i] <= threshold) {
358 lowerLimit = fSignalTime[i];
363 TF1 gauss(
"gaus",
"gaus", lowerLimit, upperLimit);
365 auto signal_graph = std::unique_ptr<TGraph>(GetGraph());
367 TFitResultPtr fitResult =
368 signal_graph->Fit(&gauss,
"QNRS");
371 if (!fitResult->IsValid()) {
375 double energy = gauss.GetParameter(0);
376 double time = gauss.GetParameter(1);
378 return make_pair(time, energy);
383optional<pair<Double_t, Double_t>>
384TRestDetectorSignal::GetPeakLandau()
386 Int_t maxRaw = GetMaxIndex();
387 Double_t maxRawTime =
391 Double_t threshold = GetData(maxRaw) * 0.9;
393 Double_t lowerLimit = maxRawTime, upperLimit = maxRawTime;
396 for (
int i = maxRaw; i >= 0; --i) {
397 if (GetData(i) <= threshold) {
398 lowerLimit = GetTime(i);
404 for (
int i = maxRaw; i < GetNumberOfPoints(); ++i) {
405 if (GetData(i) <= threshold) {
406 upperLimit = GetTime(i);
411 TF1 landau(
"landau",
"landau", lowerLimit, upperLimit);
413 auto signal_graph = std::unique_ptr<TGraph>(GetGraph());
415 TFitResultPtr fitResult =
416 signal_graph->Fit(&landau,
"QNRS");
418 if (!fitResult->IsValid()) {
422 double energy = landau.GetParameter(0);
423 double time = landau.GetParameter(1);
425 return make_pair(time, energy);
430Double_t agetResponseFunction(Double_t* x, Double_t* par) {
435 (x[0] - par[1] + 1.1664) /
437 Double_t f = par[0] / 0.0440895 * exp(-3 * (arg)) * (arg) * (arg) *
442optional<pair<Double_t, Double_t>>
443TRestDetectorSignal::GetPeakAget()
445 Int_t maxRaw = GetMaxIndex();
446 Double_t maxRawTime =
450 Double_t threshold = GetData(maxRaw) * 0.9;
452 Double_t lowerLimit = maxRawTime, upperLimit = maxRawTime;
455 for (
int i = maxRaw; i >= 0; --i) {
456 if (GetData(i) <= threshold) {
457 lowerLimit = GetTime(i);
463 for (
int i = maxRaw; i < GetNumberOfPoints(); ++i) {
464 if (GetData(i) <= threshold) {
465 upperLimit = GetTime(i);
470 TF1 aget(
"aget", agetResponseFunction, lowerLimit, upperLimit, 3);
471 aget.SetParameters(500, maxRawTime, 1.2);
473 auto signal_graph = std::unique_ptr<TGraph>(GetGraph());
475 TFitResultPtr fitResult =
476 signal_graph->Fit(&aget,
"QNRS");
479 if (!fitResult->IsValid()) {
483 double energy = aget.GetParameter(0);
484 double time = aget.GetParameter(1);
486 return make_pair(time, energy);
489Double_t TRestDetectorSignal::GetMaxPeakTime(Int_t from, Int_t to) {
return GetTime(GetMaxIndex(from, to)); }
491Double_t TRestDetectorSignal::GetMinPeakValue() {
return GetData(GetMinIndex()); }
493Int_t TRestDetectorSignal::GetMinIndex()
const {
494 Double_t min = numeric_limits<Double_t>::max();
497 for (
int i = 0; i < GetNumberOfPoints(); i++) {
498 if (this->GetData(i) < min) {
507Double_t TRestDetectorSignal::GetMinTime()
const {
508 if (GetNumberOfPoints() == 0) {
511 Double_t minTime = numeric_limits<Double_t>::max();
512 for (
int i = 0; i < GetNumberOfPoints(); i++) {
513 const Double_t time = GetTime(i);
514 if (time < minTime) {
521Double_t TRestDetectorSignal::GetMaxTime()
const {
522 if (GetNumberOfPoints() == 0) {
525 Double_t maxTime = numeric_limits<Double_t>::min();
526 for (
int i = 0; i < GetNumberOfPoints(); i++) {
527 const auto time = GetTime(i);
528 if (time > maxTime) {
535Int_t TRestDetectorSignal::GetTimeIndex(Double_t t) {
538 for (
int n = 0; n < GetNumberOfPoints(); n++) {
539 if (time == fSignalTime[n]) {
546Bool_t TRestDetectorSignal::isSorted()
const {
547 for (
int i = 0; i < GetNumberOfPoints() - 1; i++) {
548 if (GetTime(i + 1) < GetTime(i)) {
555void TRestDetectorSignal::Sort() {
556 while (!isSorted()) {
557 for (
int i = 0; i < GetNumberOfPoints(); i++) {
558 for (
int j = i; j < GetNumberOfPoints(); j++) {
559 if (GetTime(i) > GetTime(j)) {
560 iter_swap(fSignalTime.begin() + i, fSignalTime.begin() + j);
561 iter_swap(fSignalCharge.begin() + i, fSignalCharge.begin() + j);
568void TRestDetectorSignal::GetDifferentialSignal(
TRestDetectorSignal* diffSignal, Int_t smearPoints) {
571 for (
int i = 0; i < smearPoints; i++) diffSignal->
IncreaseAmplitude(GetTime(i), 0);
573 for (
int i = smearPoints; i < this->GetNumberOfPoints() - smearPoints; i++) {
574 Double_t value = (this->GetData(i + smearPoints) - GetData(i - smearPoints)) /
575 (GetTime(i + smearPoints) - GetTime(i - smearPoints));
576 Double_t time = (GetTime(i + smearPoints) + GetTime(i - smearPoints)) / 2.;
581 for (
int i = GetNumberOfPoints() - smearPoints; i < GetNumberOfPoints(); i++) {
586void TRestDetectorSignal::GetSignalDelayed(
TRestDetectorSignal* delayedSignal, Int_t delay) {
589 for (
int i = 0; i < delay; i++) delayedSignal->
IncreaseAmplitude(GetTime(i), GetData(i));
591 for (
int i = delay; i < GetNumberOfPoints(); i++) {
596void TRestDetectorSignal::GetSignalSmoothed(
TRestDetectorSignal* smthSignal, Int_t averagingPoints) {
599 averagingPoints = (averagingPoints / 2) * 2 + 1;
601 Double_t sum = GetIntegral(0, averagingPoints);
602 for (
int i = 0; i <= averagingPoints / 2; i++)
605 for (
int i = averagingPoints / 2 + 1; i < GetNumberOfPoints() - averagingPoints / 2; i++) {
606 sum -= this->GetData(i - (averagingPoints / 2 + 1));
607 sum += this->GetData(i + averagingPoints / 2);
611 for (
int i = GetNumberOfPoints() - averagingPoints / 2; i < GetNumberOfPoints(); i++)
615Double_t TRestDetectorSignal::GetBaseLine(Int_t startBin, Int_t endBin) {
616 if (endBin - startBin <= 0)
return 0.;
618 Double_t baseLine = 0;
619 for (
int i = startBin; i < endBin; i++) baseLine += fSignalCharge[i];
621 return baseLine / (endBin - startBin);
624Double_t TRestDetectorSignal::GetStandardDeviation(Int_t startBin, Int_t endBin) {
625 Double_t bL = GetBaseLine(startBin, endBin);
626 return GetBaseLineSigma(startBin, endBin, bL);
629Double_t TRestDetectorSignal::GetBaseLineSigma(Int_t startBin, Int_t endBin, Double_t baseline) {
630 Double_t bL = baseline;
631 if (bL == 0) bL = GetBaseLine(startBin, endBin);
633 Double_t baseLineSigma = 0;
634 for (
int i = startBin; i < endBin; i++)
635 baseLineSigma += (bL - fSignalCharge[i]) * (bL - fSignalCharge[i]);
637 return TMath::Sqrt(baseLineSigma / (endBin - startBin));
640Double_t TRestDetectorSignal::SubstractBaseline(Int_t startBin, Int_t endBin) {
641 Double_t bL = GetBaseLine(startBin, endBin);
648void TRestDetectorSignal::AddOffset(Double_t offset) {
649 for (
int i = 0; i < GetNumberOfPoints(); i++) fSignalCharge[i] = fSignalCharge[i] + offset;
652void TRestDetectorSignal::MultiplySignalBy(Double_t factor) {
653 for (
int i = 0; i < GetNumberOfPoints(); i++) fSignalCharge[i] = factor * fSignalCharge[i];
656void TRestDetectorSignal::ExponentialConvolution(Double_t fromTime, Double_t decayTime, Double_t offset) {
657 for (
int i = 0; i < GetNumberOfPoints(); i++) {
658 if (fSignalTime[i] > fromTime) {
660 (fSignalCharge[i] - offset) * exp(-(fSignalTime[i] - fromTime) / decayTime) + offset;
666 if (this->GetNumberOfPoints() != inSignal->GetNumberOfPoints()) {
667 cout <<
"ERROR : I cannot add two signals with different number of points" << endl;
671 Int_t badSignalTimes = 0;
673 for (
int i = 0; i < GetNumberOfPoints(); i++)
674 if (GetTime(i) != inSignal->GetTime(i)) {
675 cout <<
"Time : " << GetTime(i) <<
" != " << inSignal->GetTime(i) << endl;
679 if (badSignalTimes) {
680 cout <<
"ERROR : The times of signal addition must be the same" << endl;
684 for (
int i = 0; i < GetNumberOfPoints(); i++) fSignalCharge[i] += inSignal->GetData(i);
687void TRestDetectorSignal::AddGaussianSignal(Double_t amp, Double_t sigma, Double_t time, Int_t N,
688 Double_t fromTime, Double_t toTime) {
689 for (
int i = 0; i < N; i++) {
690 Double_t tme = fromTime + (double)i / (N - 1) * (toTime - fromTime);
692 Double_t dta = 300 + amp * TMath::Exp(-0.5 * (tme - time) * (tme - time) / sigma / sigma);
694 cout <<
"T : " << tme <<
" D : " << dta << endl;
699void TRestDetectorSignal::GetWhiteNoiseSignal(
TRestDetectorSignal* noiseSignal, Double_t noiseLevel) {
702 for (
int i = 0; i < GetNumberOfPoints(); i++) {
703 TRandom3* fRandom =
new TRandom3(0);
705 noiseSignal->
IncreaseAmplitude(GetTime(i), GetData(i) + fRandom->Gaus(0, noiseLevel));
711void TRestDetectorSignal::GetSignalGaussianConvolution(
TRestDetectorSignal* convSignal, Double_t sigma,
715 Int_t nPoints = GetMaxTime() - GetMinTime();
716 TF1* fGaus =
new TF1(
"fGauss",
"exp(-0.5*((x-[1])/[2])**2)", -nPoints, nPoints);
717 sigma = sigma * 1000.;
718 fGaus->SetParameter(2, sigma);
720 Double_t totChargeInitial = 0.;
721 Double_t totChargeFinal = 0.;
726 for (
int i = 0; i < GetNumberOfPoints(); i++) totChargeInitial += fSignalCharge[i];
729 for (
int i = GetMinTime() - nSigmas * sigma; i < GetMaxTime() + nSigmas * sigma; i++) {
730 for (
int j = 0; j < GetNumberOfPoints(); j++) {
731 if (TMath::Abs(i - GetTime(j)) > nSigmas * sigma)
continue;
732 if (TMath::Abs(i - GetTime(j)) > nSigmas * sigma && i < GetTime(j))
break;
734 fGaus->SetParameter(1, GetTime(j));
735 sum = fSignalCharge[j] / TMath::Sqrt(2. * TMath::Pi()) / sigma * fGaus->Integral(i, i + 1);
738 totChargeFinal += sum;
742 cout <<
"Initial charge of the pulse " << totChargeInitial << endl;
743 cout <<
"Final charge of the pulse " << totChargeFinal << endl;
746void TRestDetectorSignal::WriteSignalToTextFile(
const TString& filename)
const {
747 FILE* fff = fopen(filename.Data(),
"w");
748 for (
int i = 0; i < GetNumberOfPoints(); i++) {
749 fprintf(fff,
"%e\t%e\n", GetTime(i), GetData(i));
754void TRestDetectorSignal::Print()
const {
755 cout <<
"Signal ID : " << GetSignalID() << endl;
756 cout <<
"Integral : " << GetIntegral() << endl;
757 if (!GetSignalName().empty()) {
758 cout <<
"Name: " << GetSignalName() << endl;
760 if (!GetSignalType().empty()) {
761 cout <<
"Type: " << GetSignalType() << endl;
764 cout <<
"------------------------------------------------" << endl;
765 for (
int i = 0; i < GetNumberOfPoints(); i++) {
766 cout <<
"Time : " << GetTime(i) <<
" Charge : " << GetData(i) << endl;
769 cout <<
"================================================" << endl;
772TGraph* TRestDetectorSignal::GetGraph(Int_t color) {
773 if (fGraph !=
nullptr) {
778 fGraph =
new TGraph();
783 fGraph->SetLineWidth(2);
784 fGraph->SetLineColor(color);
785 fGraph->SetMarkerStyle(7);
788 for (
int n = 0; n < GetNumberOfPoints(); n++) {
789 fGraph->SetPoint(points, GetTime(n), GetData(n));
void IncreaseAmplitude(const TVector2 &p)
If the point already exists inside the detector signal event, the amplitude value will be added to th...
void SetPoint(const TVector2 &p)
If the point already exists inside the detector signal event, it will be overwritten....