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);
1030 vector<pair<UShort_t, double>> peaks;
1032 const UShort_t smoothingWindow =
1036 if (numPoints == 0) {
1041 vector<double> smoothedValues(numPoints, 0.0);
1042 double currentSum = 0.0;
1043 UShort_t windowSize = smoothingWindow + 1;
1046 for (UShort_t i = 0; i < static_cast<UShort_t>(std::min<size_t>(windowSize, numPoints)); ++i) {
1049 smoothedValues[0] = currentSum / windowSize;
1051 for (UShort_t i = 1; i < numPoints; ++i) {
1052 if (i < smoothingWindow / 2 + 1) {
1055 UShort_t currentWindowSize =
1056 static_cast<UShort_t
>(std::min<size_t>(windowSize, i + smoothingWindow / 2 + 1));
1057 for (UShort_t j = 0; j < currentWindowSize; ++j) {
1060 smoothedValues[i] = currentSum / currentWindowSize;
1061 }
else if (i > numPoints - smoothingWindow / 2 - 1) {
1064 UShort_t currentWindowSize =
1065 static_cast<UShort_t
>(std::min<size_t>(windowSize, numPoints - i + smoothingWindow / 2));
1066 for (UShort_t j = i - smoothingWindow / 2; j < numPoints; ++j) {
1069 smoothedValues[i] = currentSum / currentWindowSize;
1072 currentSum -=
GetRawData(i - smoothingWindow / 2 - 1);
1073 currentSum +=
GetRawData(i + smoothingWindow / 2);
1074 smoothedValues[i] = currentSum / windowSize;
1079 for (UShort_t i = 0; i < numPoints; ++i) {
1080 const double smoothedValue = smoothedValues[i];
1082 if (i >= smoothingWindow / 2 && i < numPoints - smoothingWindow / 2) {
1084 int numGreaterEqual = 0;
1086 for (UShort_t j = i - smoothingWindow / 2; j <= i + smoothingWindow / 2; ++j) {
1087 if (j != i && smoothedValue <= smoothedValues[j]) {
1089 if (numGreaterEqual >
1101 if (isPeak && smoothedValue > threshold) {
1102 if (peaks.empty() || i - peaks.back().first >= distance) {
1105 double maxAmplitude = smoothedValues[i];
1108 for (std::vector<double>::size_type j = i + 1;
1109 j <= i + distance && j < smoothedValues.size(); ++j) {
1110 if (smoothedValues[j] > maxAmplitude) {
1111 maxAmplitude = smoothedValues[j];
1120 double peakAmplitude = (amplitude1 + amplitude2 + amplitude3) / 3.0;
1123 peaks.emplace_back(maxBin, peakAmplitude);
1132vector<pair<UShort_t, double>> TRestRawSignal::GetPeaksVeto(
double threshold, UShort_t distance)
const {
1133 vector<pair<UShort_t, double>> peaks;
1135 const UShort_t smoothingWindow =
1139 if (numPoints == 0) {
1144 vector<double> smoothedValues(numPoints, 0.0);
1145 double currentSum = 0.0;
1146 UShort_t windowSize = smoothingWindow + 1;
1149 for (UShort_t i = 0; i < static_cast<UShort_t>(std::min<size_t>(windowSize, numPoints)); ++i) {
1152 smoothedValues[0] = currentSum / windowSize;
1154 for (UShort_t i = 1; i < numPoints; ++i) {
1155 if (i < smoothingWindow / 2 + 1) {
1158 UShort_t currentWindowSize =
1159 static_cast<UShort_t
>(std::min<size_t>(windowSize, i + smoothingWindow / 2 + 1));
1160 for (UShort_t j = 0; j < currentWindowSize; ++j) {
1163 smoothedValues[i] = currentSum / currentWindowSize;
1164 }
else if (i > numPoints - smoothingWindow / 2 - 1) {
1167 UShort_t currentWindowSize =
1168 static_cast<UShort_t
>(std::min<size_t>(windowSize, numPoints - i + smoothingWindow / 2));
1169 for (UShort_t j = i - smoothingWindow / 2; j < numPoints; ++j) {
1172 smoothedValues[i] = currentSum / currentWindowSize;
1175 currentSum -=
GetRawData(i - smoothingWindow / 2 - 1);
1176 currentSum +=
GetRawData(i + smoothingWindow / 2);
1177 smoothedValues[i] = currentSum / windowSize;
1182 for (
size_t i = 0; i < numPoints; ++i) {
1183 const double smoothedValue = smoothedValues[i];
1185 if (i >= smoothingWindow / 2 && i < numPoints - smoothingWindow / 2) {
1187 int numGreaterEqual = 0;
1189 for (
size_t j = i - smoothingWindow / 2; j <= i + smoothingWindow / 2; ++j) {
1190 if (j != i && smoothedValue <= smoothedValues[j]) {
1192 if (numGreaterEqual >
1202 if (isPeak && smoothedValue > threshold) {
1203 if (peaks.empty() || i - peaks.back().first >= distance) {
1204 auto peakPosition = double(i);
1205 auto formattedPeakPosition =
static_cast<UShort_t
>(peakPosition);
1206 double peakAmplitude =
GetRawData(formattedPeakPosition);
1208 peaks.emplace_back(formattedPeakPosition, peakAmplitude);
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.
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.
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].
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.