26 #include "TRestDetectorSignal.h"
30 #include <TFitResult.h>
41 TRestDetectorSignal::TRestDetectorSignal() {
46 fSignalCharge.clear();
48 fPointsOverThreshold.clear();
51 TRestDetectorSignal::~TRestDetectorSignal() {
55 void TRestDetectorSignal::NewPoint(Float_t time, Float_t data) {
56 fSignalTime.push_back(time);
57 fSignalCharge.push_back(data);
76 Int_t index = GetTimeIndex(p.X());
81 fSignalTime[index] = x;
82 fSignalCharge[index] += y;
84 fSignalTime.push_back(x);
85 fSignalCharge.push_back(y);
97 Int_t index = GetTimeIndex(p.X());
102 fSignalTime[index] = x;
103 fSignalCharge[index] = y;
105 fSignalTime.push_back(x);
106 fSignalCharge.push_back(y);
127 fSignalTime[index] = t;
128 fSignalCharge[index] = d;
131 Double_t TRestDetectorSignal::GetIntegral(Int_t startBin, Int_t endBin)
const {
135 if (endBin <= 0 || endBin > GetNumberOfPoints()) {
136 endBin = GetNumberOfPoints();
140 for (
int i = startBin; i < endBin; i++) {
147 void TRestDetectorSignal::Normalize(Double_t scale) {
148 Double_t sum = GetIntegral();
150 for (
int i = 0; i < GetNumberOfPoints(); i++) fSignalCharge[i] = scale * GetData(i) / sum;
153 Double_t TRestDetectorSignal::GetIntegralWithTime(Double_t startTime, Double_t endTime)
const {
155 for (
int i = 0; i < GetNumberOfPoints(); i++) {
156 if (GetTime(i) >= startTime && GetTime(i) < endTime) {
164 Double_t TRestDetectorSignal::GetMaxPeakWithTime(Double_t startTime, Double_t endTime) {
165 Double_t max = std::numeric_limits<double>::min();
167 for (
int i = 0; i < GetNumberOfPoints(); i++)
168 if (GetTime(i) >= startTime && GetTime(i) < endTime) {
169 if (this->GetData(i) > max) max = GetData(i);
235 Double_t TRestDetectorSignal::GetAverage(Int_t start, Int_t end) {
238 if (end == 0) end = this->GetNumberOfPoints();
241 for (
int i = start; i <= end; i++) {
242 sum += this->GetData(i);
244 return sum / (end - start + 1);
247 Int_t TRestDetectorSignal::GetMaxPeakWidth() {
250 Int_t mIndex = this->GetMaxIndex();
251 Double_t maxValue = this->GetData(mIndex);
253 Double_t value = maxValue;
254 Int_t rightIndex = mIndex;
255 while (value > maxValue / 2) {
256 value = this->GetData(rightIndex);
259 Int_t leftIndex = mIndex;
261 while (value > maxValue / 2) {
262 value = this->GetData(leftIndex);
266 return rightIndex - leftIndex;
269 Double_t TRestDetectorSignal::GetMaxPeakValue() {
return GetData(GetMaxIndex()); }
271 Int_t TRestDetectorSignal::GetMaxIndex(Int_t from, Int_t to) {
272 Double_t max = std::numeric_limits<double>::min();
275 if (from < 0) from = 0;
276 if (to > GetNumberOfPoints()) to = GetNumberOfPoints();
278 if (to == 0) to = GetNumberOfPoints();
280 for (
int i = from; i < to; i++) {
281 if (this->GetData(i) > max) {
293 TRestDetectorSignal::GetMaxGauss()
295 Int_t maxRaw = GetMaxIndex();
296 Double_t maxRawTime =
298 Double_t energy = 0, time = 0;
299 Double_t lowerLimit = maxRawTime - 0.2;
300 Double_t upperLimit = maxRawTime + 0.4;
302 TF1* gaus =
new TF1(
"gaus",
"gaus", lowerLimit, upperLimit);
303 TH1F* h1 =
new TH1F(
"h1",
"h1", 1000, 0,
307 for (
int i = 0; i < GetNumberOfPoints(); i++) {
308 h1->Fill(GetTime(i), GetData(i));
317 TFitResultPtr fitResult =
318 h1->Fit(gaus,
"QNRS");
321 if (fitResult->IsValid()) {
322 energy = gaus->GetParameter(0);
323 time = gaus->GetParameter(1);
329 <<
"WARNING: bad fit to signal with ID " << GetID() <<
" with maximum at time = " << maxRawTime
332 <<
"Failed fit parameters = " << gaus->GetParameter(0) <<
" || " << gaus->GetParameter(1)
333 <<
" || " << gaus->GetParameter(2) <<
"\n"
334 <<
"Assigned fit parameters : energy = " << energy <<
", time = " << time << endl;
344 TVector2 fitParam(time, energy);
355 TRestDetectorSignal::GetMaxLandau()
357 Int_t maxRaw = GetMaxIndex();
358 Double_t maxRawTime =
360 Double_t energy = 0, time = 0;
361 Double_t lowerLimit = maxRawTime - 0.2;
362 Double_t upperLimit = maxRawTime + 0.4;
364 TF1* landau =
new TF1(
"landau",
"landau", lowerLimit, upperLimit);
365 TH1F* h1 =
new TH1F(
"h1",
"h1", 1000, 0,
369 for (
int i = 0; i < GetNumberOfPoints(); i++) {
370 h1->Fill(GetTime(i), GetData(i));
373 TFitResultPtr fitResult =
374 h1->Fit(landau,
"QNRS");
376 if (fitResult->IsValid()) {
377 energy = landau->GetParameter(0);
378 time = landau->GetParameter(1);
384 <<
"WARNING: bad fit to signal with ID " << GetID() <<
" with maximum at time = " << maxRawTime
387 <<
"Failed fit parameters = " << landau->GetParameter(0) <<
" || " << landau->GetParameter(1)
388 <<
" || " << landau->GetParameter(2) <<
"\n"
389 <<
"Assigned fit parameters : energy = " << energy <<
", time = " << time << endl;
399 TVector2 fitParam(time, energy);
409 Double_t agetResponseFunction(Double_t* x, Double_t* par) {
414 (x[0] - par[1] + 1.1664) /
416 Double_t f = par[0] / 0.0440895 * exp(-3 * (arg)) * (arg) * (arg) *
422 TRestDetectorSignal::GetMaxAget()
424 Int_t maxRaw = GetMaxIndex();
425 Double_t maxRawTime =
427 Double_t energy = 0, time = 0;
429 Double_t lowerLimit = maxRawTime - 0.2;
430 Double_t upperLimit = maxRawTime + 0.7;
432 TF1* aget =
new TF1(
"aget", agetResponseFunction, lowerLimit, upperLimit, 3);
433 TH1F* h1 =
new TH1F(
"h1",
"h1", 1000, 0,
435 aget->SetParameters(500, maxRawTime, 1.2);
438 for (
int i = 0; i < GetNumberOfPoints(); i++) {
439 h1->Fill(GetTime(i), GetData(i));
442 TFitResultPtr fitResult =
443 h1->Fit(aget,
"QNRS");
446 if (fitResult->IsValid()) {
447 energy = aget->GetParameter(0);
448 time = aget->GetParameter(1);
454 <<
"WARNING: bad fit to signal with ID " << GetID() <<
" with maximum at time = " << maxRawTime
457 <<
"Failed fit parameters = " << aget->GetParameter(0) <<
" || " << aget->GetParameter(1)
458 <<
" || " << aget->GetParameter(2) <<
"\n"
459 <<
"Assigned fit parameters : energy = " << energy <<
", time = " << time << endl;
462 TVector2 fitParam(time, energy);
469 Double_t TRestDetectorSignal::GetMaxPeakTime(Int_t from, Int_t to) {
return GetTime(GetMaxIndex(from, to)); }
471 Double_t TRestDetectorSignal::GetMinPeakValue() {
return GetData(GetMinIndex()); }
473 Int_t TRestDetectorSignal::GetMinIndex() {
474 Double_t min = numeric_limits<double>::max();
477 for (
int i = 0; i < GetNumberOfPoints(); i++) {
478 if (this->GetData(i) < min) {
487 Double_t TRestDetectorSignal::GetMinTime()
const {
488 if (GetNumberOfPoints() == 0) {
491 Double_t minTime = numeric_limits<float>::max();
492 for (
int n = 0; n < GetNumberOfPoints(); n++) {
493 if (minTime > fSignalTime[n]) {
494 minTime = fSignalTime[n];
501 Double_t TRestDetectorSignal::GetMaxTime()
const {
502 if (GetNumberOfPoints() == 0) {
505 Double_t maxTime = numeric_limits<float>::min();
506 for (
int n = 0; n < GetNumberOfPoints(); n++) {
507 if (maxTime < fSignalTime[n]) {
508 maxTime = fSignalTime[n];
514 Int_t TRestDetectorSignal::GetTimeIndex(Double_t t) {
517 for (
int n = 0; n < GetNumberOfPoints(); n++)
518 if (time == fSignalTime[n])
return n;
522 Bool_t TRestDetectorSignal::isSorted() {
523 for (
int i = 0; i < GetNumberOfPoints() - 1; i++) {
524 if (GetTime(i + 1) < GetTime(i))
return false;
529 void TRestDetectorSignal::Sort() {
530 while (!isSorted()) {
531 for (
int i = 0; i < GetNumberOfPoints(); i++) {
532 for (
int j = i; j < GetNumberOfPoints(); j++) {
533 if (GetTime(i) > GetTime(j)) {
534 iter_swap(fSignalTime.begin() + i, fSignalTime.begin() + j);
535 iter_swap(fSignalCharge.begin() + i, fSignalCharge.begin() + j);
542 void TRestDetectorSignal::GetDifferentialSignal(
TRestDetectorSignal* diffSignal, Int_t smearPoints) {
545 for (
int i = 0; i < smearPoints; i++) diffSignal->
IncreaseAmplitude(GetTime(i), 0);
547 for (
int i = smearPoints; i < this->GetNumberOfPoints() - smearPoints; i++) {
548 Double_t value = (this->GetData(i + smearPoints) - GetData(i - smearPoints)) /
549 (GetTime(i + smearPoints) - GetTime(i - smearPoints));
550 Double_t time = (GetTime(i + smearPoints) + GetTime(i - smearPoints)) / 2.;
555 for (
int i = GetNumberOfPoints() - smearPoints; i < GetNumberOfPoints(); i++) {
560 void TRestDetectorSignal::GetSignalDelayed(
TRestDetectorSignal* delayedSignal, Int_t delay) {
563 for (
int i = 0; i < delay; i++) delayedSignal->
IncreaseAmplitude(GetTime(i), GetData(i));
565 for (
int i = delay; i < GetNumberOfPoints(); i++) {
570 void TRestDetectorSignal::GetSignalSmoothed(
TRestDetectorSignal* smthSignal, Int_t averagingPoints) {
573 averagingPoints = (averagingPoints / 2) * 2 + 1;
575 Double_t sum = GetIntegral(0, averagingPoints);
576 for (
int i = 0; i <= averagingPoints / 2; i++)
579 for (
int i = averagingPoints / 2 + 1; i < GetNumberOfPoints() - averagingPoints / 2; i++) {
580 sum -= this->GetData(i - (averagingPoints / 2 + 1));
581 sum += this->GetData(i + averagingPoints / 2);
585 for (
int i = GetNumberOfPoints() - averagingPoints / 2; i < GetNumberOfPoints(); i++)
589 Double_t TRestDetectorSignal::GetBaseLine(Int_t startBin, Int_t endBin) {
590 if (endBin - startBin <= 0)
return 0.;
592 Double_t baseLine = 0;
593 for (
int i = startBin; i < endBin; i++) baseLine += fSignalCharge[i];
595 return baseLine / (endBin - startBin);
598 Double_t TRestDetectorSignal::GetStandardDeviation(Int_t startBin, Int_t endBin) {
599 Double_t bL = GetBaseLine(startBin, endBin);
600 return GetBaseLineSigma(startBin, endBin, bL);
603 Double_t TRestDetectorSignal::GetBaseLineSigma(Int_t startBin, Int_t endBin, Double_t baseline) {
604 Double_t bL = baseline;
605 if (bL == 0) bL = GetBaseLine(startBin, endBin);
607 Double_t baseLineSigma = 0;
608 for (
int i = startBin; i < endBin; i++)
609 baseLineSigma += (bL - fSignalCharge[i]) * (bL - fSignalCharge[i]);
611 return TMath::Sqrt(baseLineSigma / (endBin - startBin));
614 Double_t TRestDetectorSignal::SubstractBaseline(Int_t startBin, Int_t endBin) {
615 Double_t bL = GetBaseLine(startBin, endBin);
622 void TRestDetectorSignal::AddOffset(Double_t offset) {
623 for (
int i = 0; i < GetNumberOfPoints(); i++) fSignalCharge[i] = fSignalCharge[i] + offset;
626 void TRestDetectorSignal::MultiplySignalBy(Double_t factor) {
627 for (
int i = 0; i < GetNumberOfPoints(); i++) fSignalCharge[i] = factor * fSignalCharge[i];
630 void TRestDetectorSignal::ExponentialConvolution(Double_t fromTime, Double_t decayTime, Double_t offset) {
631 for (
int i = 0; i < GetNumberOfPoints(); i++) {
632 if (fSignalTime[i] > fromTime)
634 (fSignalCharge[i] - offset) * exp(-(fSignalTime[i] - fromTime) / decayTime) + offset;
639 if (this->GetNumberOfPoints() != inSignal->GetNumberOfPoints()) {
640 cout <<
"ERROR : I cannot add two signals with different number of points" << endl;
644 Int_t badSignalTimes = 0;
646 for (
int i = 0; i < GetNumberOfPoints(); i++)
647 if (GetTime(i) != inSignal->GetTime(i)) {
648 cout <<
"Time : " << GetTime(i) <<
" != " << inSignal->GetTime(i) << endl;
652 if (badSignalTimes) {
653 cout <<
"ERROR : The times of signal addition must be the same" << endl;
657 for (
int i = 0; i < GetNumberOfPoints(); i++) fSignalCharge[i] += inSignal->GetData(i);
660 void TRestDetectorSignal::AddGaussianSignal(Double_t amp, Double_t sigma, Double_t time, Int_t N,
661 Double_t fromTime, Double_t toTime) {
662 for (
int i = 0; i < N; i++) {
663 Double_t tme = fromTime + (double)i / (N - 1) * (toTime - fromTime);
665 Double_t dta = 300 + amp * TMath::Exp(-0.5 * (tme - time) * (tme - time) / sigma / sigma);
667 cout <<
"T : " << tme <<
" D : " << dta << endl;
668 IncreaseAmplitude(tme, dta);
672 void TRestDetectorSignal::GetWhiteNoiseSignal(
TRestDetectorSignal* noiseSignal, Double_t noiseLevel) {
675 for (
int i = 0; i < GetNumberOfPoints(); i++) {
676 TRandom3* fRandom =
new TRandom3(0);
678 noiseSignal->
IncreaseAmplitude(GetTime(i), GetData(i) + fRandom->Gaus(0, noiseLevel));
684 void TRestDetectorSignal::GetSignalGaussianConvolution(
TRestDetectorSignal* convSignal, Double_t sigma,
688 Int_t nPoints = GetMaxTime() - GetMinTime();
689 TF1* fGaus =
new TF1(
"fGauss",
"exp(-0.5*((x-[1])/[2])**2)", -nPoints, nPoints);
690 sigma = sigma * 1000.;
691 fGaus->SetParameter(2, sigma);
693 Double_t totChargeInitial = 0.;
694 Double_t totChargeFinal = 0.;
699 for (
int i = 0; i < GetNumberOfPoints(); i++) totChargeInitial += fSignalCharge[i];
702 for (
int i = GetMinTime() - nSigmas * sigma; i < GetMaxTime() + nSigmas * sigma; i++) {
703 for (
int j = 0; j < GetNumberOfPoints(); j++) {
704 if (TMath::Abs(i - GetTime(j)) > nSigmas * sigma)
continue;
705 if (TMath::Abs(i - GetTime(j)) > nSigmas * sigma && i < GetTime(j))
break;
707 fGaus->SetParameter(1, GetTime(j));
708 sum = fSignalCharge[j] / TMath::Sqrt(2. * TMath::Pi()) / sigma * fGaus->Integral(i, i + 1);
711 totChargeFinal += sum;
715 cout <<
"Initial charge of the pulse " << totChargeInitial << endl;
716 cout <<
"Final charge of the pulse " << totChargeFinal << endl;
719 void TRestDetectorSignal::WriteSignalToTextFile(
const TString& filename) {
720 FILE* fff = fopen(filename.Data(),
"w");
721 for (
int i = 0; i < GetNumberOfPoints(); i++) {
722 fprintf(fff,
"%e\t%e\n", GetTime(i), GetData(i));
727 void TRestDetectorSignal::Print()
const {
728 cout <<
"Signal ID : " << GetSignalID() << endl;
729 cout <<
"Integral : " << GetIntegral() << endl;
730 if (!GetSignalName().empty()) {
731 cout <<
"Name: " << GetSignalName() << endl;
733 if (!GetSignalType().empty()) {
734 cout <<
"Type: " << GetSignalType() << endl;
737 cout <<
"------------------------------------------------" << endl;
738 for (
int i = 0; i < GetNumberOfPoints(); i++) {
739 cout <<
"Time : " << GetTime(i) <<
" Charge : " << GetData(i) << endl;
742 cout <<
"================================================" << endl;
745 TGraph* TRestDetectorSignal::GetGraph(Int_t color) {
746 if (fGraph !=
nullptr) {
751 fGraph =
new TGraph();
756 fGraph->SetLineWidth(2);
757 fGraph->SetLineColor(color);
758 fGraph->SetMarkerStyle(7);
761 for (
int n = 0; n < GetNumberOfPoints(); n++) {
762 fGraph->SetPoint(points, GetTime(n), GetData(n));
void IncreaseAmplitude(TVector2 p)
If the point already exists inside the detector signal event, the amplitude value will be added to th...
void SetPoint(TVector2 p)
If the point already exists inside the detector signal event, it will be overwritten....