26#include "TRestDetectorSignal.h"
30#include <TFitResult.h>
42TRestDetectorSignal::TRestDetectorSignal() {
47 fSignalCharge.clear();
49 fPointsOverThreshold.clear();
52TRestDetectorSignal::~TRestDetectorSignal() =
default;
54void TRestDetectorSignal::NewPoint(Double_t time, Double_t data) {
55 fSignalTime.push_back(time);
56 fSignalCharge.push_back(data);
74 Int_t index = GetTimeIndex(x);
77 fSignalTime[index] = x;
78 fSignalCharge[index] += y;
80 fSignalTime.push_back(x);
81 fSignalCharge.push_back(y);
93 Int_t index = GetTimeIndex(p.X());
98 fSignalTime[index] = x;
99 fSignalCharge[index] = y;
101 fSignalTime.push_back(x);
102 fSignalCharge.push_back(y);
123 fSignalTime[index] = t;
124 fSignalCharge[index] = d;
127Double_t TRestDetectorSignal::GetIntegral(Int_t startBin, Int_t endBin)
const {
131 if (endBin <= 0 || endBin > GetNumberOfPoints()) {
132 endBin = GetNumberOfPoints();
136 for (
int i = startBin; i < endBin; i++) {
143void TRestDetectorSignal::Normalize(Double_t scale) {
144 Double_t sum = GetIntegral();
145 for (
int i = 0; i < GetNumberOfPoints(); i++) {
146 fSignalCharge[i] = scale * GetData(i) / sum;
150Double_t TRestDetectorSignal::GetIntegralWithTime(Double_t startTime, Double_t endTime)
const {
152 for (
int i = 0; i < GetNumberOfPoints(); i++) {
153 const auto time = GetTime(i);
154 if (time >= startTime && time <= endTime) {
161Double_t TRestDetectorSignal::GetMaxPeakWithTime(Double_t startTime, Double_t endTime)
const {
162 Double_t max = std::numeric_limits<double>::min();
163 for (
int i = 0; i < GetNumberOfPoints(); i++) {
164 if (GetTime(i) >= startTime && GetTime(i) < endTime) {
165 if (this->GetData(i) > max) max = GetData(i);
231Double_t TRestDetectorSignal::GetAverage(Int_t start, Int_t end) {
234 if (end == 0) end = this->GetNumberOfPoints();
237 for (
int i = start; i <= end; i++) {
238 sum += this->GetData(i);
240 return sum / (end - start + 1);
243Int_t TRestDetectorSignal::GetMaxPeakWidth() {
246 Int_t mIndex = this->GetMaxIndex();
247 Double_t maxValue = this->GetData(mIndex);
249 Double_t value = maxValue;
250 Int_t rightIndex = mIndex;
251 while (value > maxValue / 2) {
252 value = this->GetData(rightIndex);
255 Int_t leftIndex = mIndex;
257 while (value > maxValue / 2) {
258 value = this->GetData(leftIndex);
262 return rightIndex - leftIndex;
265Double_t TRestDetectorSignal::GetMaxPeakValue() {
return GetData(GetMaxIndex()); }
267Int_t TRestDetectorSignal::GetMaxIndex(Int_t from, Int_t to) {
268 Double_t max = std::numeric_limits<double>::min();
274 if (to > GetNumberOfPoints()) {
275 to = GetNumberOfPoints();
279 to = GetNumberOfPoints();
282 for (
int i = from; i < to; i++) {
283 if (this->GetData(i) > max) {
294optional<pair<Double_t, Double_t>>
295TRestDetectorSignal::GetPeakGauss()
297 const auto indexMax =
298 std::distance(fSignalCharge.begin(), std::max_element(fSignalCharge.begin(), fSignalCharge.end()));
299 const auto timeMax = fSignalTime[indexMax];
300 const auto signalMax = fSignalCharge[indexMax];
303 Double_t threshold = signalMax * 0.9;
305 Double_t lowerLimit = timeMax, upperLimit = timeMax;
308 for (
auto i = indexMax; i >= 0; --i) {
309 if (fSignalCharge[i] <= threshold) {
310 lowerLimit = fSignalTime[i];
315 for (
auto i = indexMax; i < GetNumberOfPoints(); ++i) {
316 if (fSignalCharge[i] <= threshold) {
317 lowerLimit = fSignalTime[i];
322 TF1 gauss(
"gaus",
"gaus", lowerLimit, upperLimit);
324 auto signal_graph = std::unique_ptr<TGraph>(GetGraph());
326 TFitResultPtr fitResult =
327 signal_graph->Fit(&gauss,
"QNRS");
330 if (!fitResult->IsValid()) {
334 double energy = gauss.GetParameter(0);
335 double time = gauss.GetParameter(1);
337 return make_pair(time, energy);
342optional<pair<Double_t, Double_t>>
343TRestDetectorSignal::GetPeakLandau()
345 Int_t maxRaw = GetMaxIndex();
346 Double_t maxRawTime =
350 Double_t threshold = GetData(maxRaw) * 0.9;
352 Double_t lowerLimit = maxRawTime, upperLimit = maxRawTime;
355 for (
int i = maxRaw; i >= 0; --i) {
356 if (GetData(i) <= threshold) {
357 lowerLimit = GetTime(i);
363 for (
int i = maxRaw; i < GetNumberOfPoints(); ++i) {
364 if (GetData(i) <= threshold) {
365 upperLimit = GetTime(i);
370 TF1 landau(
"landau",
"landau", lowerLimit, upperLimit);
372 auto signal_graph = std::unique_ptr<TGraph>(GetGraph());
374 TFitResultPtr fitResult =
375 signal_graph->Fit(&landau,
"QNRS");
377 if (!fitResult->IsValid()) {
381 double energy = landau.GetParameter(0);
382 double time = landau.GetParameter(1);
384 return make_pair(time, energy);
389Double_t agetResponseFunction(Double_t* x, Double_t* par) {
394 (x[0] - par[1] + 1.1664) /
396 Double_t f = par[0] / 0.0440895 * exp(-3 * (arg)) * (arg) * (arg) *
401optional<pair<Double_t, Double_t>>
402TRestDetectorSignal::GetPeakAget()
404 Int_t maxRaw = GetMaxIndex();
405 Double_t maxRawTime =
409 Double_t threshold = GetData(maxRaw) * 0.9;
411 Double_t lowerLimit = maxRawTime, upperLimit = maxRawTime;
414 for (
int i = maxRaw; i >= 0; --i) {
415 if (GetData(i) <= threshold) {
416 lowerLimit = GetTime(i);
422 for (
int i = maxRaw; i < GetNumberOfPoints(); ++i) {
423 if (GetData(i) <= threshold) {
424 upperLimit = GetTime(i);
429 TF1 aget(
"aget", agetResponseFunction, lowerLimit, upperLimit, 3);
430 aget.SetParameters(500, maxRawTime, 1.2);
432 auto signal_graph = std::unique_ptr<TGraph>(GetGraph());
434 TFitResultPtr fitResult =
435 signal_graph->Fit(&aget,
"QNRS");
438 if (!fitResult->IsValid()) {
442 double energy = aget.GetParameter(0);
443 double time = aget.GetParameter(1);
445 return make_pair(time, energy);
448Double_t TRestDetectorSignal::GetMaxPeakTime(Int_t from, Int_t to) {
return GetTime(GetMaxIndex(from, to)); }
450Double_t TRestDetectorSignal::GetMinPeakValue() {
return GetData(GetMinIndex()); }
452Int_t TRestDetectorSignal::GetMinIndex()
const {
453 Double_t min = numeric_limits<Double_t>::max();
456 for (
int i = 0; i < GetNumberOfPoints(); i++) {
457 if (this->GetData(i) < min) {
466Double_t TRestDetectorSignal::GetMinTime()
const {
467 if (GetNumberOfPoints() == 0) {
470 Double_t minTime = numeric_limits<Double_t>::max();
471 for (
int i = 0; i < GetNumberOfPoints(); i++) {
472 const Double_t time = GetTime(i);
473 if (time < minTime) {
480Double_t TRestDetectorSignal::GetMaxTime()
const {
481 if (GetNumberOfPoints() == 0) {
484 Double_t maxTime = numeric_limits<Double_t>::min();
485 for (
int i = 0; i < GetNumberOfPoints(); i++) {
486 const auto time = GetTime(i);
487 if (time > maxTime) {
494Int_t TRestDetectorSignal::GetTimeIndex(Double_t t) {
497 for (
int n = 0; n < GetNumberOfPoints(); n++) {
498 if (time == fSignalTime[n]) {
505Bool_t TRestDetectorSignal::isSorted()
const {
506 for (
int i = 0; i < GetNumberOfPoints() - 1; i++) {
507 if (GetTime(i + 1) < GetTime(i)) {
514void TRestDetectorSignal::Sort() {
515 while (!isSorted()) {
516 for (
int i = 0; i < GetNumberOfPoints(); i++) {
517 for (
int j = i; j < GetNumberOfPoints(); j++) {
518 if (GetTime(i) > GetTime(j)) {
519 iter_swap(fSignalTime.begin() + i, fSignalTime.begin() + j);
520 iter_swap(fSignalCharge.begin() + i, fSignalCharge.begin() + j);
527void TRestDetectorSignal::GetDifferentialSignal(
TRestDetectorSignal* diffSignal, Int_t smearPoints) {
530 for (
int i = 0; i < smearPoints; i++) diffSignal->
IncreaseAmplitude(GetTime(i), 0);
532 for (
int i = smearPoints; i < this->GetNumberOfPoints() - smearPoints; i++) {
533 Double_t value = (this->GetData(i + smearPoints) - GetData(i - smearPoints)) /
534 (GetTime(i + smearPoints) - GetTime(i - smearPoints));
535 Double_t time = (GetTime(i + smearPoints) + GetTime(i - smearPoints)) / 2.;
540 for (
int i = GetNumberOfPoints() - smearPoints; i < GetNumberOfPoints(); i++) {
545void TRestDetectorSignal::GetSignalDelayed(
TRestDetectorSignal* delayedSignal, Int_t delay) {
548 for (
int i = 0; i < delay; i++) delayedSignal->
IncreaseAmplitude(GetTime(i), GetData(i));
550 for (
int i = delay; i < GetNumberOfPoints(); i++) {
555void TRestDetectorSignal::GetSignalSmoothed(
TRestDetectorSignal* smthSignal, Int_t averagingPoints) {
558 averagingPoints = (averagingPoints / 2) * 2 + 1;
560 Double_t sum = GetIntegral(0, averagingPoints);
561 for (
int i = 0; i <= averagingPoints / 2; i++)
564 for (
int i = averagingPoints / 2 + 1; i < GetNumberOfPoints() - averagingPoints / 2; i++) {
565 sum -= this->GetData(i - (averagingPoints / 2 + 1));
566 sum += this->GetData(i + averagingPoints / 2);
570 for (
int i = GetNumberOfPoints() - averagingPoints / 2; i < GetNumberOfPoints(); i++)
574Double_t TRestDetectorSignal::GetBaseLine(Int_t startBin, Int_t endBin) {
575 if (endBin - startBin <= 0)
return 0.;
577 Double_t baseLine = 0;
578 for (
int i = startBin; i < endBin; i++) baseLine += fSignalCharge[i];
580 return baseLine / (endBin - startBin);
583Double_t TRestDetectorSignal::GetStandardDeviation(Int_t startBin, Int_t endBin) {
584 Double_t bL = GetBaseLine(startBin, endBin);
585 return GetBaseLineSigma(startBin, endBin, bL);
588Double_t TRestDetectorSignal::GetBaseLineSigma(Int_t startBin, Int_t endBin, Double_t baseline) {
589 Double_t bL = baseline;
590 if (bL == 0) bL = GetBaseLine(startBin, endBin);
592 Double_t baseLineSigma = 0;
593 for (
int i = startBin; i < endBin; i++)
594 baseLineSigma += (bL - fSignalCharge[i]) * (bL - fSignalCharge[i]);
596 return TMath::Sqrt(baseLineSigma / (endBin - startBin));
599Double_t TRestDetectorSignal::SubstractBaseline(Int_t startBin, Int_t endBin) {
600 Double_t bL = GetBaseLine(startBin, endBin);
607void TRestDetectorSignal::AddOffset(Double_t offset) {
608 for (
int i = 0; i < GetNumberOfPoints(); i++) fSignalCharge[i] = fSignalCharge[i] + offset;
611void TRestDetectorSignal::MultiplySignalBy(Double_t factor) {
612 for (
int i = 0; i < GetNumberOfPoints(); i++) fSignalCharge[i] = factor * fSignalCharge[i];
615void TRestDetectorSignal::ExponentialConvolution(Double_t fromTime, Double_t decayTime, Double_t offset) {
616 for (
int i = 0; i < GetNumberOfPoints(); i++) {
617 if (fSignalTime[i] > fromTime) {
619 (fSignalCharge[i] - offset) * exp(-(fSignalTime[i] - fromTime) / decayTime) + offset;
625 if (this->GetNumberOfPoints() != inSignal->GetNumberOfPoints()) {
626 cout <<
"ERROR : I cannot add two signals with different number of points" << endl;
630 Int_t badSignalTimes = 0;
632 for (
int i = 0; i < GetNumberOfPoints(); i++)
633 if (GetTime(i) != inSignal->GetTime(i)) {
634 cout <<
"Time : " << GetTime(i) <<
" != " << inSignal->GetTime(i) << endl;
638 if (badSignalTimes) {
639 cout <<
"ERROR : The times of signal addition must be the same" << endl;
643 for (
int i = 0; i < GetNumberOfPoints(); i++) fSignalCharge[i] += inSignal->GetData(i);
646void TRestDetectorSignal::AddGaussianSignal(Double_t amp, Double_t sigma, Double_t time, Int_t N,
647 Double_t fromTime, Double_t toTime) {
648 for (
int i = 0; i < N; i++) {
649 Double_t tme = fromTime + (double)i / (N - 1) * (toTime - fromTime);
651 Double_t dta = 300 + amp * TMath::Exp(-0.5 * (tme - time) * (tme - time) / sigma / sigma);
653 cout <<
"T : " << tme <<
" D : " << dta << endl;
658void TRestDetectorSignal::GetWhiteNoiseSignal(
TRestDetectorSignal* noiseSignal, Double_t noiseLevel) {
661 for (
int i = 0; i < GetNumberOfPoints(); i++) {
662 TRandom3* fRandom =
new TRandom3(0);
664 noiseSignal->
IncreaseAmplitude(GetTime(i), GetData(i) + fRandom->Gaus(0, noiseLevel));
670void TRestDetectorSignal::GetSignalGaussianConvolution(
TRestDetectorSignal* convSignal, Double_t sigma,
674 Int_t nPoints = GetMaxTime() - GetMinTime();
675 TF1* fGaus =
new TF1(
"fGauss",
"exp(-0.5*((x-[1])/[2])**2)", -nPoints, nPoints);
676 sigma = sigma * 1000.;
677 fGaus->SetParameter(2, sigma);
679 Double_t totChargeInitial = 0.;
680 Double_t totChargeFinal = 0.;
685 for (
int i = 0; i < GetNumberOfPoints(); i++) totChargeInitial += fSignalCharge[i];
688 for (
int i = GetMinTime() - nSigmas * sigma; i < GetMaxTime() + nSigmas * sigma; i++) {
689 for (
int j = 0; j < GetNumberOfPoints(); j++) {
690 if (TMath::Abs(i - GetTime(j)) > nSigmas * sigma)
continue;
691 if (TMath::Abs(i - GetTime(j)) > nSigmas * sigma && i < GetTime(j))
break;
693 fGaus->SetParameter(1, GetTime(j));
694 sum = fSignalCharge[j] / TMath::Sqrt(2. * TMath::Pi()) / sigma * fGaus->Integral(i, i + 1);
697 totChargeFinal += sum;
701 cout <<
"Initial charge of the pulse " << totChargeInitial << endl;
702 cout <<
"Final charge of the pulse " << totChargeFinal << endl;
705void TRestDetectorSignal::WriteSignalToTextFile(
const TString& filename)
const {
706 FILE* fff = fopen(filename.Data(),
"w");
707 for (
int i = 0; i < GetNumberOfPoints(); i++) {
708 fprintf(fff,
"%e\t%e\n", GetTime(i), GetData(i));
713void TRestDetectorSignal::Print()
const {
714 cout <<
"Signal ID : " << GetSignalID() << endl;
715 cout <<
"Integral : " << GetIntegral() << endl;
716 if (!GetSignalName().empty()) {
717 cout <<
"Name: " << GetSignalName() << endl;
719 if (!GetSignalType().empty()) {
720 cout <<
"Type: " << GetSignalType() << endl;
723 cout <<
"------------------------------------------------" << endl;
724 for (
int i = 0; i < GetNumberOfPoints(); i++) {
725 cout <<
"Time : " << GetTime(i) <<
" Charge : " << GetData(i) << endl;
728 cout <<
"================================================" << endl;
731TGraph* TRestDetectorSignal::GetGraph(Int_t color) {
732 if (fGraph !=
nullptr) {
737 fGraph =
new TGraph();
742 fGraph->SetLineWidth(2);
743 fGraph->SetLineColor(color);
744 fGraph->SetMarkerStyle(7);
747 for (
int n = 0; n < GetNumberOfPoints(); n++) {
748 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....