source: trunk/MagicSoft/Mars/mextralgo/MExtralgoDigitalFilter.cc@ 8744

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