/* ======================================================================== *\ ! ! * ! * This file is part of CheObs, the Modular 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 appears 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): Thomas Bretz, 1/2009 ! ! Copyright: CheObs Software Development, 2000-2009 ! ! \* ======================================================================== */ ////////////////////////////////////////////////////////////////////////////// // // MSimCamera // // This task initializes the analog channels with analog noise and simulated // the analog pulses from the photon signal. // // Input Containers: // MPhotonEvent // MPhotonStatistics // MRawRunHeader // // Output Containers: // MAnalogChannels // ////////////////////////////////////////////////////////////////////////////// #include "MSimCamera.h" #include #include #include "MLog.h" #include "MLogManip.h" #include "MSpline3.h" #include "MParSpline.h" #include "MParList.h" #include "MPhotonEvent.h" #include "MPhotonData.h" #include "MPedestalCam.h" #include "MPedestalPix.h" #include "MAnalogSignal.h" #include "MAnalogChannels.h" #include "MMcEvt.hxx" // To be replaced by a CheObs class #include "MRawRunHeader.h" ClassImp(MSimCamera); using namespace std; // -------------------------------------------------------------------------- // // Default Constructor. // MSimCamera::MSimCamera(const char* name, const char *title) : fEvt(0), fStat(0), fRunHeader(0), fElectronicNoise(0), fGain(0), fCamera(0), fMcEvt(0), fSpline(0), fBaselineGain(kFALSE), fDefaultOffset(-1), fDefaultNoise(-1), fDefaultGain(-1) { fName = name ? name : "MSimCamera"; fTitle = title ? title : "Task to simulate the electronic noise and to convert photons into pulses"; } // -------------------------------------------------------------------------- // // Search for the necessayr parameter containers. // Setup spline for pulse shape. // Int_t MSimCamera::PreProcess(MParList *pList) { fMcEvt = (MMcEvt*)pList->FindCreateObj("MMcEvt"); if (!fMcEvt) return kFALSE; fCamera = (MAnalogChannels*)pList->FindCreateObj("MAnalogChannels"); if (!fCamera) return kFALSE; fEvt = (MPhotonEvent*)pList->FindObject("MPhotonEvent"); if (!fEvt) { *fLog << err << "MPhotonEvent not found... aborting." << endl; return kFALSE; } fStat = (MPhotonStatistics*)pList->FindObject("MPhotonStatistics"); if (!fStat) { *fLog << err << "MPhotonStatistics not found... aborting." << endl; return kFALSE; } fRunHeader = (MRawRunHeader *)pList->FindObject("MRawRunHeader"); if (!fRunHeader) { *fLog << err << "MRawRunHeader not found... aborting." << endl; return kFALSE; } /* fPulsePos = (MParameterD*)pList->FindObject("IntendedPulsePos", "MParameterD"); if (!fPulsePos) { *fLog << err << "IntendedPulsePos [MParameterD] not found... aborting." << endl; return kFALSE; } */ // Create it here to make sure that MGeomApply will set the correct size fElectronicNoise = (MPedestalCam*)pList->FindCreateObj("MPedestalCam", "ElectronicNoise"); if (!fElectronicNoise) return kFALSE; fGain = (MPedestalCam*)pList->FindCreateObj("MPedestalCam", "Gain"); if (!fGain) return kFALSE; fAccidentalPhotons = (MPedestalCam*)pList->FindObject("AccidentalPhotonRates","MPedestalCam"); if(!fAccidentalPhotons) { *fLog << err << "AccidentalPhotonRates [MPedestalCam] not found... aborting." << endl; return kFALSE; } MParSpline *pulse = (MParSpline*)pList->FindObject("PulseShape", "MParSpline"); if (!pulse) { *fLog << err << "PulseShape [MParSpline] not found... aborting." << endl; return kFALSE; } if (fRunHeader->GetFreqSampling()!=1000) { *fLog << err << "ERROR - Sampling frequencies others than 1GHz are not yet supported." << endl; *fLog << warn << "FIXME - SCALE MPulsShape WITH THE SAMPLING FREQUENCY." << endl; return kFALSE; } fSpline = pulse->GetSpline(); if (!fSpline) { *fLog << err << "No spline initialized." << endl; return kFALSE; } // ---------------- Information output ---------------------- if (fBaselineGain) *fLog << inf << "Gain is also applied to the electronic noise." << endl; return kTRUE; } // -------------------------------------------------------------------------- // // FIXME: For now this is a workaround to set a baseline and the // electronic (guassian noise) // Bool_t MSimCamera::ReInit(MParList *plist) { for (int i=0; iGetSize(); i++) { MPedestalPix &ped = (*fElectronicNoise)[i]; if (fDefaultOffset>0) ped.SetPedestal(fDefaultOffset); if (fDefaultNoise>0) ped.SetPedestalRms(fDefaultNoise); ped.SetPedestalABoffset(0); ped.SetNumEvents(0); MPedestalPix &gain = (*fGain)[i]; if (fDefaultGain>0) gain.SetPedestal(fDefaultGain); gain.SetPedestalRms(0); gain.SetPedestalABoffset(0); gain.SetNumEvents(0); } return kTRUE; } // -------------------------------------------------------------------------- // // fStat->GetMaxIndex must return the maximum index possible // (equiv. number of pixels) not just the maximum index stored! // Int_t MSimCamera::Process() { // Calculate start time, end time and corresponding number of samples const Double_t freq = fRunHeader->GetFreqSampling()/1000.; // FIXME: Should we use a higher sampling here? const Double_t start = fStat->GetTimeFirst()*freq; const Double_t end = fStat->GetTimeLast() *freq; const UInt_t nlen = TMath::CeilNint(end-start); // Get number of pixels/channels const UInt_t npix = fStat->GetMaxIndex()+1; if (npix>(UInt_t)fElectronicNoise->GetSize()) { *fLog << err << "ERROR - More indices (" << npix << ") "; *fLog << "assigned than existing in camera ("; *fLog << fElectronicNoise->GetSize() << ")!" << endl; return kERROR; } const Double_t pl = fSpline->GetXmin()*freq; const Double_t pr = fSpline->GetXmax()*freq; // Init the arrays and set the range which will contain valid data fCamera->Init(npix, nlen); fCamera->SetValidRange(TMath::FloorNint(pr), TMath::CeilNint(nlen+pl)); // Add electronic noise to empty channels for (UInt_t i=0; iIntegral() * fDefaultGain; // The sampling rate I get from the RunHeader: samplingRate = fRunHeader->GetFreqSampling(); Double_t accouplingPerSlice = accidentalPhotonRate * (1 + crossTalkProb) * areaOfOnePulse / samplingRate; // The accoupling is substracted from the timeline by decreasing the // mean of the gaussian noise which is added if (!fBaselineGain) { (*fCamera)[i].AddGaussianNoise(rms, val - accouplingPerSlice); continue; } // Sorry, the name "pedestal" is misleading here // FIXME: Simulate gain fluctuations const Double_t gain = (*fGain)[i].GetPedestal(); // FIXME: We might add the base line here already. // FIXME: How stable is the offset? // FIXME: Should we write a container AppliedGain for MSImTrigger? (*fCamera)[i].AddGaussianNoise(rms*gain, (val - accouplingPerSlice)*gain); } // FIXME: Simulate correlations with neighboring pixels const Int_t num = fEvt->GetNumPhotons(); // A random shift, uniformely distributed within one slice, to make sure that // the first photon is not always aligned identically with a sample edge. // FIXME: Make it switchable const Float_t rndm = gRandom->Uniform(); // FIXME: Shell we add a random shift of [0,1] samples per channel? // Or maybe per channel and run? Double_t tot = 0; // Simulate pulses for (Int_t i=0; iGetTimeFirst())*freq+rndm;// - fSpline->GetXmin(); // FIXME: Time jitter? // FIXME: Add additional routing here? // FIMXE: How stable is the gain? if (ph.GetPrimary()!=MMcEvt::kNightSky && ph.GetPrimary()!=MMcEvt::kArtificial) tot += ph.GetWeight(); // Sorry, the name "pedestal" is misleading here // FIXME: Simulate gain fluctuations const Double_t gain = (*fGain)[idx].GetPedestal(); // === FIXME === FIXME === FIXME === Frequency!!!! (*fCamera)[idx].AddPulse(*fSpline, t, ph.GetWeight()*gain); } fMcEvt->SetPhotElfromShower(TMath::Nint(tot)); return kTRUE; } // -------------------------------------------------------------------------- // // BaselineGain: Off // Int_t MSimCamera::ReadEnv(const TEnv &env, TString prefix, Bool_t print) { Bool_t rc = kFALSE; if (IsEnvDefined(env, prefix, "BaselineGain", print)) { rc = kTRUE; fBaselineGain = GetEnvValue(env, prefix, "BaselineGain", fBaselineGain); } if (IsEnvDefined(env, prefix, "DefaultOffset", print)) { rc = kTRUE; fDefaultOffset = GetEnvValue(env, prefix, "DefaultOffset", fDefaultOffset); } if (IsEnvDefined(env, prefix, "DefaultNoise", print)) { rc = kTRUE; fDefaultNoise = GetEnvValue(env, prefix, "DefaultNoise", fDefaultNoise); } if (IsEnvDefined(env, prefix, "DefaultGain", print)) { rc = kTRUE; fDefaultGain = GetEnvValue(env, prefix, "DefaultGain", fDefaultGain); } return rc; }