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

Last change on this file since 19779 was 8918, checked in by tbretz, 17 years ago
*** empty log message ***
File size: 14.9 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 analysing 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!
18! Author(s): Hendrik Bartko, 09/2004 <mailto:hbartko@mppmu.mpg.de>
19! Author(s): Thomas Bretz, 08/2006 <mailto:tbretz@astro.uni-wuerzburg.de>
20!
21! Copyright: MAGIC Software Development, 2000-2008
22!
23!
24\* ======================================================================== */
25
26//////////////////////////////////////////////////////////////////////////////
27//
28// MExtralgoDigitalFilter
29//
30//////////////////////////////////////////////////////////////////////////////
31#include "MExtralgoDigitalFilter.h"
32
33#include <TMath.h>
34#include <TRandom.h>
35
36using namespace std;
37
38Float_t MExtralgoDigitalFilter::ExtractNoise() const
39{
40 const Int_t pos = gRandom->Integer(fNum-fWindowSize+1);
41 const Int_t frac = gRandom->Integer(fWeightsPerBin);
42
43 return Eval(fWeightsAmp, pos, frac-fWeightsPerBin/2);
44}
45
46// -----------------------------------------------------------------------------
47//
48// Calculates the chi2 of the fit, once the weights have been iterated.
49// Argument: time, obtained after a call to EvalDigitalFilterHiGain
50//
51Float_t MExtralgoDigitalFilter::GetChisq(const Int_t maxp, const Int_t frac, const Float_t sum) const
52{
53 /*
54 TMatrix g (windowh,1);
55 TMatrix gt(windowh,1);
56 TMatrix y (windowh,1);
57
58 const Float_t etau = fFineAdjustHi*sumhi;
59 const Float_t t_fine = TMath::Abs(fFineAdjustHi)< 1./fBinningResolutionHiGain ? -fFineAdjustHi : 0.;
60
61 // if (t_fine==0.)
62 // return -1.;
63
64 if (fDebug)
65 gLog << all << " fMaxPHi: " << fMaxPHi << " fIterPHi " << fIterPHi << " t_fine: " << t_fine << endl;
66
67 //
68 // Slide with a window of size windowh over the sample
69 // and calculate the arrays by interpolating the pulse shape using the
70 // fine-tuned time information.
71 //
72 for (Int_t sample=0; sample &lt; windowh; sample++)
73 {
74 const Int_t idx = fArrBinningResHalfHiGain[sample] + fIterPHi;
75 const Int_t ids = fMaxPHi + sample;
76
77 y [sample][0] = fHiGainSignalDF[ids];
78 g [sample][0] = t_fine >= 0
79 ? (fPulseShapeHiGain[idx] + t_fine*(fPulseShapeHiGain[idx+1] -fPulseShapeHiGain[idx]) )*sumhi
80 : (fPulseShapeHiGain[idx] + t_fine*(fPulseShapeHiGain[idx] -fPulseShapeHiGain[idx-1]))*sumhi;
81 gt[sample][0] = t_fine >= 0
82 ? (fPulseShapeDotHiGain[idx] + t_fine*(fPulseShapeDotHiGain[idx+1]-fPulseShapeDotHiGain[idx]) )*etau
83 : (fPulseShapeDotHiGain[idx] + t_fine*(fPulseShapeDotHiGain[idx] -fPulseShapeDotHiGain[idx-1]) )*etau;
84 }
85
86 TMatrix second = y - g - gt;
87 TMatrix first(TMatrix::kTransposed,second);
88 TMatrix chisq = first * ((*fBHiInv)*second);
89
90 return chisq[0][0]/(windowh-2);
91 */
92/*
93
94 TMatrix S(fWindowSize, 1); // Signal (start==start of window)
95 for (int i=0; i<fWindowSize; i++)
96 S[i][0] = fVal[i+maxp];
97
98 TMatrix g(fWindowSize, 1);
99 //TMatrix gT(fWindowSize, 1);
100
101 for (int i=0; i<fWindowSize; i++)
102 {
103 Int_t idx = fWeightsPerBin*i + frac;
104
105 // FIXME: Maybe we could do an interpolation on time-fineadj?
106 //Float_t slope = fPulseShapeHiGain[idx+1] -fPulseShapeHiGain[idx];
107 //Float_t slopet = fPulseShapeDotHiGain[idx+1]-fPulseShapeDotHiGain[idx];
108
109 g[i][0] = fPulseShapeHiGain[idx] *sumhi;
110 //gT[i][0] = fPulseShapeHiGainDot[idx]*tau;
111 }
112
113 TMatrix Ainv; // Autocorrelation Matrix (inverted)
114
115 TMatrix m = S - g;// - gT;
116 TMatrix mT(TMatrix::kTransposed, m);
117
118 TMatrix chisq = mT * (Ainv*m);
119
120 return chisq[0][0]/(fWindowSize-2);
121 */
122
123 Double_t sumc = 0;
124
125 TMatrix d(fWindowSize, 1); // Signal (start==start of window)
126 for (int i=0; i<fWindowSize; i++)
127 {
128 d[i][0] = fVal[i+maxp]/sum - fPulseShape[fWeightsPerBin*i + frac];
129 sumc += d[i][0]*d[i][0];
130 }
131
132/*
133 TMatrix Ainv; // Autocorrelation Matrix (inverted)
134
135 TMatrix dT(TMatrix::kTransposed, d);
136
137 TMatrix chisq = dT * (*fAinv*d);
138 */
139 return sumc;//chisq[0][0]/(fWindowSize-2);
140}
141
142Int_t MExtralgoDigitalFilter::AlignExtractionWindow(Int_t &maxp, Int_t &frac, const Double_t ampsum)
143{
144 // Align extraction window to signal position
145
146 const Double_t timesum = Eval(fWeightsTime, maxp, frac);
147
148 // Because fWeightsPerBin/2 doesn't correspond to the center
149 // of a bin the time-values extracted are slightly positive.
150 // They are roughly between -0.45 and 0.55
151 const Double_t binoffset = TMath::Even(fWeightsPerBin) ? 0.5 : 0;
152
153 // This is the time offset from the extraction position
154 Double_t tmoffset = (frac+binoffset)/fWeightsPerBin + timesum/ampsum;
155
156 // Convert the residual fraction of one slice into an
157 // offset position in the extraction weights
158 const Int_t integ = TMath::FloorNint(tmoffset+0.5);
159
160 /*
161 if (integ>0)
162 tmoffset=0.49-0.05;
163 if (integ<0)
164 tmoffset=-0.49-0.05;
165 integ=0;
166 */
167
168 // move the extractor by an offset number of slices
169 // determined by the extracted time
170 maxp -= integ;
171
172 frac = TMath::FloorNint((tmoffset-integ)*fWeightsPerBin);
173
174 // Align maxp into available range (TO BE CHECKED)
175 AlignIntoLimits(maxp, frac);
176
177 return integ;
178}
179
180void MExtralgoDigitalFilter::Extract(Int_t maxpos)
181{
182 fSignal = 0; // default is: no pulse found
183 fTime = -2; // default is: out if range (--> random)
184 fSignalDev = 0; // default is: valid
185 fTimeDev = 0; // default is: valid
186
187 // FIXME: How to handle saturation?
188
189 Double_t maxamp = -FLT_MAX;
190 Int_t maxp = -1;
191
192 //
193 // Calculate the sum of the first fWindowSize slices
194 //
195 // For the case of an even number of weights/bin there is
196 // no central bin.So we create an artificial central bin.
197 for (Int_t i=0; i<fNum-fWindowSize+1; i++)
198 {
199 const Double_t sumamp = Eval(fWeightsAmp, i);
200 if (sumamp>maxamp)
201 {
202 maxamp = sumamp;
203 maxp = i;
204 }
205 }
206
207 /*
208 // This could be for a fast but less accurate extraction....
209 maxamp = Eval(fWeightsAmp, maxpos-fWindowSize/2);
210 maxp = maxpos-fWindowSize/2;
211 */
212
213 // The number of available slices were smaller than the
214 // extraction window size of the extractor
215 if (maxp<0)
216 {
217 fSignalDev = -1; // means: is invalid
218 fTimeDev = -1; // means: is invalid
219 return;
220 }
221
222 // For some reason (by chance or because all slices contain 0)
223 // maxamp is 0. This means the signal is zero and no arrival
224 // time can be extracted (but both informations are valid)
225 if (maxamp==0)
226 return;
227
228 Int_t frac = 0;
229 const Int_t shift = AlignExtractionWindow(maxp, frac, maxamp);
230
231 // For safety we do another iteration if we have
232 // shifted the extraction window
233 if (TMath::Abs(shift)>0)
234 AlignExtractionWindow(maxp, frac);
235
236 // Now we have found the "final" position: extract time and charge
237 const Double_t sumamp = Eval(fWeightsAmp, maxp, frac);
238
239 fSignal = sumamp;
240 if (sumamp == 0)
241 return;
242
243 const Double_t sumtime = Eval(fWeightsTime, maxp, frac);
244
245 // This is used to align the weights to bins between
246 // -0.5/fWeightsPerBin and 0.5/fWeightsPerBin instead of
247 // 0 and 1./fWeightsPerBin
248 const Double_t binoffset = TMath::Even(fWeightsPerBin) ? 0.5 : 0;
249
250 fTime = maxp /*- 0.5*/ - Double_t(frac+binoffset)/fWeightsPerBin;
251
252 // To let the lowest value which can be safely extracted be>0:
253 // Take also a possible offset from timefineadjust into account
254 // Sould it be: fTime += fWindowSize/2; ???
255
256 // HERE we should add the distance from the beginning of the
257 // extraction window to the leading edge!
258 fTime += 0.5 + 0.5/fWeightsPerBin;
259 // Define in each extractor a lowest and highest extracted value!
260
261 const Float_t timefineadjust = sumtime/sumamp;
262
263 //if (TMath::Abs(timefineadjust) < 0.2)
264 fTime -= timefineadjust;
265}
266
267
268#include <TH1.h>
269#include <TH2.h>
270#include <TMatrixD.h>
271#include <TArrayF.h>
272#include <iostream>
273#include <TSpline.h>
274#include <TProfile.h>
275
276Int_t MExtralgoDigitalFilter::CalculateWeights(TH1 &shape, const TH2 &autocorr, TArrayF &weightsamp, TArrayF &weightstime, Int_t wpb)
277{
278 const Int_t weightsperbin = wpb<=0?shape.GetNbinsX()/autocorr.GetNbinsX():wpb;
279
280 if (wpb<=0 && weightsperbin*autocorr.GetNbinsX()!=shape.GetNbinsX())
281 {
282 cout << "ERROR - Number of bins mismatch..." << endl;
283 cout << " Shape: " << shape.GetNbinsX() << endl;
284 cout << " ACorr: " << autocorr.GetNbinsX() << endl;
285 return -1;
286 }
287
288 const TAxis &axe = *shape.GetXaxis();
289
290 const Int_t first = axe.GetFirst()/weightsperbin;
291 const Int_t last = axe.GetLast() /weightsperbin;
292
293 const Int_t width = last-first;
294
295 cout << "Range: " << first << " <= bin < " << last << endl;
296 cout << "Window: " << width << endl;
297 cout << "W/Bin: " << weightsperbin << endl;
298
299 // ---------------------------------------------
300
301 const Float_t sum = shape.Integral(first*weightsperbin, last*weightsperbin-1)/weightsperbin;
302 shape.Scale(1./sum);
303
304 cout << "Sum: " << sum << endl;
305
306// TGraph gr(&shape);
307// TSpline5 val("Signal", &gr);
308
309 // FIXME: DELETE!!!
310 TH1 &derivative = *static_cast<TH1*>(shape.Clone());
311 derivative.SetDirectory(0);
312 derivative.Reset();
313
314 for (int i=0; i<derivative.GetNbinsX(); i++)
315 {
316// const Float_t x = derivative.GetBinCenter(i+1);
317// derivative.SetBinContent(i+1, val.Derivative(x));
318
319 const Float_t binm = shape.GetBinContent(i+1-1);
320 const Float_t binp = shape.GetBinContent(i+1+1);
321
322 const Float_t der = (binp-binm)/2./shape.GetBinWidth(1);
323
324 derivative.SetBinContent(i+1, der);
325
326 if (derivative.InheritsFrom(TProfile::Class()))
327 static_cast<TProfile&>(derivative).SetBinEntries(i+1,1);
328 }
329
330 // ---------------------------------------------
331
332 TMatrixD B(width, width);
333 for (Int_t i=0; i<width; i++)
334 for (Int_t j=0; j<width; j++)
335 B[i][j]=autocorr.GetBinContent(i+1/*first*/, j+1/*first*/);
336
337 const TMatrixD Binv(TMatrixD::kInverted, B);
338
339 // ---------------------------------------------
340
341 weightsamp.Set(width*weightsperbin);
342 weightstime.Set(width*weightsperbin);
343
344 for (Int_t i=0; i<weightsperbin; i++)
345 {
346 TMatrixD g(width, 1);
347 TMatrixD d(width, 1);
348
349 for (Int_t bin=0; bin<width; bin++)
350 {
351 const Int_t idx = weightsperbin*(bin+first) + i;
352
353 g[bin][0]=shape.GetBinContent(idx+1);
354 d[bin][0]=derivative.GetBinContent(idx+1);
355 }
356
357 const TMatrixD gT(TMatrixD::kTransposed, g);
358 const TMatrixD dT(TMatrixD::kTransposed, d);
359
360 const TMatrixD denom = (gT*(Binv*g))*(dT*(Binv*d)) - (dT*(Binv*g))*(dT*(Binv*g));
361
362 if (denom[0][0]==0)
363 {
364 cout << "ERROR - Division by zero: denom[0][0]==0 for i=" << i << "." << endl;
365 return -1;
366 }
367
368 const TMatrixD w_amp = (dT*(Binv*d))*(gT*Binv) - (gT*(Binv*d))*(dT*Binv);
369 const TMatrixD w_time = (gT*(Binv*g))*(dT*Binv) - (gT*(Binv*d))*(gT*Binv);
370
371 for (Int_t bin=0; bin<width; bin++)
372 {
373 const Int_t idx = weightsperbin*bin + i;
374
375 weightsamp[idx] = w_amp [0][bin]/denom[0][0];
376 weightstime[idx] = w_time[0][bin]/denom[0][0];
377 }
378 }
379
380 return first*weightsperbin;
381}
382
383Int_t MExtralgoDigitalFilter::CalculateWeights2(TH1 &shape, const TH2 &autocorr, TArrayF &weightsamp, TArrayF &weightstime, Int_t wpb)
384{
385 const Int_t weightsperbin = wpb<=0?shape.GetNbinsX()/autocorr.GetNbinsX():wpb;
386
387 if (wpb<=0 && weightsperbin*autocorr.GetNbinsX()!=shape.GetNbinsX())
388 {
389 cout << "ERROR - Number of bins mismatch..." << endl;
390 cout << " Shape: " << shape.GetNbinsX() << endl;
391 cout << " ACorr: " << autocorr.GetNbinsX() << endl;
392 return -1;
393 }
394
395 const TAxis &axe = *shape.GetXaxis();
396
397 const Int_t first = axe.GetFirst()/weightsperbin;
398 const Int_t last = axe.GetLast() /weightsperbin;
399
400 const Int_t width = last-first;
401
402 cout << "Range: " << first << " <= bin < " << last << endl;
403 cout << "Window: " << width << endl;
404 cout << "W/Bin: " << weightsperbin << endl;
405
406 // ---------------------------------------------
407
408 const Float_t sum = shape.Integral(first*weightsperbin, last*weightsperbin-1)/weightsperbin;
409 shape.Scale(1./sum);
410
411 TGraph gr(&shape);
412 TSpline5 val("Signal", &gr);
413
414 // FIXME: DELETE!!!
415 TH1 &derivative = *static_cast<TH1*>(shape.Clone());
416 derivative.SetDirectory(0);
417 derivative.Reset();
418
419 for (int i=0; i<derivative.GetNbinsX(); i++)
420 {
421 const Float_t x = derivative.GetBinCenter(i+1);
422 derivative.SetBinContent(i+1, val.Derivative(x));
423
424 /*
425 const Float_t binm = shape.GetBinContent(i+1-1);
426 const Float_t binp = shape.GetBinContent(i+1+1);
427
428 const Float_t der = (binp-binm)/2./shape.GetBinWidth(1);
429
430 derivative.SetBinContent(i+1, der);
431 */
432 }
433
434 // ---------------------------------------------
435
436 TMatrixD B(width, width);
437 for (Int_t i=0; i<width; i++)
438 for (Int_t j=0; j<width; j++)
439 B[i][j]=autocorr.GetBinContent(i+first, j+first);
440 B.Invert();
441
442 // ---------------------------------------------
443
444 weightsamp.Set(width*weightsperbin);
445 weightstime.Set(width*weightsperbin);
446
447 for (Int_t i=0; i<weightsperbin; i++)
448 {
449 TMatrixD g(width, 1);
450 TMatrixD d(width, 1);
451
452 for (Int_t bin=0; bin<width; bin++)
453 {
454 const Int_t idx = weightsperbin*(bin+first) + i;
455
456 g[bin][0]=shape.GetBinContent(idx+1);
457 d[bin][0]=derivative.GetBinContent(idx+1);
458 }
459
460 const TMatrixD gT(TMatrixD::kTransposed, g);
461 const TMatrixD dT(TMatrixD::kTransposed, d);
462
463 const TMatrixD denom = (gT*(B*g))*(dT*(B*d)) - (dT*(B*g))*(dT*(B*g));
464
465 if (denom[0][0]==0)
466 {
467 cout << "ERROR - Division by zero: denom[0][0]==0 for i=" << i << "." << endl;
468 return -1;
469 }
470
471 const TMatrixD w_amp = (dT*(B*d))*(gT*B) - (gT*(B*d))*(dT*B);
472 const TMatrixD w_time = (gT*(B*g))*(dT*B) - (gT*(B*d))*(gT*B);
473
474 for (Int_t bin=0; bin<width; bin++)
475 {
476 const Int_t idx = weightsperbin*bin + i;
477
478 weightsamp[idx] = w_amp [0][bin]/denom[0][0];
479 weightstime[idx] = w_time[0][bin]/denom[0][0];
480 }
481 }
482 return first*weightsperbin;
483}
Note: See TracBrowser for help on using the repository browser.