source: branches/AddingGoogleTestEnvironment/mextralgo/MExtralgoSpline.cc@ 19779

Last change on this file since 19779 was 17887, checked in by Daniela Dorner, 11 years ago
small fix
File size: 10.4 KB
Line 
1/* ======================================================================== *\
2!
3! *
4! * This file is part of MARS, the MAGIC Analysis and Reconstruction
5! * Software. It is distributed to you in the hope that it can be a useful
6! * and timesaving tool in analyzing Data of imaging Cerenkov telescopes.
7! * It is distributed WITHOUT ANY WARRANTY.
8! *
9! * Permission to use, copy, modify and distribute this software and its
10! * documentation for any purpose is hereby granted without fee,
11! * provided that the above copyright notice appear in all copies and
12! * that both that copyright notice and this permission notice appear
13! * in supporting documentation. It is provided "as is" without express
14! * or implied warranty.
15! *
16!
17! Author(s): Thomas Bretz <mailto:tbretz@astro.uni-wuerzbrug.de>
18! Author(s): Markus Gaug 09/2004 <mailto:markus@ifae.es>
19!
20! Copyright: MAGIC Software Development, 2002-2009
21!
22!
23\* ======================================================================== */
24
25//////////////////////////////////////////////////////////////////////////////
26//
27// MExtralgoSpline
28//
29// Fast Spline extractor using a cubic spline algorithm, adapted from
30// Numerical Recipes in C++, 2nd edition, pp. 116-119.
31//
32// The coefficients "ya" are here denoted as "fVal" corresponding to
33// the FADC value subtracted by the clock-noise corrected pedestal.
34//
35// The coefficients "y2a" get immediately divided 6. and are called here
36// fDer2 although they are now not exactly the second derivative
37// coefficients any more.
38//
39// The calculation of the cubic-spline interpolated value "y" on a point
40// "x" along the FADC-slices axis becomes: EvalAt(x)
41//
42// The coefficients fDer2 are calculated with the simplified
43// algorithm in InitDerivatives.
44//
45// This algorithm takes advantage of the fact that the x-values are all
46// separated by exactly 1 which simplifies the Numerical Recipes algorithm.
47// (Note that the variables fDer are not real first derivative coefficients.)
48//
49// Note, this spline is not optimized to be evaluated many many times, but
50// it is optimized to be initialized very fast with new values again and
51// again.
52//
53//////////////////////////////////////////////////////////////////////////////
54#include "MExtralgoSpline.h"
55
56#include <iostream>
57#include <TRandom.h>
58
59#include "../mbase/MMath.h"
60#include "../mbase/MArrayF.h"
61
62using namespace std;
63
64// --------------------------------------------------------------------------
65//
66// Calculate the first and second derivative for the splie.
67//
68// The coefficients are calculated such that
69// 1) fVal[i] = Eval(i, 0)
70// 2) Eval(i-1, 1)==Eval(i, 0)
71//
72// In other words: The values with the index i describe the spline
73// between fVal[i] and fVal[i+1]
74//
75void MExtralgoSpline::InitDerivatives() const
76{
77 if (fNum<2)
78 return;
79
80 // Look up table for coefficients
81 static MArrayF lut;
82
83 // If the lut is not yet large enough: resize and reclaculate
84 if (fNum>(Int_t)lut.GetSize())
85 {
86 lut.Set(fNum);
87
88 lut[0] = 0.;
89 for (Int_t i=1; i<fNum-1; i++)
90 lut[i] = -1.0/(lut[i-1] + 4);
91 }
92
93 // Calculate the coefficients used to get reproduce the first and
94 // second derivative.
95 fDer1[0] = 0.;
96 for (Int_t i=1; i<fNum-1; i++)
97 {
98 const Float_t d1 = fVal[i+1] - 2*fVal[i] + fVal[i-1];
99 fDer1[i] = (fDer1[i-1]-d1)*lut[i];
100 }
101
102 fDer2[fNum-1] = 0.;
103 for (Int_t k=fNum-2; k>=0; k--)
104 fDer2[k] = lut[k]*fDer2[k+1] + fDer1[k];
105}
106
107// --------------------------------------------------------------------------
108//
109// Return the two results x1 and x2 of f'(x)=0 for the third order
110// polynomial (spline) in the interval i. Return the number of results.
111// (0 if the fist derivative does not have a null-point)
112//
113Int_t MExtralgoSpline::EvalDerivEq0(const Int_t i, Double_t &x1, Double_t &x2) const
114{
115 const Double_t difder = fDer2[i+1]-fDer2[i];
116 const Double_t difval = fVal[i+1] -fVal[i];
117
118 return MMath::SolvePol2(3*difder, 6*fDer2[i], difval-2*fDer2[i]-fDer2[i+1], x1, x2);
119}
120
121// --------------------------------------------------------------------------
122//
123// Solve the polynomial
124//
125// y = a*x^3 + b*x^2 + c*x + d'
126// 0 = a*x^3 + b*x^2 + c*x + d' - y
127//
128// to find y in the i-th bin. Return the result as x1, x2, x3 and the return
129// code from MMath::SolvPol3.
130//
131Int_t MExtralgoSpline::SolvePol3(Int_t i, Double_t y, Double_t &x1, Double_t &x2, Double_t &x3) const
132{
133 // y = a*x^3 + b*x^2 + c*x + d'
134 // 0 = a*x^3 + b*x^2 + c*x + d' - y
135
136 // Calculate coefficients
137 const Double_t a = fDer2[i+1]-fDer2[i];
138 const Double_t b = 3*fDer2[i];
139 const Double_t c = fVal[i+1]-fVal[i] -2*fDer2[i]-fDer2[i+1];
140 const Double_t d = fVal[i] - y;
141
142 // If the first derivative is nowhere==0 and it is increasing
143 // in one point, and the value we search is outside of the
144 // y-interval... it cannot be there
145 // if (c>0 && (d>0 || fVal[i+1]<y) && b*b<3*c*a)
146 // return -2;
147
148 return MMath::SolvePol3(a, b, c, d, x1, x2, x3);
149}
150
151// --------------------------------------------------------------------------
152//
153// Returns the highest x value in [min;max[ at which the spline in
154// the bin i is equal to y
155//
156// min and max must be in the range [0;1]
157//
158// The default for min is 0, the default for max is 1
159// The default for y is 0
160//
161Double_t MExtralgoSpline::FindYdn(Int_t i, Double_t y, Double_t min, Double_t max) const
162{
163 Double_t x1, x2, x3;
164 const Int_t rc = SolvePol3(i, y, x1, x2, x3);
165
166 Double_t x = -1;
167
168 if (rc>0 && x1>=min && x1<max && x1>x)
169 x = x1;
170 if (rc>1 && x2>=min && x2<max && x2>x)
171 x = x2;
172 if (rc>2 && x3>=min && x3<max && x3>x)
173 x = x3;
174
175 return x<0 ? -2 : x+i;
176}
177
178// --------------------------------------------------------------------------
179//
180// Returns the lowest x value in [min;max[ at which the spline in
181// the bin i is equal to y
182//
183// min and max must be in the range [0;1]
184//
185// The default for min is 0, the default for max is 1
186// The default for y is 0
187//
188Double_t MExtralgoSpline::FindYup(Int_t i, Double_t y, Double_t min, Double_t max) const
189{
190 Double_t x1, x2, x3;
191 const Int_t rc = SolvePol3(i, y, x1, x2, x3);
192
193 Double_t x = 2;
194
195 if (rc>0 && x1>min && x1<=max && x1<x)
196 x = x1;
197 if (rc>1 && x2>min && x2<=max && x2<x)
198 x = x2;
199 if (rc>2 && x3>min && x3<=max && x3<x)
200 x = x3;
201
202 return x>1 ? -2 : x+i;
203}
204
205// --------------------------------------------------------------------------
206//
207// Search analytically downward for the value y of the spline, starting
208// at x, until x==0. If y is not found or out of range -2 is returned.
209//
210Double_t MExtralgoSpline::SearchYdn(Double_t x, Double_t y) const
211{
212 if (x>=fNum-1)
213 x = fNum-1.0001;
214
215 Int_t i = TMath::FloorNint(x);
216 if (i<0)
217 return -3;
218
219 Double_t rc = FindYdn(i, y, 0, x-i);
220 while (--i>=0 && rc<0)
221 rc = FindYdn(i, y);
222
223 return rc;
224}
225
226// --------------------------------------------------------------------------
227//
228// Search analytically upwards for the value y of the spline, starting
229// at x, until x==fNum-1. If y is not found or out of range -2 is returned.
230//
231Double_t MExtralgoSpline::SearchYup(Double_t x, Double_t y) const
232{
233 if (x<0)
234 x = 0.0001;
235
236 Int_t i = TMath::FloorNint(x);
237 if (i>fNum-2)
238 return -3;
239
240 Double_t rc = FindYup(i, y, x-i, 1.);
241 while (++i<fNum-1 && rc<0)
242 rc = FindYup(i, y);
243
244 return rc;
245}
246
247// --------------------------------------------------------------------------
248//
249// Do a range check an then calculate the integral from start-fRiseTime
250// to start+fFallTime. An extrapolation of 0.5 slices is allowed.
251//
252Float_t MExtralgoSpline::CalcIntegral(Float_t pos) const
253{
254 // We allow extrapolation of 1/2 slice.
255 const Float_t min = fRiseTime; //-0.5+fRiseTime;
256 const Float_t max = fNum-1-fFallTime; //fNum-0.5+fFallTime;
257
258 if (pos<min)
259 pos = min;
260 if (pos>max)
261 pos = max;
262
263 return EvalInteg(pos-fRiseTime, pos+fFallTime);
264}
265
266Float_t MExtralgoSpline::CalcIntegral(Float_t beg, Float_t width) const
267{
268 Float_t end = beg + width;
269
270 if (beg<0)
271 {
272 end -= beg;
273 beg = 0;
274 }
275
276 if (end>fNum-1)
277 {
278 beg -= (end-fNum-1);
279 end = fNum-1;
280 }
281
282 return EvalInteg(beg, end);
283}
284
285MArrayF MExtralgoSpline::GetIntegral(bool norm) const
286{
287 MArrayF val(fNum);
288
289 //val[0] = 0;
290
291 Double_t integ = 0;
292 for (int i=0; i<fNum-1; i++)
293 {
294 integ += EvalInteg(i);
295
296 val[i+1] = integ;
297 }
298
299 if (norm)
300 for (int i=0; i<fNum-1; i++)
301 val[i+1] /= val[fNum-1];
302
303 return val;
304}
305
306Float_t MExtralgoSpline::ExtractNoise()
307{
308 if (fNum<5)
309 return 0;
310
311 if (!(fExtractionType&kIntegral))
312 {
313 const Int_t pos = gRandom->Integer(fNum-1);
314 const Float_t nsx = gRandom->Uniform();
315 return Eval(pos, nsx);
316 }
317 else
318 {
319 const Float_t pos = gRandom->Uniform(fNum-1-fRiseTime-fFallTime)+fRiseTime;
320 return CalcIntegral(pos);
321 }
322}
323
324void MExtralgoSpline::Extract(Int_t maxbin, Bool_t width)
325{
326 fSignal = 0;
327 fTime = 0;
328 fWidth = 0;
329 fSignalDev = -1;
330 fTimeDev = -1;
331 fWidthDev = -1;
332
333 if (fNum<2)
334 return;
335
336 Float_t maxpos;
337 // FIXME: Check the default if no maximum found!!!
338 GetMaxAroundI(maxbin, maxpos, fHeight);
339
340 const Float_t h = (fExtractionType&kTimeRel) ? fHeight*fHeightTm : fHeightTm;
341
342 switch (fExtractionType)
343 {
344 case kAmplitude:
345 fSignal = fHeight;
346 fTime = maxpos;
347 fSignalDev = 0; // means: is valid
348 fTimeDev = 0;
349 break;
350
351 case kAmplitudeAbs:
352 case kAmplitudeRel:
353 fSignal = fHeight;
354 fTime = SearchYdn(maxpos, h);
355 fSignalDev = 0; // means: is valid
356 fTimeDev = 0;
357 break;
358
359 case kIntegralAbs:
360 case kIntegralRel:
361 fSignal = CalcIntegral(maxpos);
362 fTime = SearchYdn(maxpos, h);
363 fSignalDev = 0; // means: is valid
364 fTimeDev = 0;
365 break;
366
367 case kIntegralDyn:
368 fTime = SearchYdn(maxpos, h);
369 fWidth = SearchYup(maxpos, h)-fTime;
370 fSignal = CalcIntegral(fTime, fWidth);
371 fTimeDev = 0;
372 fWidthDev = 0;
373 fSignalDev = 0;
374 break;
375
376 case kIntegralFixed:
377 fTime = SearchYdn(maxpos, h);
378 fSignal = CalcIntegral(fTime-fRiseTime, fRiseTime+fFallTime);
379 fTimeDev = 0;
380 fSignalDev = 0;
381 break;
382 }
383}
Note: See TracBrowser for help on using the repository browser.