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

Last change on this file since 3849 was 3849, checked in by gaug, 20 years ago
*** empty log message ***
File size: 50.6 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// - FinalizeBlindPixel()
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
189#include "MLog.h"
190#include "MLogManip.h"
191
192#include "MParList.h"
193
194#include "MRawRunHeader.h"
195#include "MRawEvtPixelIter.h"
196
197#include "MGeomCam.h"
198#include "MGeomPix.h"
199
200#include "MPedestalCam.h"
201#include "MPedestalPix.h"
202
203#include "MCalibrationChargeCam.h"
204#include "MCalibrationChargePix.h"
205#include "MCalibrationChargePINDiode.h"
206#include "MCalibrationChargeBlindPix.h"
207
208#include "MExtractedSignalCam.h"
209#include "MExtractedSignalPix.h"
210#include "MExtractedSignalBlindPixel.h"
211#include "MExtractedSignalPINDiode.h"
212
213#include "MBadPixelsCam.h"
214#include "MBadPixelsPix.h"
215
216#include "MCalibrationQECam.h"
217#include "MCalibrationQEPix.h"
218
219#include "MCalibrationCam.h"
220
221ClassImp(MCalibrationChargeCalc);
222
223using namespace std;
224
225const Float_t MCalibrationChargeCalc::fgChargeLimit = 3.;
226const Float_t MCalibrationChargeCalc::fgChargeErrLimit = 0.;
227const Float_t MCalibrationChargeCalc::fgChargeRelErrLimit = 1.;
228const Float_t MCalibrationChargeCalc::fgLambdaErrLimit = 0.2;
229const Float_t MCalibrationChargeCalc::fgLambdaCheckLimit = 0.2;
230const Float_t MCalibrationChargeCalc::fgPheErrLimit = 4.;
231// --------------------------------------------------------------------------
232//
233// Default constructor.
234//
235// Sets all pointers to NULL
236//
237// Calls AddToBranchList for:
238// - MRawEvtData.fHiGainPixId
239// - MRawEvtData.fLoGainPixId
240// - MRawEvtData.fHiGainFadcSamples
241// - MRawEvtData.fLoGainFadcSamples
242//
243// Initializes:
244// - fChargeLimit to fgChargeLimit
245// - fChargeErrLimit to fgChargeErrLimit
246// - fChargeRelErrLimit to fgChargeRelErrLimit
247// - fLambdaCheckLimit to fgLambdaCheckLimit
248// - fLambdaErrLimit to fgLambdaErrLimit
249// - fPheErrLimit to fgPheErrLimit
250// - fPulserColor to MCalibrationCam::kCT1
251//
252// Calls:
253// - Clear()
254//
255MCalibrationChargeCalc::MCalibrationChargeCalc(const char *name, const char *title)
256 : fBadPixels(NULL), fCam(NULL), fBlindPixel(NULL), fPINDiode(NULL),
257 fQECam(NULL), fGeom(NULL), fPedestals(NULL), fEvtTime(NULL)
258 {
259
260 fName = name ? name : "MCalibrationChargeCalc";
261 fTitle = title ? title : "Task to calculate the calibration constants and MCalibrationCam ";
262
263 AddToBranchList("MRawEvtData.fHiGainPixId");
264 AddToBranchList("MRawEvtData.fLoGainPixId");
265 AddToBranchList("MRawEvtData.fHiGainFadcSamples");
266 AddToBranchList("MRawEvtData.fLoGainFadcSamples");
267
268 SetChargeLimit();
269 SetChargeErrLimit();
270 SetChargeRelErrLimit();
271 SetLambdaCheckLimit();
272 SetLambdaErrLimit();
273 SetPheErrLimit();
274 SetPulserColor(MCalibrationCam::kNONE);
275
276 Clear();
277
278}
279
280// --------------------------------------------------------------------------
281//
282// Sets:
283// - all variables to 0.,
284// - all flags to kFALSE
285//
286void MCalibrationChargeCalc::Clear(const Option_t *o)
287{
288
289 fNumHiGainSamples = 0.;
290 fNumLoGainSamples = 0.;
291 fSqrtHiGainSamples = 0.;
292 fSqrtLoGainSamples = 0.;
293 SkipHiLoGainCalibration( kFALSE );
294}
295
296
297// -----------------------------------------------------------------------------------
298//
299// The following container are searched for and execution aborted if not in MParList:
300// - MPedestalCam
301//
302// The following containers are searched and created if they were not found:
303//
304// - MCalibrationQECam
305// - MBadPixelsCam
306//
307// The following output containers are only searched, but not created. If they
308// cannot be found, the corresponding calibration part is only skipped.
309//
310// - MTime
311//
312Int_t MCalibrationChargeCalc::PreProcess(MParList *pList)
313{
314
315 //
316 // Containers that have to be there.
317 //
318 fPedestals = (MPedestalCam*)pList->FindObject("MPedestalCam");
319 if (!fPedestals)
320 {
321 *fLog << err << "MPedestalCam not found... aborting" << endl;
322 return kFALSE;
323 }
324
325 //
326 // Containers that are created in case that they are not there.
327 //
328 fQECam = (MCalibrationQECam*)pList->FindCreateObj("MCalibrationQECam");
329 if (!fQECam)
330 {
331 *fLog << err << "Cannot find nor create MCalibrationQECam... aborting" << endl;
332 return kFALSE;
333 }
334
335 fBadPixels = (MBadPixelsCam*)pList->FindCreateObj("MBadPixelsCam");
336 if (!fBadPixels)
337 {
338 *fLog << err << "Could not find or create MBadPixelsCam ... aborting." << endl;
339 return kFALSE;
340 }
341
342
343 fEvtTime = (MTime*)pList->FindObject("MTime");
344
345 //
346 // Check the pulser colour --> FIXME: this solution is only valid until the arrival of the DM's
347 //
348 if (fPulserColor == MCalibrationCam::kNONE)
349 {
350 *fLog << endl;
351 *fLog << err << GetDescriptor()
352 << ": No Pulser colour has been chosen. Since the installation of the IFAE pulser box,"
353 << " you HAVE to provide the LEDs colour, otherwise there is no calibration. " << endl;
354 *fLog << "See e.g. the macro calibration.C " << endl;
355 return kFALSE;
356 }
357
358 return kTRUE;
359}
360
361
362// --------------------------------------------------------------------------
363//
364// Search for the following input containers and abort if not existing:
365// - MGeomCam
366// - MCalibrationChargeCam
367//
368// Search for the following input containers and give a warning if not existing:
369// - MCalibrationChargeBlindPix
370// - MCalibrationChargePINDiode
371//
372// It retrieves the following variables from MCalibrationChargeCam:
373//
374// - fNumHiGainSamples
375// - fNumLoGainSamples
376//
377// It defines the PixId of every pixel in:
378//
379// - MCalibrationChargeCam
380// - MCalibrationQECam
381//
382// It sets all pixels in excluded which have the flag fBadBixelsPix::IsBad() set in:
383//
384// - MCalibrationChargePix
385// - MCalibrationQEPix
386//
387// Sets the pulser colour and tests if it has not changed w.r.t. fPulserColor in:
388//
389// - MCalibrationChargeCam
390// - MCalibrationChargeBlindPix (if existing)
391// - MCalibrationChargePINDiode (if existing)
392//
393Bool_t MCalibrationChargeCalc::ReInit(MParList *pList )
394{
395
396 fGeom = (MGeomCam*)pList->FindObject("MGeomCam");
397 if (!fGeom)
398 {
399 *fLog << err << "No MGeomCam found... aborting." << endl;
400 return kFALSE;
401 }
402
403 fCam = (MCalibrationChargeCam*)pList->FindObject("MCalibrationChargeCam");
404 if (!fCam)
405 {
406 *fLog << err << "Cannot find MCalibrationChargeCam... aborting" << endl;
407 *fLog << err << "Maybe you forget to call an MFillH for the MHCalibrationChargeCam before..." << endl;
408 return kFALSE;
409 }
410
411 //
412 // Optional Containers
413 //
414 fBlindPixel = (MCalibrationChargeBlindPix*)pList->FindObject("MCalibrationChargeBlindPix");
415 if (!fBlindPixel)
416 *fLog << warn << GetDescriptor()
417 << ": MCalibrationChargeBlindPix not found... no blind pixel method! " << endl;
418
419 fPINDiode = (MCalibrationChargePINDiode*)pList->FindObject("MCalibrationChargePINDiode");
420 if (!fPINDiode)
421 *fLog << warn << GetDescriptor()
422 << "MCalibrationChargePINDiode not found... no PIN Diode method! " << endl;
423
424
425 //
426 // Initialize the pulser colours
427 //
428 if (fCam->GetPulserColor() == MCalibrationCam::kNONE)
429 {
430 fCam->SetPulserColor( fPulserColor );
431
432 if (fBlindPixel)
433 fBlindPixel->SetColor( fPulserColor );
434
435 if (fPINDiode)
436 fPINDiode->SetColor( fPulserColor );
437 }
438
439 if (fPulserColor != fCam->GetPulserColor())
440 {
441 *fLog << err << GetDescriptor()
442 << ": Pulser colour has changed w.r.t. last file in MCalibrationChargeCam" << endl;
443 *fLog << err << "This feature is not yet implemented, sorry ... aborting " << endl;
444 return kFALSE;
445 }
446
447 if (fBlindPixel)
448 if (fPulserColor != fBlindPixel->GetColor())
449 {
450 *fLog << err << GetDescriptor()
451 << ": Pulser colour has changed w.r.t. last file in MCalibrationChargeBlindPix." << endl;
452 *fLog << err << "This feature is not yet implemented, sorry ... aborting " << endl;
453 return kFALSE;
454 }
455
456 if (fPINDiode)
457 if (fPulserColor != fPINDiode->GetColor())
458 {
459 *fLog << err << GetDescriptor()
460 << ": Pulser colour has changed w.r.t. last file in MCalibrationChargePINDiode." << endl;
461 *fLog << err << "This feature is not yet implemented, sorry ... aborting " << endl;
462 return kFALSE;
463 }
464
465
466 fNumHiGainSamples = fCam->GetNumHiGainFADCSlices();
467 fNumLoGainSamples = fCam->GetNumLoGainFADCSlices();
468 fSqrtHiGainSamples = TMath::Sqrt(fNumHiGainSamples);
469 fSqrtLoGainSamples = TMath::Sqrt(fNumLoGainSamples);
470
471 UInt_t npixels = fGeom->GetNumPixels();
472
473 for (UInt_t i=0; i<npixels; i++)
474 {
475
476 MCalibrationChargePix &pix = (MCalibrationChargePix&)(*fCam) [i];
477 MCalibrationQEPix &pqe = (MCalibrationQEPix&) (*fQECam)[i];
478 MBadPixelsPix &bad = (*fBadPixels)[i];
479
480 pix.SetPixId(i);
481 pqe.SetPixId(i);
482
483 if (bad.IsBad())
484 {
485 pix.SetExcluded();
486 pqe.SetExcluded();
487 continue;
488 }
489
490 }
491
492 return kTRUE;
493}
494
495// ----------------------------------------------------------------------------------
496//
497// Nothing to be done in Process, but have a look at MHCalibrationChargeCam, instead
498//
499Int_t MCalibrationChargeCalc::Process()
500{
501 return kTRUE;
502}
503
504// -----------------------------------------------------------------------
505//
506// Return if number of executions is null.
507//
508// First loop over pixels, average areas and sectors, call:
509// - FinalizePedestals()
510// - FinalizeCharges()
511// for every entry. Count number of valid pixels in loop and return kFALSE
512// if there are none (the "Michele check").
513//
514// Call FinalizeBadPixels()
515//
516// Call FinalizeFFactorMethod() (second and third loop over pixels and areas)
517//
518// Call FinalizeBlindPixel()
519// Call FinalizePINDiode()
520//
521// Call FinalizeFFactorQECam() (fourth loop over pixels and areas)
522// Call FinalizeBlindPixelQECam() (fifth loop over pixels and areas)
523// Call FinalizePINDiodeQECam() (sixth loop over pixels and areas)
524//
525// Call MParContainer::SetReadyToSave() for fCam, fQECam, fBadPixels and
526// fBlindPixel and fPINDiode if they exist
527//
528// Print out some statistics
529//
530Int_t MCalibrationChargeCalc::PostProcess()
531{
532
533 if (GetNumExecutions()==0)
534 return kFALSE;
535
536 if (fPINDiode)
537 if (!fPINDiode->IsValid())
538 {
539 *fLog << warn << GetDescriptor()
540 << ": MCalibrationChargePINDiode is declared not valid... no PIN Diode method! " << endl;
541 fPINDiode = NULL;
542 }
543
544 if (fBlindPixel)
545 if (!fBlindPixel->IsValid())
546 {
547 *fLog << warn << GetDescriptor()
548 << ": MCalibrationChargeBlindPix is declared not valid... no Blind Pixel method! " << endl;
549 fBlindPixel = NULL;
550 }
551
552 //
553 // First loop over pixels, call FinalizePedestals and FinalizeCharges
554 //
555 Int_t nvalid = 0;
556
557 for (Int_t pixid=0; pixid<fPedestals->GetSize(); pixid++)
558 {
559
560 MCalibrationChargePix &pix = (MCalibrationChargePix&)(*fCam)[pixid];
561 //
562 // Check if the pixel has been excluded from the fits
563 //
564 if (pix.IsExcluded())
565 continue;
566
567 MPedestalPix &ped = (*fPedestals)[pixid];
568 MBadPixelsPix &bad = (*fBadPixels)[pixid];
569
570 FinalizePedestals(ped,pix);
571
572 if (FinalizeCharges(pix,bad))
573 nvalid++;
574 }
575
576 //
577 // The Michele check ...
578 //
579 if (nvalid == 0)
580 {
581 *fLog << err << GetDescriptor() << ": All pixels have non-valid calibration. "
582 << "Did you forget to fill the histograms "
583 << "(filling MHCalibrationChargeCam from MExtractedSignalCam using MFillH) ? " << endl;
584 *fLog << err << GetDescriptor() << ": Or, maybe, you have used a pedestal run "
585 << "instead of a calibration run " << endl;
586 return kFALSE;
587 }
588
589 for (UInt_t aidx=0; aidx<fGeom->GetNumAreas(); aidx++)
590 {
591
592 const MPedestalPix &ped = fPedestals->GetAverageArea(aidx);
593 MCalibrationChargePix &pix = (MCalibrationChargePix&)fCam->GetAverageArea(aidx);
594
595 FinalizePedestals(ped,pix);
596 FinalizeCharges(pix, fCam->GetAverageBadArea(aidx));
597 }
598
599 for (UInt_t sector=0; sector<fGeom->GetNumSectors(); sector++)
600 {
601
602 const MPedestalPix &ped = fPedestals->GetAverageSector(sector);
603 MCalibrationChargePix &pix = (MCalibrationChargePix&)fCam->GetAverageSector(sector);
604
605 FinalizePedestals(ped,pix);
606 FinalizeCharges(pix, fCam->GetAverageBadSector(sector));
607 }
608
609 //
610 // Finalize Bad Pixels
611 //
612 FinalizeBadPixels();
613
614 //
615 // Finalize F-Factor method
616 //
617 if (!FinalizeFFactorMethod())
618 {
619 *fLog << warn << "Could not calculate the photons flux from the F-Factor method " << endl;
620 fCam->SetFFactorMethodValid(kFALSE);
621 return kFALSE;
622 }
623 else
624 fCam->SetFFactorMethodValid(kTRUE);
625
626 //
627 // Finalize Blind Pixel
628 //
629 if (FinalizeBlindPixel())
630 fQECam->SetBlindPixelMethodValid(kTRUE);
631 else
632 fQECam->SetBlindPixelMethodValid(kFALSE);
633
634 //
635 // Finalize PIN Diode
636 //
637 if (FinalizePINDiode())
638 fQECam->SetPINDiodeMethodValid(kTRUE);
639 else
640 fQECam->SetPINDiodeMethodValid(kFALSE);
641
642 //
643 // Finalize QE Cam
644 //
645 FinalizeFFactorQECam();
646 FinalizeBlindPixelQECam();
647 FinalizePINDiodeQECam();
648
649 //
650 // Finalize calibration statistics
651 //
652 FinalizeUnsuitablePixels();
653
654 fCam ->SetReadyToSave();
655 fQECam ->SetReadyToSave();
656 fBadPixels->SetReadyToSave();
657
658 if (fBlindPixel)
659 fBlindPixel->SetReadyToSave();
660 if (fPINDiode)
661 fPINDiode->SetReadyToSave();
662
663 *fLog << inf << endl;
664 *fLog << GetDescriptor() << ": Errors statistics:" << endl;
665
666 PrintUncalibrated(MBadPixelsPix::kChargeIsPedestal,
667 Form("%s%2.1f%s","Signal less than ",fChargeLimit," Pedestal RMS: "));
668 PrintUncalibrated(MBadPixelsPix::kChargeErrNotValid,
669 Form("%s%2.1f%s","Signal Error smaller than ",fChargeErrLimit,": "));
670 PrintUncalibrated(MBadPixelsPix::kChargeRelErrNotValid,
671 Form("%s%2.1f%s","Signal Error bigger than ",fChargeRelErrLimit," times Mean Signal: "));
672 PrintUncalibrated(MBadPixelsPix::kChargeSigmaNotValid,
673 "Signal Sigma smaller than Pedestal RMS: ");
674 PrintUncalibrated(MBadPixelsPix::kLoGainSaturation,
675 "Pixels with Low Gain Saturation: ");
676 PrintUncalibrated(MBadPixelsPix::kMeanTimeInFirstBin,
677 Form("%s%2.1f%s","Mean Abs. Arr. Time in First ",1.," Bin(s): "));
678 PrintUncalibrated(MBadPixelsPix::kMeanTimeInLast2Bins,
679 Form("%s%2.1f%s","Mean Abs. Arr. Time in Last ",2.," Bin(s): "));
680 PrintUncalibrated(MBadPixelsPix::kHiGainOscillating,
681 "Pixels with changing Hi Gain signal over time: ");
682 PrintUncalibrated(MBadPixelsPix::kLoGainOscillating,
683 "Pixels with changing Lo Gain signal over time: ");
684 PrintUncalibrated(MBadPixelsPix::kDeviatingNumPhes,
685 "Pixels with deviating number of phes: ");
686 PrintUncalibrated(MBadPixelsPix::kHiGainNotFitted,
687 "Pixels with unsuccesful Gauss fit to the Hi Gain: ");
688 PrintUncalibrated(MBadPixelsPix::kLoGainNotFitted,
689 "Pixels with unsuccesful Gauss fit to the Lo Gain: ");
690
691 return kTRUE;
692}
693
694// ----------------------------------------------------------------------------------
695//
696// Retrieves pedestal and pedestal RMS from MPedestalPix
697// Retrieves total entries from MPedestalCam
698// Sets pedestal*fNumHiGainSamples and pedestal*fNumLoGainSamples in MCalibrationChargePix
699// Sets pedRMS *fSqrtHiGainSamples and pedRMS *fSqrtLoGainSamples in MCalibrationChargePix
700//
701// If the flag MCalibrationPix::IsHiGainSaturation() is set, call also:
702// - MCalibrationChargePix::CalcLoGainPedestal()
703//
704void MCalibrationChargeCalc::FinalizePedestals(const MPedestalPix &ped, MCalibrationChargePix &cal)
705{
706
707 //
708 // get the pedestals
709 //
710 const Float_t pedes = ped.GetPedestal();
711 const Float_t prms = ped.GetPedestalRms();
712 const Float_t num = TMath::Sqrt((Float_t)fPedestals->GetTotalEntries());
713
714 //
715 // set them in the calibration camera
716 //
717 if (cal.IsHiGainSaturation())
718 {
719 cal.SetPedestal(pedes* fNumLoGainSamples,
720 prms * fSqrtLoGainSamples,
721 prms * fNumLoGainSamples / num);
722 cal.CalcLoGainPedestal((Float_t)fNumLoGainSamples);
723 }
724 else
725 {
726 cal.SetPedestal(pedes* fNumHiGainSamples,
727 prms * fSqrtHiGainSamples,
728 prms * fNumHiGainSamples / num);
729 }
730
731}
732
733// ----------------------------------------------------------------------------------------------------
734//
735// Check fit results validity. Bad Pixels flags are set if:
736//
737// 1) Pixel has a mean smaller than fChargeLimit*PedRMS ( Flag: MBadPixelsPix::kChargeIsPedestal)
738// 2) Pixel has a mean error smaller than fChargeErrLimit ( Flag: MBadPixelsPix::kChargeErrNotValid)
739// 3) Pixel has mean smaller than fChargeRelVarLimit times its mean error
740// ( Flag: MBadPixelsPix::kChargeRelErrNotValid)
741// 4) Pixel has a sigma bigger than its Pedestal RMS ( Flag: MBadPixelsPix::kChargeSigmaNotValid )
742//
743// Further returns if flags: MBadPixelsPix::kUnsuitableRun is set
744//
745// Calls MCalibrationChargePix::CalcReducedSigma() and sets flag: MBadPixelsPix::kChargeIsPedestal
746// if not succesful.
747//
748// Calls MCalibrationChargePix::CalcFFactorMethod() and sets flag: MBadPixelsPix::kDeviatingNumPhes)
749// if not succesful.
750//
751Bool_t MCalibrationChargeCalc::FinalizeCharges(MCalibrationChargePix &cal, MBadPixelsPix &bad)
752{
753
754 if (cal.GetMean() < fChargeLimit*cal.GetPedRms())
755 {
756 *fLog << warn << GetDescriptor() << ": Fitted Charge: " << cal.GetMean() << " is smaller than "
757 << fChargeLimit << " Pedestal RMS: " << cal.GetPedRms() << " in Pixel " << cal.GetPixId() << endl;
758 bad.SetUncalibrated( MBadPixelsPix::kChargeIsPedestal);
759 }
760
761 if (cal.GetMeanErr() < fChargeErrLimit)
762 {
763 *fLog << warn << GetDescriptor() << ": Error of Fitted Charge: " << cal.GetMeanErr()
764 << " is smaller than " << fChargeErrLimit << " in Pixel " << cal.GetPixId() << endl;
765 bad.SetUncalibrated( MBadPixelsPix::kChargeErrNotValid );
766 }
767
768 if (cal.GetMean() < fChargeRelErrLimit*cal.GetMeanErr())
769 {
770 *fLog << warn << GetDescriptor() << ": Fitted Charge: " << cal.GetMean() << " is smaller than "
771 << fChargeRelErrLimit << "* its error: " << cal.GetMeanErr()
772 << " in Pixel " << cal.GetPixId() << endl;
773 bad.SetUncalibrated( MBadPixelsPix::kChargeRelErrNotValid );
774 }
775
776 if (cal.GetSigma() < cal.GetPedRms())
777 {
778 *fLog << warn << GetDescriptor() << ": Sigma of Fitted Charge: " << cal.GetSigma()
779 << " smaller than Pedestal RMS: " << cal.GetPedRms() << " in Pixel " << cal.GetPixId() << endl;
780 bad.SetUncalibrated( MBadPixelsPix::kChargeSigmaNotValid );
781 }
782
783 if (bad.IsUnsuitable(MBadPixelsPix::kUnsuitableRun))
784 return kFALSE;
785
786 if (!cal.CalcReducedSigma())
787 {
788 *fLog << warn << GetDescriptor()
789 << ": Could not calculate reduced sigmas of pixel: " << cal.GetPixId() << endl;
790 bad.SetUncalibrated(MBadPixelsPix::kChargeIsPedestal);
791 return kFALSE;
792 }
793
794 if (!cal.CalcFFactorMethod())
795 {
796 *fLog << warn << GetDescriptor()
797 << ": Could not calculate F-Factor of pixel: " << cal.GetPixId() << endl;
798 bad.SetUncalibrated(MBadPixelsPix::kDeviatingNumPhes);
799 return kFALSE;
800 }
801
802 return kTRUE;
803}
804
805
806
807// -----------------------------------------------------------------------------------
808//
809// Sets pixel to MBadPixelsPix::kUnsuitableRun, if one of the following flags is set:
810// - MBadPixelsPix::kChargeIsPedestal
811// - MBadPixelsPix::kChargeErrNotValid
812// - MBadPixelsPix::kChargeRelErrNotValid
813// - MBadPixelsPix::kChargeSigmaNotValid
814// - MBadPixelsPix::kMeanTimeInFirstBin
815// - MBadPixelsPix::kMeanTimeInLast2Bins
816// - MBadPixelsPix::kDeviatingNumPhes
817//
818// - Call MCalibrationPix::SetExcluded() for the bad pixels
819//
820void MCalibrationChargeCalc::FinalizeBadPixels()
821{
822
823 for (Int_t i=0; i<fBadPixels->GetSize(); i++)
824 {
825
826 MBadPixelsPix &bad = (*fBadPixels)[i];
827 MCalibrationPix &pix = (*fCam)[i];
828
829 if (bad.IsUncalibrated( MBadPixelsPix::kChargeIsPedestal))
830 bad.SetUnsuitable( MBadPixelsPix::kUnsuitableRun );
831
832 if (bad.IsUncalibrated( MBadPixelsPix::kChargeErrNotValid ))
833 bad.SetUnsuitable( MBadPixelsPix::kUnsuitableRun );
834
835 if (bad.IsUncalibrated( MBadPixelsPix::kChargeRelErrNotValid ))
836 bad.SetUnsuitable( MBadPixelsPix::kUnsuitableRun );
837
838 if (bad.IsUncalibrated( MBadPixelsPix::kChargeSigmaNotValid ))
839 bad.SetUnsuitable( MBadPixelsPix::kUnsuitableRun );
840
841 if (bad.IsUncalibrated( MBadPixelsPix::kMeanTimeInFirstBin ))
842 bad.SetUnsuitable( MBadPixelsPix::kUnsuitableRun );
843
844 if (bad.IsUncalibrated( MBadPixelsPix::kMeanTimeInLast2Bins ))
845 bad.SetUnsuitable( MBadPixelsPix::kUnsuitableRun );
846
847 if (bad.IsUncalibrated( MBadPixelsPix::kDeviatingNumPhes ))
848 bad.SetUnsuitable( MBadPixelsPix::kUnsuitableRun );
849 // bad.SetUnsuitable( MBadPixelsPix::kUnreliableRun );
850
851 if (bad.IsUnsuitable( MBadPixelsPix::kUnsuitableRun ))
852 pix.SetExcluded();
853
854 }
855}
856
857// ------------------------------------------------------------------------
858//
859//
860// First loop: Calculate a mean and mean RMS of photo-electrons per area index
861// Include only pixels which are not MBadPixelsPix::kUnsuitableRun or
862// MBadPixelsPix::kUnreliableRun (see FinalizeBadPixels()) and set
863// MCalibrationChargePix::SetFFactorMethodValid(kFALSE) in that case.
864//
865// Second loop: Get weighted mean number of photo-electrons and its RMS including
866// only pixels with flag MCalibrationChargePix::IsFFactorMethodValid()
867// and further exclude those deviating by more than fPheErrLimit mean
868// sigmas from the mean (obtained in first loop). Set
869// MBadPixelsPix::kDeviatingNumPhes if excluded.
870//
871// Set weighted mean and variance of photo-electrons per area index in:
872// average area pixels of MCalibrationChargeCam (obtained from:
873// MCalibrationChargeCam::GetAverageArea() )
874//
875// Set weighted mean and variance of photo-electrons per sector in:
876// average sector pixels of MCalibrationChargeCam (obtained from:
877// MCalibrationChargeCam::GetAverageSector() )
878//
879Bool_t MCalibrationChargeCalc::FinalizeFFactorMethod()
880{
881
882 const UInt_t npixels = fGeom->GetNumPixels();
883 const UInt_t nareas = fGeom->GetNumAreas();
884 const UInt_t nsectors = fGeom->GetNumSectors();
885
886 Float_t lowlim [nareas];
887 Float_t upplim [nareas];
888 Float_t areavars [nareas];
889 Float_t areaweights [nareas], sectorweights [nsectors];
890 Float_t areaphes [nareas], sectorphes [nsectors];
891 Int_t numareavalid[nareas], numsectorvalid[nsectors];
892
893 memset(lowlim ,0, nareas * sizeof(Float_t));
894 memset(upplim ,0, nareas * sizeof(Float_t));
895 memset(areaphes ,0, nareas * sizeof(Float_t));
896 memset(areavars ,0, nareas * sizeof(Float_t));
897 memset(areaweights ,0, nareas * sizeof(Float_t));
898 memset(numareavalid ,0, nareas * sizeof(Int_t ));
899 memset(sectorweights ,0, nsectors * sizeof(Float_t));
900 memset(sectorphes ,0, nsectors * sizeof(Float_t));
901 memset(numsectorvalid,0, nsectors * sizeof(Int_t ));
902
903 //
904 // First loop: Get mean number of photo-electrons and the RMS
905 // The loop is only to recognize later pixels with very deviating numbers
906 //
907 for (UInt_t i=0; i<npixels; i++)
908 {
909
910 MCalibrationChargePix &pix = (MCalibrationChargePix&)(*fCam) [i];
911 MBadPixelsPix &bad = (*fBadPixels)[i];
912
913 if (!pix.IsFFactorMethodValid())
914 continue;
915
916 if (bad.IsUnsuitable(MBadPixelsPix::kUnsuitableRun))
917 {
918 pix.SetFFactorMethodValid(kFALSE);
919 continue;
920 }
921
922 if (bad.IsUnsuitable(MBadPixelsPix::kUnreliableRun))
923 continue;
924
925 const Float_t nphe = pix.GetPheFFactorMethod();
926 const Float_t nvar = pix.GetPheFFactorMethodVar();
927 const Int_t aidx = (*fGeom)[i].GetAidx();
928
929 if (nvar > 0.)
930 {
931 areaphes [aidx] += nphe;
932 areavars [aidx] += nvar;
933 numareavalid[aidx] ++;
934 }
935 }
936
937 for (UInt_t i=0; i<nareas; i++)
938 {
939 if (numareavalid[i] == 0)
940 {
941 *fLog << warn << GetDescriptor() << ": No pixels with valid number of photo-electrons found "
942 << "in area index: " << i << endl;
943 continue;
944 }
945
946 areaphes[i] = areaphes[i] / numareavalid[i];
947 areavars[i] = areavars[i] / numareavalid[i];
948 lowlim [i] = areaphes[i] - fPheErrLimit*TMath::Sqrt(areavars[i]);
949 upplim [i] = areaphes[i] + fPheErrLimit*TMath::Sqrt(areavars[i]);
950 }
951
952 memset(numareavalid,0,nareas*sizeof(Int_t));
953 memset(areaphes ,0,nareas*sizeof(Int_t));
954 memset(areavars ,0,nareas*sizeof(Int_t));
955
956 //
957 // Second loop: Get weighted mean number of photo-electrons and its RMS excluding
958 // pixels deviating by more than fPheErrLimit sigma.
959 // Set the conversion factor FADC counts to photo-electrons
960 //
961 for (UInt_t i=0; i<npixels; i++)
962 {
963
964 MCalibrationChargePix &pix = (MCalibrationChargePix&)(*fCam)[i];
965
966 if (!pix.IsFFactorMethodValid())
967 continue;
968
969 const Float_t nvar = pix.GetPheFFactorMethodVar();
970
971 if (nvar <= 0.)
972 {
973 pix.SetFFactorMethodValid(kFALSE);
974 continue;
975 }
976
977 MBadPixelsPix &bad = (*fBadPixels)[i];
978
979 const Int_t aidx = (*fGeom)[i].GetAidx();
980 const Int_t sector = (*fGeom)[i].GetSector();
981 const Float_t nphe = pix.GetPheFFactorMethod();
982
983 if ( nphe < lowlim[aidx] || nphe > upplim[aidx] )
984 {
985 *fLog << warn << GetDescriptor() << ": Deviating number of photo-electrons: "
986 << Form("%4.2f",nphe) << " out of accepted limits: ["
987 << Form("%4.2f%s%4.2f",lowlim[aidx],",",upplim[aidx]) << "] in pixel " << i << endl;
988 bad.SetUncalibrated( MBadPixelsPix::kDeviatingNumPhes );
989 bad.SetUnsuitable ( MBadPixelsPix::kUnsuitableRun );
990 pix.SetExcluded();
991 // bad.SetUnsuitable ( MBadPixelsPix::kUnreliableRun );
992 continue;
993 }
994
995 const Float_t weight = 1./nvar;
996
997 areaweights [aidx] += weight;
998 areaphes [aidx] += weight*nphe;
999 numareavalid [aidx] ++;
1000 sectorweights [sector] += weight;
1001 sectorphes [sector] += weight*nphe;
1002 numsectorvalid[sector] ++;
1003 }
1004
1005 for (UInt_t aidx=0; aidx<nareas; aidx++)
1006 {
1007
1008 MCalibrationChargePix &apix = (MCalibrationChargePix&)fCam->GetAverageArea(aidx);
1009
1010 if (areaweights[aidx] <= 0. || areaphes[aidx] <= 0.)
1011 {
1012 *fLog << warn << " Mean number of phe's from area index " << aidx << " cannot be calculated: "
1013 << " Sum of weights: " << areaweights[aidx]
1014 << " Sum of weighted phes: " << areaphes[aidx] << endl;
1015 apix.SetFFactorMethodValid(kFALSE);
1016 continue;
1017 }
1018
1019 *fLog << inf << "Replacing number photo-electrons of average area idx " << aidx << ": "
1020 << Form("%5.3f%s%5.3f",apix.GetPheFFactorMethod()," +- ",apix.GetPheFFactorMethodErr()) << endl;
1021 *fLog << inf << " by average number of photo-electrons from area idx " << aidx << ": "
1022 << Form("%5.3f%s%5.3f",areaphes[aidx] / areaweights[aidx]," +- ",
1023 TMath::Sqrt(1./areaweights[aidx])) << endl;
1024
1025 apix.SetPheFFactorMethod ( areaphes[aidx]/ areaweights[aidx] );
1026 apix.SetPheFFactorMethodVar( 1. / areaweights[aidx] );
1027 apix.SetFFactorMethodValid ( kTRUE );
1028
1029 }
1030
1031 for (UInt_t sector=0; sector<nsectors; sector++)
1032 {
1033
1034 MCalibrationChargePix &spix = (MCalibrationChargePix&)fCam->GetAverageSector(sector);
1035
1036 if (sectorweights[sector] <= 0. || sectorphes[sector] <= 0.)
1037 {
1038 *fLog << warn << " Mean number of phe's from sector " << sector << " cannot be calculated: "
1039 << " Sum of weights: " << sectorweights[sector]
1040 << " Sum of weighted phes: " << sectorphes[sector] << endl;
1041 spix.SetFFactorMethodValid(kFALSE);
1042 continue;
1043 }
1044
1045 *fLog << inf << "Replacing number photo-electrons of average sector " << sector << ": "
1046 << Form("%5.3f%s%5.3f",spix.GetPheFFactorMethod()," +- ",spix.GetPheFFactorMethodErr()) << endl;
1047 *fLog << inf << " by average number photo-electrons from sector " << sector << ": "
1048 << Form("%5.3f%s%5.3f",sectorphes[sector]/ sectorweights[sector]," +- ",
1049 TMath::Sqrt(1./sectorweights[sector])) << endl;
1050
1051 spix.SetPheFFactorMethod ( sectorphes[sector]/ sectorweights[sector] );
1052 spix.SetPheFFactorMethodVar( 1. / sectorweights[sector] );
1053 spix.SetFFactorMethodValid ( kTRUE );
1054
1055 }
1056
1057 return kTRUE;
1058}
1059
1060
1061// ------------------------------------------------------------------------
1062//
1063// Returns kFALSE if pointer to MCalibrationChargeBlindPix is NULL
1064//
1065// The check returns kFALSE if:
1066//
1067// 1) fLambda and fLambdaCheck are separated relatively to each other by more than fLambdaCheckLimit
1068// 2) BlindPixel has an fLambdaErr greater than fLambdaErrLimit
1069//
1070// Calls:
1071// - MCalibrationChargeBlindPix::CalcFluxInsidePlexiglass()
1072//
1073Bool_t MCalibrationChargeCalc::FinalizeBlindPixel()
1074{
1075
1076 if (!fBlindPixel)
1077 return kFALSE;
1078
1079 const Float_t lambda = fBlindPixel->GetLambda();
1080 const Float_t lambdaerr = fBlindPixel->GetLambdaErr();
1081 const Float_t lambdacheck = fBlindPixel->GetLambdaCheck();
1082
1083 if (2.*(lambdacheck-lambda)/(lambdacheck+lambda) < fLambdaCheckLimit)
1084 {
1085 *fLog << warn << GetDescriptor() << ": Lambda and Lambda-Check differ by more than "
1086 << fLambdaCheckLimit << " in the Blind Pixel " << endl;
1087 return kFALSE;
1088 }
1089
1090 if (lambdaerr < fLambdaErrLimit)
1091 {
1092 *fLog << warn << GetDescriptor() << ": Error of Fitted Lambda is greater than "
1093 << fLambdaErrLimit << " in Blind Pixel " << endl;
1094 return kFALSE;
1095 }
1096
1097 if (!fBlindPixel->CalcFluxInsidePlexiglass())
1098 {
1099 *fLog << warn << "Could not calculate the flux of photons from the Blind Pixel, "
1100 << "will skip Blind Pixel Calibration " << endl;
1101 return kFALSE;
1102 }
1103
1104 return kTRUE;
1105}
1106
1107// ------------------------------------------------------------------------
1108//
1109// Returns kFALSE if pointer to MCalibrationChargePINDiode is NULL
1110//
1111// The check returns kFALSE if:
1112//
1113// 1) PINDiode has a fitted charge smaller than fChargeLimit*PedRMS
1114// 2) PINDiode has a fit error smaller than fChargeErrLimit
1115// 3) PINDiode has a fitted charge smaller its fChargeRelErrLimit times its charge error
1116// 4) PINDiode has a charge sigma smaller than its Pedestal RMS
1117//
1118// Calls:
1119// - MCalibrationChargePINDiode::CalcFluxOutsidePlexiglass()
1120//
1121Bool_t MCalibrationChargeCalc::FinalizePINDiode()
1122{
1123
1124 if (!fPINDiode)
1125 return kFALSE;
1126
1127 if (fPINDiode->GetMean() < fChargeLimit*fPINDiode->GetPedRms())
1128 {
1129 *fLog << warn << GetDescriptor() << ": Fitted Charge is smaller than "
1130 << fChargeLimit << " Pedestal RMS in PINDiode " << endl;
1131 return kFALSE;
1132 }
1133
1134 if (fPINDiode->GetMeanErr() < fChargeErrLimit)
1135 {
1136 *fLog << warn << GetDescriptor() << ": Error of Fitted Charge is smaller than "
1137 << fChargeErrLimit << " in PINDiode " << endl;
1138 return kFALSE;
1139 }
1140
1141 if (fPINDiode->GetMean() < fChargeRelErrLimit*fPINDiode->GetMeanErr())
1142 {
1143 *fLog << warn << GetDescriptor() << ": Fitted Charge is smaller than "
1144 << fChargeRelErrLimit << "* its error in PINDiode " << endl;
1145 return kFALSE;
1146 }
1147
1148 if (fPINDiode->GetSigma() < fPINDiode->GetPedRms())
1149 {
1150 *fLog << warn << GetDescriptor()
1151 << ": Sigma of Fitted Charge smaller than Pedestal RMS in PINDiode " << endl;
1152 return kFALSE;
1153 }
1154
1155
1156 if (!fPINDiode->CalcFluxOutsidePlexiglass())
1157 {
1158 *fLog << warn << "Could not calculate the flux of photons from the PIN Diode, "
1159 << "will skip PIN Diode Calibration " << endl;
1160 return kFALSE;
1161 }
1162
1163 return kTRUE;
1164}
1165
1166// ------------------------------------------------------------------------
1167//
1168// Calculate the average number of photons outside the plexiglass with the
1169// formula:
1170//
1171// av.Num.photons(area index) = av.Num.Phes(area index)
1172// / MCalibrationQEPix::GetDefaultQE(fPulserColor)
1173// / MCalibrationQECam::GetPlexiglassQE()
1174//
1175// Calculate the variance on the average number of photons.
1176//
1177// Loop over pixels:
1178//
1179// - Continue, if not MCalibrationChargePix::IsFFactorMethodValid() and set:
1180// MCalibrationQEPix::SetFFactorMethodValid(kFALSE,fPulserColor)
1181//
1182// - Call MCalibrationChargePix::CalcMeanFFactor(av.Num.photons) and set:
1183// MCalibrationQEPix::SetFFactorMethodValid(kFALSE,fPulserColor) if not succesful
1184//
1185// - Calculate the quantum efficiency with the formula:
1186//
1187// QE = ( Num.Phes / av.Num.photons ) * MGeomCam::GetPixRatio()
1188//
1189// - Set QE in MCalibrationQEPix::SetQEFFactor ( QE, fPulserColor );
1190// - Set Variance of QE in MCalibrationQEPix::SetQEFFactorVar ( Variance, fPulserColor );
1191// - Set bit MCalibrationQEPix::SetFFactorMethodValid(kTRUE,fPulserColor)
1192//
1193// - Call MCalibrationQEPix::UpdateFFactorMethod()
1194//
1195void MCalibrationChargeCalc::FinalizeFFactorQECam()
1196{
1197
1198 MCalibrationChargePix &avpix = (MCalibrationChargePix&)fCam->GetAverageArea(0);
1199 MCalibrationQEPix &qepix = (MCalibrationQEPix&) fQECam->GetAverageArea(0);
1200
1201 const Float_t avphotons = avpix.GetPheFFactorMethod()
1202 / qepix.GetQEFFactor(fPulserColor)
1203 / fQECam->GetPlexiglassQE();
1204
1205 const Float_t avphotrelvar = avpix.GetPheFFactorMethodRelVar()
1206 + qepix.GetQEFFactorRelVar(fPulserColor)
1207 + fQECam->GetPlexiglassQERelVar();
1208
1209 const UInt_t npixels = fGeom->GetNumPixels();
1210
1211 for (UInt_t i=0; i<npixels; i++)
1212 {
1213
1214 MCalibrationChargePix &pix = (MCalibrationChargePix&)(*fCam)[i];
1215 MCalibrationQEPix &qepix = (MCalibrationQEPix&) (*fQECam)[i];
1216
1217 if (!pix.IsFFactorMethodValid())
1218 {
1219 qepix.SetFFactorMethodValid(kFALSE,fPulserColor);
1220 continue;
1221 }
1222
1223 const Float_t photons = avphotons / fGeom->GetPixRatio(i);
1224 const Float_t qe = pix.GetPheFFactorMethod() / photons ;
1225
1226 if (!pix.CalcMeanFFactor( photons , avphotrelvar ))
1227 {
1228 pix.SetFFactorMethodValid(kFALSE);
1229 qepix.SetFFactorMethodValid(kFALSE, fPulserColor);
1230 (*fBadPixels)[i].SetUncalibrated( MBadPixelsPix::kDeviatingNumPhes );
1231 }
1232
1233 const Float_t qerelvar = avphotrelvar + pix.GetPheFFactorMethodRelVar();
1234
1235 qepix.SetQEFFactor ( qe , fPulserColor );
1236 qepix.SetQEFFactorVar ( qerelvar*qe*qe, fPulserColor );
1237 qepix.SetFFactorMethodValid( kTRUE , fPulserColor );
1238
1239 if (!qepix.UpdateFFactorMethod())
1240 *fLog << warn << GetDescriptor()
1241 << ": Cannot update Quantum efficiencies with the F-Factor Method" << endl;
1242 }
1243}
1244
1245
1246// ------------------------------------------------------------------------
1247//
1248// Loop over pixels:
1249//
1250// - Continue, if not MCalibrationChargeBlindPix::IsFluxInsidePlexiglassAvailable() and set:
1251// MCalibrationQEPix::SetBlindPixelMethodValid(kFALSE,fPulserColor)
1252//
1253// - Calculate the quantum efficiency with the formula:
1254//
1255// QE = Num.Phes / MCalibrationChargeBlindPix::GetFluxInsidePlexiglass()
1256// / MGeomPix::GetA() * MCalibrationQECam::GetPlexiglassQE()
1257//
1258// - Set QE in MCalibrationQEPix::SetQEBlindPixel ( QE, fPulserColor );
1259// - Set Variance of QE in MCalibrationQEPix::SetQEBlindPixelVar ( Variance, fPulserColor );
1260// - Set bit MCalibrationQEPix::SetBlindPixelMethodValid(kTRUE,fPulserColor)
1261//
1262// - Call MCalibrationQEPix::UpdateBlindPixelMethod()
1263//
1264void MCalibrationChargeCalc::FinalizeBlindPixelQECam()
1265{
1266
1267 const UInt_t npixels = fGeom->GetNumPixels();
1268
1269 //
1270 // With the knowledge of the overall photon flux, calculate the
1271 // quantum efficiencies after the Blind Pixel and PIN Diode method
1272 //
1273 for (UInt_t i=0; i<npixels; i++)
1274 {
1275
1276 MCalibrationQEPix &qepix = (MCalibrationQEPix&) (*fQECam)[i];
1277
1278 if (!fBlindPixel)
1279 {
1280 qepix.SetBlindPixelMethodValid(kFALSE, fPulserColor);
1281 continue;
1282 }
1283
1284 if (!fBlindPixel->IsFluxInsidePlexiglassAvailable())
1285 {
1286 qepix.SetBlindPixelMethodValid(kFALSE, fPulserColor);
1287 continue;
1288 }
1289
1290 MBadPixelsPix &bad = (*fBadPixels)[i];
1291
1292 if (!bad.IsUnsuitable (MBadPixelsPix::kUnsuitableRun))
1293 {
1294 qepix.SetBlindPixelMethodValid(kFALSE, fPulserColor);
1295 continue;
1296 }
1297
1298 MCalibrationChargePix &pix = (MCalibrationChargePix&)(*fCam)[i];
1299 MGeomPix &geo = (*fGeom)[i];
1300
1301 const Float_t qe = pix.GetPheFFactorMethod()
1302 / fBlindPixel->GetFluxInsidePlexiglass()
1303 / geo.GetA()
1304 * fQECam->GetPlexiglassQE();
1305
1306 const Float_t qerelvar = fBlindPixel->GetFluxInsidePlexiglassRelVar()
1307 + fQECam->GetPlexiglassQERelVar()
1308 + pix.GetPheFFactorMethodRelVar();
1309
1310 qepix.SetQEBlindPixel ( qe , fPulserColor );
1311 qepix.SetQEBlindPixelVar ( qerelvar*qe*qe, fPulserColor );
1312 qepix.UpdateBlindPixelMethod();
1313 }
1314}
1315
1316// ------------------------------------------------------------------------
1317//
1318// Loop over pixels:
1319//
1320// - Continue, if not MCalibrationChargePINDiode::IsFluxOutsidePlexiglassAvailable() and set:
1321// MCalibrationQEPix::SetPINDiodeMethodValid(kFALSE,fPulserColor)
1322//
1323// - Calculate the quantum efficiency with the formula:
1324//
1325// QE = Num.Phes / MCalibrationChargePINDiode::GetFluxOutsidePlexiglass() / MGeomPix::GetA()
1326//
1327// - Set QE in MCalibrationQEPix::SetQEPINDiode ( QE, fPulserColor );
1328// - Set Variance of QE in MCalibrationQEPix::SetQEPINDiodeVar ( Variance, fPulserColor );
1329// - Set bit MCalibrationQEPix::SetPINDiodeMethodValid(kTRUE,fPulserColor)
1330//
1331// - Call MCalibrationQEPix::UpdatePINDiodeMethod()
1332//
1333void MCalibrationChargeCalc::FinalizePINDiodeQECam()
1334{
1335
1336 const UInt_t npixels = fGeom->GetNumPixels();
1337
1338 //
1339 // With the knowledge of the overall photon flux, calculate the
1340 // quantum efficiencies after the PIN Diode method
1341 //
1342 for (UInt_t i=0; i<npixels; i++)
1343 {
1344
1345 MCalibrationQEPix &qepix = (MCalibrationQEPix&) (*fQECam)[i];
1346
1347 if (!fPINDiode)
1348 {
1349 qepix.SetPINDiodeMethodValid(kFALSE, fPulserColor);
1350 continue;
1351 }
1352
1353 if (!fPINDiode->IsFluxOutsidePlexiglassAvailable())
1354 {
1355 qepix.SetPINDiodeMethodValid(kFALSE, fPulserColor);
1356 continue;
1357 }
1358
1359 MBadPixelsPix &bad = (*fBadPixels)[i];
1360
1361 if (!bad.IsUnsuitable (MBadPixelsPix::kUnsuitableRun))
1362 {
1363 qepix.SetPINDiodeMethodValid(kFALSE, fPulserColor);
1364 continue;
1365 }
1366
1367 MCalibrationChargePix &pix = (MCalibrationChargePix&)(*fCam)[i];
1368 MGeomPix &geo = (*fGeom)[i];
1369
1370 const Float_t qe = pix.GetPheFFactorMethod()
1371 / fPINDiode->GetFluxOutsidePlexiglass()
1372 / geo.GetA();
1373
1374 const Float_t qerelvar = fPINDiode->GetFluxOutsidePlexiglassRelVar() + pix.GetPheFFactorMethodRelVar();
1375
1376 qepix.SetQEPINDiode ( qe , fPulserColor );
1377 qepix.SetQEPINDiodeVar ( qerelvar*qe*qe, fPulserColor );
1378 qepix.UpdateBlindPixelMethod();
1379 }
1380}
1381
1382// -----------------------------------------------------------------------------------------------
1383//
1384// - Print out statistics about BadPixels of type UnsuitableType_t
1385// - store numbers of bad pixels of each type in fCam
1386//
1387void MCalibrationChargeCalc::FinalizeUnsuitablePixels()
1388{
1389
1390 *fLog << inf << endl;
1391 *fLog << GetDescriptor() << ": Calibration statistics:" << endl;
1392 *fLog << dec << setfill(' ');
1393
1394 const Int_t nareas = fGeom->GetNumAreas();
1395
1396 Int_t counts[nareas];
1397 memset(counts,0,nareas*sizeof(Int_t));
1398
1399 for (Int_t i=0; i<fBadPixels->GetSize(); i++)
1400 {
1401 MBadPixelsPix &bad = (*fBadPixels)[i];
1402 if (!bad.IsBad())
1403 {
1404 const Int_t aidx = (*fGeom)[i].GetAidx();
1405 counts[aidx]++;
1406 }
1407 }
1408
1409 if (fGeom->InheritsFrom("MGeomCamMagic"))
1410 *fLog << " " << setw(7) << "Successfully calibrated Pixels: "
1411 << Form("%s%3i%s%3i","Inner: ",counts[0]," Outer: ",counts[1]) << endl;
1412
1413 memset(counts,0,nareas*sizeof(Int_t));
1414
1415 for (Int_t i=0; i<fBadPixels->GetSize(); i++)
1416 {
1417 MBadPixelsPix &bad = (*fBadPixels)[i];
1418 if (bad.IsUnsuitable(MBadPixelsPix::kUnsuitableRun))
1419 {
1420 const Int_t aidx = (*fGeom)[i].GetAidx();
1421 counts[aidx]++;
1422 }
1423 }
1424
1425 for (Int_t aidx=0; aidx<nareas; aidx++)
1426 fCam->SetNumUncalibrated(counts[aidx], aidx);
1427
1428 if (fGeom->InheritsFrom("MGeomCamMagic"))
1429 *fLog << " " << setw(7) << "Uncalibrated Pixels: "
1430 << Form("%s%3i%s%3i","Inner: ",counts[0]," Outer: ",counts[1]) << endl;
1431
1432 memset(counts,0,nareas*sizeof(Int_t));
1433
1434 for (Int_t i=0; i<fBadPixels->GetSize(); i++)
1435 {
1436 MBadPixelsPix &bad = (*fBadPixels)[i];
1437 if (bad.IsUnsuitable(MBadPixelsPix::kUnreliableRun))
1438 {
1439 const Int_t aidx = (*fGeom)[i].GetAidx();
1440 counts[aidx]++;
1441 }
1442 }
1443
1444 for (Int_t aidx=0; aidx<nareas; aidx++)
1445 fCam->SetNumUnreliable(counts[aidx], aidx);
1446
1447 *fLog << " " << setw(7) << "Unreliable Pixels: "
1448 << Form("%s%3i%s%3i","Inner: ",counts[0]," Outer: ",counts[1]) << endl;
1449
1450}
1451
1452// -----------------------------------------------------------------------------------------------
1453//
1454// Print out statistics about BadPixels of type UncalibratedType_t
1455//
1456void MCalibrationChargeCalc::PrintUncalibrated(MBadPixelsPix::UncalibratedType_t typ, const char *text) const
1457{
1458
1459 UInt_t countinner = 0;
1460 UInt_t countouter = 0;
1461 for (Int_t i=0; i<fBadPixels->GetSize(); i++)
1462 {
1463 MBadPixelsPix &bad = (*fBadPixels)[i];
1464 if (bad.IsUncalibrated(typ))
1465 {
1466 if (fGeom->GetPixRatio(i) == 1.)
1467 countinner++;
1468 else
1469 countouter++;
1470 }
1471 }
1472
1473 *fLog << " " << setw(7) << text
1474 << Form("%s%3i%s%3i","Inner: ",countinner," Outer: ",countouter) << endl;
1475}
1476
Note: See TracBrowser for help on using the repository browser.