60#include "TRestRawSignal.h"
136 if (value > numeric_limits<Short_t>::max()) {
137 value = numeric_limits<Short_t>::max();
138 }
else if (value < numeric_limits<Short_t>::min()) {
139 value = numeric_limits<Short_t>::min();
152 std::cout <<
"TRestRawSignal::GetSignalData: outside limits" << endl;
153 std::cout <<
"Warnings at TRestRawSignal have been disabled" << endl;
154 fShowWarnings =
false;
184 std::cout <<
"TRestRawSignal::IncreaseBinBy: outside limits" << endl;
185 std::cout <<
"Warnings at TRestRawSignal have been disabled" << endl;
186 fShowWarnings =
false;
230 double pointTh = thrPar.X();
231 double signalTh = thrPar.Y();
237 if (this->
GetData(i) > threshold) {
239 std::vector<double> pulse;
240 pulse.push_back(this->
GetData(i));
249 while (i <
fRange.Y() && this->GetData(i) > threshold) {
250 if (TMath::Abs(this->
GetData(i) - this->
GetData(i - 1)) > threshold) {
256 if (flatN < nPointsFlat) {
257 pulse.push_back(this->
GetData(i));
264 if (pulse.size() >= (
unsigned int)nPointsOver) {
267 double mean = std::accumulate(pulse.begin(), pulse.end(), 0.0) / double(pulse.size());
268 double sq_sum = std::inner_product(pulse.begin(), pulse.end(), pulse.begin(), 0.0);
269 double stdev = std::sqrt(sq_sum /
double(pulse.size()) - mean * mean);
272 for (
int j = pos; j < i; j++) {
338 for (
int i = startBin; i < endBin; i++) {
352 std::cout <<
"TRestRawSignal::GetThresholdIntegral. "
353 "InitializePointsOverThreshold should be "
356 fShowWarnings =
false;
369 cout <<
"REST Warning. TRestRawSignal::GetSlopeIntegral. "
370 "InitializePointsOverThreshold should be called first."
392 cout <<
"REST Warning. TRestRawSignal::GetRiseSlope. "
393 "InitializePointsOverThreshold should be called first."
416 cout <<
"REST Warning. TRestRawSignal::GetRiseTime. "
417 "InitializePointsOverThreshold should be called first."
437 cout <<
"REST Warning. TRestRawSignal::GetTripleMaxIntegral. "
438 "InitializePointsOverThreshold should be called first."
456 Double_t a2 =
GetData(cBin - 1);
457 Double_t a3 =
GetData(cBin + 1);
467 if (startBin < 0) startBin = 0;
471 for (
int i = startBin; i <= endBin; i++) sum += this->
GetData(i);
473 return sum / (endBin - startBin + 1);
482 Double_t maxValue = this->
GetData(mIndex);
484 Double_t value = maxValue;
485 Int_t rightIndex = mIndex;
486 while (value > maxValue / 2) {
487 value = this->
GetData(rightIndex);
490 Int_t leftIndex = mIndex;
492 while (value > maxValue / 2) {
493 value = this->
GetData(leftIndex);
497 return rightIndex - leftIndex;
511 Double_t max = numeric_limits<Double_t>::min();
539 Double_t min = numeric_limits<Double_t>::max();
559 if (Nflat <= 0)
return false;
566 for (
int i = index; i < index + Nflat; i++) {
570 if (i == index + Nflat - 1) {
589 if (smearPoints <= 0) smearPoints = 1;
592 for (
int i = 0; i < smearPoints; i++) {
597 Double_t value = 0.5 * (this->
GetData(i + smearPoints) -
GetData(i - smearPoints)) / smearPoints;
599 diffSignal->
AddPoint((Short_t)value);
616 TRandom3 random(
fSeed);
619 Double_t value = this->
GetData(i) + random.Gaus(0, noiseLevel);
636 averagingPoints = (averagingPoints / 2) * 2 + 1;
640 for (
int i = 0; i <= averagingPoints / 2; i++) smoothedSignal->
AddPoint((Short_t)sumAvg);
642 for (
int i = averagingPoints / 2 + 1; i <
GetNumberOfPoints() - averagingPoints / 2; i++) {
643 sumAvg -= this->
GetRawData(i - (averagingPoints / 2 + 1)) / averagingPoints;
644 sumAvg += this->
GetRawData(i + averagingPoints / 2) / averagingPoints;
645 smoothedSignal->
AddPoint((Short_t)sumAvg);
662 std::vector<Float_t> result;
667 averagingPoints = (averagingPoints / 2) * 2 + 1;
671 for (
int i = 0; i <= averagingPoints / 2; i++) result[i] = sumAvg;
673 for (
int i = averagingPoints / 2 + 1; i <
GetNumberOfPoints() - averagingPoints / 2; i++) {
674 sumAvg -= this->
GetRawData(i - (averagingPoints / 2 + 1)) / averagingPoints;
675 sumAvg += this->
GetRawData(i + averagingPoints / 2) / averagingPoints;
681 }
else if (ToUpper(option) ==
"EXCLUDE OUTLIERS") {
684 cout <<
"TRestRawSignal::GetSignalSmoothed. Error! No such option!" << endl;
703 averagingPoints = (averagingPoints / 2) * 2 + 1;
708 for (
int i = 0; i <= averagingPoints / 2; i++) result[i] = sumAvg;
712 for (
int i = averagingPoints / 2 + 1; i <
GetNumberOfPoints() - averagingPoints / 2; i++) {
713 amplitude = this->
GetRawData(i - (averagingPoints / 2 + 1));
715 : amplitude / averagingPoints;
716 amplitude = this->
GetRawData(i + averagingPoints / 2);
718 : amplitude / averagingPoints;
740 std::vector<Float_t> averagedSignal =
GetSignalSmoothed(averagingPoints,
"EXCLUDE OUTLIERS");
753 if (endBin - startBin <= 0) {
756 cout <<
"TRestRawSignal::CalculateBaseLine. Error! Baseline range exceeds the rawdata depth!!"
760 Double_t baseLine = 0;
761 for (
int i = startBin; i < endBin; i++) baseLine +=
fSignalData[i];
762 fBaseLine = baseLine / (endBin - startBin);
772 if (endBin - startBin <= 0) {
775 cout <<
"TRestRawSignal::CalculateBaseLine. Error! Baseline range exceeds the rawdata depth!!"
779 vector<Short_t>::const_iterator first =
fSignalData.begin() + startBin;
780 vector<Short_t>::const_iterator last =
fSignalData.begin() + endBin;
781 vector<Short_t> v(first, last);
782 const Short_t* signalInRange = &v[0];
783 fBaseLine = TMath::Median(endBin - startBin, signalInRange);
794 if (endBin - startBin <= 0) {
797 }
else if (endBin >
static_cast<int>(
fSignalData.size())) {
798 cout <<
"TRestRawSignal::CalculateBaseLine. Error! Baseline range exceeds the rawdata depth!!"
804 std::sort(data.begin(), data.end());
807 size_t dataSize = data.size();
808 Short_t Q1 = data[dataSize / 4];
809 Short_t Q3 = data[(3 * dataSize) / 4];
810 Double_t lowerBound = Q1;
811 Double_t upperBound = Q3;
814 std::vector<Short_t> filteredData;
815 for (
const auto& value : data) {
816 if (value >= lowerBound && value <= upperBound) {
817 filteredData.emplace_back(value);
822 if (filteredData.empty()) {
826 fBaseLine = TMath::Median(filteredData.size(), &filteredData[0]);
843 if (ToUpper(option) ==
"ROBUST") {
846 }
else if (ToUpper(option) ==
"OUTLIERS") {
861 if (endBin - startBin <= 0) {
864 Double_t baseLineSigma = 0;
865 for (
int i = startBin; i < endBin; i++)
867 fBaseLineSigma = TMath::Sqrt(baseLineSigma / (endBin - startBin));
878 if (endBin - startBin <= 0) {
881 vector<Short_t>::const_iterator first =
fSignalData.begin() + startBin;
882 vector<Short_t>::const_iterator last =
fSignalData.begin() + endBin;
883 vector<Short_t> v(first, last);
884 std::sort(v.begin(), v.end());
885 Short_t Q1 = v[(int)(endBin - startBin) * 0.25];
886 Short_t Q3 = v[(int)(endBin - startBin) * 0.75];
887 Double_t IQR = Q3 - Q1;
900 if (endBin - startBin <= 0) {
903 }
else if (endBin >
static_cast<int>(
fSignalData.size())) {
904 cout <<
"TRestRawSignal::CalculateBaseLineSigma. Error! Range exceeds the rawdata depth!!" << endl;
909 std::sort(data.begin(), data.end());
912 size_t dataSize = data.size();
913 Short_t Q1 = data[dataSize / 4];
914 Short_t Q3 = data[(3 * dataSize) / 4];
915 Double_t lowerBound = Q1;
916 Double_t upperBound = Q3;
919 std::vector<Short_t> filteredData;
920 for (
const auto& value : data) {
921 if (value >= lowerBound && value <= upperBound) {
922 filteredData.emplace_back(value);
927 if (filteredData.empty()) {
931 std::accumulate(filteredData.begin(), filteredData.end(), 0.0) / filteredData.size();
932 double variance = 0.0;
933 for (
const auto& value : filteredData) {
934 variance += std::pow(value - mean, 2);
965 cout <<
"ERROR : TRestRawSignal::SignalAddition." << endl;
966 cout <<
"I cannot add two signals with different number of points" << endl;
980 FILE* file = fopen(filename.Data(),
"w");
989 cout <<
"---------------------" << endl;
990 cout <<
"Signal id : " << this->
GetSignalID() << endl;
991 cout <<
"Baseline : " <<
fBaseLine << endl;
993 cout <<
"+++++++++++++++++++++" << endl;
995 cout <<
"Bin : " << i <<
" amplitude : " <<
GetRawData(i) << endl;
996 cout <<
"---------------------" << endl;
1007 fGraph->SetLineColor(color % 8 + 1);
1008 fGraph->SetMarkerStyle(7);
1031 double signalBaseLine)
const {
1032 std::vector<std::tuple<double, UShort_t, double>> peaks;
1034 const UShort_t smoothingWindow =
1038 if (numPoints == 0) {
1043 vector<double> smoothedValues(numPoints, 0.0);
1044 double currentSum = 0.0;
1045 UShort_t windowSize = smoothingWindow + 1;
1048 for (UShort_t i = 0; i < static_cast<UShort_t>(std::min<size_t>(windowSize, numPoints)); ++i) {
1051 smoothedValues[0] = currentSum / windowSize;
1053 for (UShort_t i = 1; i < numPoints; ++i) {
1054 if (i < smoothingWindow / 2 + 1) {
1057 UShort_t currentWindowSize =
1058 static_cast<UShort_t
>(std::min<size_t>(windowSize, i + smoothingWindow / 2 + 1));
1059 for (UShort_t j = 0; j < currentWindowSize; ++j) {
1062 smoothedValues[i] = currentSum / currentWindowSize;
1063 }
else if (i > numPoints - smoothingWindow / 2 - 1) {
1066 UShort_t currentWindowSize =
1067 static_cast<UShort_t
>(std::min<size_t>(windowSize, numPoints - i + smoothingWindow / 2));
1068 for (UShort_t j = i - smoothingWindow / 2; j < numPoints; ++j) {
1071 smoothedValues[i] = currentSum / currentWindowSize;
1074 currentSum -=
GetRawData(i - smoothingWindow / 2 - 1);
1075 currentSum +=
GetRawData(i + smoothingWindow / 2);
1076 smoothedValues[i] = currentSum / windowSize;
1081 for (UShort_t i = 0; i < numPoints; ++i) {
1082 const double smoothedValue = smoothedValues[i];
1084 if (i >= smoothingWindow / 2 && i < numPoints - smoothingWindow / 2) {
1086 int numGreaterEqual = 0;
1088 for (UShort_t j = i - smoothingWindow / 2; j <= i + smoothingWindow / 2; ++j) {
1089 if (j != i && smoothedValue <= smoothedValues[j]) {
1091 if (numGreaterEqual >
1103 if (isPeak && smoothedValue > threshold) {
1104 if (peaks.empty() || i - std::get<0>(peaks.back()) >= distance) {
1107 double maxAmplitude = smoothedValues[i];
1110 for (std::vector<double>::size_type j = i + 1;
1111 j <= i + distance && j < smoothedValues.size(); ++j) {
1112 if (smoothedValues[j] > maxAmplitude) {
1113 maxAmplitude = smoothedValues[j];
1122 double peakAmplitude = (amplitude1 + amplitude2 + amplitude3) / 3.0;
1123 double peakAmplitudeBaseLineCorrected = peakAmplitude - signalBaseLine;
1126 peaks.emplace_back(maxBin, peakAmplitude, peakAmplitudeBaseLineCorrected);
1135std::vector<std::tuple<double, UShort_t, double>> TRestRawSignal::GetPeaksVeto(
double threshold,
1137 double signalBaseLine)
const {
1138 std::vector<std::tuple<double, UShort_t, double>> peaks;
1140 const UShort_t smoothingWindow =
1144 if (numPoints == 0) {
1149 vector<double> smoothedValues(numPoints, 0.0);
1150 double currentSum = 0.0;
1151 UShort_t windowSize = smoothingWindow + 1;
1154 for (UShort_t i = 0; i < static_cast<UShort_t>(std::min<size_t>(windowSize, numPoints)); ++i) {
1157 smoothedValues[0] = currentSum / windowSize;
1159 for (UShort_t i = 1; i < numPoints; ++i) {
1160 if (i < smoothingWindow / 2 + 1) {
1163 UShort_t currentWindowSize =
1164 static_cast<UShort_t
>(std::min<size_t>(windowSize, i + smoothingWindow / 2 + 1));
1165 for (UShort_t j = 0; j < currentWindowSize; ++j) {
1168 smoothedValues[i] = currentSum / currentWindowSize;
1169 }
else if (i > numPoints - smoothingWindow / 2 - 1) {
1172 UShort_t currentWindowSize =
1173 static_cast<UShort_t
>(std::min<size_t>(windowSize, numPoints - i + smoothingWindow / 2));
1174 for (UShort_t j = i - smoothingWindow / 2; j < numPoints; ++j) {
1177 smoothedValues[i] = currentSum / currentWindowSize;
1180 currentSum -=
GetRawData(i - smoothingWindow / 2 - 1);
1181 currentSum +=
GetRawData(i + smoothingWindow / 2);
1182 smoothedValues[i] = currentSum / windowSize;
1187 for (
size_t i = 0; i < numPoints; ++i) {
1188 const double smoothedValue = smoothedValues[i];
1190 if (i >= smoothingWindow / 2 && i < numPoints - smoothingWindow / 2) {
1192 int numGreaterEqual = 0;
1194 for (
size_t j = i - smoothingWindow / 2; j <= i + smoothingWindow / 2; ++j) {
1195 if (j != i && smoothedValue <= smoothedValues[j]) {
1197 if (numGreaterEqual >
1207 if (isPeak && smoothedValue > threshold) {
1208 if (peaks.empty() || i - std::get<0>(peaks.back()) >= distance) {
1209 auto peakPosition = double(i);
1210 auto formattedPeakPosition =
static_cast<UShort_t
>(peakPosition);
1211 double peakAmplitude =
GetRawData(formattedPeakPosition);
1212 double peakAmplitudeBaseLineCorrected = peakAmplitude - signalBaseLine;
1214 peaks.emplace_back(formattedPeakPosition, peakAmplitude, peakAmplitudeBaseLineCorrected);
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.
TGraph * fGraph
A TGraph pointer used to store the TRestRawSignal drawing.
Double_t fBaseLine
This baseline value will be subtracted from GetData for any raw signal observable calculation.
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...
std::vector< Short_t > fSignalData
Vector with the data of the signal.
void Print() const
It prints the signal data on screen.
Double_t fThresholdIntegral
It stores the integral value obtained from the points identified over threshold.
Int_t fSignalID
An integer value used to attribute a unique identification number to the signal.
Double_t GetMaxPeakValue()
It returns the amplitude of the signal maximum, baseline will be corrected if CalculateBaseLine was c...
void CalculateBaseLineSigmaExcludeOutliers(Int_t startBin, Int_t endBin)
This method is called by CalculateBaseLine with the "OUTLIERS"-option to determine the value of the b...
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.
void SignalAddition(const TRestRawSignal &signal)
This method adds the signal provided by argument to the existing signal.
Int_t fTailPoints
It defines the number of points to include after point over threshold definition. NOT implemented.
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...
void CalculateBaseLineMedianExcludeOutliers(Int_t startBin, Int_t endBin)
This method is called by CalculateBaseLine with the "OUTLIERS"-option and is used to determine the va...
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].
std::vector< std::tuple< double, UShort_t, double > > GetPeaks(double threshold, UShort_t distance=5, double signalBaseLine=0.0) const
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...
std::vector< Int_t > fPointsOverThreshold
A std::vector containing the index of points that are identified over threshold.
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.
UInt_t fSeed
Seed used for random number generation.
Double_t GetSlopeIntegral()
It returns the integral of points identified over threshold found in the first positive rise of the s...
Double_t fBaseLineSigma
The baseline fluctuation calculated as the standard deviation of the baseline.
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 fHeadPoints
It defines the number of points to include before point over threshold definition....
Int_t GetMaxPeakBin()
It returns the bin at which the maximum peak amplitude happens.
Int_t GetSignalID() const
Returns the value of signal ID.
void GetBaseLineCorrected(TRestRawSignal *smoothedSignal, Int_t averagingPoints)
It applies the moving average filter (GetSignalSmoothed) to the signal, which is then subtracted from...
TVector2 fRange
Any signal calculation will be restricted to the following range definition.
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.