source: JEM-EUSO/esaf_cc_at_lal/packages/reconstruction/modules/shower/fitting/src/MedianFit.cc @ 114

Last change on this file since 114 was 114, checked in by moretto, 11 years ago

actual version of ESAF at CCin2p3

File size: 6.8 KB
Line 
1// ESAF : Euso Simulation and Analysis Framework
2// $Id: MedianFit.cc 2949 2011-06-26 18:39:34Z mabl $
3// R. Pesce created Jan, 29 2004
4
5/*****************************************************************************
6 * ESAF: Euso Simulation and Analysis Framework                              *
7 *                                                                           *
8 *  Id: MedianFit                                                            *
9 *  Package: Fitting                                                         *
10 *  Coordinator: <coordinator>                                               *
11 *                                                                           *
12 *****************************************************************************/
13
14//_____________________________________________________________________________
15//
16// TrackDirection2Module
17//
18// <extensive class description>
19
20#include <iostream>
21#include "MedianFit.hh"
22#include "TMath.h"
23
24using namespace TMath;
25
26ClassImp(MedianFit)
27
28//___________________________________________________________________________
29MedianFit::MedianFit( Int_t numpoints, vector<Double_t> x, vector<Double_t> y ) {
30    //
31    // ctor
32    //
33   
34    fNumPoints = numpoints;
35    fSlope = 0;
36    fOffset = 0;
37    fAbsoluteDeviation = 0;
38    fPointsX = x;
39    fPointsY = y;
40    Do();
41}
42
43//___________________________________________________________________________
44MedianFit::~MedianFit() {
45    //
46    // dtor
47    //
48   
49    fPointsX.clear();
50    fPointsY.clear();
51}
52
53
54//___________________________________________________________________________
55void MedianFit::Do() {
56    //
57    // Median fit algorithm
58    // Adapted from "Numerical Recipes in C" pag.704
59    //
60   
61    if ( fNumPoints < 2 ) return;
62   
63    Double_t XSum = 0;
64    Double_t XSqSum = 0;
65    Double_t YSum = 0;
66    Double_t XYSum = 0;
67
68    for( Int_t i=0; i<fNumPoints; i++ ) {
69        XSum += fPointsX[i];
70        XSqSum += fPointsX[i] * fPointsX[i];
71        YSum += fPointsY[i];
72        XYSum += fPointsX[i] * fPointsY[i];
73    }
74
75    // method of least squares for a first guess for slope and offset
76    fOffset = (XSqSum * YSum - XSum * XYSum) / (fNumPoints * XSqSum - XSum * XSum);
77    fSlope = (fNumPoints * XYSum - XSum * YSum) / (fNumPoints * XSqSum - XSum * XSum);
78    Double_t chisquare = 0;
79    for( Int_t i=0; i<fNumPoints; i++ ) {
80        chisquare += Power((fPointsY[i] - (fOffset + fSlope * fPointsX[i] )),2);
81    }
82
83    // standard deviation: idea of how big an interaction step to take
84    Double_t sigmaslope = Sqrt(chisquare / fNumPoints * XSqSum - XSum * XSum);
85   
86    Double_t b1 = fSlope;
87    Double_t r1 = RoFunc( b1 );
88
89    if ( sigmaslope > 0 ) {
90        Double_t b2 = fSlope + Sign(3. * sigmaslope, r1);
91        // gues bracket as 3-sigma away, in the downhill direction known from r1
92        Double_t r2 = RoFunc( b2 );
93        if ( b2 == b1 ) {
94            fAbsoluteDeviation /= fNumPoints;
95            return;
96        }
97        // bracketing
98        while( r1*r2 > 0 ) {
99            fSlope = b2 + 1.6 * ( b2 - b1 );
100            b1 = b2;
101            r1 = r2;
102            b2 = fSlope;
103            r2 = RoFunc( b2 );
104        }
105        sigmaslope *= 0.01;
106        // refine until error a negligible number of sigmas
107        while( Abs(b2-b1) > sigmaslope ) {
108            fSlope = b1 + 0.5 * ( b2 - b1 );  // bisection
109            if ( ( fSlope == b1 ) || ( fSlope == b2 ) ) break;
110            Double_t r = RoFunc( fSlope );
111            if ( r*r1 >= 0 ) {
112                r1 = r;
113                b1 = fSlope;
114            } else {
115                r2 = r;
116                b2 = fSlope;
117            }
118        }
119    }
120    fAbsoluteDeviation /= fNumPoints;
121}
122
123//___________________________________________________________________________
124Double_t MedianFit::RoFunc( Double_t b ) {
125    //
126    // Method used by median fit
127    // Adapted from "Numerical Recipes in C pag.705"
128    //
129
130    vector<Double_t> dummy;
131   
132    for( Int_t i=0; i<fNumPoints; i++ ) {
133        dummy.push_back( fPointsY[i]- b * fPointsX[i] );
134    }
135
136    if ( ( fNumPoints & 1 ) == 0 ) {
137        Int_t j = fNumPoints >> 1;
138        fOffset = 0.5 * (Select( j, dummy ) + Select( j + 1, dummy ));
139    } else {
140        fOffset = Select( (fNumPoints+1)>>1, dummy);
141    }
142   
143    Float_t sum = 0.;
144    fAbsoluteDeviation = 0.;
145    for( Int_t i=0; i<fNumPoints; i++ ) {
146        Double_t d = fPointsY[i] - ( fOffset + b * fPointsX[i] );
147        fAbsoluteDeviation += Abs(d);
148        if ( fPointsY[i] != 0 )
149            d /= fPointsY[i];
150        if ( Abs(d) > 1.0e-7)
151            sum += ( d >= 0 ? fPointsX[i] : -fPointsX[i] );
152    }
153   
154    return sum;
155}
156
157//___________________________________________________________________________
158Double_t MedianFit::Select( Int_t k, vector<Double_t> vec ) {
159    //
160    // Find the k-th smallest element in a vector; used to find the median
161    // Adapted from "Numerical Recipes in C" pag.342
162    //
163   
164    Int_t l = 0;
165    Int_t ir = vec.size() - 1;
166
167    for( ; ; ) {
168        if ( ir <= l + 1 ) {                           // active partition contains 1 or 2 elements
169            if ( ir == l + 1 && vec[ir] < vec[l] ) {   // active partition contains 2 elements
170                Double_t temp = vec[l]; vec[l] = vec[ir]; vec[ir] = temp;
171            }
172            return vec[k-1];
173        } else {
174            // choose median of left, center and right elements as partitioning element a
175            // rearrange so that vec[l] <= vec[l+1] <= vec[ir]
176            Int_t middle = ( l + ir ) >> 1;
177            Double_t temp = vec[middle]; vec[middle] = vec[l+1]; vec[l+1] = temp;
178            if ( vec[l] > vec[ir] ) {
179                temp = vec[l]; vec[l] = vec[ir]; vec[ir] = temp;
180            }
181            if ( vec[l+1] > vec[ir] ) {
182                temp = vec[l+1]; vec[l+1] = vec[ir]; vec[ir] = temp;
183            }
184            if ( vec[l] > vec[l+1] ) {
185                temp = vec[l]; vec[l] = vec[l+1]; vec[l+1] = temp;
186            }
187            // initialize pointers for partitioning
188            Int_t i = l + 1;
189            Int_t j = ir;
190            Double_t a = vec[l+1];        // partitioning element
191            for( ; ; ) {
192                do {                     // scan up to find element > a
193                    i++;
194                } while( vec[i] < a );   // && i< (Int_t)vec.size() );
195                do {                     // scan down to find element < a
196                    j--;
197                } while( vec[j] > a );  //&& j>=0 );
198                if ( j < i ) break;      // pointers crossed; partitioning complete
199                temp = vec[i]; vec[i] = vec[j]; vec[j] = temp;
200            }
201            vec[l+1] = vec[j];           // insert partitioning element
202            vec[j] = a;
203            if ( j >= (k-1) ) ir = j - 1;    // keep active the partiction that contains the k-th element
204            if ( j <= (k-1) ) l = i;
205        }
206    }
207}
Note: See TracBrowser for help on using the repository browser.