source: trunk/MagicSoft/Mars/msignal/MExtractTimeAndChargeSpline.cc@ 5498

Last change on this file since 5498 was 5497, checked in by gaug, 21 years ago
*** empty log message ***
File size: 32.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 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): Markus Gaug 09/2004 <mailto:markus@ifae.es>
18!
19! Copyright: MAGIC Software Development, 2002-2004
20!
21!
22\* ======================================================================== */
23//////////////////////////////////////////////////////////////////////////////
24//
25// MExtractTimeAndChargeSpline
26//
27// Fast Spline extractor using a cubic spline algorithm, adapted from
28// Numerical Recipes in C++, 2nd edition, pp. 116-119.
29//
30// The coefficients "ya" are here denoted as "fHiGainSignal" and "fLoGainSignal"
31// which means the FADC value subtracted by the clock-noise corrected pedestal.
32//
33// The coefficients "y2a" get immediately divided 6. and are called here
34// "fHiGainSecondDeriv" and "fLoGainSecondDeriv" although they are now not exactly
35// the second derivative coefficients any more.
36//
37// The calculation of the cubic-spline interpolated value "y" on a point
38// "x" along the FADC-slices axis becomes:
39//
40// y = a*fHiGainSignal[klo] + b*fHiGainSignal[khi]
41// + (a*a*a-a)*fHiGainSecondDeriv[klo] + (b*b*b-b)*fHiGainSecondDeriv[khi]
42//
43// with:
44// a = (khi - x)
45// b = (x - klo)
46//
47// and "klo" being the lower bin edge FADC index and "khi" the upper bin edge FADC index.
48// fHiGainSignal[klo] and fHiGainSignal[khi] are the FADC values at "klo" and "khi".
49//
50// An analogues formula is used for the low-gain values.
51//
52// The coefficients fHiGainSecondDeriv and fLoGainSecondDeriv are calculated with the
53// following simplified algorithm:
54//
55// for (Int_t i=1;i<range-1;i++) {
56// pp = fHiGainSecondDeriv[i-1] + 4.;
57// fHiGainFirstDeriv[i] = fHiGainSignal[i+1] - 2.*fHiGainSignal[i] + fHiGainSignal[i-1]
58// fHiGainFirstDeriv[i] = (6.0*fHiGainFirstDeriv[i]-fHiGainFirstDeriv[i-1])/pp;
59// }
60//
61// for (Int_t k=range-2;k>=0;k--)
62// fHiGainSecondDeriv[k] = (fHiGainSecondDeriv[k]*fHiGainSecondDeriv[k+1] + fHiGainFirstDeriv[k])/6.;
63//
64//
65// This algorithm takes advantage of the fact that the x-values are all separated by exactly 1
66// which simplifies the Numerical Recipes algorithm.
67// (Note that the variables "fHiGainFirstDeriv" are not real first derivative coefficients.)
68//
69//
70// The algorithm to search the time proceeds as follows:
71//
72// 1) Calculate all fHiGainSignal from fHiGainFirst to fHiGainLast
73// (note that an "overlap" to the low-gain arrays is possible: i.e. fHiGainLast>14 in the case of
74// the MAGIC FADCs).
75// 2) Remember the position of the slice with the highest content "fAbMax" at "fAbMaxPos".
76// 3) If one or more slices are saturated or fAbMaxPos is less than 2 slices from fHiGainFirst,
77// return fAbMaxPos as time and fAbMax as charge (note that the pedestal is subtracted here).
78// 4) Calculate all fHiGainSecondDeriv from the fHiGainSignal array
79// 5) Search for the maximum, starting in interval fAbMaxPos-1 in steps of 0.2 till fAbMaxPos-0.2.
80// If no maximum is found, go to interval fAbMaxPos+1.
81// --> 4 function evaluations
82// 6) Search for the absolute maximum from fAbMaxPos to fAbMaxPos+1 in steps of 0.2
83// --> 4 function evaluations
84// 7) Try a better precision searching from new max. position fAbMaxPos-0.2 to fAbMaxPos+0.2
85// in steps of 0.025 (83 psec. in the case of the MAGIC FADCs).
86// --> 14 function evaluations
87// 8) If Time Extraction Type kMaximum has been chosen, the position of the found maximum is
88// returned, else:
89// 9) The Half Maximum is calculated.
90// 10) fHiGainSignal is called beginning from fAbMaxPos-1 backwards until a value smaller than fHalfMax
91// is found at "klo".
92// 11) Then, the spline value between "klo" and "klo"+1 is halfed by means of bisection as long as
93// the difference between fHalfMax and spline evaluation is less than fResolution (default: 0.01).
94// --> maximum 12 interations.
95//
96// The algorithm to search the charge proceeds as follows:
97//
98// 1) If Charge Type: kAmplitude was chosen, return the Maximum of the spline, found during the
99// time search.
100// 2) If Charge Type: kIntegral was chosen, sum the fHiGainSignal between:
101// (Int_t)(fAbMaxPos - fRiseTime) and
102// (Int_t)(fAbMaxPos + fFallTime)
103// (default: fRiseTime: 1.5, fFallTime: 4.5)
104// 3) Sum only half the values of the edge slices
105// 4) Sum 1.5*fHiGainSecondDeriv of the not-edge slices using the "natural cubic
106// spline with second derivatives set to 0. at the edges.
107// (Remember that fHiGainSecondDeriv had been divided by 6.)
108//
109// The values: fNumHiGainSamples and fNumLoGainSamples are set to:
110// 1) If Charge Type: kAmplitude was chosen: 1.
111// 2) If Charge Type: kIntegral was chosen: TMath::Floor(fRiseTime + fFallTime)
112// or: TMath::Floor(fRiseTime + fFallTime + 1.) in the case of the low-gain
113//
114// Call: SetRange(fHiGainFirst, fHiGainLast, fLoGainFirst, fLoGainLast)
115// to modify the ranges.
116//
117// Defaults:
118// fHiGainFirst = 2
119// fHiGainLast = 14
120// fLoGainFirst = 2
121// fLoGainLast = 14
122//
123// Call: SetResolution() to define the resolution of the half-maximum search.
124// Default: 0.01
125//
126// Call: SetRiseTime() and SetFallTime() to define the integration ranges
127// for the case, the extraction type kIntegral has been chosen.
128//
129// Call: - SetTimeType(MExtractTimeAndChargeSpline::kMaximum) for extraction
130// the position of the maximum (default)
131// --> needs 22 function evaluations
132// - SetTimeType(MExtractTimeAndChargeSpline::kHalfMaximum) for extraction
133// the position of the half maximum at the rising edge.
134// --> needs max. 34 function evaluations
135// - SetChargeType(MExtractTimeAndChargeSpline::kAmplitude) for the
136// computation of the amplitude at the maximum (default)
137// --> no further function evaluation needed
138// - SetChargeType(MExtractTimeAndChargeSpline::kIntegral) for the
139// computation of the integral beneith the spline between fRiseTime
140// from the position of the maximum to fFallTime after the position of
141// the maximum. The Low Gain is computed with one more slice at the falling
142// edge.
143// --> needs one more simple summation loop over 7 slices.
144//
145//////////////////////////////////////////////////////////////////////////////
146#include "MExtractTimeAndChargeSpline.h"
147
148#include "MPedestalPix.h"
149
150#include "MLog.h"
151#include "MLogManip.h"
152
153ClassImp(MExtractTimeAndChargeSpline);
154
155using namespace std;
156
157const Byte_t MExtractTimeAndChargeSpline::fgHiGainFirst = 2;
158const Byte_t MExtractTimeAndChargeSpline::fgHiGainLast = 14;
159const Byte_t MExtractTimeAndChargeSpline::fgLoGainFirst = 2;
160const Byte_t MExtractTimeAndChargeSpline::fgLoGainLast = 14;
161const Float_t MExtractTimeAndChargeSpline::fgResolution = 0.01;
162const Float_t MExtractTimeAndChargeSpline::fgRiseTime = 1.5;
163const Float_t MExtractTimeAndChargeSpline::fgFallTime = 4.5;
164// --------------------------------------------------------------------------
165//
166// Default constructor.
167//
168// Calls:
169// - SetRange(fgHiGainFirst, fgHiGainLast, fgLoGainFirst, fgLoGainLast)
170//
171// Initializes:
172// - fResolution to fgResolution
173// - fRiseTime to fgRiseTime
174// - fFallTime to fgFallTime
175// - Time Extraction Type to kMaximum
176// - Charge Extraction Type to kAmplitude
177//
178MExtractTimeAndChargeSpline::MExtractTimeAndChargeSpline(const char *name, const char *title)
179 : fHiGainSignal(NULL), fLoGainSignal(NULL),
180 fHiGainFirstDeriv(NULL), fLoGainFirstDeriv(NULL),
181 fHiGainSecondDeriv(NULL), fLoGainSecondDeriv(NULL),
182 fAbMax(0.), fAbMaxPos(0.), fHalfMax(0.)
183{
184
185 fName = name ? name : "MExtractTimeAndChargeSpline";
186 fTitle = title ? title : "Calculate photons arrival time using a fast spline";
187
188 SetResolution();
189 SetRiseTime();
190 SetFallTime();
191
192 SetRange(fgHiGainFirst, fgHiGainLast, fgLoGainFirst, fgLoGainLast);
193
194 SetTimeType();
195 SetChargeType();
196
197}
198
199// --------------------------------------------------------------------------
200//
201// Destructor: Deletes the arrays
202//
203MExtractTimeAndChargeSpline::~MExtractTimeAndChargeSpline()
204{
205
206 if (fHiGainSignal)
207 delete [] fHiGainSignal;
208 if (fLoGainSignal)
209 delete [] fLoGainSignal;
210 if (fHiGainFirstDeriv)
211 delete [] fHiGainFirstDeriv;
212 if (fLoGainFirstDeriv)
213 delete [] fLoGainFirstDeriv;
214 if (fHiGainSecondDeriv)
215 delete [] fHiGainSecondDeriv;
216 if (fLoGainSecondDeriv)
217 delete [] fLoGainSecondDeriv;
218
219}
220
221//-------------------------------------------------------------------
222//
223// Set the ranges
224// In order to set the fNum...Samples variables correctly for the case,
225// the integral is computed, have to overwrite this function and make an
226// explicit call to SetChargeType().
227//
228void MExtractTimeAndChargeSpline::SetRange(Byte_t hifirst, Byte_t hilast, Byte_t lofirst, Byte_t lolast)
229{
230
231 MExtractor::SetRange(hifirst, hilast, lofirst, lolast);
232
233 if (IsExtractionType(kIntegral))
234 SetChargeType(kIntegral);
235 if (IsExtractionType(kAmplitude))
236 SetChargeType(kAmplitude);
237
238}
239
240
241//-------------------------------------------------------------------
242//
243// Set the Time Extraction type. Possible are:
244// - kMaximum: Search the maximum of the spline and return its position
245// - kHalfMaximum: Search the half maximum left from the maximum and return
246// its position
247//
248void MExtractTimeAndChargeSpline::SetTimeType( ExtractionType_t typ )
249{
250
251 CLRBIT(fFlags,kMaximum);
252 CLRBIT(fFlags,kHalfMaximum);
253 SETBIT(fFlags,typ);
254
255}
256
257//-------------------------------------------------------------------
258//
259// Set the Charge Extraction type. Possible are:
260// - kAmplitude: Search the value of the spline at the maximum
261// - kIntegral: Integral the spline from fHiGainFirst to fHiGainLast,
262// by counting the edge bins only half and setting the
263// second derivative to zero, there.
264//
265void MExtractTimeAndChargeSpline::SetChargeType( ExtractionType_t typ )
266{
267
268 CLRBIT(fFlags,kAmplitude);
269 CLRBIT(fFlags,kIntegral );
270
271 SETBIT(fFlags,typ);
272
273}
274
275
276// --------------------------------------------------------------------------
277//
278// ReInit
279//
280// Calls:
281// - MExtractTimeAndCharge::ReInit(pList);
282// - Deletes all arrays, if not NULL
283// - Creates new arrays according to the extraction range
284//
285Bool_t MExtractTimeAndChargeSpline::ReInit(MParList *pList)
286{
287
288 if (fHiGainSignal)
289 delete [] fHiGainSignal;
290 if (fLoGainSignal)
291 delete [] fLoGainSignal;
292 if (fHiGainFirstDeriv)
293 delete [] fHiGainFirstDeriv;
294 if (fLoGainFirstDeriv)
295 delete [] fLoGainFirstDeriv;
296 if (fHiGainSecondDeriv)
297 delete [] fHiGainSecondDeriv;
298 if (fLoGainSecondDeriv)
299 delete [] fLoGainSecondDeriv;
300
301 Int_t range = fHiGainLast - fHiGainFirst + 1 + fHiLoLast;
302
303 fHiGainSignal = new Float_t[range];
304 memset(fHiGainSignal,0,range*sizeof(Float_t));
305 fHiGainFirstDeriv = new Float_t[range];
306 memset(fHiGainFirstDeriv,0,range*sizeof(Float_t));
307 fHiGainSecondDeriv = new Float_t[range];
308 memset(fHiGainSecondDeriv,0,range*sizeof(Float_t));
309
310 range = fLoGainLast - fLoGainFirst + 1;
311
312 fLoGainSignal = new Float_t[range];
313 memset(fLoGainSignal,0,range*sizeof(Float_t));
314 fLoGainFirstDeriv = new Float_t[range];
315 memset(fLoGainFirstDeriv,0,range*sizeof(Float_t));
316 fLoGainSecondDeriv = new Float_t[range];
317 memset(fLoGainSecondDeriv,0,range*sizeof(Float_t));
318
319 if (IsExtractionType(kAmplitude))
320 {
321 fNumHiGainSamples = 1.;
322 fNumLoGainSamples = fLoGainLast ? 1. : 0.;
323 fSqrtHiGainSamples = 1.;
324 fSqrtLoGainSamples = 1.;
325 }
326
327 if (IsExtractionType(kIntegral))
328 {
329 fNumHiGainSamples = fRiseTime + fFallTime;
330 fNumLoGainSamples = fLoGainLast ? fNumHiGainSamples + 1. : 0.;
331 fSqrtHiGainSamples = TMath::Sqrt(fNumHiGainSamples);
332 fSqrtLoGainSamples = TMath::Sqrt(fNumLoGainSamples);
333 }
334
335 if (!MExtractTimeAndCharge::ReInit(pList))
336 return kFALSE;
337
338 return kTRUE;
339}
340
341
342// --------------------------------------------------------------------------
343//
344// Calculates the arrival time and charge for each pixel
345//
346void MExtractTimeAndChargeSpline::FindTimeAndChargeHiGain(Byte_t *first, Byte_t *logain, Float_t &sum, Float_t &dsum,
347 Float_t &time, Float_t &dtime,
348 Byte_t &sat, const MPedestalPix &ped, const Bool_t abflag)
349{
350
351 Int_t range = fHiGainLast - fHiGainFirst + 1;
352 const Byte_t *end = first + range;
353 Byte_t *p = first;
354 Int_t count = 0;
355
356 const Float_t pedes = ped.GetPedestal();
357 const Float_t ABoffs = ped.GetPedestalABoffset();
358
359 Float_t pedmean[2];
360 pedmean[0] = pedes + ABoffs;
361 pedmean[1] = pedes - ABoffs;
362
363 fAbMax = 0.;
364 fAbMaxPos = 0.;
365 Byte_t maxpos = 0;
366
367 //
368 // Check for saturation in all other slices
369 //
370 while (p<end)
371 {
372
373 const Int_t ids = fHiGainFirst + count ;
374 const Float_t signal = (Float_t)*p - pedmean[(ids+abflag) & 0x1];
375 fHiGainSignal[count] = signal;
376
377 if (signal > fAbMax + 0.1) /* the 0.1 is necessary for the ultra-high enery events saturating many slices */
378 {
379 fAbMax = signal;
380 maxpos = p-first;
381 }
382
383 if (*p++ >= fSaturationLimit)
384 sat++;
385
386 count++;
387 }
388
389 if (fHiLoLast != 0)
390 {
391
392 end = logain + fHiLoLast;
393
394 while (logain<end)
395 {
396
397 const Int_t ids = fHiGainFirst + range ;
398 const Float_t signal = (Float_t)*logain - pedmean[(ids+abflag) & 0x1];
399 fHiGainSignal[range] = signal;
400 range++;
401
402 if (signal > fAbMax)
403 {
404 fAbMax = signal;
405 maxpos = logain-first;
406 }
407
408 if (*logain >= fSaturationLimit)
409 sat++;
410
411 logain++;
412 }
413 }
414
415 Float_t pp;
416
417 fHiGainSecondDeriv[0] = 0.;
418 fHiGainFirstDeriv[0] = 0.;
419
420 for (Int_t i=1;i<range-1;i++)
421 {
422 pp = fHiGainSecondDeriv[i-1] + 4.;
423 fHiGainSecondDeriv[i] = -1.0/pp;
424 fHiGainFirstDeriv [i] = fHiGainSignal[i+1] - fHiGainSignal[i] - fHiGainSignal[i] + fHiGainSignal[i-1];
425 fHiGainFirstDeriv [i] = (6.0*fHiGainFirstDeriv[i]-fHiGainFirstDeriv[i-1])/pp;
426 }
427
428 fHiGainSecondDeriv[range-1] = 0.;
429
430 for (Int_t k=range-2;k>=0;k--)
431 fHiGainSecondDeriv[k] = fHiGainSecondDeriv[k]*fHiGainSecondDeriv[k+1] + fHiGainFirstDeriv[k];
432 for (Int_t k=range-2;k>=0;k--)
433 fHiGainSecondDeriv[k] /= 6.;
434
435 if (IsNoiseCalculation() && IsExtractionType(kAmplitude))
436 {
437 //
438 // Take the spline value at the middle of the third slice (to avoid egde effects)
439 //
440 sum = 0.5*fHiGainSignal[2]
441 + 0.5*fHiGainSignal[3]
442 + (-0.375)*fHiGainSecondDeriv[2]
443 + (-0.375)*fHiGainSecondDeriv[3];
444 return;
445 }
446
447 if (IsNoiseCalculation() && IsExtractionType(kIntegral))
448 {
449 //
450 // Take the spline value at the middle of the third slice (to avoid egde effects)
451 //
452 Int_t first = 2;
453 Int_t last = first + (Int_t)(fRiseTime+fFallTime);
454 CalcIntegralHiGain(sum,first,last);
455 return;
456 }
457
458 //
459 // Allow no saturated slice
460 // and
461 // Don't start if the maxpos is too close to the left limit.
462 //
463 if ((sat || maxpos < 2))
464 {
465 time = IsExtractionType(kMaximum)
466 ? (Float_t)(fHiGainFirst + maxpos)
467 : (Float_t)(fHiGainFirst + maxpos - 1);
468 sum = IsExtractionType(kAmplitude)
469 ? fAbMax : 0.;
470 return;
471 }
472
473 //
474 // Now find the maximum
475 //
476 Float_t step = 0.2; // start with step size of 1ns and loop again with the smaller one
477 Float_t lower = (Float_t)maxpos-1.;
478 Float_t upper = (Float_t)maxpos;
479 fAbMaxPos = upper;
480 Float_t x = lower;
481 Float_t y = 0.;
482 Float_t a = 1.;
483 Float_t b = 0.;
484 Int_t klo = maxpos-1;
485 Int_t khi = maxpos;
486
487 //
488 // Search for the maximum, starting in interval maxpos-1 in steps of 0.2 till maxpos-0.2.
489 // If no maximum is found, go to interval maxpos+1.
490 //
491 while ( x < upper - 0.3 )
492 {
493
494 x += step;
495 a -= step;
496 b += step;
497
498 y = a*fHiGainSignal[klo]
499 + b*fHiGainSignal[khi]
500 + (a*a*a-a)*fHiGainSecondDeriv[klo]
501 + (b*b*b-b)*fHiGainSecondDeriv[khi];
502
503 if (y > fAbMax)
504 {
505 fAbMax = y;
506 fAbMaxPos = x;
507 }
508
509 // *fLog << err << x << " " << y << " " << fAbMaxPos<< endl;
510 }
511
512 //
513 // Search for the absolute maximum from maxpos to maxpos+1 in steps of 0.2
514 //
515 if (fAbMaxPos > upper-0.1)
516 {
517
518 upper = (Float_t)maxpos+1.;
519 lower = (Float_t)maxpos;
520 x = lower;
521 a = 1.;
522 b = 0.;
523 khi = maxpos+1;
524 klo = maxpos;
525
526 while (x<upper-0.3)
527 {
528
529 x += step;
530 a -= step;
531 b += step;
532
533 y = a*fHiGainSignal[klo]
534 + b*fHiGainSignal[khi]
535 + (a*a*a-a)*fHiGainSecondDeriv[klo]
536 + (b*b*b-b)*fHiGainSecondDeriv[khi];
537
538 if (y > fAbMax)
539 {
540 fAbMax = y;
541 fAbMaxPos = x;
542 }
543 // *fLog << inf << x << " " << y << " " << fAbMaxPos << endl;
544
545 }
546 }
547
548
549 //
550 // Now, the time, abmax and khicont and klocont are set correctly within the previous precision.
551 // Try a better precision.
552 //
553 const Float_t up = fAbMaxPos+step-0.035;
554 const Float_t lo = fAbMaxPos-step+0.035;
555 const Float_t maxpossave = fAbMaxPos;
556
557 x = fAbMaxPos;
558 a = upper - x;
559 b = x - lower;
560
561 step = 0.025; // step size of 83 ps
562
563 while (x<up)
564 {
565
566 x += step;
567 a -= step;
568 b += step;
569
570 y = a*fHiGainSignal[klo]
571 + b*fHiGainSignal[khi]
572 + (a*a*a-a)*fHiGainSecondDeriv[klo]
573 + (b*b*b-b)*fHiGainSecondDeriv[khi];
574
575 if (y > fAbMax)
576 {
577 fAbMax = y;
578 fAbMaxPos = x;
579 }
580 // *fLog << inf << x << " " << y << " " << fAbMaxPos << endl;
581 }
582
583 //
584 // Second, try from time down to time-0.2 in steps of 0.025.
585 //
586 x = maxpossave;
587
588 //
589 // Test the possibility that the absolute maximum has not been found between
590 // maxpos and maxpos+0.025, then we have to look between maxpos-0.025 and maxpos
591 // which requires new setting of klocont and khicont
592 //
593 if (x < klo + 0.02)
594 {
595 klo--;
596 khi--;
597 upper--;
598 lower--;
599 }
600
601 a = upper - x;
602 b = x - lower;
603
604 while (x>lo)
605 {
606
607 x -= step;
608 a += step;
609 b -= step;
610
611 y = a*fHiGainSignal[klo]
612 + b*fHiGainSignal[khi]
613 + (a*a*a-a)*fHiGainSecondDeriv[klo]
614 + (b*b*b-b)*fHiGainSecondDeriv[khi];
615
616 if (y > fAbMax)
617 {
618 fAbMax = y;
619 fAbMaxPos = x;
620 }
621 // *fLog << warn << x << " " << y << " " << fAbMaxPos << endl;
622 }
623
624 if (IsExtractionType(kMaximum))
625 {
626 time = (Float_t)fHiGainFirst + fAbMaxPos;
627 dtime = 0.025;
628 }
629 else
630 {
631 fHalfMax = fAbMax/2.;
632
633 //
634 // Now, loop from the maximum bin leftward down in order to find the position of the half maximum.
635 // First, find the right FADC slice:
636 //
637 klo = maxpos - 1;
638 while (klo >= 0)
639 {
640 if (fHiGainSignal[klo] < fHalfMax)
641 break;
642 klo--;
643 }
644
645 //
646 // Loop from the beginning of the slice upwards to reach the fHalfMax:
647 // With means of bisection:
648 //
649 x = (Float_t)klo;
650 a = 1.;
651 b = 0.;
652
653 step = 0.5;
654 Bool_t back = kFALSE;
655
656 Int_t maxcnt = 50;
657 Int_t cnt = 0;
658
659 while (TMath::Abs(y-fHalfMax) > fResolution)
660 {
661
662 if (back)
663 {
664 x -= step;
665 a += step;
666 b -= step;
667 }
668 else
669 {
670 x += step;
671 a -= step;
672 b += step;
673 }
674
675 y = a*fHiGainSignal[klo]
676 + b*fHiGainSignal[khi]
677 + (a*a*a-a)*fHiGainSecondDeriv[klo]
678 + (b*b*b-b)*fHiGainSecondDeriv[khi];
679
680 if (y > fHalfMax)
681 back = kTRUE;
682 else
683 back = kFALSE;
684
685 if (++cnt > maxcnt)
686 {
687 // *fLog << inf << x << " " << y << " " << fHalfMax << endl;
688 break;
689 }
690
691 step /= 2.;
692 }
693
694 time = (Float_t)fHiGainFirst + x;
695 dtime = fResolution;
696 }
697
698 if (IsExtractionType(kAmplitude))
699 {
700 sum = fAbMax;
701 return;
702 }
703
704 if (IsExtractionType(kIntegral))
705 {
706 //
707 // Now integrate the whole thing!
708 //
709 Int_t startslice = (Int_t)(fAbMaxPos - fRiseTime);
710 Int_t lastslice = (Int_t)(fAbMaxPos + fFallTime);
711
712 if (lastslice > range)
713 {
714 lastslice = range;
715 startslice += (lastslice - range);
716 }
717
718 CalcIntegralHiGain(sum, startslice, lastslice);
719 }
720
721}
722
723
724// --------------------------------------------------------------------------
725//
726// Calculates the arrival time and charge for each pixel
727//
728void MExtractTimeAndChargeSpline::FindTimeAndChargeLoGain(Byte_t *first, Float_t &sum, Float_t &dsum,
729 Float_t &time, Float_t &dtime,
730 Byte_t &sat, const MPedestalPix &ped, const Bool_t abflag)
731{
732
733 Int_t range = fLoGainLast - fLoGainFirst + 1;
734 const Byte_t *end = first + range;
735 Byte_t *p = first;
736 Int_t count = 0;
737
738 Float_t pedes = ped.GetPedestal();
739 const Float_t ABoffs = ped.GetPedestalABoffset();
740
741 Float_t pedmean[2];
742 pedmean[0] = pedes + ABoffs;
743 pedmean[1] = pedes - ABoffs;
744
745 fAbMax = 0.;
746 fAbMaxPos = 0.;
747 Byte_t maxpos = 0;
748
749 //
750 // Check for saturation in all other slices
751 //
752 while (p<end)
753 {
754
755 const Int_t ids = fLoGainFirst + count ;
756 const Float_t signal = (Float_t)*p - pedmean[(ids+abflag) & 0x1];
757 fLoGainSignal[count] = signal;
758
759 if (signal > fAbMax)
760 {
761 fAbMax = signal;
762 maxpos = p-first;
763 }
764
765 if (*p >= fSaturationLimit)
766 sat++;
767
768 p++;
769 count++;
770 }
771
772 Float_t pp;
773
774 fLoGainSecondDeriv[0] = 0.;
775 fLoGainFirstDeriv[0] = 0.;
776
777 for (Int_t i=1;i<range-1;i++)
778 {
779 pp = fLoGainSecondDeriv[i-1] + 4.;
780 fLoGainSecondDeriv[i] = -1.0/pp;
781 fLoGainFirstDeriv [i] = fLoGainSignal[i+1] - fLoGainSignal[i] - fLoGainSignal[i] + fLoGainSignal[i-1];
782 fLoGainFirstDeriv [i] = (6.0*fLoGainFirstDeriv[i]-fLoGainFirstDeriv[i-1])/pp;
783 }
784
785 fLoGainSecondDeriv[range-1] = 0.;
786 for (Int_t k=range-2;k>=0;k--)
787 fLoGainSecondDeriv[k] = fLoGainSecondDeriv[k]*fLoGainSecondDeriv[k+1] + fLoGainFirstDeriv[k];
788 for (Int_t k=range-2;k>=0;k--)
789 fLoGainSecondDeriv[k] /= 6.;
790
791 if (IsNoiseCalculation() && IsExtractionType(kAmplitude))
792 {
793 //
794 // Take the spline value at the middle of the third slice (to avoid egde effects)
795 //
796 sum = 0.5*fLoGainSignal[2]
797 + 0.5*fLoGainSignal[3]
798 + (-0.375)*fLoGainSecondDeriv[2]
799 + (-0.375)*fLoGainSecondDeriv[3];
800 return;
801 }
802
803 if (IsNoiseCalculation() && IsExtractionType(kIntegral))
804 {
805 //
806 // Take the spline value at the middle of the third slice (to avoid egde effects)
807 //
808 Int_t first = 2;
809 Int_t last = first + (Int_t)(fRiseTime+fFallTime);
810 CalcIntegralLoGain(sum,first,last);
811 return;
812 }
813
814 //
815 // Allow no saturated slice
816 // and
817 // Don't start if the maxpos is too close to the left limit.
818 //
819 if (sat || maxpos < 1)
820 {
821 time = IsExtractionType(kMaximum)
822 ? (Float_t)(fLoGainFirst + maxpos)
823 : (Float_t)(fLoGainFirst + maxpos - 1);
824 return;
825 }
826
827 if (maxpos < 2 && IsExtractionType(kHalfMaximum))
828 {
829 time = (Float_t)(fLoGainFirst + maxpos - 1);
830 return;
831 }
832
833 //
834 // Now find the maximum
835 //
836 Float_t step = 0.2; // start with step size of 1ns and loop again with the smaller one
837 Float_t lower = (Float_t)maxpos-1.;
838 Float_t upper = (Float_t)maxpos;
839 fAbMaxPos = upper;
840 Float_t x = lower;
841 Float_t y = 0.;
842 Float_t a = 1.;
843 Float_t b = 0.;
844 Int_t klo = maxpos-1;
845 Int_t khi = maxpos;
846
847 //
848 // Search for the maximum, starting in interval maxpos-1 in steps of 0.2 till maxpos-0.2.
849 // If no maximum is found, go to interval maxpos+1.
850 //
851 while ( x < upper - 0.3 )
852 {
853
854 x += step;
855 a -= step;
856 b += step;
857
858 y = a*fLoGainSignal[klo]
859 + b*fLoGainSignal[khi]
860 + (a*a*a-a)*fLoGainSecondDeriv[klo]
861 + (b*b*b-b)*fLoGainSecondDeriv[khi];
862
863 if (y > fAbMax)
864 {
865 fAbMax = y;
866 fAbMaxPos = x;
867 }
868
869 // *fLog << err << x << " " << y << " " << fAbMaxPos<< endl;
870 }
871
872 //
873 // Test the possibility that the absolute maximum has not been found before the
874 // maxpos and search from maxpos to maxpos+1 in steps of 0.2
875 //
876 if (fAbMaxPos > upper-0.1)
877 {
878
879 upper = (Float_t)maxpos+1.;
880 lower = (Float_t)maxpos;
881 x = lower;
882 a = 1.;
883 b = 0.;
884 khi = maxpos+1;
885 klo = maxpos;
886
887 while (x<upper-0.3)
888 {
889
890 x += step;
891 a -= step;
892 b += step;
893
894 y = a*fLoGainSignal[klo]
895 + b*fLoGainSignal[khi]
896 + (a*a*a-a)*fLoGainSecondDeriv[klo]
897 + (b*b*b-b)*fLoGainSecondDeriv[khi];
898
899 if (y > fAbMax)
900 {
901 fAbMax = y;
902 fAbMaxPos = x;
903 }
904 // *fLog << inf << x << " " << y << " " << fAbMaxPos << endl;
905
906 }
907 }
908
909
910 //
911 // Now, the time, abmax and khicont and klocont are set correctly within the previous precision.
912 // Try a better precision.
913 //
914 const Float_t up = fAbMaxPos+step-0.035;
915 const Float_t lo = fAbMaxPos-step+0.035;
916 const Float_t maxpossave = fAbMaxPos;
917
918 x = fAbMaxPos;
919 a = upper - x;
920 b = x - lower;
921
922 step = 0.025; // step size of 83 ps
923
924 while (x<up)
925 {
926
927 x += step;
928 a -= step;
929 b += step;
930
931 y = a*fLoGainSignal[klo]
932 + b*fLoGainSignal[khi]
933 + (a*a*a-a)*fLoGainSecondDeriv[klo]
934 + (b*b*b-b)*fLoGainSecondDeriv[khi];
935
936 if (y > fAbMax)
937 {
938 fAbMax = y;
939 fAbMaxPos = x;
940 }
941 // *fLog << inf << x << " " << y << " " << fAbMaxPos << endl;
942 }
943
944 //
945 // Second, try from time down to time-0.2 in steps of 0.025.
946 //
947 x = maxpossave;
948
949 //
950 // Test the possibility that the absolute maximum has not been found between
951 // maxpos and maxpos+0.02, then we have to look between maxpos-0.02 and maxpos
952 // which requires new setting of klocont and khicont
953 //
954 if (x < klo + 0.02)
955 {
956 klo--;
957 khi--;
958 upper--;
959 lower--;
960 }
961
962 a = upper - x;
963 b = x - lower;
964
965 while (x>lo)
966 {
967
968 x -= step;
969 a += step;
970 b -= step;
971
972 y = a*fLoGainSignal[klo]
973 + b*fLoGainSignal[khi]
974 + (a*a*a-a)*fLoGainSecondDeriv[klo]
975 + (b*b*b-b)*fLoGainSecondDeriv[khi];
976
977 if (y > fAbMax)
978 {
979 fAbMax = y;
980 fAbMaxPos = x;
981 }
982 // *fLog << warn << x << " " << y << " " << fAbMaxPos << endl;
983 }
984
985 if (IsExtractionType(kMaximum))
986 {
987 time = (Float_t)fLoGainFirst + fAbMaxPos;
988 dtime = 0.02;
989 }
990 else
991 {
992 fHalfMax = fAbMax/2.;
993
994 //
995 // Now, loop from the maximum bin leftward down in order to find the position of the half maximum.
996 // First, find the right FADC slice:
997 //
998 klo = maxpos - 1;
999 while (klo >= 0)
1000 {
1001 if (fLoGainSignal[klo] < fHalfMax)
1002 break;
1003 klo--;
1004 }
1005
1006 //
1007 // Loop from the beginning of the slice upwards to reach the fHalfMax:
1008 // With means of bisection:
1009 //
1010 x = (Float_t)klo;
1011 a = 1.;
1012 b = 0.;
1013
1014 step = 0.5;
1015 Bool_t back = kFALSE;
1016
1017 Int_t maxcnt = 50;
1018 Int_t cnt = 0;
1019
1020 while (TMath::Abs(y-fHalfMax) > fResolution)
1021 {
1022
1023 if (back)
1024 {
1025 x -= step;
1026 a += step;
1027 b -= step;
1028 }
1029 else
1030 {
1031 x += step;
1032 a -= step;
1033 b += step;
1034 }
1035
1036 y = a*fLoGainSignal[klo]
1037 + b*fLoGainSignal[khi]
1038 + (a*a*a-a)*fLoGainSecondDeriv[klo]
1039 + (b*b*b-b)*fLoGainSecondDeriv[khi];
1040
1041 if (y > fHalfMax)
1042 back = kTRUE;
1043 else
1044 back = kFALSE;
1045
1046 if (++cnt > maxcnt)
1047 {
1048 // *fLog << inf << x << " " << y << " " << fHalfMax << endl;
1049 break;
1050 }
1051
1052 step /= 2.;
1053 }
1054
1055 time = (Float_t)fLoGainFirst + x;
1056 dtime = fResolution;
1057 }
1058
1059 if (IsExtractionType(kAmplitude))
1060 {
1061 sum = fAbMax;
1062 return;
1063 }
1064
1065 if (IsExtractionType(kIntegral))
1066 {
1067 //
1068 // Now integrate the whole thing!
1069 //
1070 Int_t startslice = (Int_t)(fAbMaxPos - fRiseTime);
1071 Int_t lastslice = (Int_t)(fAbMaxPos + fFallTime + 1);
1072
1073 if (lastslice > range)
1074 {
1075 lastslice = range;
1076 startslice += (lastslice - range);
1077 }
1078 CalcIntegralLoGain(sum, startslice, lastslice);
1079 }
1080}
1081
1082void MExtractTimeAndChargeSpline::CalcIntegralHiGain(Float_t &sum, Int_t startslice, Int_t lastslice)
1083{
1084
1085 if (startslice < 0)
1086 {
1087 lastslice -= startslice;
1088 startslice = 0;
1089 }
1090
1091 Int_t i = startslice;
1092 sum = 0.5*fHiGainSignal[i];
1093
1094 //
1095 // We sum 1.5 times the second deriv. coefficients because these had been
1096 // divided by 6. already. Usually, 0.25*fHiGainSecondDeriv should be added.
1097 //
1098 for (i=startslice+1; i<lastslice; i++)
1099 sum += fHiGainSignal[i] + 1.5*fHiGainSecondDeriv[i];
1100
1101 sum += 0.5*fHiGainSignal[lastslice];
1102
1103}
1104
1105void MExtractTimeAndChargeSpline::CalcIntegralLoGain(Float_t &sum, Int_t startslice, Int_t lastslice)
1106{
1107
1108 if (startslice < 0)
1109 {
1110 lastslice -= startslice;
1111 startslice = 0;
1112 }
1113
1114 Int_t i = startslice;
1115 sum = 0.5*fLoGainSignal[i];
1116
1117 //
1118 // We sum 1.5 times the second deriv. coefficients because these had been
1119 // divided by 6. already. Usually, 0.25*fLoGainSecondDeriv should be added.
1120 //
1121 for (i=startslice+1; i<lastslice; i++)
1122 sum += fLoGainSignal[i] + 1.5*fLoGainSecondDeriv[i];
1123
1124 sum += 0.5*fLoGainSignal[lastslice];
1125
1126}
1127
1128
1129
1130// --------------------------------------------------------------------------
1131//
1132// In addition to the resources of the base-class MExtractor:
1133// MJPedestal.MExtractor.WindowSizeHiGain: 6
1134// MJPedestal.MExtractor.WindowSizeLoGain: 6
1135//
1136Int_t MExtractTimeAndChargeSpline::ReadEnv(const TEnv &env, TString prefix, Bool_t print)
1137{
1138
1139 Bool_t rc = kFALSE;
1140
1141 if (IsEnvDefined(env, prefix, "Resolution", print))
1142 {
1143 SetResolution(GetEnvValue(env, prefix, "Resolution",fResolution));
1144 rc = kTRUE;
1145 }
1146 if (IsEnvDefined(env, prefix, "RiseTime", print))
1147 {
1148 SetRiseTime(GetEnvValue(env, prefix, "RiseTime", fRiseTime));
1149 rc = kTRUE;
1150 }
1151 if (IsEnvDefined(env, prefix, "FallTime", print))
1152 {
1153 SetFallTime(GetEnvValue(env, prefix, "FallTime", fFallTime));
1154 rc = kTRUE;
1155 }
1156
1157 Bool_t b = kFALSE;
1158
1159 if (IsEnvDefined(env, prefix, "Amplitude", print))
1160 {
1161 b = GetEnvValue(env, prefix, "Amplitude", IsExtractionType(kAmplitude));
1162 if (b)
1163 SetChargeType(kAmplitude);
1164 rc = kTRUE;
1165 }
1166 if (IsEnvDefined(env, prefix, "Integral", print))
1167 {
1168 b = GetEnvValue(env, prefix, "Integral", IsExtractionType(kIntegral));
1169 if (b)
1170 SetChargeType(kIntegral);
1171 rc = kTRUE;
1172 }
1173 if (IsEnvDefined(env, prefix, "Maximum", print))
1174 {
1175 b = GetEnvValue(env, prefix, "Maximum", IsExtractionType(kMaximum));
1176 if (b)
1177 SetTimeType(kMaximum);
1178 rc = kTRUE;
1179 }
1180 if (IsEnvDefined(env, prefix, "HalfMaximum", print))
1181 {
1182 b = GetEnvValue(env, prefix, "HalfMaximum", IsExtractionType(kHalfMaximum));
1183 if (b)
1184 SetTimeType(kHalfMaximum);
1185 rc = kTRUE;
1186 }
1187
1188 return MExtractTimeAndCharge::ReadEnv(env, prefix, print) ? kTRUE : rc;
1189
1190}
1191
1192
Note: See TracBrowser for help on using the repository browser.