/* ======================================================================== *\ ! ! * ! * 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 ! ! \* ======================================================================== */ ////////////////////////////////////////////////////////////////////////////// // // MSimAbsorption // // Task to calculate wavelength or incident angle dependent absorption // // Input Containers: // MPhotonEvent // MCorsikaEvtHeader // MCorsikaRunHeader // // Output Containers: // MPhotonEvent // ////////////////////////////////////////////////////////////////////////////// #include "MSimAbsorption.h" #include #include #include #include "MLog.h" #include "MLogManip.h" #include "MParList.h" #include "MBinning.h" #include "MArrayD.h" #include "MSpline3.h" #include "MCorsikaEvtHeader.h" #include "MCorsikaRunHeader.h" #include "MPhotonEvent.h" #include "MPhotonData.h" ClassImp(MSimAbsorption); using namespace std; // -------------------------------------------------------------------------- // // Default Constructor. // MSimAbsorption::MSimAbsorption(const char* name, const char *title) : fEvt(0), fHeader(0), fSpline(0), fUseTheta(kFALSE) { fName = name ? name : "MSimAbsorption"; fTitle = title ? title : "Task to calculate wavelength dependent absorption"; } // -------------------------------------------------------------------------- // // Calls Clear() // MSimAbsorption::~MSimAbsorption() { Clear(); } // -------------------------------------------------------------------------- // // Delete fSpline and set to 0. // void MSimAbsorption::Clear(Option_t *) { if (fSpline) delete fSpline; fSpline=0; } // -------------------------------------------------------------------------- // // Read a TGraph from a file and return a newly allocated MSpline3. // MSpline3 *MSimAbsorption::ReadSpline(const char *fname) { *fLog << inf << "Reading spline from " << fname << endl; TGraph g(fname); if (g.GetN()==0) { *fLog << err << "ERROR - No data points from " << fname << "." << endl; return 0; } // option: b1/e1 b2/e2 (first second derivative?) // option: valbeg/valend (first second derivative?) return new MSpline3(g); } // -------------------------------------------------------------------------- // // Initializes a spline from min to max with n points with 1. // void MSimAbsorption::InitUnity(UInt_t n, Float_t min, Float_t max) { // Delete the existing spline Clear(); // We need at least two points (the edges) if (n<2) return; // Initialize an array with the x-values const MBinning bins(n-1, min, max); // Initialize an array with all one MArrayD y(n); y.Reset(1); // Set the spline fSpline = new MSpline3(bins.GetEdges(), y.GetArray(), n); } // -------------------------------------------------------------------------- // // Takes the existing fSpline and multiplies it with the given spline. // As x-points the values from fSpline are used. // void MSimAbsorption::Multiply(const TSpline3 &spline) { if (!fSpline) { Clear(); // WARNING WARNING WARNING: This is a very dangerous cast! fSpline = (MSpline3*)spline.Clone(); return; } // Initialize a TGraph with the number of knots from a TSpline TGraph g(fSpline->GetNp()); // Loop over all knots for (int i=0; iGetNp(); i++) { // Get th i-th knot Double_t x, y; fSpline->GetKnot(i, x, y); // Multiply y by the value from the given spline y *= spline.Eval(x); // push the point "back" g.SetPoint(i, x, y); } // Clear the spline and initialize a new one from the updated TGraph Clear(); fSpline = new MSpline3(g); } // -------------------------------------------------------------------------- // // Initializes a TSpline3 with n knots x and y. Call Multiply for it. // void MSimAbsorption::Multiply(UInt_t n, const Double_t *x, const Double_t *y) { const TSpline3 spline("Spline", const_cast(x), const_cast(y), n); Multiply(spline); } // -------------------------------------------------------------------------- // // Read a Spline from a file using ReadSpline. // Call Multiply for it. // void MSimAbsorption::Multiply(const char *fname) { const MSpline3 *spline = ReadSpline(fname); if (!spline) return; fFileName = ""; Multiply(*spline); delete spline; } // -------------------------------------------------------------------------- // // Read a spline from a file and set fSpline accfordingly. // Bool_t MSimAbsorption::ReadFile(const char *fname) { if (fname) fFileName = fname; MSpline3 *spline = ReadSpline(fFileName); if (!spline) return kFALSE; // option: b1/e1 b2/e2 (first second derivative?) // option: valbeg/valend (first second derivative?) Clear(); fSpline = spline; return kTRUE; } // -------------------------------------------------------------------------- // // Search for the needed parameter containers. Read spline from file // calling ReadFile(); // Int_t MSimAbsorption::PreProcess(MParList *pList) { if (fFileName.IsNull()) { *fLog << inf << "No file given... skipping." << endl; return kSKIP; } fEvt = (MPhotonEvent*)pList->FindObject("MPhotonEvent"); if (!fEvt) { *fLog << err << "MPhotonEvent not found... aborting." << endl; return kFALSE; } fHeader = (MCorsikaEvtHeader*)pList->FindObject("MCorsikaEvtHeader"); if (!fHeader) { *fLog << err << "MCorsikaEvtHeader not found... aborting." << endl; return kFALSE; } *fLog << inf << "Using " << (fUseTheta?"Theta":"Wavelength") << " for absorption." << endl; return ReadFile(); } // -------------------------------------------------------------------------- // Bool_t MSimAbsorption::ReInit(MParList *pList) { MCorsikaRunHeader *h = (MCorsikaRunHeader*)pList->FindObject("MCorsikaRunHeader"); if (!h) { *fLog << err << "MCorsikaRunHeader not found... aborting." << endl; return kFALSE; } if (h->GetWavelengthMin()GetXmin()) *fLog << warn << "WARNING - Lower bound of wavelength bandwidth exceeds lower bound of spline." << endl; if (h->GetWavelengthMax()>fSpline->GetXmax()) *fLog << warn << "WARNING - Upper bound of wavelength bandwidth exceeds upper bound of spline." << endl; return kTRUE; } // -------------------------------------------------------------------------- // // Throw all events out of the MPhotonEvent which don't survive. // Depending on fUseTheta either the wavelength or the incident angle // is used. // Int_t MSimAbsorption::Process() { // Get the number of photons in the list const Int_t num = fEvt->GetNumPhotons(); // Counter for number of total and final events Int_t cnt = 0; for (Int_t i=0; iEval(wl); // Get a random value between 0 and 1 to determine whether the photn will survive // gRandom->Rndm() = [0;1[ if (gRandom->Rndm()>=eff) continue; // Copy the surviving events bakc in the list (*fEvt)[cnt++] = ph; } // Now we shrink the array to the number of new entries. fEvt->Shrink(cnt); return kTRUE; } // -------------------------------------------------------------------------- // // FileName: reflectivity.txt // UseTheta: No // Int_t MSimAbsorption::ReadEnv(const TEnv &env, TString prefix, Bool_t print) { Bool_t rc = kFALSE; if (IsEnvDefined(env, prefix, "FileName", print)) { rc = kTRUE; SetFileName(GetEnvValue(env, prefix, "FileName", fFileName)); } if (IsEnvDefined(env, prefix, "UseTheta", print)) { rc = kTRUE; SetUseTheta(GetEnvValue(env, prefix, "UseTheta", fUseTheta)); } return rc; }