source: trunk/MagicSoft/Mars/mcalib/MCalibrationChargeCalc.cc@ 5032

Last change on this file since 5032 was 5032, checked in by gaug, 20 years ago
*** empty log message ***
File size: 73.7 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): Markus Gaug 02/2004 <mailto:markus@ifae.es>
19!
20! Copyright: MAGIC Software Development, 2000-2004
21!
22!
23\* ======================================================================== */
24
25//////////////////////////////////////////////////////////////////////////////
26//
27// MCalibrationChargeCalc
28//
29// Task to calculate the calibration conversion factors and quantum efficiencies
30// from the fit results to the summed FADC slice distributions delivered by
31// MCalibrationChargeCam, MCalibrationChargePix, MCalibrationChargeBlindPix and
32// MCalibrationChargePINDiode, calculated and filled by MHCalibrationChargeCam,
33// MHCalibrationChargePix, MHCalibrationChargeBlindPix and MHCalibrationChargePINDiode.
34//
35// PreProcess(): Initialize pointers to MCalibrationChargeCam, MCalibrationChargeBlindPix
36// MCalibrationChargePINDiode and MCalibrationQECam
37//
38// Initialize pulser light wavelength
39//
40// ReInit(): MCalibrationCam::InitSize(NumPixels) is called from MGeomApply (which allocates
41// memory in a TClonesArray of type MCalibrationChargePix)
42// Initializes pointer to MBadPixelsCam
43//
44// Process(): Nothing to be done, histograms getting filled by MHCalibrationChargeCam
45//
46// PostProcess(): - FinalizePedestals()
47// - FinalizeCharges()
48// - FinalizeFFactorMethod()
49// - FinalizeBadPixels()
50// - FinalizeBlindCam()
51// - FinalizePINDiode()
52// - FinalizeFFactorQECam()
53// - FinalizeBlindPixelQECam()
54// - FinalizePINDiodeQECam()
55//
56// Input Containers:
57// MCalibrationChargeCam
58// MCalibrationChargeBlindPix
59// MCalibrationChargePINDiode
60// MCalibrationQECam
61// MPedestalCam
62// MBadPixelsCam
63// MGeomCam
64// MTime
65//
66// Output Containers:
67// MCalibrationChargeCam
68// MCalibrationChargeBlindPix
69// MCalibrationChargePINDiode
70// MCalibrationQECam
71// MBadPixelsCam
72//
73//
74// Preliminary description of the calibration in photons (email from 12/02/04)
75//
76// Why calibrating in photons:
77// ===========================
78//
79// At the Barcelona meeting in 2002, we decided to calibrate the camera in
80// photons. This for the following reasons:
81//
82// * The physical quantity arriving at the camera are photons. This is
83// the direct physical information from the air shower. The photons
84// have a flux and a spectrum.
85//
86// * The photon fluxes depend mostly on the shower energy (with
87// corrections deriving from the observation conditions), while the photon
88// spectra depend mostly on the observation conditions: zenith angle,
89// quality of the air, also the impact parameter of the shower.
90//
91// * The photomultiplier, in turn, has different response properties
92// (quantum efficiencies) for photons of different colour. (Moreover,
93// different pixels have slightly different quantum efficiencies).
94// The resulting number of photo-electrons is then amplified (linearly)
95// with respect to the photo-electron flux.
96//
97// * In the ideal case, one would like to disentagle the effects
98// of the observation conditions from the primary particle energy (which
99// one likes to measure). To do so, one needs:
100//
101// 1) A reliable calibration relating the FADC counts to the photo-electron
102// flux -> This is accomplished with the F-Factor method.
103//
104// 2) A reliable calibration of the wavelength-dependent quantum efficiency
105// -> This is accomplished with the combination of the three methods,
106// together with QE-measurements performed by David in order to do
107// the interpolation.
108//
109// 3) A reliable calibration of the observation conditions. This means:
110// - Tracing the atmospheric conditions -> LIDAR
111// - Tracing the observation zenith angle -> Drive System
112//
113// 4) Some knowlegde about the impact parameter:
114// - This is the only part which cannot be accomplished well with a
115// single telescope. We would thus need to convolute the spectrum
116// over the distribution of impact parameters.
117//
118//
119// How an ideal calibration would look like:
120// =========================================
121//
122// We know from the combined PIN-Diode and Blind-Pixel Method the response of
123// each pixel to well-measured light fluxes in three representative
124// wavelengths (green, blue, UV). We also know the response to these light
125// fluxes in photo-electrons. Thus, we can derive:
126//
127// - conversion factors to photo-electrons
128// - conversion factors to photons in three wavelengths.
129//
130// Together with David's measurements and some MC-simulation, we should be
131// able to derive tables for typical Cherenkov-photon spectra - convoluted
132// with the impact parameters and depending on the athmospheric conditions
133// and the zenith angle (the "outer parameters").
134//
135// From these tables we can create "calibration tables" containing some
136// effective quantum efficiency depending on these outer parameters and which
137// are different for each pixel.
138//
139// In an ideal MCalibrate, one would thus have to convert first the FADC
140// slices to Photo-electrons and then, depending on the outer parameters,
141// look up the effective quantum efficiency and get the mean number of
142// photons which is then used for the further analysis.
143//
144// How the (first) MAGIC calibration should look like:
145// ===================================================
146//
147// For the moment, we have only one reliable calibration method, although
148// with very large systematic errors. This is the F-Factor method. Knowing
149// that the light is uniform over the whole camera (which I would not at all
150// guarantee in the case of the CT1 pulser), one could in principle already
151// perform a relative calibration of the quantum efficiencies in the UV.
152// However, the spread in QE at UV is about 10-15% (according to the plot
153// that Abelardo sent around last time. The spread in photo-electrons is 15%
154// for the inner pixels, but much larger (40%) for the outer ones.
155//
156// I'm not sure if we can already say that we have measured the relative
157// difference in quantum efficiency for the inner pixels and produce a first
158// QE-table for each pixel. To so, I would rather check in other wavelengths
159// (which we can do in about one-two weeks when the optical transmission of
160// the calibration trigger is installed).
161//
162// Thus, for the moment being, I would join Thomas proposal to calibrate in
163// photo-electrons and apply one stupid average quantum efficiency for all
164// pixels. This keeping in mind that we will have much preciser information
165// in about one to two weeks.
166//
167//
168// What MCalibrate should calculate and what should be stored:
169// ===========================================================
170//
171// It is clear that in the end, MCerPhotEvt will store photons.
172// MCalibrationCam stores the conversionfactors to photo-electrons and also
173// some tables of how to apply the conversion to photons, given the outer
174// parameters. This is not yet implemented and not even discussed.
175//
176// To start, I would suggest that we define the "average quantum efficiency"
177// (maybe something like 25+-3%) and apply them equally to all
178// photo-electrons. Later, this average factor can be easily replaced by a
179// pixel-dependent factor and later by a (pixel-dependent) table.
180//
181//
182//
183//////////////////////////////////////////////////////////////////////////////
184#include "MCalibrationChargeCalc.h"
185
186#include <TSystem.h>
187#include <TH1.h>
188#include <TF1.h>
189
190#include "MLog.h"
191#include "MLogManip.h"
192
193#include "MParList.h"
194
195#include "MRawEvtHeader.h"
196
197#include "MGeomCam.h"
198#include "MGeomPix.h"
199#include "MHCamera.h"
200
201#include "MPedestalCam.h"
202#include "MPedestalPix.h"
203
204#include "MCalibrationIntensityChargeCam.h"
205#include "MCalibrationIntensityQECam.h"
206#include "MCalibrationIntensityBlindCam.h"
207
208#include "MCalibrationChargeCam.h"
209#include "MCalibrationChargePix.h"
210#include "MCalibrationChargePINDiode.h"
211#include "MCalibrationBlindPix.h"
212#include "MCalibrationBlindCam.h"
213
214#include "MExtractedSignalCam.h"
215#include "MExtractedSignalPix.h"
216#include "MExtractedSignalBlindPixel.h"
217#include "MExtractedSignalPINDiode.h"
218
219#include "MBadPixelsIntensityCam.h"
220#include "MBadPixelsCam.h"
221
222#include "MCalibrationQECam.h"
223#include "MCalibrationQEPix.h"
224
225ClassImp(MCalibrationChargeCalc);
226
227using namespace std;
228
229const Float_t MCalibrationChargeCalc::fgChargeLimit = 2.5;
230const Float_t MCalibrationChargeCalc::fgChargeErrLimit = 0.;
231const Float_t MCalibrationChargeCalc::fgChargeRelErrLimit = 1.;
232const Float_t MCalibrationChargeCalc::fgLambdaErrLimit = 0.2;
233const Float_t MCalibrationChargeCalc::fgLambdaCheckLimit = 0.5;
234const Float_t MCalibrationChargeCalc::fgPheErrLimit = 4.5;
235const Float_t MCalibrationChargeCalc::fgFFactorErrLimit = 4.5;
236// --------------------------------------------------------------------------
237//
238// Default constructor.
239//
240// Sets the pointer to fQECam and fGeom to NULL
241//
242// Calls AddToBranchList for:
243// - MRawEvtData.fHiGainPixId
244// - MRawEvtData.fLoGainPixId
245// - MRawEvtData.fHiGainFadcSamples
246// - MRawEvtData.fLoGainFadcSamples
247//
248// Initializes:
249// - fChargeLimit to fgChargeLimit
250// - fChargeErrLimit to fgChargeErrLimit
251// - fChargeRelErrLimit to fgChargeRelErrLimit
252// - fFFactorErrLimit to fgFFactorErrLimit
253// - fLambdaCheckLimit to fgLambdaCheckLimit
254// - fLambdaErrLimit to fgLambdaErrLimit
255// - fPheErrLimit to fgPheErrLimit
256// - fPulserColor to MCalibrationCam::kCT1
257// - fOutputPath to "."
258// - fOutputFile to "ChargeCalibStat.txt"
259// - flag debug to kFALSE
260//
261// Sets all checks
262//
263// Calls:
264// - Clear()
265//
266MCalibrationChargeCalc::MCalibrationChargeCalc(const char *name, const char *title)
267 :
268 fGeom(NULL), fSignal(NULL), fHeader(NULL)
269{
270
271 fName = name ? name : "MCalibrationChargeCalc";
272 fTitle = title ? title : "Task to calculate the calibration constants and MCalibrationCam ";
273
274 AddToBranchList("MRawEvtData.fHiGainPixId");
275 AddToBranchList("MRawEvtData.fLoGainPixId");
276 AddToBranchList("MRawEvtData.fHiGainFadcSamples");
277 AddToBranchList("MRawEvtData.fLoGainFadcSamples");
278
279 SetChargeLimit ();
280 SetChargeErrLimit ();
281 SetChargeRelErrLimit ();
282 SetFFactorErrLimit ();
283 SetLambdaCheckLimit ();
284 SetLambdaErrLimit ();
285 SetPheErrLimit ();
286 SetOutputPath ();
287 SetOutputFile ();
288 SetDebug ( kFALSE );
289
290 SetCheckDeadPixels ();
291 SetCheckDeviatingBehavior();
292 SetCheckExtractionWindow ();
293 SetCheckHistOverflow ();
294 SetCheckOscillations ();
295
296 Clear();
297
298}
299
300// --------------------------------------------------------------------------
301//
302// Sets:
303// - all variables to 0.,
304// - all flags to kFALSE
305// - all pointers to NULL
306// - the pulser colour to kNONE
307// - fBlindPixelFlags to 0
308// - fPINDiodeFlags to 0
309//
310void MCalibrationChargeCalc::Clear(const Option_t *o)
311{
312
313 fNumHiGainSamples = 0.;
314 fNumLoGainSamples = 0.;
315 fSqrtHiGainSamples = 0.;
316 fSqrtLoGainSamples = 0.;
317 fNumInnerFFactorMethodUsed = 0;
318
319 fIntensBad = NULL;
320 fBadPixels = NULL;
321 fIntensCam = NULL;
322 fCam = NULL;
323 fIntensQE = NULL;
324 fQECam = NULL;
325 fIntensBlind = NULL;
326 fBlindCam = NULL;
327 fPINDiode = NULL;
328 fPedestals = NULL;
329
330 fPulserPattern = 0;
331 SetPulserColor ( MCalibrationCam::kNONE );
332
333 fBlindPixelFlags.Set(0);
334 fPINDiodeFlags .Set(0);
335 fResultFlags .Set(0);
336}
337
338
339// -----------------------------------------------------------------------------------
340//
341// The following container are searched for and execution aborted if not in MParList:
342// - MPedestalCam
343//
344// The following containers are searched and created if they were not found:
345//
346// - MCalibrationQECam
347// - MBadPixelsCam
348//
349Int_t MCalibrationChargeCalc::PreProcess(MParList *pList)
350{
351
352 fHeader = (MRawEvtHeader*)pList->FindObject("MRawEvtHeader");
353 if (!fHeader)
354 {
355 *fLog << err << "MRawEvtHeader not found... abort." << endl;
356 return kFALSE;
357 }
358
359 //
360 // Containers that have to be there.
361 //
362 fPedestals = (MPedestalCam*)pList->FindObject("MPedestalCam");
363 if (!fPedestals)
364 {
365 *fLog << err << "MPedestalCam not found... aborting" << endl;
366 return kFALSE;
367 }
368
369 fSignal = (MExtractedSignalCam*)pList->FindObject("MExtractedSignalCam");
370 if (!fSignal)
371 {
372 *fLog << err << "MExtractedSignalCam not found... aborting" << endl;
373 return kFALSE;
374 }
375
376 fHeader = (MRawEvtHeader*)pList->FindObject("MRawEvtHeader");
377 if (!fHeader)
378 {
379 *fLog << err << "MRawEvtHeader not found... abort." << endl;
380 return kFALSE;
381 }
382
383
384 return kTRUE;
385}
386
387
388// --------------------------------------------------------------------------
389//
390// Search for the following input containers and abort if not existing:
391// - MGeomCam
392// - MCalibrationChargeCam
393//
394// Search for the following input containers and give a warning if not existing:
395// - MCalibrationBlindPix
396// - MCalibrationChargePINDiode
397//
398// It retrieves the following variables from MCalibrationChargeCam:
399//
400// - fNumHiGainSamples
401// - fNumLoGainSamples
402//
403// It defines the PixId of every pixel in:
404//
405// - MCalibrationIntensityChargeCam
406// - MCalibrationChargeCam
407// - MCalibrationQECam
408//
409// It sets all pixels in excluded which have the flag fBadBixelsPix::IsBad() set in:
410//
411// - MCalibrationChargePix
412// - MCalibrationQEPix
413//
414// Sets the pulser colour and tests if it has not changed w.r.t. fPulserColor in:
415//
416// - MCalibrationChargeCam
417// - MCalibrationBlindPix (if existing)
418// - MCalibrationChargePINDiode (if existing)
419//
420Bool_t MCalibrationChargeCalc::ReInit(MParList *pList )
421{
422
423 fGeom = (MGeomCam*)pList->FindObject("MGeomCam");
424 if (!fGeom)
425 {
426 *fLog << err << "No MGeomCam found... aborting." << endl;
427 return kFALSE;
428 }
429
430 fIntensCam = (MCalibrationIntensityChargeCam*)pList->FindObject(AddSerialNumber("MCalibrationIntensityChargeCam"));
431 if (fIntensCam)
432 *fLog << inf << "Found MCalibrationIntensityChargeCam ... " << endl;
433 else
434 {
435 fCam = (MCalibrationChargeCam*)pList->FindObject(AddSerialNumber("MCalibrationChargeCam"));
436 if (!fCam)
437 {
438 *fLog << err << "Cannot find MCalibrationChargeCam ... abort." << endl;
439 *fLog << err << "Maybe you forget to call an MFillH for the MHCalibrationChargeCam before..." << endl;
440 return kFALSE;
441 }
442 }
443
444 fIntensQE = (MCalibrationIntensityQECam*)pList->FindObject(AddSerialNumber("MCalibrationIntensityQECam"));
445 if (fIntensQE)
446 *fLog << inf << "Found MCalibrationIntensityQECam ... " << endl;
447 else
448 {
449 fQECam = (MCalibrationQECam*)pList->FindObject(AddSerialNumber("MCalibrationQECam"));
450 if (!fQECam)
451 {
452 *fLog << err << "Cannot find MCalibrationQECam ... abort." << endl;
453 *fLog << err << "Maybe you forget to call an MFillH for the MHCalibrationQECam before..." << endl;
454 return kFALSE;
455 }
456 }
457
458 fIntensBlind = (MCalibrationIntensityBlindCam*)pList->FindObject(AddSerialNumber("MCalibrationIntensityBlindCam"));
459 if (fIntensBlind)
460 *fLog << inf << "Found MCalibrationIntensityBlindCam ... " << endl;
461 else
462 {
463 fBlindCam = (MCalibrationBlindCam*)pList->FindObject(AddSerialNumber("MCalibrationBlindCam"));
464 if (!fBlindCam)
465 {
466 *fLog << endl;
467 *fLog << warn << GetDescriptor()
468 << ": No MCalibrationBlindCam found... no Blind Pixel method! " << endl;
469 return kFALSE;
470 }
471 }
472
473 fIntensBad = (MBadPixelsIntensityCam*)pList->FindObject(AddSerialNumber("MBadPixelsIntensityCam"));
474 if (fIntensBad)
475 *fLog << inf << "Found MBadPixelsIntensityCam ... " << endl;
476 else
477 {
478 fBadPixels = (MBadPixelsCam*)pList->FindObject(AddSerialNumber("MBadPixelsCam"));
479 if (!fBadPixels)
480 {
481 *fLog << err << "Cannot find MBadPixelsCam ... abort." << endl;
482 return kFALSE;
483 }
484 }
485
486 //
487 // Optional Containers
488 //
489 fPINDiode = (MCalibrationChargePINDiode*)pList->FindObject("MCalibrationChargePINDiode");
490 if (!fPINDiode)
491 {
492 *fLog << endl;
493 *fLog << warn << GetDescriptor()
494 << ": MCalibrationChargePINDiode not found... no PIN Diode method! " << endl;
495 }
496
497 fNumHiGainSamples = fSignal->GetNumUsedHiGainFADCSlices();
498 fNumLoGainSamples = fSignal->GetNumUsedLoGainFADCSlices();
499
500 fSqrtHiGainSamples = TMath::Sqrt(fNumHiGainSamples);
501 fSqrtLoGainSamples = TMath::Sqrt(fNumLoGainSamples);
502
503 UInt_t npixels = fGeom->GetNumPixels();
504
505 for (UInt_t i=0; i<npixels; i++)
506 {
507
508 MCalibrationChargePix &pix = fIntensCam
509 ? (MCalibrationChargePix&)(*fIntensCam)[i]
510 : (MCalibrationChargePix&)(*fCam) [i];
511 MCalibrationQEPix &pqe = fIntensQE
512 ? (MCalibrationQEPix&) (*fIntensQE)[i]
513 : (MCalibrationQEPix&) (*fQECam)[i];
514 MBadPixelsPix &bad = fIntensBad
515 ? (*fIntensBad)[i]
516 : (*fBadPixels)[i];
517
518 pix.SetPixId(i);
519 pqe.SetPixId(i);
520
521 if (bad.IsBad())
522 {
523 pix.SetExcluded();
524 pqe.SetExcluded();
525 continue;
526 }
527
528 if (IsDebug())
529 pix.SetDebug();
530 }
531
532 return kTRUE;
533}
534
535// ----------------------------------------------------------------------------------
536//
537// Set the correct colour to the charge containers
538//
539Int_t MCalibrationChargeCalc::Process()
540{
541
542 const UInt_t pattern = fHeader->GetCalibrationPattern();
543
544 if (pattern == fPulserPattern)
545 return kTRUE;
546
547 enum ColorCode_t
548 {
549 kSlot1Green = BIT(0),
550 kSlot2Green = BIT(1),
551 kSlot3Blue = BIT(2),
552 kSlot4UV = BIT(3),
553 kSlot5UV = BIT(4),
554 kSlot6Blue = BIT(5),
555 kSlot7Blue = BIT(6),
556 kSlot8Blue = BIT(7),
557 kSlot9AttBlue = BIT(8),
558 kSlot10Blue = BIT(9),
559 kSlot11Blue = BIT(10),
560 kSlot12UV = BIT(11),
561 kSlot13UV = BIT(12),
562 kSlot14Blue = BIT(13),
563 kSlot15Green = BIT(14),
564 kSlot16AttGreen = BIT(15),
565 kCT1Pulser = BIT(16),
566 kAnyGreen = kSlot1Green | kSlot2Green | kSlot15Green | kSlot16AttGreen,
567 kAnyUV = kSlot4UV | kSlot5UV | kSlot12UV | kSlot13UV,
568 kAnyBlue = kSlot3Blue | kSlot6Blue | kSlot7Blue | kSlot8Blue
569 | kSlot9AttBlue| kSlot10Blue | kSlot11Blue | kSlot14Blue
570 };
571
572 //
573 // The pattern has changed, we have to initialize everything new!!!
574 //
575 *fLog << inf << GetDescriptor() << "- New pulser pattern: " ;
576 for (Int_t i=16; i>= 0; i--)
577 *fLog << (pattern >> i & 1);
578 *fLog << endl;
579 fPulserPattern = pattern;
580
581 //
582 // Now retrieve the colour and check if not various colours have been used
583 //
584 fPulserColor = MCalibrationCam::kNONE;
585
586 if (fPulserPattern & kAnyGreen)
587 fPulserColor = MCalibrationCam::kGREEN;
588
589 if ((fPulserPattern & kAnyBlue ||
590 fPulserPattern & kAnyUV ||
591 fPulserPattern & kCT1Pulser) && fPulserColor != MCalibrationCam::kNONE)
592 {
593 *fLog << err << "Multiple colours used simultaneously in calibration file. Will skip this part!" << endl;
594 return kCONTINUE;
595 }
596
597 if (fPulserColor == MCalibrationCam::kNONE)
598 {
599 if (fPulserPattern & kAnyBlue)
600 fPulserColor = MCalibrationCam::kBLUE;
601 if (fPulserPattern & kAnyUV)
602 fPulserColor = MCalibrationCam::kUV;
603 if (fPulserPattern & kCT1Pulser)
604 fPulserColor = MCalibrationCam::kCT1;
605 }
606
607 *fLog << inf << "Found new colour ... " << flush;
608
609 switch (fPulserColor)
610 {
611 case MCalibrationCam::kGREEN: *fLog << "Green."; break;
612 case MCalibrationCam::kBLUE: *fLog << "Blue."; break;
613 case MCalibrationCam::kUV: *fLog << "UV."; break;
614 case MCalibrationCam::kCT1: *fLog << "CT1."; break;
615 default: break;
616 }
617 *fLog << endl;
618
619 //
620 // Initialize the pulser colours
621 //
622 if (fIntensCam)
623 fIntensCam->SetPulserColor( fPulserColor );
624 else
625 fCam->SetPulserColor( fPulserColor );
626
627 if (fIntensBlind)
628 fIntensBlind->SetPulserColor( fPulserColor );
629 else if (fBlindCam)
630 fBlindCam->SetPulserColor( fPulserColor );
631
632 if (fPINDiode)
633 fPINDiode->SetColor( fPulserColor );
634
635 return kTRUE;
636}
637
638// -----------------------------------------------------------------------
639//
640// Return if number of executions is null.
641//
642// First loop over pixels, average areas and sectors, call:
643// - FinalizePedestals()
644// - FinalizeCharges()
645// for every entry. Count number of valid pixels in loop and return kFALSE
646// if there are none (the "Michele check").
647//
648// Call FinalizeBadPixels()
649//
650// Call FinalizeFFactorMethod() (second and third loop over pixels and areas)
651//
652// Call FinalizeBlindCam()
653// Call FinalizePINDiode()
654//
655// Call FinalizeFFactorQECam() (fourth loop over pixels and areas)
656// Call FinalizeBlindPixelQECam() (fifth loop over pixels and areas)
657// Call FinalizePINDiodeQECam() (sixth loop over pixels and areas)
658//
659// Call FinalizeUnsuitablePixels()
660//
661// Call MParContainer::SetReadyToSave() for fIntensCam, fCam, fQECam, fBadPixels and
662// fBlindCam and fPINDiode if they exist
663//
664// Print out some statistics
665//
666Int_t MCalibrationChargeCalc::PostProcess()
667{
668
669 if (GetNumExecutions()==0)
670 return kFALSE;
671
672 *fLog << endl;
673
674 if (fPINDiode)
675 if (!fPINDiode->IsValid())
676 {
677 *fLog << warn << GetDescriptor()
678 << ": MCalibrationChargePINDiode is declared not valid... no PIN Diode method! " << endl;
679 fPINDiode = NULL;
680 }
681
682 *fLog << endl;
683
684 MCalibrationBlindCam *blindcam = fIntensBlind
685 ? (MCalibrationBlindCam*)fIntensBlind->GetCam() : fBlindCam;
686 MCalibrationQECam *qecam = fIntensQE
687 ? (MCalibrationQECam*) fIntensQE->GetCam() : fQECam;
688 MCalibrationChargeCam *chargecam = fIntensCam
689 ? (MCalibrationChargeCam*)fIntensCam->GetCam() : fCam;
690 MBadPixelsCam *badcam = fIntensBad
691 ? (MBadPixelsCam*) fIntensBad->GetCam() : fBadPixels;
692
693 //
694 // First loop over pixels, call FinalizePedestals and FinalizeCharges
695 //
696 Int_t nvalid = 0;
697
698 for (Int_t pixid=0; pixid<fPedestals->GetSize(); pixid++)
699 {
700
701 MCalibrationChargePix &pix = (MCalibrationChargePix&)(*chargecam)[pixid];
702 //
703 // Check if the pixel has been excluded from the fits
704 //
705 if (pix.IsExcluded())
706 continue;
707
708 MPedestalPix &ped = (*fPedestals)[pixid];
709 MBadPixelsPix &bad = (*badcam) [pixid];
710
711 const Int_t aidx = (*fGeom)[pixid].GetAidx();
712
713 FinalizePedestals(ped,pix,aidx);
714
715 if (FinalizeCharges(pix,bad,"pixel "))
716 nvalid++;
717 }
718
719 *fLog << endl;
720 //
721 // The Michele check ...
722 //
723 if (nvalid == 0)
724 {
725 *fLog << err << GetDescriptor() << ": All pixels have non-valid calibration. "
726 << "Did you forget to fill the histograms "
727 << "(filling MHCalibrationChargeCam from MExtractedSignalCam using MFillH) ? " << endl;
728 *fLog << err << GetDescriptor() << ": Or, maybe, you have used a pedestal run "
729 << "instead of a calibration run " << endl;
730 return kFALSE;
731 }
732
733 for (UInt_t aidx=0; aidx<fGeom->GetNumAreas(); aidx++)
734 {
735
736 const MPedestalPix &ped = fPedestals->GetAverageArea(aidx);
737 MCalibrationChargePix &pix = (MCalibrationChargePix&)chargecam->GetAverageArea(aidx);
738
739 FinalizePedestals(ped,pix,aidx);
740 FinalizeCharges(pix,
741 fIntensCam ? fIntensCam->GetAverageBadArea(aidx) : fCam->GetAverageBadArea(aidx),
742 "area id");
743 }
744
745 *fLog << endl;
746
747 for (UInt_t sector=0; sector<fGeom->GetNumSectors(); sector++)
748 {
749
750 const MPedestalPix &ped = fPedestals->GetAverageSector(sector);
751
752 MCalibrationChargePix &pix = (MCalibrationChargePix&)chargecam->GetAverageSector(sector);
753 FinalizePedestals(ped,pix, 0);
754 }
755
756 *fLog << endl;
757
758 //
759 // Finalize Bad Pixels
760 //
761 FinalizeBadPixels();
762
763 //
764 // Finalize F-Factor method
765 //
766 if (FinalizeFFactorMethod())
767 chargecam->SetFFactorMethodValid(kTRUE);
768 else
769 {
770 *fLog << warn << "Could not calculate the photons flux from the F-Factor method " << endl;
771 chargecam->SetFFactorMethodValid(kFALSE);
772 return kFALSE;
773 }
774
775 *fLog << endl;
776 //
777 // Finalize Blind Pixel
778 //
779 qecam->SetBlindPixelMethodValid(FinalizeBlindCam());
780
781 //
782 // Finalize PIN Diode
783 //
784 qecam->SetBlindPixelMethodValid(FinalizePINDiode());
785
786 //
787 // Finalize QE Cam
788 //
789 FinalizeFFactorQECam();
790 FinalizeBlindPixelQECam();
791 FinalizePINDiodeQECam();
792 FinalizeCombinedQECam();
793
794 //
795 // Re-direct the output to an ascii-file from now on:
796 //
797 MLog asciilog;
798 asciilog.SetOutputFile(GetOutputFile(),kTRUE);
799 SetLogStream(&asciilog);
800 //
801 // Finalize calibration statistics
802 //
803 FinalizeUnsuitablePixels();
804
805 chargecam->SetReadyToSave();
806 qecam ->SetReadyToSave();
807 badcam ->SetReadyToSave();
808
809 if (blindcam)
810 blindcam->SetReadyToSave();
811 if (fPINDiode)
812 fPINDiode->SetReadyToSave();
813
814 *fLog << inf << endl;
815 *fLog << GetDescriptor() << ": Fatal errors statistics:" << endl;
816
817 PrintUncalibrated(MBadPixelsPix::kChargeIsPedestal,
818 Form("%s%2.1f%s","Signal less than ",fChargeLimit," Pedestal RMS: "));
819 PrintUncalibrated(MBadPixelsPix::kChargeRelErrNotValid,
820 Form("%s%2.1f%s","Signal Error bigger than ",fChargeRelErrLimit," times Mean Signal: "));
821 PrintUncalibrated(MBadPixelsPix::kLoGainSaturation,
822 "Pixels with Low Gain Saturation: ");
823 PrintUncalibrated(MBadPixelsPix::kMeanTimeInFirstBin,
824 Form("%s%2.1f%s","Mean Abs. Arr. Time in First ",1.," Bin(s): "));
825 PrintUncalibrated(MBadPixelsPix::kMeanTimeInLast2Bins,
826 Form("%s%2.1f%s","Mean Abs. Arr. Time in Last ",2.," Bin(s): "));
827 PrintUncalibrated(MBadPixelsPix::kDeviatingNumPhes,
828 "Pixels with deviating number of phes: ");
829 PrintUncalibrated(MBadPixelsPix::kDeviatingFFactor,
830 "Pixels with deviating F-Factor: ");
831
832 *fLog << inf << endl;
833 *fLog << GetDescriptor() << ": Unreliable errors statistics:" << endl;
834
835 PrintUncalibrated(MBadPixelsPix::kChargeSigmaNotValid,
836 "Signal Sigma smaller than Pedestal RMS: ");
837 PrintUncalibrated(MBadPixelsPix::kHiGainOscillating,
838 "Pixels with changing Hi Gain signal over time: ");
839 PrintUncalibrated(MBadPixelsPix::kLoGainOscillating,
840 "Pixels with changing Lo Gain signal over time: ");
841 PrintUncalibrated(MBadPixelsPix::kHiGainNotFitted,
842 "Pixels with unsuccesful Gauss fit to the Hi Gain: ");
843 PrintUncalibrated(MBadPixelsPix::kLoGainNotFitted,
844 "Pixels with unsuccesful Gauss fit to the Lo Gain: ");
845
846 SetLogStream(&gLog);
847
848 return kTRUE;
849}
850
851// ----------------------------------------------------------------------------------
852//
853// Retrieves pedestal and pedestal RMS from MPedestalPix
854// Retrieves total entries from MPedestalCam
855// Sets pedestal*fNumHiGainSamples and pedestal*fNumLoGainSamples in MCalibrationChargePix
856// Sets pedRMS *fSqrtHiGainSamples and pedRMS *fSqrtLoGainSamples in MCalibrationChargePix
857//
858// If the flag MCalibrationPix::IsHiGainSaturation() is set, call also:
859// - MCalibrationChargePix::CalcLoGainPedestal()
860//
861void MCalibrationChargeCalc::FinalizePedestals(const MPedestalPix &ped, MCalibrationChargePix &cal, const Int_t aidx)
862{
863
864 //
865 // get the pedestals
866 //
867 const Float_t pedes = ped.GetPedestal();
868 const Float_t prms = ped.GetPedestalRms();
869 const Int_t num = fPedestals->GetTotalEntries();
870
871 //
872 // RMS error set by PedCalcFromLoGain, 0 in case MPedCalcPedRun was used.
873 //
874 const Float_t prmserr = num>0 ? prms/TMath::Sqrt(2.*num) : ped.GetPedestalRmsError();
875
876 //
877 // set them in the calibration camera
878 //
879 if (cal.IsHiGainSaturation())
880 {
881 cal.SetPedestal(pedes * fNumLoGainSamples,
882 prms * fSqrtLoGainSamples,
883 prmserr * fSqrtLoGainSamples);
884 cal.CalcLoGainPedestal((Float_t)fNumLoGainSamples, aidx);
885 }
886 else
887 {
888 cal.SetPedestal(pedes * fNumHiGainSamples,
889 prms * fSqrtHiGainSamples,
890 prmserr * fSqrtHiGainSamples);
891 }
892
893}
894
895// ----------------------------------------------------------------------------------------------------
896//
897// Check fit results validity. Bad Pixels flags are set if:
898//
899// 1) Pixel has a mean smaller than fChargeLimit*PedRMS ( Flag: MBadPixelsPix::kChargeIsPedestal)
900// 2) Pixel has a mean error smaller than fChargeErrLimit ( Flag: MBadPixelsPix::kChargeErrNotValid)
901// 3) Pixel has mean smaller than fChargeRelVarLimit times its mean error
902// ( Flag: MBadPixelsPix::kChargeRelErrNotValid)
903// 4) Pixel has a sigma bigger than its Pedestal RMS ( Flag: MBadPixelsPix::kChargeSigmaNotValid )
904//
905// Further returns if flags: MBadPixelsPix::kUnsuitableRun is set
906//
907// Calls MCalibrationChargePix::CalcReducedSigma() and sets flag: MBadPixelsPix::kChargeIsPedestal
908// and returns kFALSE if not succesful.
909//
910// Calls MCalibrationChargePix::CalcFFactor() and sets flag: MBadPixelsPix::kDeviatingNumPhes)
911// and returns kFALSE if not succesful.
912//
913// Calls MCalibrationChargePix::CalcConvFFactor()and sets flag: MBadPixelsPix::kDeviatingNumPhes)
914// and returns kFALSE if not succesful.
915//
916Bool_t MCalibrationChargeCalc::FinalizeCharges(MCalibrationChargePix &cal, MBadPixelsPix &bad, const char* what)
917{
918
919 if (bad.IsUnsuitable(MBadPixelsPix::kUnsuitableRun))
920 return kFALSE;
921
922 if (cal.GetMean() < fChargeLimit*cal.GetPedRms())
923 {
924 *fLog << warn << GetDescriptor()
925 << Form(": Fitted Charge: %5.2f is smaller than %2.1f",cal.GetMean(),fChargeLimit)
926 << Form(" Pedestal RMS: %5.2f in %s%4i",cal.GetPedRms(),what,cal.GetPixId()) << endl;
927 bad.SetUncalibrated( MBadPixelsPix::kChargeIsPedestal);
928 }
929
930 if (cal.GetMean() < fChargeRelErrLimit*cal.GetMeanErr())
931 {
932 *fLog << warn << GetDescriptor()
933 << Form(": Fitted Charge: %4.2f is smaller than %2.1f",cal.GetMean(),fChargeRelErrLimit)
934 << Form(" times its error: %4.2f in %s%4i",cal.GetMeanErr(),what,cal.GetPixId()) << endl;
935 bad.SetUncalibrated( MBadPixelsPix::kChargeRelErrNotValid );
936 }
937
938 if (cal.GetSigma() < cal.GetPedRms())
939 {
940 *fLog << warn << GetDescriptor()
941 << Form(": Sigma of Fitted Charge: %6.2f is smaller than",cal.GetSigma())
942 << Form(" Ped. RMS: %5.2f in %s%4i",cal.GetPedRms(),what,cal.GetPixId()) << endl;
943 bad.SetUncalibrated( MBadPixelsPix::kChargeSigmaNotValid );
944 return kFALSE;
945 }
946
947 if (!cal.CalcReducedSigma())
948 {
949 *fLog << warn << GetDescriptor()
950 << Form(": Could not calculate the reduced sigma in %s: ",what)
951 << Form(" %4i",cal.GetPixId())
952 << endl;
953 bad.SetUncalibrated( MBadPixelsPix::kChargeSigmaNotValid );
954 return kFALSE;
955 }
956
957 if (!cal.CalcFFactor())
958 {
959 *fLog << warn << GetDescriptor()
960 << Form(": Could not calculate the F-Factor in %s: ",what)
961 << Form(" %4i",cal.GetPixId())
962 << endl;
963 bad.SetUncalibrated(MBadPixelsPix::kDeviatingNumPhes);
964 return kFALSE;
965 }
966
967 if (!cal.CalcConvFFactor())
968 {
969 *fLog << warn << GetDescriptor()
970 << Form(": Could not calculate the Conv. FADC counts to Phes in %s: ",what)
971 << Form(" %4i",cal.GetPixId())
972 << endl;
973 bad.SetUncalibrated(MBadPixelsPix::kDeviatingNumPhes);
974 return kFALSE;
975 }
976
977 return kTRUE;
978}
979
980
981
982// -----------------------------------------------------------------------------------
983//
984// Sets pixel to MBadPixelsPix::kUnsuitableRun, if one of the following flags is set:
985// - MBadPixelsPix::kChargeIsPedestal
986// - MBadPixelsPix::kChargeRelErrNotValid
987// - MBadPixelsPix::kMeanTimeInFirstBin
988// - MBadPixelsPix::kMeanTimeInLast2Bins
989// - MBadPixelsPix::kDeviatingNumPhes
990// - MBadPixelsPix::kHiGainOverFlow
991// - MBadPixelsPix::kLoGainOverFlow
992//
993// - Call MCalibrationPix::SetExcluded() for the bad pixels
994//
995// Sets pixel to MBadPixelsPix::kUnreliableRun, if one of the following flags is set:
996// - MBadPixelsPix::kChargeSigmaNotValid
997//
998void MCalibrationChargeCalc::FinalizeBadPixels()
999{
1000
1001 MBadPixelsCam *badcam = fIntensBad
1002 ? (MBadPixelsCam*) fIntensBad->GetCam() : fBadPixels;
1003 MCalibrationChargeCam *chargecam = fIntensCam
1004 ? (MCalibrationChargeCam*)fIntensCam->GetCam() : fCam;
1005
1006 for (Int_t i=0; i<badcam->GetSize(); i++)
1007 {
1008
1009 MBadPixelsPix &bad = (*badcam) [i];
1010 MCalibrationPix &pix = (*chargecam)[i];
1011
1012 if (IsCheckDeadPixels())
1013 {
1014 if (bad.IsUncalibrated( MBadPixelsPix::kChargeIsPedestal))
1015 bad.SetUnsuitable( MBadPixelsPix::kUnsuitableRun );
1016
1017 if (bad.IsUncalibrated( MBadPixelsPix::kChargeErrNotValid ))
1018 bad.SetUnsuitable( MBadPixelsPix::kUnsuitableRun );
1019
1020 if (bad.IsUncalibrated( MBadPixelsPix::kChargeRelErrNotValid ))
1021 bad.SetUnsuitable( MBadPixelsPix::kUnsuitableRun );
1022 }
1023
1024 if (IsCheckExtractionWindow())
1025 {
1026 if (bad.IsUncalibrated( MBadPixelsPix::kMeanTimeInFirstBin ))
1027 bad.SetUnsuitable( MBadPixelsPix::kUnsuitableRun );
1028
1029 if (bad.IsUncalibrated( MBadPixelsPix::kMeanTimeInLast2Bins ))
1030 bad.SetUnsuitable( MBadPixelsPix::kUnsuitableRun );
1031 }
1032
1033 if (IsCheckDeviatingBehavior())
1034 {
1035 if (bad.IsUncalibrated( MBadPixelsPix::kDeviatingNumPhes ))
1036 bad.SetUnsuitable( MBadPixelsPix::kUnsuitableRun );
1037 }
1038
1039 if (IsCheckHistOverflow())
1040 {
1041 if (bad.IsUncalibrated( MBadPixelsPix::kHiGainOverFlow ))
1042 bad.SetUnsuitable( MBadPixelsPix::kUnsuitableRun );
1043
1044 if (bad.IsUncalibrated( MBadPixelsPix::kLoGainOverFlow ))
1045 bad.SetUnsuitable( MBadPixelsPix::kUnsuitableRun );
1046 }
1047
1048 if (bad.IsUnsuitable( MBadPixelsPix::kUnsuitableRun ))
1049 pix.SetExcluded();
1050
1051 if (bad.IsUncalibrated( MBadPixelsPix::kChargeSigmaNotValid ))
1052 bad.SetUnsuitable( MBadPixelsPix::kUnreliableRun );
1053 }
1054}
1055
1056// ------------------------------------------------------------------------
1057//
1058//
1059// First loop: Calculate a mean and mean RMS of photo-electrons per area index
1060// Include only pixels which are not MBadPixelsPix::kUnsuitableRun nor
1061// MBadPixelsPix::kChargeSigmaNotValid (see FinalizeBadPixels()) and set
1062// MCalibrationChargePix::SetFFactorMethodValid(kFALSE) in that case.
1063//
1064// Second loop: Get mean number of photo-electrons and its RMS including
1065// only pixels with flag MCalibrationChargePix::IsFFactorMethodValid()
1066// and further exclude those deviating by more than fPheErrLimit mean
1067// sigmas from the mean (obtained in first loop). Set
1068// MBadPixelsPix::kDeviatingNumPhes if excluded.
1069//
1070// For the suitable pixels with flag MBadPixelsPix::kChargeSigmaNotValid
1071// set the number of photo-electrons as the mean number of photo-electrons
1072// calculated in that area index.
1073//
1074// Set weighted mean and variance of photo-electrons per area index in:
1075// average area pixels of MCalibrationChargeCam (obtained from:
1076// MCalibrationChargeCam::GetAverageArea() )
1077//
1078// Set weighted mean and variance of photo-electrons per sector in:
1079// average sector pixels of MCalibrationChargeCam (obtained from:
1080// MCalibrationChargeCam::GetAverageSector() )
1081//
1082//
1083// Third loop: Set mean number of photo-electrons and its RMS in the pixels
1084// only excluded as: MBadPixelsPix::kChargeSigmaNotValid
1085//
1086Bool_t MCalibrationChargeCalc::FinalizeFFactorMethod()
1087{
1088
1089 MBadPixelsCam *badcam = fIntensBad
1090 ? (MBadPixelsCam*) fIntensBad->GetCam() : fBadPixels;
1091 MCalibrationChargeCam *chargecam = fIntensCam
1092 ? (MCalibrationChargeCam*)fIntensCam->GetCam() : fCam;
1093
1094 const Int_t npixels = fGeom->GetNumPixels();
1095 const Int_t nareas = fGeom->GetNumAreas();
1096 const Int_t nsectors = fGeom->GetNumSectors();
1097
1098 TArrayF lowlim (nareas);
1099 TArrayF upplim (nareas);
1100 TArrayD areavars (nareas);
1101 TArrayD areaweights (nareas);
1102 TArrayD sectorweights (nsectors);
1103 TArrayD areaphes (nareas);
1104 TArrayD sectorphes (nsectors);
1105 TArrayI numareavalid (nareas);
1106 TArrayI numsectorvalid(nsectors);
1107
1108 //
1109 // First loop: Get mean number of photo-electrons and the RMS
1110 // The loop is only to recognize later pixels with very deviating numbers
1111 //
1112 MHCamera camphes(*fGeom,"Camphes","Phes in Camera");
1113
1114 for (Int_t i=0; i<npixels; i++)
1115 {
1116
1117 MCalibrationChargePix &pix = (MCalibrationChargePix&)(*chargecam)[i];
1118 MBadPixelsPix &bad = (*badcam)[i];
1119
1120 if (!pix.IsFFactorMethodValid())
1121 continue;
1122
1123 if (bad.IsUnsuitable(MBadPixelsPix::kUnsuitableRun))
1124 {
1125 pix.SetFFactorMethodValid(kFALSE);
1126 continue;
1127 }
1128
1129 if (bad.IsUncalibrated(MBadPixelsPix::kChargeSigmaNotValid))
1130 continue;
1131
1132 const Float_t nphe = pix.GetPheFFactorMethod();
1133 const Int_t aidx = (*fGeom)[i].GetAidx();
1134
1135 camphes.Fill(i,nphe);
1136 camphes.SetUsed(i);
1137
1138 areaphes [aidx] += nphe;
1139 areavars [aidx] += nphe*nphe;
1140 numareavalid[aidx] ++;
1141 }
1142
1143 for (Int_t i=0; i<nareas; i++)
1144 {
1145 if (numareavalid[i] == 0)
1146 {
1147 *fLog << warn << GetDescriptor() << ": No pixels with valid number of photo-electrons found "
1148 << "in area index: " << i << endl;
1149 continue;
1150 }
1151
1152 if (numareavalid[i] == 1)
1153 areavars[i] = 0.;
1154 else if (numareavalid[i] == 0)
1155 {
1156 areaphes[i] = -1.;
1157 areaweights[i] = -1.;
1158 }
1159 else
1160 {
1161 areavars[i] = (areavars[i] - areaphes[i]*areaphes[i]/numareavalid[i]) / (numareavalid[i]-1);
1162 areaphes[i] = areaphes[i] / numareavalid[i];
1163 }
1164
1165 if (areavars[i] < 0.)
1166 {
1167 *fLog << warn << GetDescriptor() << ": No pixels with valid variance of photo-electrons found "
1168 << "in area index: " << i << endl;
1169 continue;
1170 }
1171
1172 lowlim [i] = areaphes[i] - fPheErrLimit*TMath::Sqrt(areavars[i]);
1173 upplim [i] = areaphes[i] + fPheErrLimit*TMath::Sqrt(areavars[i]);
1174
1175 TH1D *hist = camphes.ProjectionS(TArrayI(),TArrayI(1,&i),"_py",100);
1176 hist->Fit("gaus","Q");
1177 const Float_t mean = hist->GetFunction("gaus")->GetParameter(1);
1178 const Float_t sigma = hist->GetFunction("gaus")->GetParameter(2);
1179 const Int_t ndf = hist->GetFunction("gaus")->GetNDF();
1180
1181 if (IsDebug())
1182 hist->DrawClone();
1183
1184 if (ndf < 2)
1185 {
1186 *fLog << warn << GetDescriptor() << ": Cannot use a Gauss fit to the number of photo-electrons "
1187 << "in the camera with area index: " << i << endl;
1188 *fLog << warn << GetDescriptor() << ": Number of dof.: " << ndf << " is smaller than 2 " << endl;
1189 *fLog << warn << GetDescriptor() << ": Will use the simple mean and rms " << endl;
1190 delete hist;
1191 continue;
1192 }
1193
1194 const Double_t prob = hist->GetFunction("gaus")->GetProb();
1195
1196 if (prob < 0.001)
1197 {
1198 *fLog << warn << GetDescriptor() << ": Cannot use a Gauss fit to the number of photo-electrons "
1199 << "in the camera with area index: " << i << endl;
1200 *fLog << warn << GetDescriptor() << ": Fit probability " << prob
1201 << " is smaller than 0.001 " << endl;
1202 *fLog << warn << GetDescriptor() << ": Will use the simple mean and rms " << endl;
1203 delete hist;
1204 continue;
1205 }
1206
1207 *fLog << inf << GetDescriptor() << ": Mean number of photo-electrons "
1208 << "with area idx " << i << ": "
1209 << Form("%7.2f+-%6.2f",mean,sigma) << endl;
1210
1211 lowlim [i] = mean - fPheErrLimit*sigma;
1212 upplim [i] = mean + fPheErrLimit*sigma;
1213
1214 delete hist;
1215 }
1216
1217 *fLog << endl;
1218
1219 numareavalid.Reset();
1220 areaphes .Reset();
1221 areavars .Reset();
1222 //
1223 // Second loop: Get mean number of photo-electrons and its RMS excluding
1224 // pixels deviating by more than fPheErrLimit sigma.
1225 // Set the conversion factor FADC counts to photo-electrons
1226 //
1227 for (Int_t i=0; i<npixels; i++)
1228 {
1229
1230 MCalibrationChargePix &pix = (MCalibrationChargePix&)(*chargecam)[i];
1231
1232 if (!pix.IsFFactorMethodValid())
1233 continue;
1234
1235 MBadPixelsPix &bad = (*badcam)[i];
1236
1237 if (bad.IsUncalibrated(MBadPixelsPix::kChargeSigmaNotValid))
1238 continue;
1239
1240 const Float_t nvar = pix.GetPheFFactorMethodVar();
1241
1242 if (nvar <= 0.)
1243 {
1244 pix.SetFFactorMethodValid(kFALSE);
1245 continue;
1246 }
1247
1248 const Int_t aidx = (*fGeom)[i].GetAidx();
1249 const Int_t sector = (*fGeom)[i].GetSector();
1250 const Float_t area = (*fGeom)[i].GetA();
1251 const Float_t nphe = pix.GetPheFFactorMethod();
1252
1253 if ( nphe < lowlim[aidx] || nphe > upplim[aidx] )
1254 {
1255 *fLog << warn << GetDescriptor() << ": Number of phes: "
1256 << Form("%7.2f out of %3.1f sigma limit: ",nphe,fPheErrLimit)
1257 << Form("[%7.2f,%7.2f] pixel%4i",lowlim[aidx],upplim[aidx],i) << endl;
1258 bad.SetUncalibrated( MBadPixelsPix::kDeviatingNumPhes );
1259 if (IsCheckDeviatingBehavior())
1260 {
1261 bad.SetUnsuitable ( MBadPixelsPix::kUnsuitableRun );
1262 pix.SetFFactorMethodValid(kFALSE);
1263 }
1264 continue;
1265 }
1266
1267 areaweights [aidx] += nphe*nphe;
1268 areaphes [aidx] += nphe;
1269 numareavalid [aidx] ++;
1270
1271 if (aidx == 0)
1272 fNumInnerFFactorMethodUsed++;
1273
1274 sectorweights [sector] += nphe*nphe/area/area;
1275 sectorphes [sector] += nphe/area;
1276 numsectorvalid[sector] ++;
1277 }
1278
1279 *fLog << endl;
1280
1281 for (Int_t aidx=0; aidx<nareas; aidx++)
1282 {
1283
1284 MCalibrationChargePix &apix = (MCalibrationChargePix&)chargecam->GetAverageArea(aidx);
1285
1286 if (numareavalid[aidx] == 1)
1287 areaweights[aidx] = 0.;
1288 else if (numareavalid[aidx] == 0)
1289 {
1290 areaphes[aidx] = -1.;
1291 areaweights[aidx] = -1.;
1292 }
1293 else
1294 {
1295 areaweights[aidx] = (areaweights[aidx] - areaphes[aidx]*areaphes[aidx]/numareavalid[aidx])
1296 / (numareavalid[aidx]-1);
1297 areaphes[aidx] /= numareavalid[aidx];
1298 }
1299
1300 if (areaweights[aidx] < 0. || areaphes[aidx] <= 0.)
1301 {
1302 *fLog << warn << GetDescriptor()
1303 << ": Mean number phes from area index " << aidx << " could not be calculated: "
1304 << " Mean: " << areaphes[aidx]
1305 << " Variance: " << areaweights[aidx] << endl;
1306 apix.SetFFactorMethodValid(kFALSE);
1307 continue;
1308 }
1309
1310 *fLog << inf << GetDescriptor()
1311 << ": Average total number phes in area idx " << aidx << ": "
1312 << Form("%7.2f%s%6.2f",areaphes[aidx]," +- ",TMath::Sqrt(areaweights[aidx])) << endl;
1313
1314 apix.SetPheFFactorMethod ( areaphes[aidx] );
1315 apix.SetPheFFactorMethodVar( areaweights[aidx] / numareavalid[aidx] );
1316 apix.SetFFactorMethodValid ( kTRUE );
1317
1318 }
1319
1320 *fLog << endl;
1321
1322 for (Int_t sector=0; sector<nsectors; sector++)
1323 {
1324
1325 if (numsectorvalid[sector] == 1)
1326 sectorweights[sector] = 0.;
1327 else if (numsectorvalid[sector] == 0)
1328 {
1329 sectorphes[sector] = -1.;
1330 sectorweights[sector] = -1.;
1331 }
1332 else
1333 {
1334 sectorweights[sector] = (sectorweights[sector]
1335 - sectorphes[sector]*sectorphes[sector]/numsectorvalid[sector]
1336 )
1337 / (numsectorvalid[sector]-1.);
1338 sectorphes[sector] /= numsectorvalid[sector];
1339 }
1340
1341 MCalibrationChargePix &spix = (MCalibrationChargePix&)chargecam->GetAverageSector(sector);
1342
1343 if (sectorweights[sector] < 0. || sectorphes[sector] <= 0.)
1344 {
1345 *fLog << warn << GetDescriptor()
1346 <<": Mean number phes per area for sector " << sector << " could not be calculated: "
1347 << " Mean: " << sectorphes[sector]
1348 << " Variance: " << sectorweights[sector] << endl;
1349 spix.SetFFactorMethodValid(kFALSE);
1350 continue;
1351 }
1352
1353 *fLog << inf << GetDescriptor()
1354 << ": Average number phes per area in sector " << sector << ": "
1355 << Form("%5.2f+-%4.2f [phe/mm^2]",sectorphes[sector],TMath::Sqrt(sectorweights[sector]))
1356 << endl;
1357
1358 spix.SetPheFFactorMethod ( sectorphes[sector] );
1359 spix.SetPheFFactorMethodVar( sectorweights[sector] / numsectorvalid[sector]);
1360 spix.SetFFactorMethodValid ( kTRUE );
1361
1362 }
1363
1364 //
1365 // Third loop: Set mean number of photo-electrons and its RMS in the pixels
1366 // only excluded as: MBadPixelsPix::kChargeSigmaNotValid
1367 //
1368 for (Int_t i=0; i<npixels; i++)
1369 {
1370
1371 MCalibrationChargePix &pix = (MCalibrationChargePix&)(*chargecam)[i];
1372 MBadPixelsPix &bad = (*badcam)[i];
1373
1374 if (bad.IsUnsuitable(MBadPixelsPix::kUnsuitableRun))
1375 continue;
1376
1377 if (bad.IsUncalibrated(MBadPixelsPix::kChargeSigmaNotValid))
1378 {
1379 const Int_t aidx = (*fGeom)[i].GetAidx();
1380 MCalibrationChargePix &apix = (MCalibrationChargePix&)chargecam->GetAverageArea(aidx);
1381
1382 pix.SetPheFFactorMethod ( apix.GetPheFFactorMethod() );
1383 pix.SetPheFFactorMethodVar( apix.GetPheFFactorMethodVar() );
1384 if (!pix.CalcConvFFactor())
1385 {
1386 *fLog << warn << GetDescriptor()
1387 << ": Could not calculate the Conv. FADC counts to Phes in pixel: "
1388 << Form(" %4i",pix.GetPixId())
1389 << endl;
1390 bad.SetUncalibrated( MBadPixelsPix::kDeviatingNumPhes );
1391 if (IsCheckDeviatingBehavior())
1392 bad.SetUnsuitable ( MBadPixelsPix::kUnsuitableRun );
1393 }
1394 }
1395 }
1396
1397 return kTRUE;
1398}
1399
1400
1401
1402// ------------------------------------------------------------------------
1403//
1404// Returns kFALSE if pointer to MCalibrationBlindCam is NULL
1405//
1406// The check returns kFALSE if:
1407//
1408// 1) fLambda and fLambdaCheck are separated relatively to each other by more than fLambdaCheckLimit
1409// 2) BlindPixel has an fLambdaErr greater than fLambdaErrLimit
1410//
1411// Calls:
1412// - MCalibrationBlindPix::CalcFluxInsidePlexiglass()
1413//
1414Bool_t MCalibrationChargeCalc::FinalizeBlindCam()
1415{
1416
1417 MCalibrationBlindCam *blindcam = fIntensBlind
1418 ? (MCalibrationBlindCam*)fIntensBlind->GetCam() : fBlindCam;
1419
1420 if (!blindcam)
1421 return kFALSE;
1422
1423 Int_t nvalid = 0;
1424
1425 for (Int_t i=0; i<blindcam->GetSize(); i++)
1426 {
1427
1428 MCalibrationBlindPix &blindpix = (MCalibrationBlindPix&)(*blindcam)[i];
1429
1430 if (!blindpix.IsValid())
1431 continue;
1432
1433 const Float_t lambda = blindpix.GetLambda();
1434 const Float_t lambdaerr = blindpix.GetLambdaErr();
1435 const Float_t lambdacheck = blindpix.GetLambdaCheck();
1436
1437 if (2.*(lambdacheck-lambda)/(lambdacheck+lambda) > fLambdaCheckLimit)
1438 {
1439 *fLog << warn << GetDescriptor()
1440 << Form("%s%4.2f%s%4.2f%s%4.2f%s%2i",": Lambda: ",lambda," and Lambda-Check: ",
1441 lambdacheck," differ by more than ",fLambdaCheckLimit," in the Blind Pixel Nr.",i)
1442 << endl;
1443 blindpix.SetValid(kFALSE);
1444 continue;
1445 }
1446
1447 if (lambdaerr > fLambdaErrLimit)
1448 {
1449 *fLog << warn << GetDescriptor()
1450 << Form("%s%4.2f%s%4.2f%s%2i",": Error of Fitted Lambda: ",lambdaerr," is greater than ",
1451 fLambdaErrLimit," in Blind Pixel Nr.",i) << endl;
1452 blindpix.SetValid(kFALSE);
1453 continue;
1454 }
1455
1456 if (!blindpix.CalcFluxInsidePlexiglass())
1457 {
1458 *fLog << warn << "Could not calculate the flux of photons from Blind Pixel Nr." << i << endl;
1459 blindpix.SetValid(kFALSE);
1460 continue;
1461 }
1462
1463 nvalid++;
1464 }
1465
1466 if (!nvalid)
1467 return kFALSE;
1468
1469 return kTRUE;
1470}
1471
1472// ------------------------------------------------------------------------
1473//
1474// Returns kFALSE if pointer to MCalibrationChargePINDiode is NULL
1475//
1476// The check returns kFALSE if:
1477//
1478// 1) PINDiode has a fitted charge smaller than fChargeLimit*PedRMS
1479// 2) PINDiode has a fit error smaller than fChargeErrLimit
1480// 3) PINDiode has a fitted charge smaller its fChargeRelErrLimit times its charge error
1481// 4) PINDiode has a charge sigma smaller than its Pedestal RMS
1482//
1483// Calls:
1484// - MCalibrationChargePINDiode::CalcFluxOutsidePlexiglass()
1485//
1486Bool_t MCalibrationChargeCalc::FinalizePINDiode()
1487{
1488
1489 if (!fPINDiode)
1490 return kFALSE;
1491
1492 if (fPINDiode->GetMean() < fChargeLimit*fPINDiode->GetPedRms())
1493 {
1494 *fLog << warn << GetDescriptor() << ": Fitted Charge is smaller than "
1495 << fChargeLimit << " Pedestal RMS in PINDiode " << endl;
1496 return kFALSE;
1497 }
1498
1499 if (fPINDiode->GetMeanErr() < fChargeErrLimit)
1500 {
1501 *fLog << warn << GetDescriptor() << ": Error of Fitted Charge is smaller than "
1502 << fChargeErrLimit << " in PINDiode " << endl;
1503 return kFALSE;
1504 }
1505
1506 if (fPINDiode->GetMean() < fChargeRelErrLimit*fPINDiode->GetMeanErr())
1507 {
1508 *fLog << warn << GetDescriptor() << ": Fitted Charge is smaller than "
1509 << fChargeRelErrLimit << "* its error in PINDiode " << endl;
1510 return kFALSE;
1511 }
1512
1513 if (fPINDiode->GetSigma() < fPINDiode->GetPedRms())
1514 {
1515 *fLog << warn << GetDescriptor()
1516 << ": Sigma of Fitted Charge smaller than Pedestal RMS in PINDiode " << endl;
1517 return kFALSE;
1518 }
1519
1520
1521 if (!fPINDiode->CalcFluxOutsidePlexiglass())
1522 {
1523 *fLog << warn << "Could not calculate the flux of photons from the PIN Diode, "
1524 << "will skip PIN Diode Calibration " << endl;
1525 return kFALSE;
1526 }
1527
1528 return kTRUE;
1529}
1530
1531// ------------------------------------------------------------------------
1532//
1533// Calculate the average number of photons outside the plexiglass with the
1534// formula:
1535//
1536// av.Num.photons(area index) = av.Num.Phes(area index)
1537// / MCalibrationQEPix::GetDefaultQE(fPulserColor)
1538// / MCalibrationQEPix::GetPMTCollectionEff()
1539// / MCalibrationQEPix::GetLightGuidesEff(fPulserColor)
1540// / MCalibrationQECam::GetPlexiglassQE()
1541//
1542// Calculate the variance on the average number of photons assuming that the error on the
1543// Quantum efficiency is reduced by the number of used inner pixels, but the rest of the
1544// values keeps it ordinary error since it is systematic.
1545//
1546// Loop over pixels:
1547//
1548// - Continue, if not MCalibrationChargePix::IsFFactorMethodValid() and set:
1549// MCalibrationQEPix::SetFFactorMethodValid(kFALSE,fPulserColor)
1550//
1551// - Call MCalibrationChargePix::CalcMeanFFactor(av.Num.photons) and set:
1552// MCalibrationQEPix::SetFFactorMethodValid(kFALSE,fPulserColor) if not succesful
1553//
1554// - Calculate the quantum efficiency with the formula:
1555//
1556// QE = ( Num.Phes / av.Num.photons ) * MGeomCam::GetPixRatio()
1557//
1558// - Set QE in MCalibrationQEPix::SetQEFFactor ( QE, fPulserColor );
1559//
1560// - Set Variance of QE in MCalibrationQEPix::SetQEFFactorVar ( Variance, fPulserColor );
1561// - Set bit MCalibrationQEPix::SetFFactorMethodValid(kTRUE,fPulserColor)
1562//
1563// - Call MCalibrationQEPix::UpdateFFactorMethod()
1564//
1565void MCalibrationChargeCalc::FinalizeFFactorQECam()
1566{
1567
1568 if (fNumInnerFFactorMethodUsed < 2)
1569 {
1570 *fLog << warn << GetDescriptor()
1571 << ": Could not calculate F-Factor Method: Less than 2 inner pixels valid! " << endl;
1572 return;
1573 }
1574
1575 MCalibrationQECam *qecam = fIntensQE
1576 ? (MCalibrationQECam*) fIntensQE->GetCam() : fQECam;
1577 MCalibrationChargeCam *chargecam = fIntensCam
1578 ? (MCalibrationChargeCam*)fIntensCam->GetCam() : fCam;
1579 MBadPixelsCam *badcam = fIntensBad
1580 ? (MBadPixelsCam*) fIntensBad->GetCam() : fBadPixels;
1581
1582 MCalibrationChargePix &avpix = (MCalibrationChargePix&)chargecam->GetAverageArea(0);
1583 MCalibrationQEPix &qepix = (MCalibrationQEPix&) qecam->GetAverageArea(0);
1584
1585 const Float_t avphotons = avpix.GetPheFFactorMethod()
1586 / qepix.GetDefaultQE(fPulserColor)
1587 / qepix.GetPMTCollectionEff()
1588 / qepix.GetLightGuidesEff(fPulserColor)
1589 / qecam->GetPlexiglassQE();
1590
1591 const Float_t avphotrelvar = avpix.GetPheFFactorMethodRelVar()
1592 + qepix.GetDefaultQERelVar(fPulserColor) / fNumInnerFFactorMethodUsed
1593 + qepix.GetPMTCollectionEffRelVar()
1594 + qepix.GetLightGuidesEffRelVar(fPulserColor)
1595 + qecam->GetPlexiglassQERelVar();
1596
1597 const UInt_t nareas = fGeom->GetNumAreas();
1598
1599 //
1600 // Set the results in the MCalibrationChargeCam
1601 //
1602 chargecam->SetNumPhotonsFFactorMethod (avphotons);
1603
1604 if (avphotrelvar > 0.)
1605 chargecam->SetNumPhotonsFFactorMethodErr(TMath::Sqrt( avphotrelvar * avphotons * avphotons));
1606
1607 TArrayF lowlim (nareas);
1608 TArrayF upplim (nareas);
1609 TArrayD avffactorphotons (nareas);
1610 TArrayD avffactorphotvar (nareas);
1611 TArrayI numffactor (nareas);
1612
1613 const UInt_t npixels = fGeom->GetNumPixels();
1614
1615 MHCamera camffactor(*fGeom,"Camffactor","F-Factor in Camera");
1616
1617 for (UInt_t i=0; i<npixels; i++)
1618 {
1619
1620 MCalibrationChargePix &pix = (MCalibrationChargePix&)(*chargecam)[i];
1621 MCalibrationQEPix &qepix = (MCalibrationQEPix&) (*qecam) [i];
1622 MBadPixelsPix &bad = (*badcam) [i];
1623
1624 if (bad.IsUnsuitable(MBadPixelsPix::kUnsuitableRun))
1625 continue;
1626
1627 const Float_t photons = avphotons / fGeom->GetPixRatio(i);
1628 const Float_t qe = pix.GetPheFFactorMethod() / photons ;
1629
1630 const Float_t qerelvar = avphotrelvar + pix.GetPheFFactorMethodRelVar();
1631
1632 qepix.SetQEFFactor ( qe , fPulserColor );
1633 qepix.SetQEFFactorVar ( qerelvar*qe*qe, fPulserColor );
1634 qepix.SetFFactorMethodValid( kTRUE , fPulserColor );
1635
1636 if (!qepix.UpdateFFactorMethod())
1637 *fLog << warn << GetDescriptor()
1638 << ": Cannot update Quantum efficiencies with the F-Factor Method" << endl;
1639
1640 //
1641 // The following pixels are those with deviating sigma, but otherwise OK,
1642 // probably those with stars during the pedestal run, but not the cal. run.
1643 //
1644 if (!pix.CalcMeanFFactor( photons , avphotrelvar ))
1645 {
1646 bad.SetUncalibrated( MBadPixelsPix::kDeviatingFFactor );
1647 if (IsCheckDeviatingBehavior())
1648 bad.SetUnsuitable ( MBadPixelsPix::kUnreliableRun );
1649 continue;
1650 }
1651
1652 const Int_t aidx = (*fGeom)[i].GetAidx();
1653 const Float_t ffactor = pix.GetMeanFFactorFADC2Phot();
1654
1655 camffactor.Fill(i,ffactor);
1656 camffactor.SetUsed(i);
1657
1658 avffactorphotons[aidx] += ffactor;
1659 avffactorphotvar[aidx] += ffactor*ffactor;
1660 numffactor[aidx]++;
1661 }
1662
1663 for (UInt_t i=0; i<nareas; i++)
1664 {
1665
1666 if (numffactor[i] == 0)
1667 {
1668 *fLog << warn << GetDescriptor() << ": No pixels with valid total F-Factor found "
1669 << "in area index: " << i << endl;
1670 continue;
1671 }
1672
1673 avffactorphotvar[i] = (avffactorphotvar[i] - avffactorphotons[i]*avffactorphotons[i]/numffactor[i])
1674 / (numffactor[i]-1.);
1675 avffactorphotons[i] = avffactorphotons[i] / numffactor[i];
1676
1677 if (avffactorphotvar[i] < 0.)
1678 {
1679 *fLog << warn << GetDescriptor() << ": No pixels with valid variance of total F-Factor found "
1680 << "in area index: " << i << endl;
1681 continue;
1682 }
1683
1684 lowlim [i] = 1.1; // Lowest known F-Factor of a PMT
1685 upplim [i] = avffactorphotons[i] + fFFactorErrLimit*TMath::Sqrt(avffactorphotvar[i]);
1686
1687 TArrayI area(1);
1688 area[0] = i;
1689
1690 TH1D *hist = camffactor.ProjectionS(TArrayI(),area,"_py",100);
1691 hist->Fit("gaus","Q");
1692 const Float_t mean = hist->GetFunction("gaus")->GetParameter(1);
1693 const Float_t sigma = hist->GetFunction("gaus")->GetParameter(2);
1694 const Int_t ndf = hist->GetFunction("gaus")->GetNDF();
1695
1696 if (IsDebug())
1697 camffactor.DrawClone();
1698
1699 if (ndf < 2)
1700 {
1701 *fLog << warn << GetDescriptor() << ": Cannot use a Gauss fit to the F-Factor "
1702 << "in the camera with area index: " << i << endl;
1703 *fLog << warn << GetDescriptor() << ": Number of dof.: " << ndf << " is smaller than 2 " << endl;
1704 *fLog << warn << GetDescriptor() << ": Will use the simple mean and rms " << endl;
1705 delete hist;
1706 continue;
1707 }
1708
1709 const Double_t prob = hist->GetFunction("gaus")->GetProb();
1710
1711 if (prob < 0.001)
1712 {
1713 *fLog << warn << GetDescriptor() << ": Cannot use a Gauss fit to the F-Factor "
1714 << "in the camera with area index: " << i << endl;
1715 *fLog << warn << GetDescriptor() << ": Fit probability " << prob
1716 << " is smaller than 0.001 " << endl;
1717 *fLog << warn << GetDescriptor() << ": Will use the simple mean and rms " << endl;
1718 delete hist;
1719 continue;
1720 }
1721
1722 *fLog << inf << GetDescriptor() << ": Mean F-Factor "
1723 << "with area index #" << i << ": "
1724 << Form("%4.2f+-%4.2f",mean,sigma) << endl;
1725
1726 lowlim [i] = 1.1;
1727 upplim [i] = mean + fFFactorErrLimit*sigma;
1728
1729 delete hist;
1730 }
1731
1732 *fLog << endl;
1733
1734 for (UInt_t i=0; i<npixels; i++)
1735 {
1736
1737 MCalibrationChargePix &pix = (MCalibrationChargePix&)(*chargecam)[i];
1738 MBadPixelsPix &bad = (*badcam) [i];
1739
1740 if (bad.IsUnsuitable(MBadPixelsPix::kUnsuitableRun))
1741 continue;
1742
1743 const Float_t ffactor = pix.GetMeanFFactorFADC2Phot();
1744 const Int_t aidx = (*fGeom)[i].GetAidx();
1745
1746 if ( ffactor < lowlim[aidx] || ffactor > upplim[aidx] )
1747 {
1748 *fLog << warn << GetDescriptor() << ": Overall F-Factor "
1749 << Form("%5.2f",ffactor) << " out of range ["
1750 << Form("%5.2f,%5.2f",lowlim[aidx],upplim[aidx]) << "] pixel " << i << endl;
1751
1752 bad.SetUncalibrated( MBadPixelsPix::kDeviatingFFactor );
1753 if (IsCheckDeviatingBehavior())
1754 bad.SetUnsuitable ( MBadPixelsPix::kUnsuitableRun );
1755 }
1756 }
1757
1758 for (UInt_t i=0; i<npixels; i++)
1759 {
1760
1761 MCalibrationChargePix &pix = (MCalibrationChargePix&)(*chargecam)[i];
1762 MCalibrationQEPix &qepix = (MCalibrationQEPix&) (*qecam) [i];
1763 MBadPixelsPix &bad = (*badcam) [i];
1764
1765 if (bad.IsUnsuitable(MBadPixelsPix::kUnsuitableRun))
1766 {
1767 qepix.SetFFactorMethodValid(kFALSE,fPulserColor);
1768 pix.SetFFactorMethodValid(kFALSE);
1769 pix.SetExcluded();
1770 continue;
1771 }
1772 }
1773}
1774
1775
1776// ------------------------------------------------------------------------
1777//
1778// Loop over pixels:
1779//
1780// - Continue, if not MCalibrationBlindPix::IsFluxInsidePlexiglassAvailable() and set:
1781// MCalibrationQEPix::SetBlindPixelMethodValid(kFALSE,fPulserColor)
1782//
1783// - Calculate the quantum efficiency with the formula:
1784//
1785// QE = Num.Phes / MCalibrationBlindPix::GetFluxInsidePlexiglass()
1786// / MGeomPix::GetA() * MCalibrationQECam::GetPlexiglassQE()
1787//
1788// - Set QE in MCalibrationQEPix::SetQEBlindPixel ( QE, fPulserColor );
1789// - Set Variance of QE in MCalibrationQEPix::SetQEBlindPixelVar ( Variance, fPulserColor );
1790// - Set bit MCalibrationQEPix::SetBlindPixelMethodValid(kTRUE,fPulserColor)
1791//
1792// - Call MCalibrationQEPix::UpdateBlindPixelMethod()
1793//
1794void MCalibrationChargeCalc::FinalizeBlindPixelQECam()
1795{
1796
1797
1798 MCalibrationBlindCam *blindcam = fIntensBlind
1799 ? (MCalibrationBlindCam*) fIntensBlind->GetCam(): fBlindCam;
1800 MBadPixelsCam *badcam = fIntensBad
1801 ? (MBadPixelsCam*) fIntensBad->GetCam() : fBadPixels;
1802 MCalibrationQECam *qecam = fIntensQE
1803 ? (MCalibrationQECam*) fIntensQE->GetCam() : fQECam;
1804 MCalibrationChargeCam *chargecam = fIntensCam
1805 ? (MCalibrationChargeCam*)fIntensCam->GetCam() : fCam;
1806
1807 //
1808 // Set the results in the MCalibrationChargeCam
1809 //
1810 if (!blindcam || !(blindcam->IsFluxInsidePlexiglassAvailable()))
1811 {
1812
1813 const Float_t photons = blindcam->GetFluxInsidePlexiglass() * (*fGeom)[0].GetA()
1814 / qecam->GetPlexiglassQE();
1815 chargecam->SetNumPhotonsBlindPixelMethod(photons);
1816
1817 const Float_t photrelvar = blindcam->GetFluxInsidePlexiglassRelVar()
1818 + qecam->GetPlexiglassQERelVar();
1819
1820 if (photrelvar > 0.)
1821 chargecam->SetNumPhotonsBlindPixelMethodErr(TMath::Sqrt( photrelvar * photons * photons));
1822 }
1823
1824 //
1825 // With the knowledge of the overall photon flux, calculate the
1826 // quantum efficiencies after the Blind Pixel and PIN Diode method
1827 //
1828 const UInt_t npixels = fGeom->GetNumPixels();
1829 for (UInt_t i=0; i<npixels; i++)
1830 {
1831
1832 MCalibrationQEPix &qepix = (MCalibrationQEPix&) (*qecam) [i];
1833
1834 if (!blindcam || !(blindcam->IsFluxInsidePlexiglassAvailable()))
1835 {
1836 qepix.SetBlindPixelMethodValid(kFALSE, fPulserColor);
1837 continue;
1838 }
1839
1840 MBadPixelsPix &bad = (*badcam) [i];
1841
1842 if (bad.IsUnsuitable (MBadPixelsPix::kUnsuitableRun))
1843 {
1844 qepix.SetBlindPixelMethodValid(kFALSE, fPulserColor);
1845 continue;
1846 }
1847
1848 MCalibrationChargePix &pix = (MCalibrationChargePix&)(*chargecam)[i];
1849 MGeomPix &geo = (*fGeom) [i];
1850
1851 const Float_t qe = pix.GetPheFFactorMethod()
1852 / blindcam->GetFluxInsidePlexiglass()
1853 / geo.GetA()
1854 * qecam->GetPlexiglassQE();
1855
1856 const Float_t qerelvar = blindcam->GetFluxInsidePlexiglassRelVar()
1857 + qecam->GetPlexiglassQERelVar()
1858 + pix.GetPheFFactorMethodRelVar();
1859
1860 qepix.SetQEBlindPixel ( qe , fPulserColor );
1861 qepix.SetQEBlindPixelVar ( qerelvar*qe*qe, fPulserColor );
1862 qepix.SetBlindPixelMethodValid( kTRUE , fPulserColor );
1863
1864 if (!qepix.UpdateBlindPixelMethod())
1865 *fLog << warn << GetDescriptor()
1866 << ": Cannot update Quantum efficiencies with the Blind Pixel Method" << endl;
1867 }
1868}
1869
1870// ------------------------------------------------------------------------
1871//
1872// Loop over pixels:
1873//
1874// - Continue, if not MCalibrationChargePINDiode::IsFluxOutsidePlexiglassAvailable() and set:
1875// MCalibrationQEPix::SetPINDiodeMethodValid(kFALSE,fPulserColor)
1876//
1877// - Calculate the quantum efficiency with the formula:
1878//
1879// QE = Num.Phes / MCalibrationChargePINDiode::GetFluxOutsidePlexiglass() / MGeomPix::GetA()
1880//
1881// - Set QE in MCalibrationQEPix::SetQEPINDiode ( QE, fPulserColor );
1882// - Set Variance of QE in MCalibrationQEPix::SetQEPINDiodeVar ( Variance, fPulserColor );
1883// - Set bit MCalibrationQEPix::SetPINDiodeMethodValid(kTRUE,fPulserColor)
1884//
1885// - Call MCalibrationQEPix::UpdatePINDiodeMethod()
1886//
1887void MCalibrationChargeCalc::FinalizePINDiodeQECam()
1888{
1889
1890 const UInt_t npixels = fGeom->GetNumPixels();
1891
1892 MCalibrationQECam *qecam = fIntensQE
1893 ? (MCalibrationQECam*) fIntensQE->GetCam() : fQECam;
1894 MCalibrationChargeCam *chargecam = fIntensCam
1895 ? (MCalibrationChargeCam*)fIntensCam->GetCam() : fCam;
1896 MBadPixelsCam *badcam = fIntensBad
1897 ? (MBadPixelsCam*) fIntensBad->GetCam() : fBadPixels;
1898 //
1899 // With the knowledge of the overall photon flux, calculate the
1900 // quantum efficiencies after the PIN Diode method
1901 //
1902 for (UInt_t i=0; i<npixels; i++)
1903 {
1904
1905 MCalibrationQEPix &qepix = (MCalibrationQEPix&) (*qecam) [i];
1906
1907 if (!fPINDiode)
1908 {
1909 qepix.SetPINDiodeMethodValid(kFALSE, fPulserColor);
1910 continue;
1911 }
1912
1913 if (!fPINDiode->IsFluxOutsidePlexiglassAvailable())
1914 {
1915 qepix.SetPINDiodeMethodValid(kFALSE, fPulserColor);
1916 continue;
1917 }
1918
1919 MBadPixelsPix &bad = (*badcam) [i];
1920
1921 if (!bad.IsUnsuitable (MBadPixelsPix::kUnsuitableRun))
1922 {
1923 qepix.SetPINDiodeMethodValid(kFALSE, fPulserColor);
1924 continue;
1925 }
1926
1927 MCalibrationChargePix &pix = (MCalibrationChargePix&)(*chargecam)[i];
1928 MGeomPix &geo = (*fGeom) [i];
1929
1930 const Float_t qe = pix.GetPheFFactorMethod()
1931 / fPINDiode->GetFluxOutsidePlexiglass()
1932 / geo.GetA();
1933
1934 const Float_t qerelvar = fPINDiode->GetFluxOutsidePlexiglassRelVar() + pix.GetPheFFactorMethodRelVar();
1935
1936 qepix.SetQEPINDiode ( qe , fPulserColor );
1937 qepix.SetQEPINDiodeVar ( qerelvar*qe*qe, fPulserColor );
1938 qepix.SetPINDiodeMethodValid( kTRUE , fPulserColor );
1939
1940 if (!qepix.UpdatePINDiodeMethod())
1941 *fLog << warn << GetDescriptor()
1942 << ": Cannot update Quantum efficiencies with the PIN Diode Method" << endl;
1943 }
1944}
1945
1946// ------------------------------------------------------------------------
1947//
1948// Loop over pixels:
1949//
1950// - Call MCalibrationQEPix::UpdateCombinedMethod()
1951//
1952void MCalibrationChargeCalc::FinalizeCombinedQECam()
1953{
1954
1955 const UInt_t npixels = fGeom->GetNumPixels();
1956
1957 MCalibrationQECam *qecam = fIntensQE
1958 ? (MCalibrationQECam*) fIntensQE->GetCam() : fQECam;
1959 MBadPixelsCam *badcam = fIntensBad
1960 ? (MBadPixelsCam*) fIntensBad->GetCam() : fBadPixels;
1961
1962 for (UInt_t i=0; i<npixels; i++)
1963 {
1964
1965 MCalibrationQEPix &qepix = (MCalibrationQEPix&) (*qecam) [i];
1966 MBadPixelsPix &bad = (*badcam) [i];
1967
1968 if (!bad.IsUnsuitable (MBadPixelsPix::kUnsuitableRun))
1969 {
1970 qepix.SetPINDiodeMethodValid(kFALSE, fPulserColor);
1971 continue;
1972 }
1973
1974 qepix.UpdateCombinedMethod();
1975 }
1976}
1977
1978// -----------------------------------------------------------------------------------------------
1979//
1980// - Print out statistics about BadPixels of type UnsuitableType_t
1981// - store numbers of bad pixels of each type in fCam or fIntensCam
1982//
1983void MCalibrationChargeCalc::FinalizeUnsuitablePixels()
1984{
1985
1986 *fLog << inf << endl;
1987 *fLog << GetDescriptor() << ": Charge Calibration status:" << endl;
1988 *fLog << dec << setfill(' ');
1989
1990 const Int_t nareas = fGeom->GetNumAreas();
1991
1992 TArrayI counts(nareas);
1993
1994 MBadPixelsCam *badcam = fIntensBad
1995 ? (MBadPixelsCam*)fIntensBad->GetCam() : fBadPixels;
1996 MCalibrationChargeCam *chargecam = fIntensCam
1997 ? (MCalibrationChargeCam*)fIntensCam->GetCam() : fCam;
1998
1999 for (Int_t i=0; i<badcam->GetSize(); i++)
2000 {
2001 MBadPixelsPix &bad = (*badcam)[i];
2002 if (!bad.IsBad())
2003 {
2004 const Int_t aidx = (*fGeom)[i].GetAidx();
2005 counts[aidx]++;
2006 }
2007 }
2008
2009 if (fGeom->InheritsFrom("MGeomCamMagic"))
2010 *fLog << " " << setw(7) << "Successfully calibrated Pixels: "
2011 << Form("%s%3i%s%3i","Inner: ",counts[0]," Outer: ",counts[1]) << endl;
2012
2013 counts.Reset();
2014
2015 for (Int_t i=0; i<badcam->GetSize(); i++)
2016 {
2017 MBadPixelsPix &bad = (*badcam)[i];
2018
2019 if (bad.IsUnsuitable(MBadPixelsPix::kUnsuitableRun))
2020 {
2021 const Int_t aidx = (*fGeom)[i].GetAidx();
2022 counts[aidx]++;
2023 }
2024 }
2025
2026 for (Int_t aidx=0; aidx<nareas; aidx++)
2027 chargecam->SetNumUnsuitable(counts[aidx], aidx);
2028
2029 if (fGeom->InheritsFrom("MGeomCamMagic"))
2030 *fLog << " " << setw(7) << "Uncalibrated Pixels: "
2031 << Form("%s%3i%s%3i","Inner: ",counts[0]," Outer: ",counts[1]) << endl;
2032
2033 counts.Reset();
2034
2035 for (Int_t i=0; i<badcam->GetSize(); i++)
2036 {
2037
2038 MBadPixelsPix &bad = (*badcam)[i];
2039
2040 if (bad.IsUnsuitable(MBadPixelsPix::kUnreliableRun))
2041 {
2042 const Int_t aidx = (*fGeom)[i].GetAidx();
2043 counts[aidx]++;
2044 }
2045 }
2046
2047 for (Int_t aidx=0; aidx<nareas; aidx++)
2048 chargecam->SetNumUnreliable(counts[aidx], aidx);
2049
2050 *fLog << " " << setw(7) << "Unreliable Pixels: "
2051 << Form("%s%3i%s%3i","Inner: ",counts[0]," Outer: ",counts[1]) << endl;
2052
2053}
2054
2055// -----------------------------------------------------------------------------------------------
2056//
2057// Print out statistics about BadPixels of type UncalibratedType_t
2058//
2059void MCalibrationChargeCalc::PrintUncalibrated(MBadPixelsPix::UncalibratedType_t typ, const char *text) const
2060{
2061
2062 UInt_t countinner = 0;
2063 UInt_t countouter = 0;
2064
2065 MBadPixelsCam *badcam = fIntensBad
2066 ? (MBadPixelsCam*)fIntensBad->GetCam() : fBadPixels;
2067
2068 for (Int_t i=0; i<badcam->GetSize(); i++)
2069 {
2070 MBadPixelsPix &bad = (*badcam)[i];
2071
2072 if (bad.IsUncalibrated(typ))
2073 {
2074 if (fGeom->GetPixRatio(i) == 1.)
2075 countinner++;
2076 else
2077 countouter++;
2078 }
2079 }
2080
2081 *fLog << " " << setw(7) << text
2082 << Form("%s%3i%s%3i","Inner: ",countinner," Outer: ",countouter) << endl;
2083}
2084
2085// --------------------------------------------------------------------------
2086//
2087// Set the path for output file
2088//
2089void MCalibrationChargeCalc::SetOutputPath(TString path)
2090{
2091 fOutputPath = path;
2092 if (fOutputPath.EndsWith("/"))
2093 fOutputPath = fOutputPath(0, fOutputPath.Length()-1);
2094}
2095
2096// --------------------------------------------------------------------------
2097//
2098// Set the output file
2099//
2100void MCalibrationChargeCalc::SetOutputFile(TString file)
2101{
2102 fOutputFile = file;
2103}
2104
2105// --------------------------------------------------------------------------
2106//
2107// Get the output file
2108//
2109const char* MCalibrationChargeCalc::GetOutputFile()
2110{
2111 return Form("%s/%s", (const char*)fOutputPath, (const char*)fOutputFile);
2112}
2113
2114// --------------------------------------------------------------------------
2115//
2116// Read the environment for the following data members:
2117// - fChargeLimit
2118// - fChargeErrLimit
2119// - fChargeRelErrLimit
2120// - fDebug
2121// - fFFactorErrLimit
2122// - fLambdaErrLimit
2123// - fLambdaCheckErrLimit
2124// - fPheErrLimit
2125//
2126Int_t MCalibrationChargeCalc::ReadEnv(const TEnv &env, TString prefix, Bool_t print)
2127{
2128
2129 Bool_t rc = kFALSE;
2130 if (IsEnvDefined(env, prefix, "ChargeLimit", print))
2131 {
2132 SetChargeLimit(GetEnvValue(env, prefix, "ChargeLimit", fChargeLimit));
2133 rc = kTRUE;
2134 }
2135 if (IsEnvDefined(env, prefix, "ChargeErrLimit", print))
2136 {
2137 SetChargeErrLimit(GetEnvValue(env, prefix, "ChargeErrLimit", fChargeErrLimit));
2138 rc = kTRUE;
2139 }
2140 if (IsEnvDefined(env, prefix, "ChargeRelErrLimit", print))
2141 {
2142 SetChargeRelErrLimit(GetEnvValue(env, prefix, "ChargeRelErrLimit", fChargeRelErrLimit));
2143 rc = kTRUE;
2144 }
2145 if (IsEnvDefined(env, prefix, "Debug", print))
2146 {
2147 SetDebug(GetEnvValue(env, prefix, "Debug", IsDebug()));
2148 rc = kTRUE;
2149 }
2150 if (IsEnvDefined(env, prefix, "FFactorErrLimit", print))
2151 {
2152 SetFFactorErrLimit(GetEnvValue(env, prefix, "FFactorErrLimit", fFFactorErrLimit));
2153 rc = kTRUE;
2154 }
2155 if (IsEnvDefined(env, prefix, "LambdaErrLimit", print))
2156 {
2157 SetLambdaErrLimit(GetEnvValue(env, prefix, "LambdaErrLimit", fLambdaErrLimit));
2158 rc = kTRUE;
2159 }
2160 if (IsEnvDefined(env, prefix, "LambdaCheckLimit", print))
2161 {
2162 SetLambdaCheckLimit(GetEnvValue(env, prefix, "LambdaCheckLimit", fLambdaCheckLimit));
2163 rc = kTRUE;
2164 }
2165 if (IsEnvDefined(env, prefix, "PheErrLimit", print))
2166 {
2167 SetPheErrLimit(GetEnvValue(env, prefix, "PheErrLimit", fPheErrLimit));
2168 rc = kTRUE;
2169 }
2170 if (IsEnvDefined(env, prefix, "CheckDeadPixels", print))
2171 {
2172 SetCheckDeadPixels(GetEnvValue(env, prefix, "CheckDeadPixels", IsCheckDeadPixels()));
2173 rc = kTRUE;
2174 }
2175 if (IsEnvDefined(env, prefix, "CheckDeviatingBehavior", print))
2176 {
2177 SetCheckDeviatingBehavior(GetEnvValue(env, prefix, "CheckDeviatingBehavior", IsCheckDeviatingBehavior()));
2178 rc = kTRUE;
2179 }
2180 if (IsEnvDefined(env, prefix, "CheckExtractionWindow", print))
2181 {
2182 SetCheckExtractionWindow(GetEnvValue(env, prefix, "CheckExtractionWindow", IsCheckExtractionWindow()));
2183 rc = kTRUE;
2184 }
2185 if (IsEnvDefined(env, prefix, "CheckHistOverflow", print))
2186 {
2187 SetCheckHistOverflow(GetEnvValue(env, prefix, "CheckHistOverflow", IsCheckHistOverflow()));
2188 rc = kTRUE;
2189 }
2190 if (IsEnvDefined(env, prefix, "CheckOscillations", print))
2191 {
2192 SetCheckOscillations(GetEnvValue(env, prefix, "CheckOscillations", IsCheckOscillations()));
2193 rc = kTRUE;
2194 }
2195
2196 return rc;
2197}
Note: See TracBrowser for help on using the repository browser.