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

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