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

Last change on this file since 5544 was 5544, checked in by gaug, 20 years ago
*** empty log message ***
File size: 31.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 : fAbMax(0.), fAbMaxPos(0.), fHalfMax(0.), fRandomIter(0)
180{
181
182 fName = name ? name : "MExtractTimeAndChargeSpline";
183 fTitle = title ? title : "Calculate photons arrival time using a fast spline";
184
185 SetResolution();
186 SetRiseTime();
187 SetFallTime();
188
189 SetRange(fgHiGainFirst, fgHiGainLast, fgLoGainFirst, fgLoGainLast);
190
191 SetTimeType();
192 SetChargeType();
193
194}
195
196
197//-------------------------------------------------------------------
198//
199// Set the ranges
200// In order to set the fNum...Samples variables correctly for the case,
201// the integral is computed, have to overwrite this function and make an
202// explicit call to SetChargeType().
203//
204void MExtractTimeAndChargeSpline::SetRange(Byte_t hifirst, Byte_t hilast, Byte_t lofirst, Byte_t lolast)
205{
206
207 MExtractor::SetRange(hifirst, hilast, lofirst, lolast);
208
209 if (IsExtractionType(kIntegral))
210 SetChargeType(kIntegral);
211 if (IsExtractionType(kAmplitude))
212 SetChargeType(kAmplitude);
213
214}
215
216
217//-------------------------------------------------------------------
218//
219// Set the Time Extraction type. Possible are:
220// - kMaximum: Search the maximum of the spline and return its position
221// - kHalfMaximum: Search the half maximum left from the maximum and return
222// its position
223//
224void MExtractTimeAndChargeSpline::SetTimeType( ExtractionType_t typ )
225{
226
227 CLRBIT(fFlags,kMaximum);
228 CLRBIT(fFlags,kHalfMaximum);
229 SETBIT(fFlags,typ);
230
231}
232
233//-------------------------------------------------------------------
234//
235// Set the Charge Extraction type. Possible are:
236// - kAmplitude: Search the value of the spline at the maximum
237// - kIntegral: Integral the spline from fHiGainFirst to fHiGainLast,
238// by counting the edge bins only half and setting the
239// second derivative to zero, there.
240//
241void MExtractTimeAndChargeSpline::SetChargeType( ExtractionType_t typ )
242{
243
244 CLRBIT(fFlags,kAmplitude);
245 CLRBIT(fFlags,kIntegral );
246
247 SETBIT(fFlags,typ);
248
249}
250
251// --------------------------------------------------------------------------
252//
253// InitArrays
254//
255// Gets called in the ReInit() and initialized the arrays
256//
257Bool_t MExtractTimeAndChargeSpline::InitArrays()
258{
259
260 Int_t range = fHiGainLast - fHiGainFirst + 1 + fHiLoLast;
261
262 fHiGainSignal .Set(range);
263 fHiGainFirstDeriv .Set(range);
264 fHiGainSecondDeriv.Set(range);
265
266 range = fLoGainLast - fLoGainFirst + 1;
267
268 fLoGainSignal .Set(range);
269 fLoGainFirstDeriv .Set(range);
270 fLoGainSecondDeriv.Set(range);
271
272 fHiGainSignal .Reset();
273 fHiGainFirstDeriv .Reset();
274 fHiGainSecondDeriv.Reset();
275
276 fLoGainSignal .Reset();
277 fLoGainFirstDeriv .Reset();
278 fLoGainSecondDeriv.Reset();
279
280 if (IsExtractionType(kAmplitude))
281 {
282 fNumHiGainSamples = 1.;
283 fNumLoGainSamples = fLoGainLast ? 1. : 0.;
284 fSqrtHiGainSamples = 1.;
285 fSqrtLoGainSamples = 1.;
286 fWindowSizeHiGain = 1;
287 fWindowSizeLoGain = 1;
288 }
289
290 if (IsExtractionType(kIntegral))
291 {
292 fNumHiGainSamples = fRiseTime + fFallTime;
293 fNumLoGainSamples = fLoGainLast ? fNumHiGainSamples + 1. : 0.;
294 fSqrtHiGainSamples = TMath::Sqrt(fNumHiGainSamples);
295 fSqrtLoGainSamples = TMath::Sqrt(fNumLoGainSamples);
296 fWindowSizeHiGain = (Int_t)(fRiseTime + fFallTime);
297 fWindowSizeLoGain = (Int_t)(fRiseTime + fFallTime+1);
298 }
299
300 return kTRUE;
301
302}
303
304// --------------------------------------------------------------------------
305//
306// Calculates the arrival time and charge for each pixel
307//
308void MExtractTimeAndChargeSpline::FindTimeAndChargeHiGain(Byte_t *first, Byte_t *logain, Float_t &sum, Float_t &dsum,
309 Float_t &time, Float_t &dtime,
310 Byte_t &sat, const MPedestalPix &ped, const Bool_t abflag)
311{
312
313 Int_t range = fHiGainLast - fHiGainFirst + 1;
314 const Byte_t *end = first + range;
315 Byte_t *p = first;
316 Int_t count = 0;
317
318 const Float_t pedes = ped.GetPedestal();
319 const Float_t ABoffs = ped.GetPedestalABoffset();
320
321 Float_t pedmean[2];
322 pedmean[0] = pedes + ABoffs;
323 pedmean[1] = pedes - ABoffs;
324
325 fAbMax = 0.;
326 fAbMaxPos = 0.;
327 Byte_t maxpos = 0;
328
329 //
330 // Check for saturation in all other slices
331 //
332 while (p<end)
333 {
334
335 const Int_t ids = fHiGainFirst + count ;
336 const Float_t signal = (Float_t)*p - pedmean[(ids+abflag) & 0x1];
337 fHiGainSignal[count] = signal;
338
339 if (signal > fAbMax + 0.1) /* the 0.1 is necessary for the ultra-high enery events saturating many slices */
340 {
341 fAbMax = signal;
342 maxpos = p-first;
343 }
344
345 if (*p++ >= fSaturationLimit)
346 sat++;
347
348 count++;
349 }
350
351 if (fHiLoLast != 0)
352 {
353
354 end = logain + fHiLoLast;
355
356 while (logain<end)
357 {
358
359 const Int_t ids = fHiGainFirst + range ;
360 const Float_t signal = (Float_t)*logain - pedmean[(ids+abflag) & 0x1];
361 fHiGainSignal[range] = signal;
362 range++;
363
364 if (signal > fAbMax)
365 {
366 fAbMax = signal;
367 maxpos = logain-first;
368 }
369
370 if (*logain >= fSaturationLimit)
371 sat++;
372
373 logain++;
374 }
375 }
376
377 Float_t pp;
378
379 fHiGainSecondDeriv[0] = 0.;
380 fHiGainFirstDeriv[0] = 0.;
381
382 for (Int_t i=1;i<range-1;i++)
383 {
384 pp = fHiGainSecondDeriv[i-1] + 4.;
385 fHiGainSecondDeriv[i] = -1.0/pp;
386 fHiGainFirstDeriv [i] = fHiGainSignal[i+1] - fHiGainSignal[i] - fHiGainSignal[i] + fHiGainSignal[i-1];
387 fHiGainFirstDeriv [i] = (6.0*fHiGainFirstDeriv[i]-fHiGainFirstDeriv[i-1])/pp;
388 }
389
390 fHiGainSecondDeriv[range-1] = 0.;
391
392 for (Int_t k=range-2;k>=0;k--)
393 fHiGainSecondDeriv[k] = fHiGainSecondDeriv[k]*fHiGainSecondDeriv[k+1] + fHiGainFirstDeriv[k];
394 for (Int_t k=range-2;k>=0;k--)
395 fHiGainSecondDeriv[k] /= 6.;
396
397 if (IsNoiseCalculation() && IsExtractionType(kAmplitude))
398 {
399 if (fRandomIter == (TMath::Floor(1./fResolution)))
400 fRandomIter = 0;
401
402 const Float_t b = fRandomIter * fResolution;
403 const Float_t a = 1. - b;
404
405 fRandomIter++;
406
407 sum = a*fHiGainSignal[1]
408 + b*fHiGainSignal[2]
409 + (a*a*a-a)*fHiGainSecondDeriv[1]
410 + (b*b*b-b)*fHiGainSecondDeriv[2];
411 return;
412 }
413
414 if (IsNoiseCalculation() && IsExtractionType(kIntegral))
415 {
416 //
417 // Take the spline value at the middle of the third slice (to avoid egde effects)
418 //
419 Int_t first = 2;
420 Int_t last = first + (Int_t)(fRiseTime+fFallTime);
421 CalcIntegralHiGain(sum,first,last);
422 return;
423 }
424
425 //
426 // Allow no saturated slice
427 // and
428 // Don't start if the maxpos is too close to the left limit.
429 //
430 if ((sat || maxpos < 2))
431 {
432 time = IsExtractionType(kMaximum)
433 ? (Float_t)(fHiGainFirst + maxpos)
434 : (Float_t)(fHiGainFirst + maxpos - 1);
435 sum = IsExtractionType(kAmplitude)
436 ? fAbMax : 0.;
437 return;
438 }
439
440 //
441 // Now find the maximum
442 //
443 Float_t step = 0.2; // start with step size of 1ns and loop again with the smaller one
444 Float_t lower = (Float_t)maxpos-1.;
445 Float_t upper = (Float_t)maxpos;
446 fAbMaxPos = upper;
447 Float_t x = lower;
448 Float_t y = 0.;
449 Float_t a = 1.;
450 Float_t b = 0.;
451 Int_t klo = maxpos-1;
452 Int_t khi = maxpos;
453
454 //
455 // Search for the maximum, starting in interval maxpos-1 in steps of 0.2 till maxpos-0.2.
456 // If no maximum is found, go to interval maxpos+1.
457 //
458 while ( x < upper - 0.3 )
459 {
460
461 x += step;
462 a -= step;
463 b += step;
464
465 y = a*fHiGainSignal[klo]
466 + b*fHiGainSignal[khi]
467 + (a*a*a-a)*fHiGainSecondDeriv[klo]
468 + (b*b*b-b)*fHiGainSecondDeriv[khi];
469
470 if (y > fAbMax)
471 {
472 fAbMax = y;
473 fAbMaxPos = x;
474 }
475
476 // *fLog << err << x << " " << y << " " << fAbMaxPos<< endl;
477 }
478
479 //
480 // Search for the absolute maximum from maxpos to maxpos+1 in steps of 0.2
481 //
482 if (fAbMaxPos > upper-0.1)
483 {
484
485 upper = (Float_t)maxpos+1.;
486 lower = (Float_t)maxpos;
487 x = lower;
488 a = 1.;
489 b = 0.;
490 khi = maxpos+1;
491 klo = maxpos;
492
493 while (x<upper-0.3)
494 {
495
496 x += step;
497 a -= step;
498 b += step;
499
500 y = a*fHiGainSignal[klo]
501 + b*fHiGainSignal[khi]
502 + (a*a*a-a)*fHiGainSecondDeriv[klo]
503 + (b*b*b-b)*fHiGainSecondDeriv[khi];
504
505 if (y > fAbMax)
506 {
507 fAbMax = y;
508 fAbMaxPos = x;
509 }
510 // *fLog << inf << x << " " << y << " " << fAbMaxPos << endl;
511
512 }
513 }
514
515
516 //
517 // Now, the time, abmax and khicont and klocont are set correctly within the previous precision.
518 // Try a better precision.
519 //
520 const Float_t up = fAbMaxPos+step - 1.5*fResolution;
521 const Float_t lo = fAbMaxPos-step + 1.5*fResolution;
522 const Float_t maxpossave = fAbMaxPos;
523
524 x = fAbMaxPos;
525 a = upper - x;
526 b = x - lower;
527
528 step = fResolution; // step size of 83 ps
529
530 while (x<up)
531 {
532
533 x += step;
534 a -= step;
535 b += step;
536
537 y = a*fHiGainSignal[klo]
538 + b*fHiGainSignal[khi]
539 + (a*a*a-a)*fHiGainSecondDeriv[klo]
540 + (b*b*b-b)*fHiGainSecondDeriv[khi];
541
542 if (y > fAbMax)
543 {
544 fAbMax = y;
545 fAbMaxPos = x;
546 }
547 // *fLog << inf << x << " " << y << " " << fAbMaxPos << endl;
548 }
549
550 //
551 // Second, try from time down to time-0.2 in steps of fResolution.
552 //
553 x = maxpossave;
554
555 //
556 // Test the possibility that the absolute maximum has not been found between
557 // maxpos and maxpos+0.025, then we have to look between maxpos-0.025 and maxpos
558 // which requires new setting of klocont and khicont
559 //
560 if (x < klo + fResolution/2.)
561 {
562 klo--;
563 khi--;
564 upper--;
565 lower--;
566 }
567
568 a = upper - x;
569 b = x - lower;
570
571 while (x>lo)
572 {
573
574 x -= step;
575 a += step;
576 b -= step;
577
578 y = a*fHiGainSignal[klo]
579 + b*fHiGainSignal[khi]
580 + (a*a*a-a)*fHiGainSecondDeriv[klo]
581 + (b*b*b-b)*fHiGainSecondDeriv[khi];
582
583 if (y > fAbMax)
584 {
585 fAbMax = y;
586 fAbMaxPos = x;
587 }
588 // *fLog << warn << x << " " << y << " " << fAbMaxPos << endl;
589 }
590
591 if (IsExtractionType(kMaximum))
592 {
593 time = (Float_t)fHiGainFirst + fAbMaxPos;
594 dtime = fResolution;
595 }
596 else
597 {
598 fHalfMax = fAbMax/2.;
599
600 //
601 // Now, loop from the maximum bin leftward down in order to find the position of the half maximum.
602 // First, find the right FADC slice:
603 //
604 klo = maxpos - 1;
605 while (klo >= 0)
606 {
607 if (fHiGainSignal[klo] < fHalfMax)
608 break;
609 klo--;
610 }
611
612 //
613 // Loop from the beginning of the slice upwards to reach the fHalfMax:
614 // With means of bisection:
615 //
616 x = (Float_t)klo;
617 a = 1.;
618 b = 0.;
619
620 step = 0.5;
621 Bool_t back = kFALSE;
622
623 Int_t maxcnt = 50;
624 Int_t cnt = 0;
625
626 while (TMath::Abs(y-fHalfMax) > fResolution)
627 {
628
629 if (back)
630 {
631 x -= step;
632 a += step;
633 b -= step;
634 }
635 else
636 {
637 x += step;
638 a -= step;
639 b += step;
640 }
641
642 y = a*fHiGainSignal[klo]
643 + b*fHiGainSignal[khi]
644 + (a*a*a-a)*fHiGainSecondDeriv[klo]
645 + (b*b*b-b)*fHiGainSecondDeriv[khi];
646
647 if (y > fHalfMax)
648 back = kTRUE;
649 else
650 back = kFALSE;
651
652 if (++cnt > maxcnt)
653 {
654 // *fLog << inf << x << " " << y << " " << fHalfMax << endl;
655 break;
656 }
657
658 step /= 2.;
659 }
660
661 time = (Float_t)fHiGainFirst + x;
662 dtime = fResolution;
663 }
664
665 if (IsExtractionType(kAmplitude))
666 {
667 sum = fAbMax;
668 return;
669 }
670
671 if (IsExtractionType(kIntegral))
672 {
673 //
674 // Now integrate the whole thing!
675 //
676 Int_t startslice = (Int_t)(fAbMaxPos - fRiseTime);
677 Int_t lastslice = (Int_t)(fAbMaxPos + fFallTime);
678
679 if (lastslice > range)
680 {
681 lastslice = range;
682 startslice += (lastslice - range);
683 }
684
685 CalcIntegralHiGain(sum, startslice, lastslice);
686 }
687
688}
689
690
691// --------------------------------------------------------------------------
692//
693// Calculates the arrival time and charge for each pixel
694//
695void MExtractTimeAndChargeSpline::FindTimeAndChargeLoGain(Byte_t *first, Float_t &sum, Float_t &dsum,
696 Float_t &time, Float_t &dtime,
697 Byte_t &sat, const MPedestalPix &ped, const Bool_t abflag)
698{
699
700 Int_t range = fLoGainLast - fLoGainFirst + 1;
701 const Byte_t *end = first + range;
702 Byte_t *p = first;
703 Int_t count = 0;
704
705 Float_t pedes = ped.GetPedestal();
706 const Float_t ABoffs = ped.GetPedestalABoffset();
707
708 Float_t pedmean[2];
709 pedmean[0] = pedes + ABoffs;
710 pedmean[1] = pedes - ABoffs;
711
712 fAbMax = 0.;
713 fAbMaxPos = 0.;
714 Byte_t maxpos = 0;
715
716 //
717 // Check for saturation in all other slices
718 //
719 while (p<end)
720 {
721
722 const Int_t ids = fLoGainFirst + count ;
723 const Float_t signal = (Float_t)*p - pedmean[(ids+abflag) & 0x1];
724 fLoGainSignal[count] = signal;
725
726 if (signal > fAbMax)
727 {
728 fAbMax = signal;
729 maxpos = p-first;
730 }
731
732 if (*p >= fSaturationLimit)
733 sat++;
734
735 p++;
736 count++;
737 }
738
739 Float_t pp;
740
741 fLoGainSecondDeriv[0] = 0.;
742 fLoGainFirstDeriv[0] = 0.;
743
744 for (Int_t i=1;i<range-1;i++)
745 {
746 pp = fLoGainSecondDeriv[i-1] + 4.;
747 fLoGainSecondDeriv[i] = -1.0/pp;
748 fLoGainFirstDeriv [i] = fLoGainSignal[i+1] - fLoGainSignal[i] - fLoGainSignal[i] + fLoGainSignal[i-1];
749 fLoGainFirstDeriv [i] = (6.0*fLoGainFirstDeriv[i]-fLoGainFirstDeriv[i-1])/pp;
750 }
751
752 fLoGainSecondDeriv[range-1] = 0.;
753 for (Int_t k=range-2;k>=0;k--)
754 fLoGainSecondDeriv[k] = fLoGainSecondDeriv[k]*fLoGainSecondDeriv[k+1] + fLoGainFirstDeriv[k];
755 for (Int_t k=range-2;k>=0;k--)
756 fLoGainSecondDeriv[k] /= 6.;
757
758 if (IsNoiseCalculation() && IsExtractionType(kAmplitude))
759 {
760 //
761 // Take the spline value at the middle of the third slice (to avoid egde effects)
762 //
763 sum = 0.5*fLoGainSignal[2]
764 + 0.5*fLoGainSignal[3]
765 + (-0.375)*fLoGainSecondDeriv[2]
766 + (-0.375)*fLoGainSecondDeriv[3];
767 return;
768 }
769
770 if (IsNoiseCalculation() && IsExtractionType(kIntegral))
771 {
772 //
773 // Take the spline value at the middle of the third slice (to avoid egde effects)
774 //
775 Int_t first = 2;
776 Int_t last = first + (Int_t)(fRiseTime+fFallTime);
777 CalcIntegralLoGain(sum,first,last);
778 return;
779 }
780
781 //
782 // Allow no saturated slice
783 // and
784 // Don't start if the maxpos is too close to the left limit.
785 //
786 if (sat || maxpos < 1)
787 {
788 time = IsExtractionType(kMaximum)
789 ? (Float_t)(fLoGainFirst + maxpos)
790 : (Float_t)(fLoGainFirst + maxpos - 1);
791 return;
792 }
793
794 if (maxpos < 2 && IsExtractionType(kHalfMaximum))
795 {
796 time = (Float_t)(fLoGainFirst + maxpos - 1);
797 return;
798 }
799
800 //
801 // Now find the maximum
802 //
803 Float_t step = 0.2; // start with step size of 1ns and loop again with the smaller one
804 Float_t lower = (Float_t)maxpos-1.;
805 Float_t upper = (Float_t)maxpos;
806 fAbMaxPos = upper;
807 Float_t x = lower;
808 Float_t y = 0.;
809 Float_t a = 1.;
810 Float_t b = 0.;
811 Int_t klo = maxpos-1;
812 Int_t khi = maxpos;
813
814 //
815 // Search for the maximum, starting in interval maxpos-1 in steps of 0.2 till maxpos-0.2.
816 // If no maximum is found, go to interval maxpos+1.
817 //
818 while ( x < upper - 0.3 )
819 {
820
821 x += step;
822 a -= step;
823 b += step;
824
825 y = a*fLoGainSignal[klo]
826 + b*fLoGainSignal[khi]
827 + (a*a*a-a)*fLoGainSecondDeriv[klo]
828 + (b*b*b-b)*fLoGainSecondDeriv[khi];
829
830 if (y > fAbMax)
831 {
832 fAbMax = y;
833 fAbMaxPos = x;
834 }
835
836 // *fLog << err << x << " " << y << " " << fAbMaxPos<< endl;
837 }
838
839 //
840 // Test the possibility that the absolute maximum has not been found before the
841 // maxpos and search from maxpos to maxpos+1 in steps of 0.2
842 //
843 if (fAbMaxPos > upper-0.1)
844 {
845
846 upper = (Float_t)maxpos+1.;
847 lower = (Float_t)maxpos;
848 x = lower;
849 a = 1.;
850 b = 0.;
851 khi = maxpos+1;
852 klo = maxpos;
853
854 while (x<upper-0.3)
855 {
856
857 x += step;
858 a -= step;
859 b += step;
860
861 y = a*fLoGainSignal[klo]
862 + b*fLoGainSignal[khi]
863 + (a*a*a-a)*fLoGainSecondDeriv[klo]
864 + (b*b*b-b)*fLoGainSecondDeriv[khi];
865
866 if (y > fAbMax)
867 {
868 fAbMax = y;
869 fAbMaxPos = x;
870 }
871 // *fLog << inf << x << " " << y << " " << fAbMaxPos << endl;
872
873 }
874 }
875
876
877 //
878 // Now, the time, abmax and khicont and klocont are set correctly within the previous precision.
879 // Try a better precision.
880 //
881 const Float_t up = fAbMaxPos+step - 1.5*fResolution;
882 const Float_t lo = fAbMaxPos-step + 1.5*fResolution;
883 const Float_t maxpossave = fAbMaxPos;
884
885 x = fAbMaxPos;
886 a = upper - x;
887 b = x - lower;
888
889 step = fResolution; // step size of fResolution (33 ps )
890
891 while (x<up)
892 {
893
894 x += step;
895 a -= step;
896 b += step;
897
898 y = a*fLoGainSignal[klo]
899 + b*fLoGainSignal[khi]
900 + (a*a*a-a)*fLoGainSecondDeriv[klo]
901 + (b*b*b-b)*fLoGainSecondDeriv[khi];
902
903 if (y > fAbMax)
904 {
905 fAbMax = y;
906 fAbMaxPos = x;
907 }
908 // *fLog << inf << x << " " << y << " " << fAbMaxPos << endl;
909 }
910
911 //
912 // Second, try from time down to time-0.2 in steps of 0.025.
913 //
914 x = maxpossave;
915
916 //
917 // Test the possibility that the absolute maximum has not been found between
918 // maxpos and maxpos+0.02, then we have to look between maxpos-0.02 and maxpos
919 // which requires new setting of klocont and khicont
920 //
921 if (x < klo + fResolution/2.)
922 {
923 klo--;
924 khi--;
925 upper--;
926 lower--;
927 }
928
929 a = upper - x;
930 b = x - lower;
931
932 while (x>lo)
933 {
934
935 x -= step;
936 a += step;
937 b -= step;
938
939 y = a*fLoGainSignal[klo]
940 + b*fLoGainSignal[khi]
941 + (a*a*a-a)*fLoGainSecondDeriv[klo]
942 + (b*b*b-b)*fLoGainSecondDeriv[khi];
943
944 if (y > fAbMax)
945 {
946 fAbMax = y;
947 fAbMaxPos = x;
948 }
949 // *fLog << warn << x << " " << y << " " << fAbMaxPos << endl;
950 }
951
952 if (IsExtractionType(kMaximum))
953 {
954 time = (Float_t)fLoGainFirst + fAbMaxPos;
955 dtime = fResolution;
956 }
957 else
958 {
959 fHalfMax = fAbMax/2.;
960
961 //
962 // Now, loop from the maximum bin leftward down in order to find the position of the half maximum.
963 // First, find the right FADC slice:
964 //
965 klo = maxpos - 1;
966 while (klo >= 0)
967 {
968 if (fLoGainSignal[klo] < fHalfMax)
969 break;
970 klo--;
971 }
972
973 //
974 // Loop from the beginning of the slice upwards to reach the fHalfMax:
975 // With means of bisection:
976 //
977 x = (Float_t)klo;
978 a = 1.;
979 b = 0.;
980
981 step = 0.5;
982 Bool_t back = kFALSE;
983
984 Int_t maxcnt = 50;
985 Int_t cnt = 0;
986
987 while (TMath::Abs(y-fHalfMax) > fResolution)
988 {
989
990 if (back)
991 {
992 x -= step;
993 a += step;
994 b -= step;
995 }
996 else
997 {
998 x += step;
999 a -= step;
1000 b += step;
1001 }
1002
1003 y = a*fLoGainSignal[klo]
1004 + b*fLoGainSignal[khi]
1005 + (a*a*a-a)*fLoGainSecondDeriv[klo]
1006 + (b*b*b-b)*fLoGainSecondDeriv[khi];
1007
1008 if (y > fHalfMax)
1009 back = kTRUE;
1010 else
1011 back = kFALSE;
1012
1013 if (++cnt > maxcnt)
1014 {
1015 // *fLog << inf << x << " " << y << " " << fHalfMax << endl;
1016 break;
1017 }
1018
1019 step /= 2.;
1020 }
1021
1022 time = (Float_t)fLoGainFirst + x;
1023 dtime = fResolution;
1024 }
1025
1026 if (IsExtractionType(kAmplitude))
1027 {
1028 sum = fAbMax;
1029 return;
1030 }
1031
1032 if (IsExtractionType(kIntegral))
1033 {
1034 //
1035 // Now integrate the whole thing!
1036 //
1037 Int_t startslice = (Int_t)(fAbMaxPos - fRiseTime);
1038 Int_t lastslice = (Int_t)(fAbMaxPos + fFallTime + 1);
1039
1040 if (lastslice > range)
1041 {
1042 lastslice = range;
1043 startslice += (lastslice - range);
1044 }
1045 CalcIntegralLoGain(sum, startslice, lastslice);
1046 }
1047}
1048
1049void MExtractTimeAndChargeSpline::CalcIntegralHiGain(Float_t &sum, Int_t startslice, Int_t lastslice)
1050{
1051
1052 if (startslice < 0)
1053 {
1054 lastslice -= startslice;
1055 startslice = 0;
1056 }
1057
1058 Int_t i = startslice;
1059 sum = 0.5*fHiGainSignal[i];
1060
1061 //
1062 // We sum 1.5 times the second deriv. coefficients because these had been
1063 // divided by 6. already. Usually, 0.25*fHiGainSecondDeriv should be added.
1064 //
1065 for (i=startslice+1; i<lastslice; i++)
1066 sum += fHiGainSignal[i] + 1.5*fHiGainSecondDeriv[i];
1067
1068 sum += 0.5*fHiGainSignal[lastslice];
1069
1070}
1071
1072void MExtractTimeAndChargeSpline::CalcIntegralLoGain(Float_t &sum, Int_t startslice, Int_t lastslice)
1073{
1074
1075 if (startslice < 0)
1076 {
1077 lastslice -= startslice;
1078 startslice = 0;
1079 }
1080
1081 Int_t i = startslice;
1082 sum = 0.5*fLoGainSignal[i];
1083
1084 //
1085 // We sum 1.5 times the second deriv. coefficients because these had been
1086 // divided by 6. already. Usually, 0.25*fLoGainSecondDeriv should be added.
1087 //
1088 for (i=startslice+1; i<lastslice; i++)
1089 sum += fLoGainSignal[i] + 1.5*fLoGainSecondDeriv[i];
1090
1091 sum += 0.5*fLoGainSignal[lastslice];
1092
1093}
1094
1095
1096
1097// --------------------------------------------------------------------------
1098//
1099// In addition to the resources of the base-class MExtractor:
1100// MJPedestal.MExtractor.WindowSizeHiGain: 6
1101// MJPedestal.MExtractor.WindowSizeLoGain: 6
1102//
1103Int_t MExtractTimeAndChargeSpline::ReadEnv(const TEnv &env, TString prefix, Bool_t print)
1104{
1105
1106 Bool_t rc = kFALSE;
1107
1108 if (IsEnvDefined(env, prefix, "Resolution", print))
1109 {
1110 SetResolution(GetEnvValue(env, prefix, "Resolution",fResolution));
1111 rc = kTRUE;
1112 }
1113 if (IsEnvDefined(env, prefix, "RiseTime", print))
1114 {
1115 SetRiseTime(GetEnvValue(env, prefix, "RiseTime", fRiseTime));
1116 rc = kTRUE;
1117 }
1118 if (IsEnvDefined(env, prefix, "FallTime", print))
1119 {
1120 SetFallTime(GetEnvValue(env, prefix, "FallTime", fFallTime));
1121 rc = kTRUE;
1122 }
1123
1124 Bool_t b = kFALSE;
1125
1126 if (IsEnvDefined(env, prefix, "Amplitude", print))
1127 {
1128 b = GetEnvValue(env, prefix, "Amplitude", IsExtractionType(kAmplitude));
1129 if (b)
1130 SetChargeType(kAmplitude);
1131 rc = kTRUE;
1132 }
1133 if (IsEnvDefined(env, prefix, "Integral", print))
1134 {
1135 b = GetEnvValue(env, prefix, "Integral", IsExtractionType(kIntegral));
1136 if (b)
1137 SetChargeType(kIntegral);
1138 rc = kTRUE;
1139 }
1140 if (IsEnvDefined(env, prefix, "Maximum", print))
1141 {
1142 b = GetEnvValue(env, prefix, "Maximum", IsExtractionType(kMaximum));
1143 if (b)
1144 SetTimeType(kMaximum);
1145 rc = kTRUE;
1146 }
1147 if (IsEnvDefined(env, prefix, "HalfMaximum", print))
1148 {
1149 b = GetEnvValue(env, prefix, "HalfMaximum", IsExtractionType(kHalfMaximum));
1150 if (b)
1151 SetTimeType(kHalfMaximum);
1152 rc = kTRUE;
1153 }
1154
1155 return MExtractTimeAndCharge::ReadEnv(env, prefix, print) ? kTRUE : rc;
1156
1157}
1158
1159
Note: See TracBrowser for help on using the repository browser.