60 #include "TRestRawSignal.h"
91 fSignalData.resize(nBins, 0);
104 fPointsOverThreshold.clear();
107 fThresholdIntegral = -1;
121 Int_t nBins = GetNumberOfPoints();
123 fSignalData.resize(nBins, 0);
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();
140 AddPoint((Short_t)value);
149 if (n >= GetNumberOfPoints()) {
151 std::cout <<
"TRestRawSignal::GetSignalData: outside limits" << endl;
152 std::cout <<
"Warnings at TRestRawSignal have been disabled" << endl;
153 fShowWarnings =
false;
157 return fSignalData[n];
181 if (bin >= GetNumberOfPoints()) {
183 std::cout <<
"TRestRawSignal::IncreaseBinBy: outside limits" << endl;
184 std::cout <<
"Warnings at TRestRawSignal have been disabled" << endl;
185 fShowWarnings =
false;
191 fSignalData[bin] += data;
224 if (fRange.X() < 0) fRange.SetX(0);
225 if (fRange.Y() <= 0) fRange.SetY(GetNumberOfPoints());
227 fPointsOverThreshold.clear();
229 double pointTh = thrPar.X();
230 double signalTh = thrPar.Y();
232 double threshold = pointTh * fBaseLineSigma;
234 for (
int i = fRange.X(); i < fRange.Y(); i++) {
236 if (this->GetData(i) > threshold) {
238 std::vector<double> pulse;
239 pulse.push_back(this->GetData(i));
248 while (i < fRange.Y() && this->GetData(i) > threshold) {
249 if (TMath::Abs(this->GetData(i) - this->GetData(i - 1)) > threshold) {
255 if (flatN < nPointsFlat) {
256 pulse.push_back(this->GetData(i));
263 if (pulse.size() >= (
unsigned int)nPointsOver) {
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);
270 if (stdev > signalTh * fBaseLineSigma)
271 for (
int j = pos; j < i; j++) fPointsOverThreshold.push_back(j);
276 CalculateThresholdIntegral();
285 if (fRange.X() < 0) fRange.SetX(0);
286 if (fRange.Y() <= 0 || fRange.Y() > GetNumberOfPoints()) fRange.SetY(GetNumberOfPoints());
288 fThresholdIntegral = 0;
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]);
303 if (fRange.X() < 0) fRange.SetX(0);
304 if (fRange.Y() <= 0 || fRange.Y() > GetNumberOfPoints()) fRange.SetY(GetNumberOfPoints());
307 for (
int i = fRange.X(); i < fRange.Y(); i++) sum += GetData(i);
316 if (startBin < 0) startBin = 0;
317 if (endBin <= 0 || endBin > GetNumberOfPoints()) endBin = GetNumberOfPoints();
320 for (
int i = startBin; i < endBin; i++) sum += GetRawData(i);
330 if (fThresholdIntegral == -1)
332 std::cout <<
"TRestRawSignal::GetThresholdIntegral. "
333 "InitializePointsOverThreshold should be "
336 fShowWarnings =
false;
338 return fThresholdIntegral;
347 if (fThresholdIntegral == -1)
348 cout <<
"REST Warning. TRestRawSignal::GetSlopeIntegral. "
349 "InitializePointsOverThreshold should be called first."
353 for (
unsigned int n = 0; n < fPointsOverThreshold.size(); n++) {
354 if (n + 1 >= fPointsOverThreshold.size())
return sum;
356 sum += GetData(fPointsOverThreshold[n]);
358 if (GetData(fPointsOverThreshold[n + 1]) - GetData(fPointsOverThreshold[n]) < 0)
break;
370 if (fThresholdIntegral == -1)
371 cout <<
"REST Warning. TRestRawSignal::GetRiseSlope. "
372 "InitializePointsOverThreshold should be called first."
375 if (fPointsOverThreshold.size() < 2) {
380 Int_t maxBin = GetMaxPeakBin() - 1;
382 Double_t hP = GetData(maxBin);
384 Double_t lP = GetData(fPointsOverThreshold[0]);
386 return (hP - lP) / (maxBin - fPointsOverThreshold[0]);
394 if (fThresholdIntegral == -1)
395 cout <<
"REST Warning. TRestRawSignal::GetRiseTime. "
396 "InitializePointsOverThreshold should be called first."
399 if (fPointsOverThreshold.size() < 2) {
404 return GetMaxPeakBin() - fPointsOverThreshold[0];
412 if (fRange.X() < 0) fRange.SetX(0);
413 if (fRange.Y() <= 0 || fRange.Y() > GetNumberOfPoints()) fRange.SetY(GetNumberOfPoints());
415 if (fThresholdIntegral == -1) {
416 cout <<
"REST Warning. TRestRawSignal::GetTripleMaxIntegral. "
417 "InitializePointsOverThreshold should be called first."
422 if (fPointsOverThreshold.size() < 2) {
430 Int_t cBin = GetMaxPeakBin();
432 if (cBin + 1 >= GetNumberOfPoints())
return 0;
434 Double_t a1 = GetData(cBin);
435 Double_t a2 = GetData(cBin - 1);
436 Double_t a3 = GetData(cBin + 1);
446 if (startBin < 0) startBin = 0;
447 if (endBin <= 0 || endBin > GetNumberOfPoints()) endBin = GetNumberOfPoints();
450 for (
int i = startBin; i <= endBin; i++) sum += this->GetData(i);
452 return sum / (endBin - startBin + 1);
460 Int_t mIndex = this->GetMaxPeakBin();
461 Double_t maxValue = this->GetData(mIndex);
463 Double_t value = maxValue;
464 Int_t rightIndex = mIndex;
465 while (value > maxValue / 2) {
466 value = this->GetData(rightIndex);
469 Int_t leftIndex = mIndex;
471 while (value > maxValue / 2) {
472 value = this->GetData(leftIndex);
476 return rightIndex - leftIndex;
490 Double_t max = numeric_limits<Double_t>::min();
494 if (fRange.Y() == 0 || fRange.Y() > GetNumberOfPoints()) fRange.SetY(GetNumberOfPoints());
495 if (fRange.X() < 0) fRange.SetX(0);
497 for (
int i = fRange.X(); i < fRange.Y(); i++) {
498 if (this->GetData(i) > max) {
518 Double_t min = numeric_limits<Double_t>::max();
521 if (fRange.Y() == 0 || fRange.Y() > GetNumberOfPoints()) fRange.SetY(GetNumberOfPoints());
522 if (fRange.X() < 0) fRange.SetX(0);
524 for (
int i = fRange.X(); i < fRange.Y(); i++) {
525 if (this->GetData(i) < min) {
538 if (Nflat <= 0)
return false;
540 int index = GetMaxPeakBin();
541 Short_t value = fSignalData[index];
544 if (index + Nflat <= (
int)fSignalData.size()) {
545 for (
int i = index; i < index + Nflat; i++) {
546 if (fSignalData[i] != value) {
549 if (i == index + Nflat - 1) {
568 if (smearPoints <= 0) smearPoints = 1;
571 for (
int i = 0; i < smearPoints; i++) {
575 for (
int i = smearPoints; i < this->GetNumberOfPoints() - smearPoints; i++) {
576 Double_t value = 0.5 * (this->GetData(i + smearPoints) - GetData(i - smearPoints)) / smearPoints;
578 diffSignal->
AddPoint((Short_t)value);
581 for (
int i = GetNumberOfPoints() - smearPoints; i < GetNumberOfPoints(); i++) {
595 TRandom3 random(fSeed);
597 for (
int i = 0; i < GetNumberOfPoints(); i++) {
598 Double_t value = this->GetData(i) + random.Gaus(0, noiseLevel);
615 averagingPoints = (averagingPoints / 2) * 2 + 1;
617 Double_t sumAvg = GetIntegralInRange(0, averagingPoints) / averagingPoints;
619 for (
int i = 0; i <= averagingPoints / 2; i++) smoothedSignal->
AddPoint((Short_t)sumAvg);
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);
627 for (
int i = GetNumberOfPoints() - averagingPoints / 2; i < GetNumberOfPoints(); i++)
641 std::vector<Float_t> result;
644 result.resize(GetNumberOfPoints());
646 averagingPoints = (averagingPoints / 2) * 2 + 1;
648 Float_t sumAvg = (Float_t)GetIntegralInRange(0, averagingPoints) / averagingPoints;
650 for (
int i = 0; i <= averagingPoints / 2; i++) result[i] = sumAvg;
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;
658 for (
int i = GetNumberOfPoints() - averagingPoints / 2; i < GetNumberOfPoints(); i++)
660 }
else if (ToUpper(option) ==
"EXCLUDE OUTLIERS") {
661 result = GetSignalSmoothed_ExcludeOutliers(averagingPoints);
663 cout <<
"TRestRawSignal::GetSignalSmoothed. Error! No such option!" << endl;
678 std::vector<Float_t> result(GetNumberOfPoints());
680 if (fBaseLine == 0) CalculateBaseLine(5, GetNumberOfPoints() - 5,
"ROBUST");
682 averagingPoints = (averagingPoints / 2) * 2 + 1;
684 Float_t sumAvg = (Float_t)GetIntegralInRange(0, averagingPoints) / averagingPoints;
687 for (
int i = 0; i <= averagingPoints / 2; i++) result[i] = sumAvg;
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;
702 for (
int i = GetNumberOfPoints() - averagingPoints / 2; i < GetNumberOfPoints(); i++) result[i] = sumAvg;
719 std::vector<Float_t> averagedSignal = GetSignalSmoothed(averagingPoints,
"EXCLUDE OUTLIERS");
721 for (
int i = 0; i < GetNumberOfPoints(); i++) {
722 smoothedSignal->
AddPoint(GetRawData(i) - averagedSignal[i]);
732 if (endBin - startBin <= 0) {
734 }
else if (endBin > (
int)fSignalData.size()) {
735 cout <<
"TRestRawSignal::CalculateBaseLine. Error! Baseline range exceeds the rawdata depth!!"
737 endBin = fSignalData.size();
739 Double_t baseLine = 0;
740 for (
int i = startBin; i < endBin; i++) baseLine += fSignalData[i];
741 fBaseLine = baseLine / (endBin - startBin);
751 if (endBin - startBin <= 0) {
753 }
else if (endBin > (
int)fSignalData.size()) {
754 cout <<
"TRestRawSignal::CalculateBaseLine. Error! Baseline range exceeds the rawdata depth!!"
756 endBin = fSignalData.size();
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);
777 if (ToUpper(option) ==
"ROBUST") {
778 CalculateBaseLineMedian(startBin, endBin);
779 CalculateBaseLineSigmaIQR(startBin, endBin);
781 CalculateBaseLineMean(startBin, endBin);
782 CalculateBaseLineSigmaSD(startBin, endBin);
792 if (endBin - startBin <= 0) {
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));
809 if (endBin - startBin <= 0) {
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;
828 if (fBaseLine != 0 || fBaseLineSigma != 0) fBaseLineSigma += (Double_t)offset;
829 for (
int i = 0; i < GetNumberOfPoints(); i++) fSignalData[i] = fSignalData[i] + offset;
836 for (
int i = 0; i < GetNumberOfPoints(); i++) {
837 Double_t scaledValue = value * fSignalData[i];
838 fSignalData[i] = (Short_t)scaledValue;
848 cout <<
"ERROR : TRestRawSignal::SignalAddition." << endl;
849 cout <<
"I cannot add two signals with different number of points" << endl;
853 for (
int i = 0; i < GetNumberOfPoints(); i++) {
854 fSignalData[i] += signal.
GetData(i);
863 FILE* file = fopen(filename.Data(),
"w");
864 for (
int i = 0; i < GetNumberOfPoints(); i++) fprintf(file,
"%d\t%lf\n", i, GetData(i));
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;
887 fGraph =
new TGraph();
889 fGraph->SetLineWidth(2);
890 fGraph->SetLineColor(color % 8 + 1);
891 fGraph->SetMarkerStyle(7);
893 for (
int i = 0; i < GetNumberOfPoints(); i++) {
894 fGraph->SetPoint(i, i, GetData(i));
897 fGraph->GetXaxis()->SetLimits(0, GetNumberOfPoints() - 1);
913 vector<pair<UShort_t, double>> peaks;
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);
921 if (point > threshold && point >= prevPoint && point >= nextPoint) {
923 if (peaks.empty() || i - peaks.back().first >= distance) {
924 peaks.push_back(std::make_pair(i, point));
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.