source: trunk/MagicSoft/Mars/mmontecarlo/MMcWeightEnergySpecCalc.cc@ 4933

Last change on this file since 4933 was 4835, checked in by tbretz, 20 years ago
*** empty log message ***
File size: 11.1 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): Marcos Lopez 10/2003 <mailto:marcos@gae.ucm.es>
19!
20! Copyright: MAGIC Software Development, 2000-2003
21!
22!
23\* ======================================================================== */
24
25//////////////////////////////////////////////////////////////////////////////
26//
27// MMcWeightEnergySlopeCalc
28//
29// Change the spectrum of the MC showers simulated with Corsika (a power law)
30// to a new one, which can be either, again a power law but with a different
31// spectral index, or a generalizeed spectrum. The new spectrum can be
32// pass to this class in different ways:
33// 1. Is the new spectrum will be a power law, just introduce the slope
34// of this power law.
35// 2. Is the new spectrum will have a general shape, different options are
36// available:
37// a) The new spectrum is pass as a TF1 function
38// b) The new spectrum is pass as a char*
39// c) The new spectrum is pass as a "interpreted function", i.e., a
40// function defined inside a ROOT macro, which will be invoked by the
41// ROOT Cint itself. This is the case when we use ROOT macros.
42// d) The new spectrum is pass as a "real function", i.e., a
43// function defined inside normal c++ file.
44//
45// Method:
46// ------
47//
48// -Corsika spectrun: dN/dE = A * E^(a)
49// with a = fCorsikaSlope, and A = N/integral{E*de} from ELowLim to EUppLim
50//
51// -New spectrum: dN/dE = B * g(E)
52// where B = N/integral{g*dE} from ELowLim to EUppLim, and N=NumEvents
53//
54// For converting the spectrum simulated with Corsika to the new one, we apply
55// a weight to each event, given by:
56//
57// W(E) = B/A * g(E)/E^(a)
58//
59// In the case the new spectrum is simply a power law: dN/dE = B * E^(b), we
60// have:
61//
62// W(E) = B/A * E^(b-a)
63//
64// (The factor B/A is used in order both the original and new spectrum have
65// the same area (i.e. in order they represent the same number of showers))
66//
67// Note:
68// ------
69// -If the the new spectrum is just a power law (i.e. the user only specify
70// the slope), the needed calculations (such as the integral of the
71// spectrum) are done analytically. But if the new spectrum is given as a
72// TF1 object, the calculations is done numerically.
73//
74// ToDo:
75// -----
76// -Give to the user also the possibility to specify the integral of the
77// spectrum as another TF1 object (or C++ function)
78//
79//
80// Input Containers:
81// MMcEvt, MMcRunHeader, MMcCorsikaRunHeader
82//
83// Output Container:
84// MWeight
85//
86//////////////////////////////////////////////////////////////////////////////
87
88#include "MMcWeightEnergySpecCalc.h"
89
90#include "MParList.h"
91#include "MLog.h"
92#include "MLogManip.h"
93#include "MMcEvt.hxx"
94#include "MMcRunHeader.hxx"
95#include "MMcCorsikaRunHeader.h"
96#include "MWeight.h"
97
98#include "TF1.h"
99#include "TGraph.h"
100
101ClassImp(MMcWeightEnergySpecCalc);
102
103using namespace std;
104
105
106
107void MMcWeightEnergySpecCalc::Init(const char *name, const char *title)
108{
109
110 fName = name ? name : "MMcWeightEnergySpecCalc";
111 fTitle = title ? title : "Task to calculate weights to change the energy spectrum";
112
113 AddToBranchList("MMcEvt.fEnergy");
114
115 fAllEvtsTriggered = kFALSE;
116 fTotalNumSimulatedShowers = 0;
117}
118
119
120// ---------------------------------------------------------------------------
121//
122// Constructor. The new spectrum will be just a power law.
123//
124MMcWeightEnergySpecCalc::MMcWeightEnergySpecCalc(Float_t slope,
125 const char *name, const char *title)
126{
127 fNewSpecIsPowLaw = kTRUE;
128 fNewSlope = slope;
129
130 fNewSpectrum = NULL;
131
132 Init(name,title);
133}
134
135// ---------------------------------------------------------------------------
136//
137// Constructor. The new spectrum will have a general shape, given by the user
138// as a TF1 function.
139//
140MMcWeightEnergySpecCalc::MMcWeightEnergySpecCalc(const TF1& spectrum,
141 const char *name, const char *title)
142{
143 fNewSpecIsPowLaw = kFALSE;
144 fNewSpectrum = (TF1*)spectrum.Clone();
145
146 Init(name,title);
147}
148
149// ---------------------------------------------------------------------------
150//
151// As before, but the function which represent the new spectrum is given as
152// a char* . Starting from it, we build a TF1 function
153//
154MMcWeightEnergySpecCalc::MMcWeightEnergySpecCalc(const char* spectrum,
155 const char *name, const char *title)
156{
157 fNewSpecIsPowLaw = kFALSE;
158 fNewSpectrum = new TF1("NewSpectrum",spectrum);
159
160 Init(name,title);
161}
162
163// ---------------------------------------------------------------------------
164//
165// As before, but the new spectrum is given as a intrepreted C++ function.
166// Starting from it we build a TF1 function.
167// This constructor is called for interpreted functions by CINT, i.e., when
168// the functions are declared inside a ROOT macro.
169//
170// NOTE: you muss do a casting to (void*) of the function that you pass to this
171// constructor before invoking it in a macro, e.g.
172//
173// Double_t myfunction(Double_t *x, Double_t *par)
174// {
175// ...
176// }
177//
178// MMcWeightEnergySpecCalc wcalc((void*)myfunction);
179//
180// tasklist.AddToList(&wcalc);
181//
182// otherwise ROOT will invoke the constructor McWeightEnergySpecCalc(
183// const char* spectrum, const char *name, const char *title)
184//
185MMcWeightEnergySpecCalc::MMcWeightEnergySpecCalc(void* function,
186 const char *name, const char *title)
187{
188 fNewSpecIsPowLaw = kFALSE;
189 fNewSpectrum = new TF1("NewSpectrum",function,0,1,1);
190
191 Init(name,title);
192}
193
194// ---------------------------------------------------------------------------
195//
196// As before, but this is the constructor for real functions, i.e. it is called
197// when invoked with the normal C++ compiler, i.e. not inside a ROOT macro.
198//
199MMcWeightEnergySpecCalc::MMcWeightEnergySpecCalc(Double_t (*function)(Double_t*x, Double_t* par), const Int_t npar, const char *name, const char *title)
200{
201 fNewSpecIsPowLaw = kFALSE;
202 fNewSpectrum = new TF1("NewSpectrum",function,0,1,1);
203
204 Init(name,title);
205}
206
207
208
209// ----------------------------------------------------------------------------
210//
211// Destructor. Deletes the cloned fNewSpectrum.
212//
213MMcWeightEnergySpecCalc::~MMcWeightEnergySpecCalc()
214{
215 if (fNewSpectrum)
216 delete fNewSpectrum;
217}
218
219
220
221// ---------------------------------------------------------------------------
222//
223//
224Int_t MMcWeightEnergySpecCalc::PreProcess (MParList *pList)
225{
226
227 fMcEvt = (MMcEvt*)pList->FindObject("MMcEvt");
228 if (!fMcEvt)
229 {
230 *fLog << err << dbginf << "MMcEvt not found... exit." << endl;
231 return kFALSE;
232 }
233
234 fWeight = (MWeight*)pList->FindCreateObj("MWeight");
235 if (!fWeight)
236 {
237 *fLog << err << dbginf << "MWeight not found... exit." << endl;
238 return kFALSE;
239 }
240
241 return kTRUE;
242}
243
244
245
246// ----------------------------------------------------------------------------
247//
248// Executed each time a new root file is loaded
249// We will need fCorsikaSlope and fE{Upp,Low}Lim to calculate the weights
250//
251Bool_t MMcWeightEnergySpecCalc::ReInit(MParList *plist)
252{
253 MMcRunHeader *runheader = (MMcRunHeader*)plist->FindObject("MMcRunHeader");
254 if (!runheader)
255 {
256 *fLog << err << dbginf << "Error - MMcRunHeader not found... exit." << endl;
257 return kFALSE;
258 }
259
260 MMcCorsikaRunHeader *corrunheader = (MMcCorsikaRunHeader*)plist->FindObject("MMcCorsikaRunHeader");
261 if (!corrunheader)
262 {
263 *fLog << err << dbginf << "Error - MMcCorsikaRunHeader not found... exit." << endl;
264 return kFALSE;
265 }
266
267
268 fCorsikaSlope = (Double_t)corrunheader->GetSlopeSpec();
269 fELowLim = (Double_t)corrunheader->GetELowLim();
270 fEUppLim = (Double_t)corrunheader->GetEUppLim();
271
272 fTotalNumSimulatedShowers += runheader->GetNumSimulatedShowers();
273 fAllEvtsTriggered |= runheader->GetAllEvtsTriggered();
274
275
276
277 *fLog << inf << "Slope of primaries' energy spectrum of Simulated showers: " << fCorsikaSlope << endl;
278 *fLog << inf << "Limits of energy range of Simulated showers: "
279 << fELowLim <<" - " << fEUppLim << endl;
280 *fLog << inf << "New Slope for Simulated showers: " << fNewSlope << endl;
281 *fLog << inf << "Total Number of Simulated showers: "
282 << fTotalNumSimulatedShowers << endl;
283 *fLog << inf << "Only triggered events avail: " << (fAllEvtsTriggered?"yes":"no") << endl;
284
285
286
287 //
288 // Sanity checks to be sure that we won't divide by zero later on
289 //
290 if(fCorsikaSlope == -1. || fNewSlope == -1.)
291 {
292 *fLog << err << "The Slope of the power law must be different of -1... exit" << endl;
293 return kFALSE;
294 }
295
296
297 //
298 // Starting from fCorsikaSlope and fE{Upp,Low}Lim, calculate the integrals
299 // of both, the original Corsika spectrum and the new one.
300 //
301 //
302 // For the Corsika simulated spectrum (just a power law), we have:
303 //
304 fCorSpecInt = ( pow(fEUppLim,1+fCorsikaSlope) - pow(fELowLim,1+fCorsikaSlope) ) / ( 1+fCorsikaSlope );
305
306
307 //
308 // For the new spectrum:
309 //
310 if (fNewSpecIsPowLaw) // just the integral of a power law
311 {
312 fNewSpecInt = ( pow(fEUppLim,1+fNewSlope) - pow(fELowLim,1+fNewSlope) )/ ( 1+fNewSlope );
313 }
314 else
315 {
316 fNewSpectrum->SetRange(fELowLim, fEUppLim);
317
318 // In this case we have to integrate the new spectrum numerically. We
319 // could do simply fNewSpectrum->Integral(fELowLim,fEUppLim), but ROOT
320 // fails integrating up to fEUppLim for a sharp cutoff spectrum
321
322 //
323 // Trick to calculate the integral numerically (it works better than
324 // fNewSpectrum->Integral(fELowLim,fEUppLim) (although not perfectlly)
325 //
326 fNewSpectrum->SetNpx(1000);
327 TGraph gr(fNewSpectrum,"i");
328 Int_t Npx = gr.GetN();
329 Double_t* y = gr.GetY();
330
331 const Double_t integral = y[Npx-1];
332 fNewSpecInt = integral;
333 }
334
335
336 return kTRUE;
337}
338
339
340
341// ----------------------------------------------------------------------------
342//
343//
344Int_t MMcWeightEnergySpecCalc::Process()
345{
346 const Double_t energy = fMcEvt->GetEnergy();
347
348 const Double_t C = fCorSpecInt / fNewSpecInt;
349 Double_t weight;
350
351
352 if (fNewSpecIsPowLaw)
353 weight = C * pow(energy,fNewSlope-fCorsikaSlope);
354 else
355 weight = C * fNewSpectrum->Eval(energy) / pow(energy,fCorsikaSlope);
356
357
358 fWeight->SetWeight( weight );
359
360 return kTRUE;
361}
Note: See TracBrowser for help on using the repository browser.