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

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