/* ======================================================================== *\ ! ! * ! * This file is part of MARS, the MAGIC Analysis and Reconstruction ! * Software. It is distributed to you in the hope that it can be a useful ! * and timesaving tool in analysing Data of imaging Cerenkov telescopes. ! * It is distributed WITHOUT ANY WARRANTY. ! * ! * Permission to use, copy, modify and distribute this software and its ! * documentation for any purpose is hereby granted without fee, ! * provided that the above copyright notice appear in all copies and ! * that both that copyright notice and this permission notice appear ! * in supporting documentation. It is provided "as is" without express ! * or implied warranty. ! * ! ! ! Author(s): Abelardo Moralejo, 12/2003 ! ! Copyright: MAGIC Software Development, 2000-2003 ! ! \* ======================================================================== */ ///////////////////////////////////////////////////////////////////////////// // // MMcCalibrationUpdate // // This task looks for the ěnformation about FADC pedestals in // MMcFadcHeader and translates it to the pedestal mean and rms (in adc counts). // If not already existing in the parameter list, an MCalibrationCam object // is created, with the conversion factor between photons and ADC counts is // set to 1 to allow the analysis to proceed. // // Then it creates and fills also the MPedPhotCam object containing the pedestal // mean and rms in units of photons. // // Input Containers: // MMcFadcHeader // MRawRunHeader // [MCalibrationChargeCam] (if it existed previously) // [MCalibrationQECam] (if it existed previously) // // Output Containers: // MPedPhotCam // [MCalibrationChargeCam] (if it did not exist previously) // [MCalibrationQECam] (if it did not exist previously) // ///////////////////////////////////////////////////////////////////////////// #include "MMcCalibrationUpdate.h" #include "MParList.h" #include "MLog.h" #include "MLogManip.h" #include "MCalibrationChargePix.h" #include "MCalibrationChargeCam.h" #include "MCalibrationQEPix.h" #include "MCalibrationQECam.h" #include "MExtractedSignalCam.h" #include "MExtractedSignalPix.h" #include "MGeomCam.h" #include "MPedPhotCam.h" #include "MPedPhotPix.h" #include "MRawRunHeader.h" #include "MMcRunHeader.hxx" #include "MMcFadcHeader.hxx" #include "MMcConfigRunHeader.h" ClassImp(MMcCalibrationUpdate); using namespace std; MMcCalibrationUpdate::MMcCalibrationUpdate(const char *name, const char *title) { fName = name ? name : "MMcCalibrationUpdate"; fTitle = title ? title : "Write MC pedestals and conversion factors into MCalibration Container"; fAmplitude = -1.; fAmplitudeOuter = -1.; fConversionHiLo = -1.; fFillCalibrationCam = kTRUE; fOuterPixelsGainScaling = kTRUE; } // -------------------------------------------------------------------------- // // Check for the run type. Return kTRUE if it is a MC run or if there // is no MC run header (old camera files) kFALSE in case of a different // run type // Bool_t MMcCalibrationUpdate::CheckRunType(MParList *pList) const { const MRawRunHeader *run = (MRawRunHeader*)pList->FindObject("MRawRunHeader"); if (!run) { *fLog << warn << dbginf << "Warning - cannot check file type, MRawRunHeader not found." << endl; return kTRUE; } return run->IsMonteCarloRun(); } // -------------------------------------------------------------------------- // // Make sure, that there is an MCalibrationCam Object in the Parameter List. // Int_t MMcCalibrationUpdate::PreProcess(MParList *pList) { fCalCam = (MCalibrationChargeCam*) pList->FindObject(AddSerialNumber("MCalibrationChargeCam")); fQECam = (MCalibrationQECam*) pList->FindObject(AddSerialNumber("MCalibrationQECam")); if (!fCalCam || !fQECam) { fCalCam = (MCalibrationChargeCam*) pList->FindCreateObj(AddSerialNumber("MCalibrationChargeCam")); fQECam = (MCalibrationQECam*) pList->FindCreateObj(AddSerialNumber("MCalibrationQECam")); if (!fCalCam || !fQECam) return kFALSE; } else { fFillCalibrationCam = kFALSE; *fLog << inf << AddSerialNumber("MCalibrationChargeCam") << " and " << AddSerialNumber("MCalibrationQECam") << " already exist... " << endl; } fPedPhotCam = (MPedPhotCam*) pList->FindCreateObj(AddSerialNumber("MPedPhotCam")); if (!fPedPhotCam) return kFALSE; fSignalCam = (MExtractedSignalCam*) pList->FindObject(AddSerialNumber("MExtractedSignalCam")); if (!fSignalCam) { *fLog << err << AddSerialNumber("MExtractedSignalCam") << " not found... aborting." << endl; return kFALSE; } return kTRUE; } // -------------------------------------------------------------------------- // // Check for the runtype. // Search for MGeomCam and MMcFadcHeader. // Fill the MCalibrationCam object. // Bool_t MMcCalibrationUpdate::ReInit(MParList *pList) { // // If it is no MC file skip this function... // if (!CheckRunType(pList)) { *fLog << inf << "This is no MC file... skipping." << endl; return kTRUE; } // // Now check the existence of all necessary containers. // fGeom = (MGeomCam*) pList->FindObject(AddSerialNumber("MGeomCam")); if (!fGeom) { *fLog << err << AddSerialNumber("MGeomCam") << " not found... aborting." << endl; return kFALSE; } fHeaderFadc = (MMcFadcHeader*)pList->FindObject(AddSerialNumber("MMcFadcHeader")); if (!fHeaderFadc) { *fLog << err << AddSerialNumber("MMcFadcHeader") << " not found... aborting." << endl; return kFALSE; } MMcRunHeader* mcrunh = (MMcRunHeader*) pList->FindObject("MMcRunHeader"); // // Initialize Fadc simulation parameters: // if (fAmplitude < 0) { fAmplitude = fHeaderFadc->GetAmplitud(); if (mcrunh->GetCamVersion() > 60) { fAmplitudeOuter = fHeaderFadc->GetAmplitudOuter(); fConversionHiLo = fHeaderFadc->GetLow2HighGain(); } else // old MC files, camera < v0.7 { fAmplitudeOuter = fAmplitude; fConversionHiLo = 10; // dummy value } } else // Check that following files have all the same FADC parameters { if ( fabs(fHeaderFadc->GetAmplitud()-fAmplitude) > 1.e-6 ) { *fLog << err << "Parameters of MMcFadcHeader are not the same for all files... aborting." << endl; return kFALSE; } if (mcrunh->GetCamVersion() > 60) // old MC files, camera < v0.7 { if( fabs(fHeaderFadc->GetAmplitudOuter()-fAmplitudeOuter) > 1.e-6 || fabs(fConversionHiLo-fHeaderFadc->GetLow2HighGain()) > 1.e-6 ) { *fLog << err << "Parameters of MMcFadcHeader are not the same for all files... aborting." << endl; return kFALSE; } } } // // If MCalibrationChargeCam and MCalibrationQECam already existed // in the parameter list before MMcCalibrationUpdate::PreProcess was // executed (from a previous calibration loop) we must not fill it, // hence nothing else has to be done in ReInit: // if (!fFillCalibrationCam) return kTRUE; // Now check the light collection for inner and outer pixels to // calculate the ratio between the two. FIXME! Light collection // depends on the incidence angle of the light w.r.t. the camera // plane. For the moment we take the ratio for light impinging // perpendicular to the camera plane. // // FIXME! We should look for AddSerialNumber("MMcConfigRunHeader") but // for the moment the stereo version of camera does not write one such // header per telescope (it should!) // MMcConfigRunHeader* mcconfig = (MMcConfigRunHeader*) pList->FindObject("MMcConfigRunHeader"); if (!mcconfig) { *fLog << err << "MMcConfigRunHeader" << " not found... aborting." << endl; return kFALSE; } TArrayF innerlightcoll = mcconfig->GetLightCollectionFactor(); TArrayF outerlightcoll = mcconfig->GetLightCollectionFactorOuter(); // In principle outer pixels seem to have a different average light // collection efficiency than outer ones. We set here the factor between // the two. fOuterPixelsLightCollection = outerlightcoll[90] / innerlightcoll[90]; // (at angle = 90 deg) // Set now the default conversion from ADC counts to "photoelectrons" // (in case no previous calibration existed in the parameter list). // As default we want 1 photon = 1 inner pixel ADC count // (this will make Size to be in ADC counts, which is what we want for // the MC calibration loop). To achieve this we set the ADC to // photoelectron conversion equal to the QE, which will later make the // ADC to photon conversion factor (= ADC2PhotEl/QE) to be = 1. // fADC2PhElInner = MCalibrationQEPix::gkDefaultAverageQE; // // Set the default ADC to "photoelectrons" conversion factor for outer // pixels. One can choose not to apply the known (in MC) gain factor // between inner and outer pixels, (in case fOuterPixelsGainScaling = kFALSE), // which may be useful for display purposes. // If on the contrary we apply the factor, we must take into account the // different gains photoelectrons->ADC counts, given in MC by fAmplitude // and fAmplitudeOuter. This "default" calibration is such that a shower // completely contained in the inner part would have Size in ADC counts, // whereas one partially in the outer part would have Size in "equivalent // inner ADC counts" : the "same" shower (light density distribution) would // have the same Size no matter where in the camera it lies. For this we have // also to set later (see below) the right QE for outer pixels, which may // be different from that of inner pixels. // if (fOuterPixelsGainScaling) fADC2PhElOuter = MCalibrationQEPix::gkDefaultAverageQE * (fAmplitude / fAmplitudeOuter); else fADC2PhElOuter = fADC2PhElInner; Int_t num = fCalCam->GetSize(); fCalCam->SetFFactorMethodValid ( kTRUE ); fQECam->SetFFactorMethodValid ( kTRUE ); fQECam->SetBlindPixelMethodValid ( kTRUE ); fQECam->SetCombinedMethodValid ( kTRUE ); fQECam->SetPINDiodeMethodValid ( kTRUE ); for (Int_t i=0; iGetPixRatio(i) < fGeom->GetPixRatio(0))? fADC2PhElOuter : fADC2PhElInner; calpix.SetMeanConvFADC2Phe(adc2photel); calpix.SetMeanConvFADC2PheVar(0.); calpix.SetMeanFFactorFADC2Phot(0.); // Not used for now. } // // Now set the average QE for each type of pixels. Correct outer pixels // for different light collection efficiency. // num = fQECam->GetSize(); for (Int_t i=0; iGetPixRatio(i) < fGeom->GetPixRatio(0)) avqe = MCalibrationQEPix::gkDefaultAverageQE*fOuterPixelsLightCollection; qepix.SetAverageQE(avqe); } return kTRUE; } // -------------------------------------------------------------------------- // // Fill the MCerPhotPed object // Int_t MMcCalibrationUpdate::Process() { const Int_t num = fCalCam->GetSize(); for (Int_t i=0; iGetNumUsedLoGainFADCSlices()*fHeaderFadc->GetPedestal(i) : fSignalCam->GetNumUsedHiGainFADCSlices()*fHeaderFadc->GetPedestal(i); // // In some cases, depending on the camera simulation parameters, one can // have very little or no noise in the FADC. In the case the rms of // pedestal is zero, the pixel will be cleaned out later in the image // cleaning. To avoid this problem,we set a default value of 0.01 ADC // counts for the RMS per slice: // const Double_t used = (Double_t)(sigpix.IsLoGainUsed() ? fSignalCam->GetNumUsedLoGainFADCSlices() : fSignalCam->GetNumUsedHiGainFADCSlices()); const Float_t rms0 = sigpix.IsLoGainUsed() ? fHeaderFadc->GetPedestalRmsLow(i) : fHeaderFadc->GetPedestalRmsHigh(i); const Float_t pedestrms = TMath::Sqrt(used) * (rms0>0 ? rms0 : 0.01); // // Write mean pedestal and pedestal rms per pixel // in number of photons: // MPedPhotPix &pedpix = (*fPedPhotCam)[i]; MCalibrationChargePix &calpix = (MCalibrationChargePix&)(*fCalCam)[i]; MCalibrationQEPix &qepix = (MCalibrationQEPix&)(*fQECam)[i]; qepix.SetAvNormFFactor(1.); // This factor should convert the default average QE to average QE // for a spectrum like that of Cherenkov light. See the documentation // of MCalibrationQEPix. Here it is 1 because we calibrate using // Cherenkov light. Float_t qe = qepix.GetAverageQE(); Float_t adc2phot = calpix.GetMeanConvFADC2Phe() / qe; Float_t hi2lo = calpix.GetConversionHiLo(); if (sigpix.IsLoGainUsed()) pedpix.Set(adc2phot*hi2lo*pedestmean, adc2phot*hi2lo*pedestrms); else pedpix.Set(adc2phot*pedestmean, adc2phot*pedestrms); } return kTRUE; }