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

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