source: trunk/MagicSoft/Mars/mhflux/MMcSpectrumWeight.cc@ 7094

Last change on this file since 7094 was 7094, checked in by tbretz, 19 years ago
*** empty log message ***
File size: 11.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): Thomas Bretz 5/2005 <mailto:tbretz@astro.uni-wuerzburg.de>
19! Author(s): Marcos Lopez 10/2003 <mailto:marcos@gae.ucm.es>
20!
21! Copyright: MAGIC Software Development, 2000-2005
22!
23!
24\* ======================================================================== */
25
26//////////////////////////////////////////////////////////////////////////////
27//
28// MMcWeightEnergySlopeCalc
29//
30// Change the spectrum of the MC showers simulated with Corsika (a power law)
31// to a new one, which can be either, again a power law but with a different
32// spectral index, or a generalizeed spectrum. The new spectrum can be
33// pass to this class in different ways:
34//
35// 1. Is the new spectrum will be a power law, just introduce the slope
36// of this power law.
37// 2. Is the new spectrum will have a general shape:
38// The new spectrum is passed as a char* (SetFormula())
39//
40// Method:
41// -------
42//
43// - Corsika spectrun: dN/dE = A * E^(a)
44// with a = fOldSlope, and A = N/integral{E*de} from ELowLim to EUppLim
45//
46// - New spectrum: dN/dE = B * g(E)
47// where B = N/integral{g*dE} from ELowLim to EUppLim, and N=NumEvents
48//
49// For converting the spectrum simulated with Corsika to the new one, we
50// apply a weight to each event, given by:
51//
52// W(E) = B/A * g(E)/E^(a)
53//
54// In the case the new spectrum is simply a power law: dN/dE = B * E^(b), we
55// have:
56//
57// W(E) = B/A * E^(b-a)
58//
59// (The factor B/A is used in order both the original and new spectrum have
60// the same area (i.e. in order they represent the same number of showers))
61//
62//
63// Input Containers:
64// MMcEvt
65// MMcCorsikaRunHeader
66//
67// Output Container:
68// MWeight [MParameterD]
69//
70//////////////////////////////////////////////////////////////////////////////
71#include "MMcSpectrumWeight.h"
72
73#include <TF1.h>
74
75#include "MLog.h"
76#include "MLogManip.h"
77
78#include "MParList.h"
79#include "MParameters.h"
80
81#include "MMcEvt.hxx"
82#include "MMcCorsikaRunHeader.h"
83
84ClassImp(MMcSpectrumWeight);
85
86using namespace std;
87
88void MMcSpectrumWeight::Init(const char *name, const char *title)
89{
90 fName = name ? name : "MMcSpectrumWeight";
91 fTitle = title ? title : "Task to calculate weights to change the energy spectrum";
92
93 AddToBranchList("MMcEvt.fEnergy");
94
95 fNameWeight = "MWeight";
96 fNameMcEvt = "MMcEvt";
97
98 fNewSlope = -1;
99 fOldSlope = -1;
100
101 fEnergyMin = -1;
102 fEnergyMax = -2;
103
104 fNorm = 1;
105
106 fAllowChange = kFALSE;
107
108 fFunc = NULL;
109 fMcEvt = NULL;
110 fWeight = NULL;
111}
112
113// ---------------------------------------------------------------------------
114//
115// Default Constructor.
116//
117MMcSpectrumWeight::MMcSpectrumWeight(const char *name, const char *title)
118{
119 Init(name,title);
120}
121
122// ---------------------------------------------------------------------------
123//
124// Destructor. If necessary delete fFunc
125//
126MMcSpectrumWeight::~MMcSpectrumWeight()
127{
128 if (fFunc)
129 delete fFunc;
130}
131
132// ---------------------------------------------------------------------------
133//
134// Search for
135// - fNameMcEvt [MMcEvtBasic]
136//
137// Find/Create:
138// - fNameWeight [MWeight]
139//
140Int_t MMcSpectrumWeight::PreProcess(MParList *pList)
141{
142 fMcEvt = (MMcEvt*)pList->FindObject(fNameMcEvt, "MMcEvtBasic");
143 if (!fMcEvt)
144 {
145 *fLog << err << fNameMcEvt << " [MMcEvtBasic] not found... abort." << endl;
146 return kFALSE;
147 }
148
149 fWeight = (MParameterD*)pList->FindCreateObj("MParameterD", fNameWeight);
150 if (!fWeight)
151 return kFALSE;
152
153 return kTRUE;
154}
155
156// ---------------------------------------------------------------------------
157//
158// Replace {fNameMcEvt}.fEnergy by "(x)" and return the result.
159//
160TString MMcSpectrumWeight::ReplaceX(TString str) const
161{
162 return str.ReplaceAll(Form("%s.fEnergy", fNameMcEvt.Data()), "(x)");
163}
164
165// ---------------------------------------------------------------------------
166//
167// Return the function corresponding to the mc spectrum with
168// slope fOldSlope: pow({fNameMcEvt}.fEnergy, fOldSlope)
169//
170// The slope is returned as %.3f
171//
172TString MMcSpectrumWeight::GetFormulaSpecOld() const
173{
174 return Form("pow(%s.fEnergy, %.3f)", fNameMcEvt.Data(), fOldSlope);
175}
176
177// ---------------------------------------------------------------------------
178//
179// Return the function corresponding to the new spectrum with
180// slope fNewSlope: pow({fNameMcEvt}.fEnergy, fNewSlope)
181//
182// The slope is returned as %.3f
183//
184// If a different formula is set (SetFormula()) this formula is returned
185// unchanged.
186//
187TString MMcSpectrumWeight::GetFormulaSpecNew() const
188{
189 return fFormula.IsNull() ? Form("pow(%s.fEnergy, %.3f)", fNameMcEvt.Data(), fNewSlope) : fFormula;
190}
191
192// ---------------------------------------------------------------------------
193//
194// Return the formula to calculate weights.
195// Is is compiled by
196// o = integral(fEnergyMin, fEnergyMax, GetFormulaSpecOldX());
197// n = integral(fEnergyMin, fEnergyMax, GetFormulaSpecNewX());
198//
199// result: fNorm*o/n*GetFormulaNewSpec()/GetFormulaOldSpec()
200//
201// fNorm is 1 by default but can be overwritten using SetNorm()
202//
203// If the formulas GetFormulaSpecOldX() and GetFormulaSpecNewX()
204// are equal only fNorm is returned.
205//
206// The normalization constant is returned as %.16f
207//
208// Example: 0.3712780019*(pow(MMcEvt.fEnergy,-2.270))/(pow(MMcEvt.fEnergy,-2.600))
209//
210TString MMcSpectrumWeight::GetFormulaWeights() const
211{
212 if (GetFormulaSpecOld()==GetFormulaSpecNew())
213 return Form("%.16f", fNorm);
214
215 const Double_t iold = GetSpecOldIntegral();
216 const Double_t inew = GetSpecNewIntegral();
217
218 const Double_t norm = fNorm*iold/inew;
219
220 return Form("%.16f*(%s)/(%s)", norm, GetFormulaSpecNew().Data(), GetFormulaSpecOld().Data());
221}
222
223// ---------------------------------------------------------------------------
224//
225// Returns the integral between fEnergyMin and fEnergyMax of
226// GetFormulaSpecNewX() describing the destination spectrum
227//
228Double_t MMcSpectrumWeight::GetSpecNewIntegral() const
229{
230 TF1 funcnew("Dummy", GetFormulaSpecNewX());
231 return funcnew.Integral(fEnergyMin, fEnergyMax);
232}
233
234// ---------------------------------------------------------------------------
235//
236// Returns the integral between fEnergyMin and fEnergyMax of
237// GetFormulaSpecOldX() describing the simulated spectrum
238//
239Double_t MMcSpectrumWeight::GetSpecOldIntegral() const
240{
241 TF1 funcold("Dummy", GetFormulaSpecOldX());
242 return funcold.Integral(fEnergyMin, fEnergyMax);
243}
244
245// ---------------------------------------------------------------------------
246//
247// Initialize fEnergyMin, fEnergymax and fOldSlope from MMcCorsikaRunHeader
248// by GetELowLim(), GetEUppLim() and GetSlopeSpec().
249//
250// If fEnergyMax>fEnergyMin (means: the values have already been
251// initialized) and !fAllowChange the consistency of the new values
252// with the present values is checked with a numerical precision of 1e-10.
253// If one doesn't match kFALSE is returned.
254//
255// If the mc slope is -1 kFALSE is returned.
256//
257// If the new slope for the spectrum is -1 it is set to the original MC
258// slope.
259//
260// fFunc is set to the formula returned by GetFormulaWeightsX()
261//
262Bool_t MMcSpectrumWeight::Set(const MMcCorsikaRunHeader &rh)
263{
264 if (fEnergyMax>fEnergyMin && !fAllowChange)
265 {
266 if (TMath::Abs(fOldSlope-rh.GetSlopeSpec())>1e-10)
267 {
268 *fLog << err;
269 *fLog << "ERROR - The slope of the Monte Carlo is not allowed to change ";
270 *fLog << "(" << fOldSlope << " --> " << rh.GetSlopeSpec() << ")... abort." << endl;
271 return kFALSE;
272 }
273 if (TMath::Abs(fEnergyMin-rh.GetELowLim())>1e-10)
274 {
275 *fLog << err;
276 *fLog << "ERROR - The minimum simulated Monte Carlo energy is not allowed to change ";
277 *fLog << "(" << fEnergyMin << " --> " << rh.GetELowLim() << ")... abort." << endl;
278 return kFALSE;
279 }
280 if (TMath::Abs(fEnergyMax-rh.GetEUppLim())>1e-10)
281 {
282 *fLog << err;
283 *fLog << "ERROR - The maximum simulated Monte Carlo energy is not allowed to change (";
284 *fLog << "(" << fEnergyMax << " --> " << rh.GetEUppLim() << ")... abort." << endl;
285 return kFALSE;
286 }
287 return kTRUE;
288 }
289
290 //
291 // Sanity checks to be sure that we won't divide by zero later on
292 //
293 if (rh.GetSlopeSpec()==-1)
294 {
295 *fLog << err << "The MC Slope of the power law must be different of -1... exit" << endl;
296 return kFALSE;
297 }
298
299 fOldSlope = rh.GetSlopeSpec();
300 fEnergyMin = rh.GetELowLim();
301 fEnergyMax = rh.GetEUppLim();
302
303 if (fNewSlope==-1)
304 {
305 *fLog << inf << "The new slope of the power law is -1... no weighting applied." << endl;
306 fNewSlope = fOldSlope;
307 }
308
309 TString form(GetFormulaWeightsX());
310
311 if (fFunc)
312 delete fFunc;
313
314 fFunc = new TF1("", form);
315 gROOT->GetListOfFunctions()->Remove(fFunc);
316 fFunc->SetName("SpectralWeighs");
317
318 return kTRUE;
319}
320
321// ---------------------------------------------------------------------------
322//
323// The current contants are printed
324//
325void MMcSpectrumWeight::Print(Option_t *o) const
326{
327 *fLog << all << GetDescriptor() << endl;
328 *fLog << " Simulated energy range: " << fEnergyMin << "GeV - " << fEnergyMax << "GeV" << endl;
329 *fLog << " Simulated spectral slope: " << fOldSlope << endl;
330 *fLog << " New slope: " << fNewSlope << endl;
331 *fLog << " User normalization: " << fNorm << endl;
332 *fLog << " Old Spectrum: " << GetFormulaSpecOldX() << " (I=" << GetSpecOldIntegral() << ")" << endl;
333 *fLog << " New Spectrum: " << GetFormulaSpecNewX() << " (I=" << GetSpecNewIntegral() << ")" << endl;
334 if (fFunc)
335 *fLog << " Weight function: " << fFunc->GetTitle() << endl;
336}
337
338// ----------------------------------------------------------------------------
339//
340// Executed each time a new root file is loaded
341// We will need fOldSlope and fE{Upp,Low}Lim to calculate the weights
342//
343Bool_t MMcSpectrumWeight::ReInit(MParList *plist)
344{
345 MMcCorsikaRunHeader *rh = (MMcCorsikaRunHeader*)plist->FindObject("MMcCorsikaRunHeader");
346 if (!rh)
347 {
348 *fLog << err << "MMcCorsikaRunHeader not found... abort." << endl;
349 return kFALSE;
350 }
351
352 return Set(*rh);
353}
354
355// ----------------------------------------------------------------------------
356//
357// Fill the result of the evaluation of fFunc at fEvEvt->GetEnergy
358// into the weights container.
359//
360Int_t MMcSpectrumWeight::Process()
361{
362 const Double_t e = fMcEvt->GetEnergy();
363
364 fWeight->SetVal(fFunc->Eval(e));
365
366 return kTRUE;
367}
368
369// --------------------------------------------------------------------------
370//
371// Read the setup from a TEnv, eg:
372// MMcSpectrumWeight.NewSlope: -2.6
373// MMcSpectrumWeight.Norm: 1.0
374// MMcSpectrumWeight.Formula: pow(MMcEvt.fEnergy, -2.6)
375//
376Int_t MMcSpectrumWeight::ReadEnv(const TEnv &env, TString prefix, Bool_t print)
377{
378 Bool_t rc = kFALSE;
379 if (IsEnvDefined(env, prefix, "NewSlope", print))
380 {
381 rc = kTRUE;
382 SetNewSlope(GetEnvValue(env, prefix, "NewSlope", fNewSlope));
383 }
384 if (IsEnvDefined(env, prefix, "Norm", print))
385 {
386 rc = kTRUE;
387 SetNorm(GetEnvValue(env, prefix, "Norm", fNorm));
388 }
389 if (IsEnvDefined(env, prefix, "Formula", print))
390 {
391 rc = kTRUE;
392 SetFormula(GetEnvValue(env, prefix, "Formula", fFormula));
393 }
394
395 return rc;
396}
Note: See TracBrowser for help on using the repository browser.