@@ -784,6 +784,50 @@ void TRestRawSignal::CalculateBaseLineMedian(Int_t startBin, Int_t endBin) {
784784 }
785785}
786786
787+ // /////////////////////////////////////////////
788+ // / \brief This method is called by CalculateBaseLine with the "OUTLIERS"-option and is used to determine the
789+ // / value of the baseline as the median of the data points found in the range defined between startBin and
790+ // / endBin after excluding the outliers. The median is calculated using only the values in the 25-75% removing
791+ // / big and small outliers.
792+ // /
793+ void TRestRawSignal::CalculateBaseLineMedianExcludeOutliers (Int_t startBin, Int_t endBin) {
794+ if (endBin - startBin <= 0 ) {
795+ fBaseLine = 0 .;
796+ return ;
797+ } else if (endBin > static_cast <int >(fSignalData .size ())) {
798+ cout << " TRestRawSignal::CalculateBaseLine. Error! Baseline range exceeds the rawdata depth!!"
799+ << endl;
800+ endBin = fSignalData .size ();
801+ } else {
802+ // Extract the data within the interval
803+ std::vector<Short_t> data (fSignalData .begin () + startBin, fSignalData .begin () + endBin);
804+ std::sort (data.begin (), data.end ());
805+
806+ // Calculate Q1 and Q3 for IQR
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;
812+
813+ // Filter out the outliers
814+ std::vector<Short_t> filteredData;
815+ for (const auto & value : data) {
816+ if (value >= lowerBound && value <= upperBound) {
817+ filteredData.emplace_back (value);
818+ }
819+ }
820+
821+ // Calculate median of filtered data
822+ if (filteredData.empty ()) {
823+ fBaseLine = TMath::Median (data.size (),
824+ &data[0 ]); // Fall back to original median if all values are outliers
825+ } else {
826+ fBaseLine = TMath::Median (filteredData.size (), &filteredData[0 ]);
827+ }
828+ }
829+ }
830+
787831// /////////////////////////////////////////////
788832// / \brief This method calculates the average and fluctuation of the baseline in the
789833// / specified range and writes the values to fBaseLine and fBaseLineSigma respectively.
@@ -792,12 +836,16 @@ void TRestRawSignal::CalculateBaseLineMedian(Int_t startBin, Int_t endBin) {
792836// /
793837// / \param option By setting this option to "ROBUST", the average is calculated as median,
794838// / and the fluctuation as interquartile range (IQR), which are less affected by outliers (e.g. a signal
795- // / pulse).
839+ // / pulse). By setting it to "OUTLIERS" the median and sigma will only take into account the
840+ // / 25-75% values of the interval.
796841// /
797842void TRestRawSignal::CalculateBaseLine (Int_t startBin, Int_t endBin, const std::string& option) {
798843 if (ToUpper (option) == " ROBUST" ) {
799844 CalculateBaseLineMedian (startBin, endBin);
800845 CalculateBaseLineSigmaIQR (startBin, endBin);
846+ } else if (ToUpper (option) == " OUTLIERS" ) {
847+ CalculateBaseLineMedianExcludeOutliers (startBin, endBin);
848+ CalculateBaseLineSigmaExcludeOutliers (startBin, endBin);
801849 } else {
802850 CalculateBaseLineMean (startBin, endBin);
803851 CalculateBaseLineSigmaSD (startBin, endBin);
@@ -842,6 +890,54 @@ void TRestRawSignal::CalculateBaseLineSigmaIQR(Int_t startBin, Int_t endBin) {
842890 }
843891}
844892
893+ // /////////////////////////////////////////////
894+ // / \brief This method is called by CalculateBaseLine with the "OUTLIERS"-option to
895+ // / determine the value of the baseline
896+ // / fluctuation as the standard deviation in the baseline range provided excluding outliers.
897+ // / Since outliers are strongly suppressed there is no need to use the IQR.
898+ // /
899+ void TRestRawSignal::CalculateBaseLineSigmaExcludeOutliers (Int_t startBin, Int_t endBin) {
900+ if (endBin - startBin <= 0 ) {
901+ fBaseLineSigma = 0 .;
902+ return ;
903+ } else if (endBin > static_cast <int >(fSignalData .size ())) {
904+ cout << " TRestRawSignal::CalculateBaseLineSigma. Error! Range exceeds the rawdata depth!!" << endl;
905+ endBin = fSignalData .size ();
906+ } else {
907+ // Extract the data within the interval
908+ std::vector<Short_t> data (fSignalData .begin () + startBin, fSignalData .begin () + endBin);
909+ std::sort (data.begin (), data.end ());
910+
911+ // Calculate Q1 and Q3 for IQR
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;
917+
918+ // Filter out the outliers
919+ std::vector<Short_t> filteredData;
920+ for (const auto & value : data) {
921+ if (value >= lowerBound && value <= upperBound) {
922+ filteredData.emplace_back (value);
923+ }
924+ }
925+
926+ // Calculate standard deviation of filtered data
927+ if (filteredData.empty ()) {
928+ fBaseLineSigma = 0 .; // If all values are outliers, set sigma to zero
929+ } else {
930+ double mean =
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 );
935+ }
936+ fBaseLineSigma = std::sqrt (variance / filteredData.size ()); // Standard deviation
937+ }
938+ }
939+ }
940+
845941// /////////////////////////////////////////////
846942// / \brief This method adds an offset to the signal data
847943// /
0 commit comments