source: trunk/MagicSoft/Mars/mextralgo/MExtralgoSpline.cc@ 8548

Last change on this file since 8548 was 8546, checked in by tbretz, 18 years ago
*** empty log message ***
File size: 8.0 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-2007
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//////////////////////////////////////////////////////////////////////////////
50#include "MExtralgoSpline.h"
51
52#include <TRandom.h>
53
54#include "../mbase/MMath.h"
55#include "../mbase/MArrayF.h"
56
57using namespace std;
58
59// --------------------------------------------------------------------------
60//
61// Calculate the first and second derivative for the splie.
62//
63// The coefficients are calculated such that
64// 1) fVal[i] = Eval(i, 0)
65// 2) Eval(i-1, 1)==Eval(i, 0)
66//
67// In other words: The values with the index i describe the spline
68// between fVal[i] and fVal[i+1]
69//
70void MExtralgoSpline::InitDerivatives() const
71{
72 if (fNum<2)
73 return;
74
75 // Look up table for coefficients
76 static MArrayF lut;
77
78 // If the lut is not et large enough resize and reclaculate
79 if (fNum>(Int_t)lut.GetSize())
80 {
81 lut.Set(fNum);
82
83 lut[0] = 0.;
84 for (Int_t i=1; i<fNum-1; i++)
85 lut[i] = -1.0/(lut[i-1] + 4);
86 }
87
88 // Calculate the coefficients used to get reproduce the first and
89 // second derivative.
90 fDer1[0] = 0.;
91 for (Int_t i=1; i<fNum-1; i++)
92 {
93 const Float_t d1 = fVal[i+1] - 2*fVal[i] + fVal[i-1];
94 fDer1[i] = (fDer1[i-1]-d1)*lut[i];
95 }
96
97 fDer2[fNum-1] = 0.;
98 for (Int_t k=fNum-2; k>=0; k--)
99 fDer2[k] = lut[k]*fDer2[k+1] + fDer1[k];
100}
101
102// --------------------------------------------------------------------------
103//
104// Return the two results x1 and x2 of f'(x)=0 for the third order
105// polynomial (spline) in the interval i. Return the number of results.
106// (0 if the fist derivative does not have a null-point)
107//
108Int_t MExtralgoSpline::EvalDerivEq0(const Int_t i, Double_t &x1, Double_t &x2) const
109{
110 const Double_t difder = fDer2[i+1]-fDer2[i];
111 const Double_t difval = fVal[i+1] -fVal[i];
112
113 return MMath::SolvePol2(3*difder, 6*fDer2[i], difval-2*fDer2[i]-fDer2[i+1], x1, x2);
114}
115
116// --------------------------------------------------------------------------
117//
118// Returns the highest x value in [min;max[ at which the spline in
119// the bin i is equal to y
120//
121// min and max are defined to be [0;1]
122//
123// The default for min is 0, the default for max is 1
124// The defaule for y is 0
125//
126Double_t MExtralgoSpline::FindY(Int_t i, Double_t y, Double_t min, Double_t max) const
127{
128 // y = a*x^3 + b*x^2 + c*x + d'
129 // 0 = a*x^3 + b*x^2 + c*x + d' - y
130
131 // Calculate coefficients
132 const Double_t a = fDer2[i+1]-fDer2[i];
133 const Double_t b = 3*fDer2[i];
134 const Double_t c = fVal[i+1]-fVal[i] -2*fDer2[i]-fDer2[i+1];
135 const Double_t d = fVal[i] - y;
136
137 // If the first derivative is nowhere==0 and it is increasing
138 // in one point, and the value we search is outside of the
139 // y-interval... it cannot be there
140 // if (c>0 && (d>0 || fVal[i+1]<y) && b*b<3*c*a)
141 // return -2;
142
143 Double_t x1, x2, x3;
144 const Int_t rc = MMath::SolvePol3(a, b, c, d, x1, x2, x3);
145
146 Double_t x = -1;
147 if (rc>0 && x1>=min && x1<max && x1>x)
148 x = x1;
149 if (rc>1 && x2>=min && x2<max && x2>x)
150 x = x2;
151 if (rc>2 && x3>=min && x3<max && x3>x)
152 x = x3;
153
154 return x<0 ? -2 : x+i;
155}
156
157// --------------------------------------------------------------------------
158//
159// Search analytically downward for the value y of the spline, starting
160// at x, until x==0. If y is not found -2 is returned.
161//
162Double_t MExtralgoSpline::SearchY(Float_t x, Float_t y) const
163{
164 if (x>=fNum-1)
165 x = fNum-1.0001;
166
167 Int_t i = TMath::FloorNint(x);
168 Double_t rc = FindY(i, y, 0, x-i);
169 while (--i>=0 && rc<0)
170 rc = FindY(i, y);
171
172 return rc;
173}
174
175Double_t MExtralgoSpline::SearchYup(Float_t x, Float_t y) const
176{
177 if (x<0)
178 x = 0.0001;
179
180 Int_t i = TMath::FloorNint(x);
181 Double_t rc = FindY(i, y, x-i, 1.);
182 while (i++<fNum-1 && rc<0)
183 rc = FindY(i, y);
184
185 return rc;
186}
187
188// --------------------------------------------------------------------------
189//
190// Do a range check an then calculate the integral from start-fRiseTime
191// to start+fFallTime. An extrapolation of 0.5 slices is allowed.
192//
193Float_t MExtralgoSpline::CalcIntegral(Float_t pos) const
194{
195 // In the future we will calculate the intgeral analytically.
196 // It has been tested that it gives identical results within
197 // acceptable differences.
198
199 // We allow extrapolation of 1/2 slice.
200 const Float_t min = fRiseTime; //-0.5+fRiseTime;
201 const Float_t max = fNum-1-fFallTime; //fNum-0.5+fFallTime;
202
203 if (pos<min)
204 pos = min;
205 if (pos>max)
206 pos = max;
207
208 return EvalInteg(pos-fRiseTime, pos+fFallTime);
209}
210
211Float_t MExtralgoSpline::ExtractNoise()
212{
213 if (fNum<5)
214 return 0;
215
216 if (fExtractionType == kAmplitude)
217 {
218 const Int_t pos = gRandom->Integer(fNum-1);
219 const Float_t nsx = gRandom->Uniform();
220 return Eval(pos, nsx);
221 }
222 else
223 {
224 const Float_t pos = gRandom->Uniform(fNum-1-fRiseTime-fFallTime)+fRiseTime;
225 return CalcIntegral(pos);
226 }
227}
228
229void MExtralgoSpline::Extract(Byte_t sat, Int_t maxbin, Bool_t width)
230{
231 fSignal = 0;
232 fTime = 0;
233 fWidth = 0;
234 fSignalDev = -1;
235 fTimeDev = -1;
236 fWidthDev = -1;
237
238 if (fNum<2)
239 return;
240
241 Float_t maxpos;
242 // FIXME: Check the default if no maximum found!!!
243 GetMaxAroundI(maxbin, maxpos, fHeight);
244
245 // --- End NEW ---
246
247 if (fExtractionType == kAmplitude)
248 {
249 fTime = maxpos;
250 fTimeDev = 0;
251 fSignal = fHeight;
252 fSignalDev = 0; // means: is valid
253 return;
254 }
255
256 fSignal = CalcIntegral(maxpos);
257 fSignalDev = 0; // means: is valid
258
259 if (fExtractionType==kIntegralRel && fHeightTm<0)
260 {
261 fTime = maxpos;
262 fTimeDev = 0;
263 return;
264 }
265
266 const Float_t h = fExtractionType==kIntegralAbs ? fHeightTm : fHeight*fHeightTm;
267
268 // Search downwards for fHeight/2
269 // By doing also a search upwards we could extract the pulse width
270 fTime = SearchY(maxpos, h);
271 fTimeDev = 0;
272 if (width)
273 {
274 fWidth = SearchYup(maxpos, h)-fTime;
275 fWidthDev = 0;
276 }
277}
Note: See TracBrowser for help on using the repository browser.