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

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