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

Last change on this file since 4611 was 4609, checked in by tbretz, 21 years ago
*** empty log message ***
File size: 19.4 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// Variables:
117// fgHiGainFirst; First FADC slice Hi-Gain (currently set to: 3)
118// fgHiGainLast: Last FADC slice Hi-Gain (currently set to: 14)
119// fgLoGainFirst: First FADC slice Lo-Gain (currently set to: 3)
120// fgLoGainLast: Last FADC slice Lo-Gain (currently set to: 14)
121// fgHiGainWindowSize: The extraction window Hi-Gain
122// fgLoGainWindowSize: The extraction window Lo-Gain
123// fgMaxHiGainVar: The maximum difference between the highest and lowest slice
124// in the high gain window allowed in order to use low gain
125//
126// Input Containers:
127// MRawEvtData
128// MRawRunHeader
129// MGeomCam
130//
131// Output Containers:
132// MPedestalCam
133//
134// See also: MPedestalCam, MPedestalPix, MHPedestalCam, MExtractor
135//
136/////////////////////////////////////////////////////////////////////////////
137#include "MPedCalcFromLoGain.h"
138#include "MExtractor.h"
139
140#include "MParList.h"
141
142#include "MLog.h"
143#include "MLogManip.h"
144
145#include "MRawRunHeader.h"
146#include "MRawEvtPixelIter.h"
147#include "MRawEvtData.h"
148
149#include "MPedestalPix.h"
150#include "MPedestalCam.h"
151
152#include "MGeomPix.h"
153#include "MGeomCam.h"
154
155ClassImp(MPedCalcFromLoGain);
156
157using namespace std;
158
159const Byte_t MPedCalcFromLoGain::fgHiGainFirst = 0;
160const Byte_t MPedCalcFromLoGain::fgHiGainLast = 11;
161const Byte_t MPedCalcFromLoGain::fgLoGainFirst = 1;
162const Byte_t MPedCalcFromLoGain::fgLoGainLast = 14;
163const Byte_t MPedCalcFromLoGain::fgHiGainWindowSize = 12;
164const Byte_t MPedCalcFromLoGain::fgLoGainWindowSize = 14;
165const Byte_t MPedCalcFromLoGain::fgMaxHiGainVar = 40;
166
167// --------------------------------------------------------------------------
168//
169// Default constructor:
170//
171// Sets:
172// - all pointers to NULL
173// - fWindowSizeHiGain to fgHiGainWindowSize
174// - fWindowSizeLoGain to fgLoGainWindowSize
175//
176// Calls:
177// - AddToBranchList("fHiGainPixId");
178// - AddToBranchList("fHiGainFadcSamples");
179// - SetRange(fgHiGainFirst, fgHiGainLast, fgLoGainFirst, fgLoGainLast)
180// - Clear()
181//
182MPedCalcFromLoGain::MPedCalcFromLoGain(const char *name, const char *title)
183 : fWindowSizeHiGain(fgHiGainWindowSize),
184 fWindowSizeLoGain(fgLoGainWindowSize),
185 fGeom(NULL), fPedContainerName("MPedestalCam")
186{
187 fName = name ? name : "MPedCalcFromLoGain";
188 fTitle = title ? title : "Task to calculate pedestals from pedestal runs raw data";
189
190 AddToBranchList("fHiGainPixId");
191 AddToBranchList("fLoGainPixId");
192 AddToBranchList("fHiGainFadcSamples");
193 AddToBranchList("fLoGainFadcSamples");
194
195 SetRange();
196 SetMaxHiGainVar();
197 SetPedestalUpdate(kTRUE);
198
199 Clear();
200}
201
202// --------------------------------------------------------------------------
203//
204// Sets:
205// - fNumSamplesTot to 0
206// - fRawEvt to NULL
207// - fRunHeader to NULL
208// - fPedestals to NULL
209//
210void MPedCalcFromLoGain::Clear(const Option_t *o)
211{
212 fRawEvt = NULL;
213 fRunHeader = NULL;
214 fPedestals = NULL;
215
216 // If the size is yet set, set the size
217 if (fSumx.GetSize()>0)
218 {
219 // Reset contents of arrays.
220 fSumx.Reset();
221 fSumx2.Reset();
222 fSumAB0.Reset();
223 fSumAB1.Reset();
224 fNumEventsUsed.Reset();
225 fTotalCounter.Reset();
226 }
227}
228
229// --------------------------------------------------------------------------
230//
231// SetRange:
232//
233// Calls:
234// - MExtractor::SetRange(hifirst,hilast,lofirst,lolast);
235// - SetWindowSize(fWindowSizeHiGain,fWindowSizeLoGain);
236//
237void MPedCalcFromLoGain::SetRange(Byte_t hifirst, Byte_t hilast, Byte_t lofirst, Byte_t lolast)
238{
239 MExtractor::SetRange(hifirst, hilast, lofirst, lolast);
240
241 //
242 // Redo the checks if the window is still inside the ranges
243 //
244 SetWindowSize(fWindowSizeHiGain,fWindowSizeLoGain);
245}
246
247// --------------------------------------------------------------------------
248//
249void MPedCalcFromLoGain::SetMaxHiGainVar(Byte_t maxvar)
250{
251 fMaxHiGainVar = maxvar;
252}
253
254// --------------------------------------------------------------------------
255//
256// Checks:
257// - if a window is odd, subtract one
258// - if a window is bigger than the one defined by the ranges, set it to the available range
259// - if a window is smaller than 2, set it to 2
260//
261// Sets:
262// - fNumHiGainSamples to: (Float_t)fWindowSizeHiGain
263// - fNumLoGainSamples to: (Float_t)fWindowSizeLoGain
264// - fSqrtHiGainSamples to: TMath::Sqrt(fNumHiGainSamples)
265// - fSqrtLoGainSamples to: TMath::Sqrt(fNumLoGainSamples)
266//
267void MPedCalcFromLoGain::SetWindowSize(Byte_t windowh, Byte_t windowl)
268{
269 fWindowSizeHiGain = windowh & ~1;
270 fWindowSizeLoGain = windowl & ~1;
271
272 if (fWindowSizeHiGain != windowh)
273 {
274 *fLog << warn;
275 *fLog << GetDescriptor() << ": HiGain window has to be even, set to: ";
276 *fLog << int(fWindowSizeHiGain) << " samples " << endl;
277 }
278
279 if (fWindowSizeLoGain != windowl)
280 {
281 *fLog << warn;
282 *fLog << GetDescriptor() << ": Lo Gain window has to be even, set to: ";
283 *fLog << int(fWindowSizeLoGain) << " samples " << endl;
284 }
285
286 const Byte_t availhirange = (fHiGainLast-fHiGainFirst+1) & ~1;
287 const Byte_t availlorange = (fLoGainLast-fLoGainFirst+1) & ~1;
288
289 if (fWindowSizeHiGain > availhirange)
290 {
291 *fLog << warn;
292 *fLog << GetDescriptor() << ": HiGain window " << (int)fWindowSizeHiGain;
293 *fLog << " out of range [" << (int)fHiGainFirst;
294 *fLog << "," << (int)fHiGainLast << "]" << endl;
295 *fLog << "Will set window size to " << (int)availhirange << endl;
296 fWindowSizeHiGain = availhirange;
297 }
298
299 if (fWindowSizeLoGain > availlorange)
300 {
301 *fLog << warn;
302 *fLog << GetDescriptor() << ": LoGain window " << (int)fWindowSizeLoGain;
303 *fLog << " out of range [" << (int)fLoGainFirst;
304 *fLog << "," << (int)fLoGainLast << "]" << endl;
305 *fLog << "Will set window size to " << (int)availlorange << endl;
306 fWindowSizeLoGain = availlorange;
307 }
308 /*
309 fNumHiGainSamples = (Float_t)fWindowSizeHiGain;
310 fNumLoGainSamples = (Float_t)fWindowSizeLoGain;
311
312 fSqrtHiGainSamples = TMath::Sqrt(fNumHiGainSamples);
313 fSqrtLoGainSamples = TMath::Sqrt(fNumLoGainSamples);
314 */
315}
316
317// --------------------------------------------------------------------------
318//
319// Look for the following input containers:
320//
321// - MRawEvtData
322// - MRawRunHeader
323// - MGeomCam
324//
325// The following output containers are also searched and created if
326// they were not found:
327//
328// - MPedestalCam
329//
330Int_t MPedCalcFromLoGain::PreProcess(MParList *pList)
331{
332 Clear();
333
334 fRawEvt = (MRawEvtData*)pList->FindObject("MRawEvtData");
335 if (!fRawEvt)
336 {
337 *fLog << err << "MRawEvtData not found... aborting." << endl;
338 return kFALSE;
339 }
340
341 fRunHeader = (MRawRunHeader*)pList->FindObject(AddSerialNumber("MRawRunHeader"));
342 if (!fRunHeader)
343 {
344 *fLog << err << AddSerialNumber("MRawRunHeader") << " not found... aborting." << endl;
345 return kFALSE;
346 }
347
348 fGeom = (MGeomCam*)pList->FindObject("MGeomCam");
349 if (!fGeom)
350 {
351 *fLog << err << "MGeomCam not found... aborting." << endl;
352 return kFALSE;
353 }
354
355 fPedestals = (MPedestalCam*)pList->FindCreateObj("MPedestalCam", AddSerialNumber(fPedContainerName));
356 if (!fPedestals)
357 return kFALSE;
358
359 return kTRUE;
360}
361
362// --------------------------------------------------------------------------
363//
364// The ReInit searches for:
365// - MRawRunHeader::GetNumSamplesHiGain()
366// - MRawRunHeader::GetNumSamplesLoGain()
367//
368// In case that the variables fHiGainLast and fLoGainLast are smaller than
369// the even part of the number of samples obtained from the run header, a
370// warning is given an the range is set back accordingly. A call to:
371// - SetRange(fHiGainFirst, fHiGainLast-diff, fLoGainFirst, fLoGainLast) or
372// - SetRange(fHiGainFirst, fHiGainLast, fLoGainFirst, fLoGainLast-diff)
373// is performed in that case. The variable diff means here the difference
374// between the requested range (fHiGainLast) and the available one. Note that
375// the functions SetRange() are mostly overloaded and perform more checks,
376// modifying the ranges again, if necessary.
377//
378Bool_t MPedCalcFromLoGain::ReInit(MParList *pList)
379{
380 if (fRunHeader->GetNumSamplesHiGain()<1)
381 {
382 *fLog << err << "ERROR - Number of available HiGainSamples<1... abort." << endl;
383 return kFALSE;
384 }
385 if (fRunHeader->GetNumSamplesLoGain()<1)
386 {
387 *fLog << err << "ERROR - Number of available LoGainSamples<1... abort." << endl;
388 return kFALSE;
389 }
390
391 fHiGainFirst = TMath::Max(fHiGainFirst, 0);
392 fHiGainLast = TMath::Min(fHiGainLast, fRunHeader->GetNumSamplesHiGain()-1);
393
394 fLoGainFirst = TMath::Max(fLoGainFirst, 0);
395 fLoGainLast = TMath::Min(fLoGainLast, fRunHeader->GetNumSamplesLoGain()-1);
396
397 fWindowSizeHiGain = TMath::Min(fWindowSizeHiGain, fHiGainLast-fHiGainFirst+1);
398 fWindowSizeLoGain = TMath::Min(fWindowSizeLoGain, fLoGainLast-fLoGainFirst+1);
399
400 SetRange(fHiGainFirst, fHiGainLast, fLoGainFirst, fLoGainLast);
401
402 *fLog << inf << endl;
403 *fLog << "Taking " << Form("%2d", (int)fWindowSizeHiGain) << " HiGain from " << (int)fHiGainFirst << endl;
404 *fLog << "Taking " << Form("%2d", (int)fWindowSizeLoGain) << " LoGain from " << (int)fLoGainFirst << endl;
405
406 if (fWindowSizeHiGain==0)
407 {
408 *fLog << err << "ERROR - HiGain windows size == 0... abort." << endl;
409 return kFALSE;
410 }
411 if (fWindowSizeLoGain==0)
412 {
413 *fLog << err << "ERROR - HiGain windows size == 0... abort." << endl;
414 return kFALSE;
415 }
416
417 // If the size is not yet set, set the size
418 if (fSumx.GetSize()==0)
419 {
420 const Int_t npixels = fPedestals->GetSize();
421
422 fSumx. Set(npixels);
423 fSumx2.Set(npixels);
424 fSumAB0.Set(npixels);
425 fSumAB1.Set(npixels);
426 fNumEventsUsed.Set(npixels);
427 fTotalCounter.Set(npixels);
428
429 // Reset contents of arrays.
430 fSumx.Reset();
431 fSumx2.Reset();
432 fSumAB0.Reset();
433 fSumAB1.Reset();
434 fNumEventsUsed.Reset();
435 fTotalCounter.Reset();
436 }
437
438 return kTRUE;
439}
440
441void MPedCalcFromLoGain::Calc(ULong_t n, UInt_t idx)
442{
443 const ULong_t nsamplestot = n*fWindowSizeLoGain;
444
445 const Float_t sum = fSumx.At(idx);
446 const Float_t sum2 = fSumx2.At(idx);
447 const Float_t ped = sum/nsamplestot;
448
449 // 1. Calculate the Variance of the sums:
450 Float_t var = (sum2-sum*sum/n)/(n-1.);
451
452 // 2. Scale the variance to the number of slices:
453 var /= (Float_t)(fWindowSizeLoGain);
454
455 // 3. Calculate the RMS from the Variance:
456 const Float_t rms = var<0 ? 0 : TMath::Sqrt(var);
457
458 // 4. Calculate the amplitude of the 150MHz "AB" noise
459 const Float_t abOffs = (fSumAB0[idx] - fSumAB1[idx]) / nsamplestot;
460
461 (*fPedestals)[idx].Set(ped, rms, abOffs, n);
462
463 fTotalCounter[idx]++;
464}
465
466// --------------------------------------------------------------------------
467//
468// Fill the MPedestalCam container with the signal mean and rms for the event.
469// Store the measured signal in arrays fSumx and fSumx2 so that we can
470// calculate the overall mean and rms in the PostProcess()
471//
472Int_t MPedCalcFromLoGain::Process()
473{
474 MRawEvtPixelIter pixel(fRawEvt);
475
476 while (pixel.Next())
477 {
478 const UInt_t idx = pixel.GetPixelId();
479
480 Byte_t *ptr = pixel.GetHiGainSamples() + fHiGainFirst;
481 Byte_t *end = ptr + fWindowSizeHiGain;
482
483 UInt_t sum = 0;
484 UInt_t sqr = 0;
485
486 UInt_t max = 0;
487 UInt_t min = 255;
488
489 // Find the maximum and minimum signal per slice in the high gain window
490 do {
491 if (*ptr > max)
492 max = *ptr;
493 if (*ptr < min)
494 min = *ptr;
495 } while (++ptr != end);
496
497 // If the maximum in the high gain window is smaller than
498 if (max-min>=fMaxHiGainVar || max>=255)
499 continue;
500
501 ptr = pixel.GetLoGainSamples() + fLoGainFirst;
502 end = ptr + fWindowSizeLoGain;
503
504 Byte_t *firstSlice = ptr;
505
506 do {
507 sum += *ptr;
508 sqr += *ptr * *ptr;
509 } while (++ptr != end);
510
511 const Float_t msum = (Float_t)sum;
512 const Float_t sqrsum = msum*msum;
513
514 fSumx[idx] += msum;
515 fSumx2[idx] += sqrsum;
516 fNumEventsUsed[idx]++;
517
518 // Calculate the amplitude of the 150MHz "AB" noise
519
520 Int_t abFlag = (fRunHeader->GetNumSamplesHiGain()
521 + fLoGainFirst
522 + pixel.HasABFlag()) & 0x1;
523 for (Int_t islice=0; islice<fWindowSizeLoGain; islice+=2)
524 {
525 Int_t sliceAB0 = islice + abFlag;
526 Int_t sliceAB1 = islice - abFlag + 1;
527 fSumAB0[idx] += firstSlice[sliceAB0];
528 fSumAB1[idx] += firstSlice[sliceAB1];
529 }
530
531 if (!fPedestalUpdate || fNumEventsUsed[idx]<fNumEventsDump)
532 continue;
533
534 Calc(fNumEventsDump, idx);
535
536 fNumEventsUsed[idx]=0;
537 fSumx[idx]=0;
538 fSumx2[idx]=0;
539 fSumAB0[idx]=0;
540 fSumAB1[idx]=0;
541 }
542
543 if (fPedestalUpdate)
544 {
545 fPedestals->ReCalc(*fGeom);
546 fPedestals->SetReadyToSave();
547 }
548
549 return kTRUE;
550}
551
552// --------------------------------------------------------------------------
553//
554// Compute signal mean and rms in the whole run and store it in MPedestalCam
555//
556Int_t MPedCalcFromLoGain::PostProcess()
557{
558 // Compute pedestals and rms from the whole run
559 if (fPedestalUpdate || GetNumExecutions()<1)
560 return kTRUE;
561
562 *fLog << flush << inf << "Calculating pedestals..." << flush;
563
564 Double_t sum = 0;
565
566 const Int_t npix = fGeom->GetNumPixels();
567 for (Int_t idx=0; idx<npix; idx++)
568 {
569 const ULong_t n = fNumEventsUsed[idx];
570 if (n>1)
571 Calc(n, idx);
572 sum += n;
573 }
574
575 *fLog << flush << inf << "Calculating means..." << flush;
576
577 fPedestals->SetTotalEntries((UInt_t)(sum/npix*(fWindowSizeLoGain+fWindowSizeHiGain)));
578 fPedestals->ReCalc(*fGeom);
579 fPedestals->SetReadyToSave();
580 return kTRUE;
581}
582
583Int_t MPedCalcFromLoGain::ReadEnv(const TEnv &env, TString prefix, Bool_t print)
584{
585 if (MExtractor::ReadEnv(env, prefix, print)==kERROR)
586 return kERROR;
587
588 Bool_t rc=kFALSE;
589
590 Byte_t hw = fWindowSizeHiGain;
591 Byte_t lw = fWindowSizeLoGain;
592 if (IsEnvDefined(env, prefix, "WindowSizeHiGain", print))
593 {
594 hw = GetEnvValue(env, prefix, "WindowSizeHiGain", hw);
595 rc = kTRUE;
596 }
597 if (IsEnvDefined(env, prefix, "WindowSizeLoGain", print))
598 {
599 lw = GetEnvValue(env, prefix, "WindowSizeLoGain", lw);
600 rc = kTRUE;
601 }
602
603 if (rc)
604 SetWindowSize(hw, lw);
605
606 if (IsEnvDefined(env, prefix, "NumEventsDump", print))
607 {
608 SetDumpEvents(GetEnvValue(env, prefix, "NumEventsDump", fNumEventsDump));
609 rc = kTRUE;
610 }
611
612 if (IsEnvDefined(env, prefix, "MaxHiGainVar", print))
613 {
614 SetMaxHiGainVar(GetEnvValue(env, prefix, "MaxHiGainVar", fMaxHiGainVar));
615 rc = kTRUE;
616 }
617
618 if (IsEnvDefined(env, prefix, "PedestalUpdate", print))
619 {
620 SetPedestalUpdate(GetEnvValue(env, prefix, "PedestalUpdate", fPedestalUpdate));
621 rc = kTRUE;
622 }
623
624 return rc;
625}
Note: See TracBrowser for help on using the repository browser.