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

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