Skip to content

Commit ef47bdd

Browse files
committed
Add MAD estimator to MathUtils fit collection
1 parent 3ef9196 commit ef47bdd

1 file changed

Lines changed: 76 additions & 0 deletions

File tree

  • Common/MathUtils/include/MathUtils

Common/MathUtils/include/MathUtils/fit.h

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -712,6 +712,82 @@ bool LTMUnbinnedSig(const std::vector<T>& data, std::vector<size_t>& index, std:
712712
params[4] = params[3] / std::sqrt(2.0); // error on RMS
713713
return true;
714714
}
715+
716+
//___________________________________________________________________
717+
template <typename T>
718+
T selKthMin(int k, int np, T* arr)
719+
{
720+
// Returns the k th smallest value in the array. The input array will be rearranged
721+
// to have this value in location arr[k] , with all smaller elements moved before it
722+
// (in arbitrary order) and all larger elements after (also in arbitrary order).
723+
// From Numerical Recipes in C++
724+
725+
int i, j, mid, ir = np - 1, l = 0;
726+
T a;
727+
for (;;) {
728+
if (ir <= l + 1) {
729+
if (ir == l + 1 && arr[ir] < arr[l]) {
730+
std::swap(arr[l], arr[ir]);
731+
}
732+
return arr[k];
733+
} else {
734+
int mid = (l + ir) >> 1, i = l + 1;
735+
std::swap(arr[mid], arr[i]);
736+
if (arr[i] > arr[ir]) {
737+
std::swap(arr[i], arr[ir]);
738+
}
739+
if (arr[l] > arr[ir]) {
740+
std::swap(arr[l], arr[ir]);
741+
}
742+
if (arr[i] > arr[l]) {
743+
std::swap(arr[i], arr[l]);
744+
}
745+
j = ir;
746+
a = arr[l];
747+
for (;;) {
748+
do {
749+
i++;
750+
} while (arr[i] < a);
751+
do {
752+
j--;
753+
} while (arr[j] > a);
754+
if (j < i) {
755+
break;
756+
}
757+
std::swap(arr[i], arr[j]);
758+
}
759+
arr[l] = arr[j];
760+
arr[j] = a;
761+
if (j >= k) {
762+
ir = j - 1;
763+
}
764+
if (j <= k) {
765+
l = i;
766+
}
767+
}
768+
}
769+
}
770+
771+
//___________________________________________________________________
772+
template <typename T>
773+
T MAD2Sigma(int np, T* y)
774+
{
775+
// Sigma calculated from median absolute deviations, https://en.wikipedia.org/wiki/Median_absolute_deviation
776+
// the input array is modified
777+
if (np < 2) {
778+
return 0;
779+
}
780+
int nph = np >> 1;
781+
float median = (np & 0x1) ? selKthMin(nph, np, y) : 0.5 * (selKthMin(nph - 1, np, y) + selKthMin(nph, np, y));
782+
// build abs differences to median
783+
for (int i = np; i--;) {
784+
y[i] = std::abs(y[i] - median);
785+
}
786+
// now get median of abs deviations
787+
median = (np & 0x1) ? selKthMin(nph, np, y) : 0.5 * (selKthMin(nph - 1, np, y) + selKthMin(nph, np, y));
788+
return median * 1.4826; // convert to Gaussian sigma
789+
}
790+
715791
} // namespace math_utils
716792
} // namespace o2
717793
#endif

0 commit comments

Comments
 (0)