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

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