source: trunk/MagicSoft/Mars/mpedestal/MPedCalcFromLoGain.cc@ 4565

Last change on this file since 4565 was 4565, checked in by fgoebel, 20 years ago
*** empty log message ***
File size: 19.0 KB
Line 
1/* ======================================================================== *\
2!
3! *
4! * This file is part of MARS, the MAGIC Analysis and Reconstruction
5! * Software. It is distributed to you in the hope that it can be a useful
6! * and timesaving tool in 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): Josep Flix 04/2001 <mailto:jflix@ifae.es>
19! Author(s): Thomas Bretz 05/2001 <mailto:tbretz@astro.uni-wuerzburg.de>
20! Author(s): Sebastian Commichau 12/2003
21! Author(s): Javier Rico 01/2004 <mailto:jrico@ifae.es>
22! Author(s): Markus Gaug 01/2004 <mailto:markus@ifae.es>
23! Author(s): Florian Goebel 06/2004 <mailto:fgoebel@mppmu.mpg.de>
24!
25! Copyright: MAGIC Software Development, 2000-2004
26!
27!
28\* ======================================================================== */
29
30/////////////////////////////////////////////////////////////////////////////
31//
32// MPedCalcLoGain
33//
34//
35// This task is devide form MPedCalcPedRun, described below. However, It
36// calculates the pedstals using the low gain slices, whenever the difference
37// between the highest and the lowest slice in the high gain
38// slices is below a given threshold (SetMaxHiGainVar). In this case the receiver
39// boards do not switch to lo gain and the so called lo gain slices are actually
40// high gain slices.
41//
42// MPedCalcLoGain also fills the ABoffset in MPedestalPix which allows to correct
43// the 150 MHz clock noise.
44//
45// This task takes a pedestal run file and fills MPedestalCam during
46// the Process() with the pedestal and rms computed in an event basis.
47// In the PostProcess() MPedestalCam is finally filled with the pedestal
48// mean and rms computed in a run basis.
49// More than one run (file) can be merged
50//
51// MPedCalcPedRun applies the following formula (1):
52//
53// Pedestal per slice = sum(x_i) / n / slices
54// PedRMS per slice = Sqrt( ( sum(x_i^2) - sum(x_i)^2/n ) / n-1 / slices )
55//
56// where x_i is the sum of "slices" FADC slices and sum means the sum over all
57// events. "n" is the number of events, "slices" is the number of summed FADC samples.
58//
59// Note that the slice-to-slice fluctuations are not Gaussian, but Poissonian, thus
60// asymmetric and they are correlated.
61//
62// It is important to know that the Pedestal per slice and PedRMS per slice depend
63// on the number of used FADC slices, as seen in the following plots:
64//
65//Begin_Html
66/*
67<img src="images/PedestalStudyInner.gif">
68*/
69//End_Html
70//
71//Begin_Html
72/*
73<img src="images/PedestalStudyOuter.gif">
74*/
75//
76// The plots show the inner and outer pixels, respectivly and have the following meaning:
77//
78// 1) The calculated mean pedestal per slice (from MPedCalcFromLoGain)
79// 2) The fitted mean pedestal per slice (from MHPedestalCam)
80// 3) The calculated pedestal RMS per slice (from MPedCalcFromLoGain)
81// 4) The fitted sigma of the pedestal distribution per slice
82// (from MHPedestalCam)
83// 5) The relative difference between calculation and histogram fit
84// for the mean
85// 6) The relative difference between calculation and histogram fit
86// for the sigma or RMS, respectively.
87//
88// The calculated means do not change significantly except for the case of 2 slices,
89// however the RMS changes from 5.7 per slice in the case of 2 extracted slices
90// to 8.3 per slice in the case of 26 extracted slices. This change is very significant.
91//
92// The plots have been produced on run 20123. You can reproduce them using
93// the macro pedestalstudies.C
94//
95// Usage of this class:
96// ====================
97//
98// Call: SetRange(higainfirst, higainlast, logainfirst, logainlast)
99// to modify the ranges in which the window is allowed to move.
100// Defaults are:
101//
102// fHiGainFirst = fgHiGainFirst = 0
103// fHiGainLast = fgHiGainLast = 29
104// fLoGainFirst = fgLoGainFirst = 0
105// fLoGainLast = fgLoGainLast = 14
106//
107// Call: SetWindowSize(windowhigain, windowlogain)
108// to modify the sliding window widths. Windows have to be an even number.
109// In case of odd numbers, the window will be modified.
110//
111// Defaults are:
112//
113// fHiGainWindowSize = fgHiGainWindowSize = 14
114// fLoGainWindowSize = fgLoGainWindowSize = 0
115//
116// Input Containers:
117// MRawEvtData
118// MRawRunHeader
119// MGeomCam
120//
121// Output Containers:
122// MPedestalCam
123//
124// See also: MPedestalCam, MPedestalPix, MHPedestalCam, MExtractor
125//
126/////////////////////////////////////////////////////////////////////////////
127#include "MPedCalcFromLoGain.h"
128#include "MExtractor.h"
129
130#include "MParList.h"
131
132#include "MLog.h"
133#include "MLogManip.h"
134
135#include "MRawRunHeader.h"
136#include "MRawEvtPixelIter.h"
137#include "MRawEvtData.h"
138
139#include "MPedestalPix.h"
140#include "MPedestalCam.h"
141
142#include "MGeomPix.h"
143#include "MGeomCam.h"
144
145ClassImp(MPedCalcFromLoGain);
146
147using namespace std;
148
149const Byte_t MPedCalcFromLoGain::fgHiGainFirst = 0;
150const Byte_t MPedCalcFromLoGain::fgHiGainLast = 11;
151const Byte_t MPedCalcFromLoGain::fgLoGainFirst = 1;
152const Byte_t MPedCalcFromLoGain::fgLoGainLast = 14;
153const Byte_t MPedCalcFromLoGain::fgHiGainWindowSize = 12;
154const Byte_t MPedCalcFromLoGain::fgLoGainWindowSize = 14;
155const Byte_t MPedCalcFromLoGain::fgMaxHiGainVar = 40;
156
157// --------------------------------------------------------------------------
158//
159// Default constructor:
160//
161// Sets:
162// - all pointers to NULL
163// - fWindowSizeHiGain to fgHiGainWindowSize
164// - fWindowSizeLoGain to fgLoGainWindowSize
165//
166// Calls:
167// - AddToBranchList("fHiGainPixId");
168// - AddToBranchList("fHiGainFadcSamples");
169// - SetRange(fgHiGainFirst, fgHiGainLast, fgLoGainFirst, fgLoGainLast)
170// - Clear()
171//
172MPedCalcFromLoGain::MPedCalcFromLoGain(const char *name, const char *title)
173 : fWindowSizeHiGain(fgHiGainWindowSize),
174 fWindowSizeLoGain(fgLoGainWindowSize),
175 fGeom(NULL), fPedContainerName("MPedestalCam")
176{
177 fName = name ? name : "MPedCalcFromLoGain";
178 fTitle = title ? title : "Task to calculate pedestals from pedestal runs raw data";
179
180 AddToBranchList("fHiGainPixId");
181 AddToBranchList("fHiGainFadcSamples");
182
183 SetRange(fgHiGainFirst, fgHiGainLast, fgLoGainFirst, fgLoGainLast);
184
185 SetMaxHiGainVar(fgMaxHiGainVar);
186 SetPedestalUpdate(kTRUE);
187 Clear();
188}
189
190// --------------------------------------------------------------------------
191//
192// Sets:
193// - fNumSamplesTot to 0
194// - fRawEvt to NULL
195// - fRunHeader to NULL
196// - fPedestals to NULL
197//
198void MPedCalcFromLoGain::Clear(const Option_t *o)
199{
200 fRawEvt = NULL;
201 fRunHeader = NULL;
202 fPedestals = NULL;
203}
204
205// --------------------------------------------------------------------------
206//
207// SetRange:
208//
209// Calls:
210// - MExtractor::SetRange(hifirst,hilast,lofirst,lolast);
211// - SetWindowSize(fWindowSizeHiGain,fWindowSizeLoGain);
212//
213void MPedCalcFromLoGain::SetRange(Byte_t hifirst, Byte_t hilast, Byte_t lofirst, Byte_t lolast)
214{
215 MExtractor::SetRange(hifirst,hilast,lofirst,lolast);
216
217 //
218 // Redo the checks if the window is still inside the ranges
219 //
220 SetWindowSize(fWindowSizeHiGain,fWindowSizeLoGain);
221}
222
223// --------------------------------------------------------------------------
224//
225void MPedCalcFromLoGain::SetMaxHiGainVar(Byte_t maxvar)
226{
227 fMaxHiGainVar = maxvar;
228}
229
230// --------------------------------------------------------------------------
231//
232// Checks:
233// - if a window is odd, subtract one
234// - if a window is bigger than the one defined by the ranges, set it to the available range
235// - if a window is smaller than 2, set it to 2
236//
237// Sets:
238// - fNumHiGainSamples to: (Float_t)fWindowSizeHiGain
239// - fNumLoGainSamples to: (Float_t)fWindowSizeLoGain
240// - fSqrtHiGainSamples to: TMath::Sqrt(fNumHiGainSamples)
241// - fSqrtLoGainSamples to: TMath::Sqrt(fNumLoGainSamples)
242//
243void MPedCalcFromLoGain::SetWindowSize(Byte_t windowh, Byte_t windowl)
244{
245 fWindowSizeHiGain = windowh & ~1;
246 fWindowSizeLoGain = windowl & ~1;
247
248 if (fWindowSizeHiGain != windowh)
249 *fLog << warn << GetDescriptor() << ": Hi Gain window size has to be even, set to: "
250 << int(fWindowSizeHiGain) << " samples " << endl;
251
252 if (fWindowSizeLoGain != windowl)
253 *fLog << warn << GetDescriptor() << ": Lo Gain window size has to be even, set to: "
254 << int(fWindowSizeLoGain) << " samples " << endl;
255
256 const Byte_t availhirange = (fHiGainLast-fHiGainFirst+1) & ~1;
257 const Byte_t availlorange = (fLoGainLast-fLoGainFirst+1) & ~1;
258
259 if (fWindowSizeHiGain > availhirange)
260 {
261 *fLog << warn << GetDescriptor()
262 << Form(": Hi Gain window size: %2i is bigger than available range: [%2i,%2i]",
263 (int)fWindowSizeHiGain, (int)fHiGainFirst, (int)fHiGainLast) << endl;
264 *fLog << warn << GetDescriptor()
265 << ": Will set window size to: " << (int)availhirange << endl;
266 fWindowSizeHiGain = availhirange;
267 }
268
269 if (fWindowSizeLoGain > availlorange)
270 {
271 *fLog << warn << GetDescriptor()
272 << Form(": Lo Gain window size: %2i is bigger than available range: [%2i,%2i]",
273 (int)fWindowSizeLoGain, (int)fLoGainFirst, (int)fLoGainLast) << endl;
274 *fLog << warn << GetDescriptor()
275 << ": Will set window size to: " << (int)availlorange << endl;
276 fWindowSizeLoGain = availlorange;
277 }
278
279 fNumHiGainSamples = (Float_t)fWindowSizeHiGain;
280 fNumLoGainSamples = (Float_t)fWindowSizeLoGain;
281
282 fSqrtHiGainSamples = TMath::Sqrt(fNumHiGainSamples);
283 fSqrtLoGainSamples = TMath::Sqrt(fNumLoGainSamples);
284}
285
286// --------------------------------------------------------------------------
287//
288// Look for the following input containers:
289//
290// - MRawEvtData
291// - MRawRunHeader
292// - MGeomCam
293//
294// The following output containers are also searched and created if
295// they were not found:
296//
297// - MPedestalCam
298//
299Int_t MPedCalcFromLoGain::PreProcess( MParList *pList )
300{
301 Clear();
302
303 fRawEvt = (MRawEvtData*)pList->FindObject("MRawEvtData");
304 if (!fRawEvt)
305 {
306 *fLog << err << "MRawEvtData not found... aborting." << endl;
307 return kFALSE;
308 }
309
310 fRunHeader = (MRawRunHeader*)pList->FindObject(AddSerialNumber("MRawRunHeader"));
311 if (!fRunHeader)
312 {
313 *fLog << err << AddSerialNumber("MRawRunHeader") << " not found... aborting." << endl;
314 return kFALSE;
315 }
316
317 fGeom = (MGeomCam*)pList->FindObject("MGeomCam");
318 if (!fGeom)
319 {
320 *fLog << err << "MGeomCam not found... aborting." << endl;
321 return kFALSE;
322 }
323
324 *fLog << " searching for the container " << fPedContainerName << endl;
325
326 fPedestals = (MPedestalCam*)pList->FindCreateObj( AddSerialNumber("MPedestalCam"),fPedContainerName);
327 if (!fPedestals)
328 {
329 *fLog << err << fPedContainerName << " can not be created" << endl;
330 return kFALSE;
331 }
332
333
334 return kTRUE;
335}
336
337// --------------------------------------------------------------------------
338//
339// The ReInit searches for:
340// - MRawRunHeader::GetNumSamplesHiGain()
341// - MRawRunHeader::GetNumSamplesLoGain()
342//
343// In case that the variables fHiGainLast and fLoGainLast are smaller than
344// the even part of the number of samples obtained from the run header, a
345// warning is given an the range is set back accordingly. A call to:
346// - SetRange(fHiGainFirst, fHiGainLast-diff, fLoGainFirst, fLoGainLast) or
347// - SetRange(fHiGainFirst, fHiGainLast, fLoGainFirst, fLoGainLast-diff)
348// is performed in that case. The variable diff means here the difference
349// between the requested range (fHiGainLast) and the available one. Note that
350// the functions SetRange() are mostly overloaded and perform more checks,
351// modifying the ranges again, if necessary.
352//
353Bool_t MPedCalcFromLoGain::ReInit(MParList *pList)
354{
355
356 Int_t lastdesired = (Int_t)fLoGainLast;
357 Int_t lastavailable = (Int_t)fRunHeader->GetNumSamplesLoGain()-1;
358
359 if (lastdesired > lastavailable)
360 {
361 const Int_t diff = lastdesired - lastavailable;
362 *fLog << endl;
363 *fLog << warn << GetDescriptor()
364 << Form(": Selected Lo Gain FADC Window [%2i,%2i] ranges out of the available limits: [0,%2i].",
365 (int)fLoGainFirst, lastdesired, lastavailable) << endl;
366 *fLog << GetDescriptor() << ": Will reduce the upper edge to " << (int)(fLoGainLast - diff) << endl;
367 SetRange(fHiGainFirst, fHiGainLast, fLoGainFirst, fLoGainLast-diff);
368 }
369
370 lastdesired = (Int_t)fHiGainLast;
371 lastavailable = (Int_t)fRunHeader->GetNumSamplesHiGain()-1;
372
373 if (lastdesired > lastavailable)
374 {
375 const Int_t diff = lastdesired - lastavailable;
376 *fLog << endl;
377 *fLog << warn << GetDescriptor()
378 << Form(": Selected Hi Gain Range [%2i,%2i] ranges out of the available limits: [0,%2i].",
379 (int)fHiGainFirst, lastdesired, lastavailable) << endl;
380 *fLog << warn << GetDescriptor()
381 << Form(": Will possibly use %2i samples from the Low-Gain for the High-Gain range", diff)
382 << endl;
383 fHiGainLast -= diff;
384 fHiLoLast = diff;
385 }
386
387 lastdesired = (Int_t)fHiGainFirst+fWindowSizeHiGain-1;
388 lastavailable = (Int_t)fRunHeader->GetNumSamplesHiGain()-1;
389
390 if (lastdesired > lastavailable)
391 {
392 const Int_t diff = lastdesired - lastavailable;
393 *fLog << endl;
394 *fLog << warn << GetDescriptor()
395 << Form(": Selected Hi Gain FADC Window size %2i ranges out of the available limits: [0,%2i].",
396 (int)fWindowSizeHiGain, lastavailable) << endl;
397 *fLog << warn << GetDescriptor()
398 << Form(": Will use %2i samples from the Low-Gain for the High-Gain extraction", diff)
399 << endl;
400
401 if ((Int_t)fWindowSizeHiGain > diff)
402 {
403 fWindowSizeHiGain -= diff;
404 fWindowSizeLoGain += diff;
405 }
406 else
407 {
408 fWindowSizeLoGain += fWindowSizeHiGain;
409 fLoGainFirst = diff-fWindowSizeHiGain;
410 fWindowSizeHiGain = 0;
411 }
412 }
413
414
415 Int_t npixels = fPedestals->GetSize();
416
417 if (fSumx.GetSize()==0)
418 {
419 fSumx. Set(npixels);
420 fSumx2.Set(npixels);
421 fSumAB0.Set(npixels);
422 fSumAB1.Set(npixels);
423 fNumEventsUsed.Set(npixels);
424 fTotalCounter.Set(npixels);
425
426 fSumx.Reset();
427 fSumx2.Reset();
428 fSumAB0.Reset();
429 fSumAB1.Reset();
430 fNumEventsUsed.Reset();
431 fTotalCounter.Reset();
432 }
433
434 if (fWindowSizeHiGain == 0 && fWindowSizeLoGain == 0)
435 {
436 *fLog << err << GetDescriptor()
437 << ": Number of extracted Slices is 0, abort ... " << endl;
438 return kFALSE;
439 }
440
441
442 *fLog << endl;
443 *fLog << inf << GetDescriptor() << ": Taking " << (int)fWindowSizeHiGain
444 << " HiGain FADC samples starting with slice: " << (int)fHiGainFirst << endl;
445 *fLog << inf << GetDescriptor() << ": Taking " << (int)fWindowSizeLoGain
446 << " LoGain FADC samples starting with slice: " << (int)fLoGainFirst << endl;
447
448 return kTRUE;
449}
450
451// --------------------------------------------------------------------------
452//
453// Fill the MPedestalCam container with the signal mean and rms for the event.
454// Store the measured signal in arrays fSumx and fSumx2 so that we can
455// calculate the overall mean and rms in the PostProcess()
456//
457Int_t MPedCalcFromLoGain::Process()
458{
459 MRawEvtPixelIter pixel(fRawEvt);
460
461 while (pixel.Next()) {
462
463 const UInt_t idx = pixel.GetPixelId();
464
465 Byte_t *ptr = pixel.GetHiGainSamples() + fHiGainFirst;
466 Byte_t *end = ptr + fWindowSizeHiGain;
467
468 UInt_t sum = 0;
469 UInt_t sqr = 0;
470
471 UInt_t max = 0;
472 UInt_t min = 255;
473
474 // Find the maximum and minimum signal per slice in the high gain window
475 do {
476 if (*ptr > max) {
477 max = *ptr;
478 }
479 if (*ptr < min) {
480 min = *ptr;
481 }
482 } while (++ptr != end);
483
484 // If the maximum in the high gain window is smaller than
485 if ((max-min < fMaxHiGainVar) && (max < 255)) {
486
487 Byte_t *firstSlice = pixel.GetLoGainSamples() + fLoGainFirst;
488 Byte_t *lastSlice = firstSlice + fWindowSizeLoGain;
489
490 Byte_t *slice = firstSlice;
491 do {
492 sum += *slice;
493 sqr += *slice * *slice;
494 } while (++slice != lastSlice);
495
496 const Float_t msum = (Float_t)sum;
497 const Float_t sqrsum = msum*msum;
498
499 fSumx[idx] += msum;
500 fSumx2[idx] += sqrsum;
501 fNumEventsUsed[idx]++;
502
503 // Calculate the amplitude of the 150MHz "AB" noise
504
505 Int_t abFlag = (fRunHeader->GetNumSamplesHiGain()
506 + fLoGainFirst
507 + pixel.HasABFlag()) & 0x1;
508 for (Int_t islice=0; islice<fWindowSizeLoGain; islice+=2) {
509 Int_t sliceAB0 = islice + abFlag;
510 Int_t sliceAB1 = islice + 1 - abFlag;
511 fSumAB0[idx] += firstSlice[sliceAB0];
512 fSumAB1[idx] += firstSlice[sliceAB1];
513 }
514
515 if (fPedestalUpdate && (fNumEventsUsed[idx] >= fNumEventsDump)) {
516
517 const ULong_t n = fNumEventsDump;
518
519 const ULong_t nsamplestot = n*fWindowSizeLoGain;
520
521 const Float_t sum = fSumx.At(idx);
522 const Float_t sum2 = fSumx2.At(idx);
523 const Float_t ped = sum/(nsamplestot);
524
525 // 1. Calculate the Variance of the sums:
526 Float_t var = (sum2-sum*sum/n)/(n-1.);
527
528 // 2. Scale the variance to the number of slices:
529 var /= (Float_t)(fWindowSizeLoGain);
530
531 // 3. Calculate the RMS from the Variance:
532 Float_t rms = var < 0 ? 0. : TMath::Sqrt(var);
533
534 // 4. Calculate the amplitude of the 150MHz "AB" noise
535 Float_t abOffs = (fSumAB0[idx] - fSumAB1[idx]) / nsamplestot;
536
537 (*fPedestals)[idx].Set(ped, rms, abOffs, n);
538
539 fTotalCounter[idx]++;
540 fNumEventsUsed[idx]=0;
541 fSumx[idx]=0;
542 fSumx2[idx]=0;
543 fSumAB0[idx]=0;
544 fSumAB1[idx]=0;
545 }
546 }
547 }
548
549 fPedestals->SetReadyToSave();
550
551 return kTRUE;
552}
553
554// --------------------------------------------------------------------------
555//
556// Compute signal mean and rms in the whole run and store it in MPedestalCam
557//
558Int_t MPedCalcFromLoGain::PostProcess()
559{
560
561 // Compute pedestals and rms from the whole run
562
563 if (!fPedestalUpdate) {
564
565 MRawEvtPixelIter pixel(fRawEvt);
566
567 while (pixel.Next()) {
568
569 const Int_t idx = pixel.GetPixelId();
570
571 const ULong_t n = fNumEventsUsed[idx];
572
573 if (n < 2)
574 continue;
575
576 const ULong_t nsamplestot = n*fWindowSizeLoGain;
577
578 const Float_t sum = fSumx.At(idx);
579 const Float_t sum2 = fSumx2.At(idx);
580 const Float_t ped = sum/(nsamplestot);
581
582 // 1. Calculate the Variance of the sums:
583 Float_t var = (sum2-sum*sum/n)/(n-1.);
584
585 // 2. Scale the variance to the number of slices:
586 var /= (Float_t)(fWindowSizeLoGain);
587
588 // 3. Calculate the RMS from the Variance:
589 Float_t rms = var < 0 ? 0. : TMath::Sqrt(var);
590
591 // 4. Calculate the amplitude of the 150MHz "AB" noise
592 Float_t abOffs = (fSumAB0[idx] - fSumAB1[idx]) / nsamplestot;
593
594 (*fPedestals)[idx].Set(ped, rms, abOffs, n);
595
596 fTotalCounter[idx]++;
597 }
598
599 fPedestals->SetReadyToSave();
600 }
601
602 fSumx.Reset();
603 fSumx2.Reset();
604 fSumAB0.Reset();
605 fSumAB1.Reset();
606 fNumEventsUsed.Reset();
607 fTotalCounter.Reset();
608
609 return kTRUE;
610}
Note: See TracBrowser for help on using the repository browser.