REST-for-Physics  v2.3
Rare Event Searches ToolKit for Physics
src/TRestRawSignal.cxx
1 /*************************************************************************
2  * This file is part of the REST software framework. *
3  * *
4  * Copyright (C) 2016 GIFNA/TREX (University of Zaragoza) *
5  * For more information see http://gifna.unizar.es/trex *
6  * *
7  * REST is free software: you can redistribute it and/or modify *
8  * it under the terms of the GNU General Public License as published by *
9  * the Free Software Foundation, either version 3 of the License, or *
10  * (at your option) any later version. *
11  * *
12  * REST is distributed in the hope that it will be useful, *
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15  * GNU General Public License for more details. *
16  * *
17  * You should have a copy of the GNU General Public License along with *
18  * REST in $REST_PATH/LICENSE. *
19  * If not, see http://www.gnu.org/licenses/. *
20  * For the list of contributors see $REST_PATH/CREDITS. *
21  *************************************************************************/
22 
60 #include "TRestRawSignal.h"
61 
62 #include <TAxis.h>
63 #include <TF1.h>
64 #include <TMath.h>
65 #include <TRandom3.h>
66 
67 #include <numeric>
68 
69 using namespace std;
70 
71 ClassImp(TRestRawSignal);
72 
77  fGraph = nullptr;
78 
79  Initialize();
80 }
81 
87  fGraph = nullptr;
88 
89  Initialize();
90 
91  fSignalData.resize(nBins, 0);
92 }
93 
98 
103  fSignalData.clear();
104  fPointsOverThreshold.clear();
105  fSignalID = -1;
106 
107  fThresholdIntegral = -1;
108 
109  fHeadPoints = 0;
110  fTailPoints = 0;
111 
112  fBaseLine = 0;
113  fBaseLineSigma = 0;
114 }
115 
121  Int_t nBins = GetNumberOfPoints();
122  Initialize();
123  fSignalData.resize(nBins, 0);
124 }
125 
129 void TRestRawSignal::AddPoint(Short_t value) { fSignalData.push_back(value); }
130 
134 void TRestRawSignal::AddPoint(Double_t value) {
135  if (value > numeric_limits<Short_t>::max()) {
136  value = numeric_limits<Short_t>::max();
137  } else if (value < numeric_limits<Short_t>::min()) {
138  value = numeric_limits<Short_t>::min();
139  }
140  AddPoint((Short_t)value);
141 }
142 
148 Short_t TRestRawSignal::operator[](Int_t n) {
149  if (n >= GetNumberOfPoints()) {
150  if (fShowWarnings) {
151  std::cout << "TRestRawSignal::GetSignalData: outside limits" << endl;
152  std::cout << "Warnings at TRestRawSignal have been disabled" << endl;
153  fShowWarnings = false;
154  }
155  return 0xFFFF;
156  }
157  return fSignalData[n];
158 }
159 
169 Double_t TRestRawSignal::GetData(Int_t n) const { return (Double_t)fSignalData[n] - fBaseLine; }
170 
175 Double_t TRestRawSignal::GetRawData(Int_t n) const { return (Double_t)fSignalData[n]; }
176 
180 void TRestRawSignal::IncreaseBinBy(Int_t bin, Double_t data) {
181  if (bin >= GetNumberOfPoints()) {
182  if (fShowWarnings) {
183  std::cout << "TRestRawSignal::IncreaseBinBy: outside limits" << endl;
184  std::cout << "Warnings at TRestRawSignal have been disabled" << endl;
185  fShowWarnings = false;
186  }
187 
188  return;
189  }
190 
191  fSignalData[bin] += data;
192 }
193 
222 void TRestRawSignal::InitializePointsOverThreshold(const TVector2& thrPar, Int_t nPointsOver,
223  Int_t nPointsFlat) {
224  if (fRange.X() < 0) fRange.SetX(0);
225  if (fRange.Y() <= 0) fRange.SetY(GetNumberOfPoints());
226 
227  fPointsOverThreshold.clear();
228 
229  double pointTh = thrPar.X();
230  double signalTh = thrPar.Y();
231 
232  double threshold = pointTh * fBaseLineSigma;
233 
234  for (int i = fRange.X(); i < fRange.Y(); i++) {
235  // Filling a pulse with consecutive points that are over threshold
236  if (this->GetData(i) > threshold) {
237  int pos = i;
238  std::vector<double> pulse;
239  pulse.push_back(this->GetData(i));
240  i++;
241 
242  // If the pulse ends in a flat end above the threshold, the parameter
243  // nPointsFlat will serve to artificially end the pulse.
244  // If nPointsFlat is big enough, this parameter will not affect the
245  // decision to cut this anomalous behaviour. And all points over threshold
246  // will be added to the pulse vector.
247  int flatN = 0;
248  while (i < fRange.Y() && this->GetData(i) > threshold) {
249  if (TMath::Abs(this->GetData(i) - this->GetData(i - 1)) > threshold) {
250  flatN = 0;
251  } else {
252  flatN++;
253  }
254 
255  if (flatN < nPointsFlat) {
256  pulse.push_back(this->GetData(i));
257  i++;
258  } else {
259  break;
260  }
261  }
262 
263  if (pulse.size() >= (unsigned int)nPointsOver) {
264  // auto stdev = TMath::StdDev(begin(pulse), end(pulse));
265  // calculate stdev
266  double mean = std::accumulate(pulse.begin(), pulse.end(), 0.0) / pulse.size();
267  double sq_sum = std::inner_product(pulse.begin(), pulse.end(), pulse.begin(), 0.0);
268  double stdev = std::sqrt(sq_sum / pulse.size() - mean * mean);
269 
270  if (stdev > signalTh * fBaseLineSigma)
271  for (int j = pos; j < i; j++) fPointsOverThreshold.push_back(j);
272  }
273  }
274  }
275 
276  CalculateThresholdIntegral();
277 }
278 
285  if (fRange.X() < 0) fRange.SetX(0);
286  if (fRange.Y() <= 0 || fRange.Y() > GetNumberOfPoints()) fRange.SetY(GetNumberOfPoints());
287 
288  fThresholdIntegral = 0;
289 
290  for (unsigned int n = 0; n < fPointsOverThreshold.size(); n++) {
291  if (fPointsOverThreshold[n] >= fRange.X() && fPointsOverThreshold[n] < fRange.Y()) {
292  fThresholdIntegral += GetData(fPointsOverThreshold[n]);
293  }
294  }
295 }
296 
303  if (fRange.X() < 0) fRange.SetX(0);
304  if (fRange.Y() <= 0 || fRange.Y() > GetNumberOfPoints()) fRange.SetY(GetNumberOfPoints());
305 
306  Double_t sum = 0;
307  for (int i = fRange.X(); i < fRange.Y(); i++) sum += GetData(i);
308  return sum;
309 }
310 
315 Double_t TRestRawSignal::GetIntegralInRange(Int_t startBin, Int_t endBin) {
316  if (startBin < 0) startBin = 0;
317  if (endBin <= 0 || endBin > GetNumberOfPoints()) endBin = GetNumberOfPoints();
318 
319  Double_t sum = 0;
320  for (int i = startBin; i < endBin; i++) sum += GetRawData(i);
321  return sum;
322 }
323 
330  if (fThresholdIntegral == -1)
331  if (fShowWarnings) {
332  std::cout << "TRestRawSignal::GetThresholdIntegral. "
333  "InitializePointsOverThreshold should be "
334  "called first!"
335  << endl;
336  fShowWarnings = false;
337  }
338  return fThresholdIntegral;
339 }
340 
347  if (fThresholdIntegral == -1)
348  cout << "REST Warning. TRestRawSignal::GetSlopeIntegral. "
349  "InitializePointsOverThreshold should be called first."
350  << endl;
351 
352  Double_t sum = 0;
353  for (unsigned int n = 0; n < fPointsOverThreshold.size(); n++) {
354  if (n + 1 >= fPointsOverThreshold.size()) return sum;
355 
356  sum += GetData(fPointsOverThreshold[n]);
357 
358  if (GetData(fPointsOverThreshold[n + 1]) - GetData(fPointsOverThreshold[n]) < 0) break;
359  }
360  return sum;
361 }
362 
370  if (fThresholdIntegral == -1)
371  cout << "REST Warning. TRestRawSignal::GetRiseSlope. "
372  "InitializePointsOverThreshold should be called first."
373  << endl;
374 
375  if (fPointsOverThreshold.size() < 2) {
376  // cout << "REST Warning. TRestRawSignal::GetRiseSlope. Less than 2 points!." << endl;
377  return 0;
378  }
379 
380  Int_t maxBin = GetMaxPeakBin() - 1;
381 
382  Double_t hP = GetData(maxBin);
383 
384  Double_t lP = GetData(fPointsOverThreshold[0]);
385 
386  return (hP - lP) / (maxBin - fPointsOverThreshold[0]);
387 }
388 
394  if (fThresholdIntegral == -1)
395  cout << "REST Warning. TRestRawSignal::GetRiseTime. "
396  "InitializePointsOverThreshold should be called first."
397  << endl;
398 
399  if (fPointsOverThreshold.size() < 2) {
400  // cout << "REST Warning. TRestRawSignal::GetRiseTime. Less than 2 points!." << endl;
401  return 0;
402  }
403 
404  return GetMaxPeakBin() - fPointsOverThreshold[0];
405 }
406 
412  if (fRange.X() < 0) fRange.SetX(0);
413  if (fRange.Y() <= 0 || fRange.Y() > GetNumberOfPoints()) fRange.SetY(GetNumberOfPoints());
414 
415  if (fThresholdIntegral == -1) {
416  cout << "REST Warning. TRestRawSignal::GetTripleMaxIntegral. "
417  "InitializePointsOverThreshold should be called first."
418  << endl;
419  return 0;
420  }
421 
422  if (fPointsOverThreshold.size() < 2) {
423  // cout << "REST Warning. TRestRawSignal::GetTripleMaxIntegral. Points over
424  // "
425  // "threshold = "
426  // << fPointsOverThreshold.size() << endl;
427  return 0;
428  }
429 
430  Int_t cBin = GetMaxPeakBin();
431 
432  if (cBin + 1 >= GetNumberOfPoints()) return 0;
433 
434  Double_t a1 = GetData(cBin);
435  Double_t a2 = GetData(cBin - 1);
436  Double_t a3 = GetData(cBin + 1);
437 
438  return a1 + a2 + a3;
439 }
440 
445 Double_t TRestRawSignal::GetAverageInRange(Int_t startBin, Int_t endBin) {
446  if (startBin < 0) startBin = 0;
447  if (endBin <= 0 || endBin > GetNumberOfPoints()) endBin = GetNumberOfPoints();
448 
449  Double_t sum = 0;
450  for (int i = startBin; i <= endBin; i++) sum += this->GetData(i);
451 
452  return sum / (endBin - startBin + 1);
453 }
454 
460  Int_t mIndex = this->GetMaxPeakBin();
461  Double_t maxValue = this->GetData(mIndex);
462 
463  Double_t value = maxValue;
464  Int_t rightIndex = mIndex;
465  while (value > maxValue / 2) {
466  value = this->GetData(rightIndex);
467  rightIndex++;
468  }
469  Int_t leftIndex = mIndex;
470  value = maxValue;
471  while (value > maxValue / 2) {
472  value = this->GetData(leftIndex);
473  leftIndex--;
474  }
475 
476  return rightIndex - leftIndex;
477 }
478 
484 Double_t TRestRawSignal::GetMaxPeakValue() { return GetData(GetMaxPeakBin()); }
485 
490  Double_t max = numeric_limits<Double_t>::min();
491 
492  Int_t index = 0;
493 
494  if (fRange.Y() == 0 || fRange.Y() > GetNumberOfPoints()) fRange.SetY(GetNumberOfPoints());
495  if (fRange.X() < 0) fRange.SetX(0);
496 
497  for (int i = fRange.X(); i < fRange.Y(); i++) {
498  if (this->GetData(i) > max) {
499  max = GetData(i);
500  index = i;
501  }
502  }
503 
504  return index;
505 }
506 
512 Double_t TRestRawSignal::GetMinPeakValue() { return GetData(GetMinPeakBin()); }
513 
518  Double_t min = numeric_limits<Double_t>::max();
519  Int_t index = 0;
520 
521  if (fRange.Y() == 0 || fRange.Y() > GetNumberOfPoints()) fRange.SetY(GetNumberOfPoints());
522  if (fRange.X() < 0) fRange.SetX(0);
523 
524  for (int i = fRange.X(); i < fRange.Y(); i++) {
525  if (this->GetData(i) < min) {
526  min = GetData(i);
527  index = i;
528  }
529  }
530 
531  return index;
532 }
533 
538  if (Nflat <= 0) return false;
539  // GetMaxPeakBin() will always find the first max peak bin if multiple bins are in same max value.
540  int index = GetMaxPeakBin();
541  Short_t value = fSignalData[index];
542 
543  bool sat = false;
544  if (index + Nflat <= (int)fSignalData.size()) {
545  for (int i = index; i < index + Nflat; i++) {
546  if (fSignalData[i] != value) {
547  break;
548  }
549  if (i == index + Nflat - 1) {
550  sat = true;
551  }
552  }
553  }
554 
555  return sat;
556 }
557 
567 void TRestRawSignal::GetDifferentialSignal(TRestRawSignal* diffSignal, Int_t smearPoints) {
568  if (smearPoints <= 0) smearPoints = 1;
569  diffSignal->Initialize();
570 
571  for (int i = 0; i < smearPoints; i++) {
572  diffSignal->AddPoint((Short_t)0);
573  }
574 
575  for (int i = smearPoints; i < this->GetNumberOfPoints() - smearPoints; i++) {
576  Double_t value = 0.5 * (this->GetData(i + smearPoints) - GetData(i - smearPoints)) / smearPoints;
577 
578  diffSignal->AddPoint((Short_t)value);
579  }
580 
581  for (int i = GetNumberOfPoints() - smearPoints; i < GetNumberOfPoints(); i++) {
582  diffSignal->AddPoint((Short_t)0);
583  }
584 }
585 
594 void TRestRawSignal::GetWhiteNoiseSignal(TRestRawSignal* noiseSignal, Double_t noiseLevel) {
595  TRandom3 random(fSeed);
596 
597  for (int i = 0; i < GetNumberOfPoints(); i++) {
598  Double_t value = this->GetData(i) + random.Gaus(0, noiseLevel);
599  // do not cast as short so that there are no problems with overflows
600  // (https://github.com/rest-for-physics/rawlib/issues/113)
601  noiseSignal->AddPoint(value);
602  }
603 }
604 
612 void TRestRawSignal::GetSignalSmoothed(TRestRawSignal* smoothedSignal, Int_t averagingPoints) {
613  smoothedSignal->Initialize();
614 
615  averagingPoints = (averagingPoints / 2) * 2 + 1; // make it odd >= averagingPoints
616 
617  Double_t sumAvg = GetIntegralInRange(0, averagingPoints) / averagingPoints;
618 
619  for (int i = 0; i <= averagingPoints / 2; i++) smoothedSignal->AddPoint((Short_t)sumAvg);
620 
621  for (int i = averagingPoints / 2 + 1; i < GetNumberOfPoints() - averagingPoints / 2; i++) {
622  sumAvg -= this->GetRawData(i - (averagingPoints / 2 + 1)) / averagingPoints;
623  sumAvg += this->GetRawData(i + averagingPoints / 2) / averagingPoints;
624  smoothedSignal->AddPoint((Short_t)sumAvg);
625  }
626 
627  for (int i = GetNumberOfPoints() - averagingPoints / 2; i < GetNumberOfPoints(); i++)
628  smoothedSignal->AddPoint(sumAvg);
629 }
630 
640 std::vector<Float_t> TRestRawSignal::GetSignalSmoothed(Int_t averagingPoints, std::string option) {
641  std::vector<Float_t> result;
642 
643  if (option == "") {
644  result.resize(GetNumberOfPoints());
645 
646  averagingPoints = (averagingPoints / 2) * 2 + 1; // make it odd >= averagingPoints
647 
648  Float_t sumAvg = (Float_t)GetIntegralInRange(0, averagingPoints) / averagingPoints;
649 
650  for (int i = 0; i <= averagingPoints / 2; i++) result[i] = sumAvg;
651 
652  for (int i = averagingPoints / 2 + 1; i < GetNumberOfPoints() - averagingPoints / 2; i++) {
653  sumAvg -= this->GetRawData(i - (averagingPoints / 2 + 1)) / averagingPoints;
654  sumAvg += this->GetRawData(i + averagingPoints / 2) / averagingPoints;
655  result[i] = sumAvg;
656  }
657 
658  for (int i = GetNumberOfPoints() - averagingPoints / 2; i < GetNumberOfPoints(); i++)
659  result[i] = sumAvg;
660  } else if (ToUpper(option) == "EXCLUDE OUTLIERS") {
661  result = GetSignalSmoothed_ExcludeOutliers(averagingPoints);
662  } else {
663  cout << "TRestRawSignal::GetSignalSmoothed. Error! No such option!" << endl;
664  }
665  return result;
666 }
667 
677 std::vector<Float_t> TRestRawSignal::GetSignalSmoothed_ExcludeOutliers(Int_t averagingPoints) {
678  std::vector<Float_t> result(GetNumberOfPoints());
679 
680  if (fBaseLine == 0) CalculateBaseLine(5, GetNumberOfPoints() - 5, "ROBUST");
681 
682  averagingPoints = (averagingPoints / 2) * 2 + 1; // make it odd >= averagingPoints
683 
684  Float_t sumAvg = (Float_t)GetIntegralInRange(0, averagingPoints) / averagingPoints;
685 
686  // Points at the beginning, where we can calculate a moving average
687  for (int i = 0; i <= averagingPoints / 2; i++) result[i] = sumAvg;
688 
689  // Points in the middle
690  float_t amplitude;
691  for (int i = averagingPoints / 2 + 1; i < GetNumberOfPoints() - averagingPoints / 2; i++) {
692  amplitude = this->GetRawData(i - (averagingPoints / 2 + 1));
693  sumAvg -= (std::abs(amplitude - fBaseLine) > 3 * fBaseLineSigma) ? fBaseLine / averagingPoints
694  : amplitude / averagingPoints;
695  amplitude = this->GetRawData(i + averagingPoints / 2);
696  sumAvg += (std::abs(amplitude - fBaseLine) > 3 * fBaseLineSigma) ? fBaseLine / averagingPoints
697  : amplitude / averagingPoints;
698  result[i] = sumAvg;
699  }
700 
701  // Points at the end, where we can calculate a moving average
702  for (int i = GetNumberOfPoints() - averagingPoints / 2; i < GetNumberOfPoints(); i++) result[i] = sumAvg;
703  return result;
704 }
705 
716 void TRestRawSignal::GetBaseLineCorrected(TRestRawSignal* smoothedSignal, Int_t averagingPoints) {
717  smoothedSignal->Initialize();
718 
719  std::vector<Float_t> averagedSignal = GetSignalSmoothed(averagingPoints, "EXCLUDE OUTLIERS");
720 
721  for (int i = 0; i < GetNumberOfPoints(); i++) {
722  smoothedSignal->AddPoint(GetRawData(i) - averagedSignal[i]);
723  }
724 }
725 
731 void TRestRawSignal::CalculateBaseLineMean(Int_t startBin, Int_t endBin) {
732  if (endBin - startBin <= 0) {
733  fBaseLine = 0.;
734  } else if (endBin > (int)fSignalData.size()) {
735  cout << "TRestRawSignal::CalculateBaseLine. Error! Baseline range exceeds the rawdata depth!!"
736  << endl;
737  endBin = fSignalData.size();
738  } else {
739  Double_t baseLine = 0;
740  for (int i = startBin; i < endBin; i++) baseLine += fSignalData[i];
741  fBaseLine = baseLine / (endBin - startBin);
742  }
743 }
744 
750 void TRestRawSignal::CalculateBaseLineMedian(Int_t startBin, Int_t endBin) {
751  if (endBin - startBin <= 0) {
752  fBaseLine = 0.;
753  } else if (endBin > (int)fSignalData.size()) {
754  cout << "TRestRawSignal::CalculateBaseLine. Error! Baseline range exceeds the rawdata depth!!"
755  << endl;
756  endBin = fSignalData.size();
757  } else {
758  vector<Short_t>::const_iterator first = fSignalData.begin() + startBin;
759  vector<Short_t>::const_iterator last = fSignalData.begin() + endBin;
760  vector<Short_t> v(first, last);
761  const Short_t* signalInRange = &v[0];
762  fBaseLine = TMath::Median(endBin - startBin, signalInRange);
763  }
764 }
765 
776 void TRestRawSignal::CalculateBaseLine(Int_t startBin, Int_t endBin, const std::string& option) {
777  if (ToUpper(option) == "ROBUST") {
778  CalculateBaseLineMedian(startBin, endBin);
779  CalculateBaseLineSigmaIQR(startBin, endBin);
780  } else {
781  CalculateBaseLineMean(startBin, endBin);
782  CalculateBaseLineSigmaSD(startBin, endBin);
783  }
784 }
785 
791 void TRestRawSignal::CalculateBaseLineSigmaSD(Int_t startBin, Int_t endBin) {
792  if (endBin - startBin <= 0) {
793  fBaseLineSigma = 0;
794  } else {
795  Double_t baseLineSigma = 0;
796  for (int i = startBin; i < endBin; i++)
797  baseLineSigma += (fBaseLine - fSignalData[i]) * (fBaseLine - fSignalData[i]);
798  fBaseLineSigma = TMath::Sqrt(baseLineSigma / (endBin - startBin));
799  }
800 }
801 
808 void TRestRawSignal::CalculateBaseLineSigmaIQR(Int_t startBin, Int_t endBin) {
809  if (endBin - startBin <= 0) {
810  fBaseLineSigma = 0;
811  } else {
812  vector<Short_t>::const_iterator first = fSignalData.begin() + startBin;
813  vector<Short_t>::const_iterator last = fSignalData.begin() + endBin;
814  vector<Short_t> v(first, last);
815  std::sort(v.begin(), v.end());
816  Short_t Q1 = v[(int)(endBin - startBin) * 0.25];
817  Short_t Q3 = v[(int)(endBin - startBin) * 0.75];
818  Double_t IQR = Q3 - Q1;
819  fBaseLineSigma =
820  IQR / 1.349; // IQR/1.349 equals the standard deviation in case of normally distributed data
821  }
822 }
823 
827 void TRestRawSignal::AddOffset(Short_t offset) {
828  if (fBaseLine != 0 || fBaseLineSigma != 0) fBaseLineSigma += (Double_t)offset;
829  for (int i = 0; i < GetNumberOfPoints(); i++) fSignalData[i] = fSignalData[i] + offset;
830 }
831 
835 void TRestRawSignal::Scale(Double_t value) {
836  for (int i = 0; i < GetNumberOfPoints(); i++) {
837  Double_t scaledValue = value * fSignalData[i];
838  fSignalData[i] = (Short_t)scaledValue;
839  }
840 }
841 
847  if (this->GetNumberOfPoints() != signal.GetNumberOfPoints()) {
848  cout << "ERROR : TRestRawSignal::SignalAddition." << endl;
849  cout << "I cannot add two signals with different number of points" << endl;
850  return;
851  }
852 
853  for (int i = 0; i < GetNumberOfPoints(); i++) {
854  fSignalData[i] += signal.GetData(i);
855  }
856 }
857 
861 void TRestRawSignal::WriteSignalToTextFile(const TString& filename) {
862  // We should check it is writable
863  FILE* file = fopen(filename.Data(), "w");
864  for (int i = 0; i < GetNumberOfPoints(); i++) fprintf(file, "%d\t%lf\n", i, GetData(i));
865  fclose(file);
866 }
867 
871 void TRestRawSignal::Print() const {
872  cout << "---------------------" << endl;
873  cout << "Signal id : " << this->GetSignalID() << endl;
874  cout << "Baseline : " << fBaseLine << endl;
875  cout << "Baseline sigma : " << fBaseLineSigma << endl;
876  cout << "+++++++++++++++++++++" << endl;
877  for (int i = 0; i < GetNumberOfPoints(); i++)
878  cout << "Bin : " << i << " amplitude : " << GetRawData(i) << endl;
879  cout << "---------------------" << endl;
880 }
881 
885 TGraph* TRestRawSignal::GetGraph(Int_t color) {
886  delete fGraph;
887  fGraph = new TGraph();
888 
889  fGraph->SetLineWidth(2);
890  fGraph->SetLineColor(color % 8 + 1);
891  fGraph->SetMarkerStyle(7);
892 
893  for (int i = 0; i < GetNumberOfPoints(); i++) {
894  fGraph->SetPoint(i, i, GetData(i));
895  }
896 
897  fGraph->GetXaxis()->SetLimits(0, GetNumberOfPoints() - 1);
898 
899  /*
900  * To draw x axis in multiples of 2
901  for (int i = 0; i < values.size(); i++) {
902  if (i % 32 != 0 && i != values.size() - 1){
903  continue;
904  }
905  fGraph->GetXaxis()->SetBinLabel(fGraph->GetXaxis()->FindBin(i), std::to_string(i).c_str());
906  }
907  */
908 
909  return fGraph;
910 }
911 
912 vector<pair<UShort_t, double>> TRestRawSignal::GetPeaks(double threshold, UShort_t distance) const {
913  vector<pair<UShort_t, double>> peaks;
914 
915  for (UShort_t i = 0; i < GetNumberOfPoints(); i++) {
916  const double point = GetRawData(i);
917  if (i > 0 && i < GetNumberOfPoints() - 1) {
918  double prevPoint = GetRawData(i - 1);
919  double nextPoint = GetRawData(i + 1);
920 
921  if (point > threshold && point >= prevPoint && point >= nextPoint) {
922  // Check if the peak is spaced far enough from the previous peak
923  if (peaks.empty() || i - peaks.back().first >= distance) {
924  peaks.push_back(std::make_pair(i, point));
925  }
926  }
927  }
928  }
929  return peaks;
930 }
It defines a Short_t array with a physical parameter that evolves in time using a fixed time bin.
Int_t GetMinPeakBin()
It returns the bin at which the minimum peak amplitude happens.
void WriteSignalToTextFile(const TString &filename)
This method dumps to a text file the data inside fSignalData.
Double_t GetThresholdIntegral()
It returns the integral of points identified over threshold. InitializePointsOverThreshold should hav...
~TRestRawSignal()
Default destructor.
void GetSignalSmoothed(TRestRawSignal *smoothedSignal, Int_t averagingPoints)
It smoothes the existing signal and places it at the signal pointer given by argument.
Double_t GetRiseSlope()
It returns the rate of change or slope from the points that have been identified over threshlold on t...
void Print() const
It prints the signal data on screen.
Double_t GetMaxPeakValue()
It returns the amplitude of the signal maximum, baseline will be corrected if CalculateBaseLine was c...
std::vector< Float_t > GetSignalSmoothed_ExcludeOutliers(Int_t averagingPoints)
It smooths the existing signal and returns it in a vector of Float_t values. This method excludes poi...
Double_t GetMinPeakValue()
It returns the amplitude of the signal minimum, baseline will be corrected if CalculateBaseLine was c...
void CalculateBaseLine(Int_t startBin, Int_t endBin, const std::string &option="")
This method calculates the average and fluctuation of the baseline in the specified range and writes ...
void CalculateThresholdIntegral()
This method will be called each time InitializePointsOverThreshold is called to re-define the value o...
void Initialize()
Initialization of TRestRawSignal members.
void CalculateBaseLineMean(Int_t startBin, Int_t endBin)
This method is called by CalculateBaseLine and is used to determine the value of the baseline as aver...
void CalculateBaseLineSigmaSD(Int_t startBin, Int_t endBin)
This method is called by CalculateBaseLine to determine the value of the baseline fluctuation as its ...
TRestRawSignal()
Default constructor.
Short_t operator[](Int_t n)
It overloads the operator [] so that we can retrieve a particular point n in the form rawSignal[n].
void InitializePointsOverThreshold(const TVector2 &thrPar, Int_t nPointsOver, Int_t nPointsFlat=512)
It initializes the fPointsOverThreshold array with the indexes of data points that are found over thr...
Double_t GetIntegralInRange(Int_t startBin, Int_t endBin)
It returns the integral of points found in the specific range given by (startBin,endBin).
void Reset()
Initializes the existing signal data and sets it to zero while keeping the array size.
std::vector< std::pair< UShort_t, double > > GetPeaks(double threshold, UShort_t distance=5) const
void SignalAddition(const TRestRawSignal &signal)
This method adds the signal provided by argument to the existing signal.
void AddOffset(Short_t offset)
This method adds an offset to the signal data.
Int_t GetMaxPeakWidth()
It returns the temporal width of the peak with maximum amplitude inside the signal.
Int_t GetRiseTime()
It returns the time required from the signal to reach the maximum. InitializePointsOverThreshold shou...
Double_t GetAverageInRange(Int_t startBin, Int_t endBin)
It returns the average of the points found in the range (startBin, endBin)
void IncreaseBinBy(Int_t bin, Double_t data)
It adds the content of data to fSignalData[bin].
void GetDifferentialSignal(TRestRawSignal *diffSignal, Int_t smearPoints)
It calculates the differential signal of the existing signal and it will place at the signal pointer ...
void CalculateBaseLineMedian(Int_t startBin, Int_t endBin)
This method is called by CalculateBaseLine with the "ROBUST"-option and is used to determine the valu...
Double_t GetRawData(Int_t n) const
It returns the original data value of point n without baseline correction.
Double_t GetData(Int_t n) const
It returns the data value of point n including baseline correction.
Double_t GetTripleMaxIntegral()
It returns the integral calculated using the maximum signal amplitude and its neightbour points.
void Scale(Double_t value)
This method scales the signal by a given value.
Double_t GetIntegral()
It returns the integral of points found in the region defined by fRange. If fRange was not defined th...
void AddPoint(Short_t)
Adds a new point to the end of the signal data array.
TGraph * GetGraph(Int_t color=1)
It builds a TGraph object that can be used for drawing.
Double_t GetSlopeIntegral()
It returns the integral of points identified over threshold found in the first positive rise of the s...
void GetWhiteNoiseSignal(TRestRawSignal *noiseSignal, Double_t noiseLevel=1.)
It calculates an arbitrary Gaussian noise placing it at the signal pointer given by argument....
Bool_t IsADCSaturation(int Nflat=3)
It returns whether the signal has ADC saturation.
Int_t GetMaxPeakBin()
It returns the bin at which the maximum peak amplitude happens.
void GetBaseLineCorrected(TRestRawSignal *smoothedSignal, Int_t averagingPoints)
It applies the moving average filter (GetSignalSmoothed) to the signal, which is then subtracted from...
void CalculateBaseLineSigmaIQR(Int_t startBin, Int_t endBin)
This method is called by CalculateBaseLine with the "ROBUST"-option to determine the value of the bas...
Int_t GetNumberOfPoints() const
Returns the actual number of points, or size of the signal.