@@ -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