source: trunk/MagicSoft/Mars/mhistmc/MHMcCT1CollectionArea.cc@ 2300

Last change on this file since 2300 was 2273, checked in by tbretz, 22 years ago
*** empty log message ***
File size: 15.7 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): A. Moralejo 3/2003 <mailto:moralejo@pd.infn.it>
19!
20! Copyright: MAGIC Software Development, 2000-2003
21!
22!
23\* ======================================================================== */
24
25//////////////////////////////////////////////////////////////////////////////
26// //
27// MHMcCT1CollectionArea //
28// //
29//////////////////////////////////////////////////////////////////////////////
30
31#include "MHMcCT1CollectionArea.h"
32
33#include <TH2.h>
34#include <TCanvas.h>
35
36#include "MMcEvt.hxx"
37#include "MH.h"
38#include "MBinning.h"
39#include "MParList.h"
40#include "MLog.h"
41#include "MLogManip.h"
42
43ClassImp(MHMcCT1CollectionArea);
44
45using namespace std;
46
47// --------------------------------------------------------------------------
48//
49// Creates the three necessary histograms:
50// - selected showers (input)
51// - all showers (input)
52// - collection area (result)
53//
54MHMcCT1CollectionArea::MHMcCT1CollectionArea(const char *name, const char *title) :
55 fEaxis(kLog10)
56{
57 //
58 // nbins, minEnergy, maxEnergy defaults:
59 // we set the energy range from 100 Gev to 30000 GeV (in log, 3.5 orders
60 // of magnitude) and for each order we take 10 subdivisions --> 35 xbins
61 // we set the theta range from 12.5 to 48 deg, with 6 bins (the latter
62 // choice has been done to make the bin centers as close as possible to
63 // the actual zenith angles in the CT1 MC sample).
64 //
65
66 fName = name ? name : "MHMcCT1CollectionArea";
67 fTitle = title ? title : "Collection Area vs. log10 Energy";
68
69 fHistAll = new TH2D;
70 fHistSel = new TH2D;
71 fHistCol = new TH2D;
72
73 fHistCol->SetName(fName);
74 fHistAll->SetName("AllEvents");
75 fHistSel->SetName("SelectedEvents");
76
77 fHistCol->SetTitle(fTitle);
78 fHistAll->SetTitle("All showers - Theta vs log10 Energy distribution");
79 fHistSel->SetTitle("Selected showers - Theta vs log10 Energy distribution");
80
81 fHistAll->SetDirectory(NULL);
82 fHistSel->SetDirectory(NULL);
83 fHistCol->SetDirectory(NULL);
84
85 fHistAll->SetXTitle("log10(E [GeV])");
86 fHistAll->SetYTitle("\\Theta [\\circ]");
87 fHistAll->SetZTitle("Counts");
88
89 fHistSel->SetXTitle("log10(E [GeV])");
90 fHistSel->SetYTitle("\\Theta [\\circ]");
91 fHistSel->SetZTitle("Counts");
92
93 fHistCol->SetXTitle("log10(E [GeV])");
94 fHistCol->SetYTitle("theta [deg]");
95 fHistCol->SetZTitle("A [m^{2}]");
96
97}
98
99// --------------------------------------------------------------------------
100//
101// Delete the three histograms
102//
103MHMcCT1CollectionArea::~MHMcCT1CollectionArea()
104{
105 delete fHistAll;
106 delete fHistSel;
107 delete fHistCol;
108}
109
110// --------------------------------------------------------------------------
111//
112// Set the binnings and prepare the filling of the histograms
113//
114Bool_t MHMcCT1CollectionArea::SetupFill(const MParList *plist)
115{
116 const MBinning* binsenergy = (MBinning*)plist->FindObject("BinningE");
117 const MBinning* binstheta = (MBinning*)plist->FindObject("BinningTheta");
118
119 if (!binsenergy || !binstheta)
120 {
121 *fLog << err << dbginf << "At least one MBinning not found... aborting.";
122 *fLog << endl;
123 return kFALSE;
124 }
125
126 SetBinning(fHistAll, binsenergy, binstheta);
127 SetBinning(fHistSel, binsenergy, binstheta);
128 SetBinning(fHistCol, binsenergy, binstheta);
129
130 fHistAll->Sumw2();
131 fHistSel->Sumw2();
132 fHistCol->Sumw2();
133
134 if (fEaxis == kLinear)
135 {
136 fTitle = "Collection Area vs. Energy";
137 fHistCol->SetTitle(fTitle);
138 fHistAll->SetTitle("All showers - Theta vs Energy distribution");
139 fHistSel->SetTitle("Selected showers - Theta vs Energy distribution");
140 fHistCol->SetXTitle("E [GeV]");
141 fHistAll->SetXTitle("E [GeV]");
142 fHistSel->SetXTitle("E [GeV]");
143 }
144
145 return kTRUE;
146}
147
148
149// --------------------------------------------------------------------------
150//
151// Fill data into the histogram which contains the selected showers
152//
153Bool_t MHMcCT1CollectionArea::Fill(const MParContainer *par, const Stat_t w)
154{
155 MMcEvt &mcevt = *(MMcEvt*)par;
156
157 const Double_t E = fEaxis==kLinear ? mcevt.GetEnergy() : log10(mcevt.GetEnergy());
158
159 fHistSel->Fill(E, kRad2Deg*mcevt.GetTelescopeTheta(), w);
160
161 return kTRUE;
162}
163
164// --------------------------------------------------------------------------
165//
166// Draw the histogram with all showers
167//
168void MHMcCT1CollectionArea::DrawAll(Option_t* option)
169{
170 if (!gPad)
171 MH::MakeDefCanvas(fHistAll);
172
173 fHistAll->Draw(option);
174
175 gPad->Modified();
176 gPad->Update();
177}
178
179// --------------------------------------------------------------------------
180//
181// Draw the histogram with the selected showers only.
182//
183void MHMcCT1CollectionArea::DrawSel(Option_t* option)
184{
185 if (!gPad)
186 MH::MakeDefCanvas(fHistSel);
187
188 fHistSel->Draw(option);
189
190 gPad->Modified();
191 gPad->Update();
192}
193
194// --------------------------------------------------------------------------
195//
196// Creates a new canvas and draws the histogram into it.
197// Be careful: The histogram belongs to this object and won't get deleted
198// together with the canvas.
199//
200TObject *MHMcCT1CollectionArea::DrawClone(Option_t* option) const
201{
202 TCanvas &c = *MakeDefCanvas("CollArea", "Collection area plots", 600, 600);
203 c.Divide(2,2);
204
205 //
206 // This is necessary to get the expected behaviour of DrawClone
207 //
208 gROOT->SetSelectedPad(NULL);
209
210 c.cd(1);
211 if (fEaxis == kLinear)
212 gPad->SetLogx();
213 fHistCol->SetDirectory(NULL);
214 fHistCol->DrawCopy(option);
215
216 c.cd(2);
217 if (fEaxis == kLinear)
218 gPad->SetLogx();
219 fHistSel->SetDirectory(NULL);
220 fHistSel->DrawCopy(option);
221
222 c.cd(3);
223 if (fEaxis == kLinear)
224 gPad->SetLogx();
225 fHistAll->SetDirectory(NULL);
226 fHistAll->DrawCopy(option);
227
228
229 c.Modified();
230 c.Update();
231
232 return &c;
233}
234
235void MHMcCT1CollectionArea::Draw(Option_t* option)
236{
237 if (!gPad)
238 MH::MakeDefCanvas(fHistCol);
239
240 fHistCol->Draw(option);
241
242 gPad->Modified();
243 gPad->Update();
244}
245
246//
247// Calculate the Efficiency (collection area) for the CT1 MC sample
248// and set the 'ReadyToSave' flag
249//
250void MHMcCT1CollectionArea::CalcEfficiency()
251{
252 //
253 // Here we estimate the total number of showers in each energy bin
254 // from the known the energy range and spectral index of the generated
255 // showers. This procedure is intended for the CT1 MC files. The total
256 // number of generated events, collection area, spectral index etc will be
257 // set here by hand, so make sure that the MC sample you are using is the
258 // right one (check all these quantities in your files and compare with
259 // what is written below. In some theta bins, there are two different
260 // productions, with different energy limits but with the same spectral
261 // slope. We account for this when calculating the original number of
262 // events in each energy bin.
263 //
264 // The theta angle with which the MC data (from D. Kranich) were produced
265 // is not exactly the center of the theta bins we are using (the bin limits
266 // should be 0.0, 17.5, 23.5, 29.5, 35.5, 42., 50.). The theta variable in
267 // the MC root file has nevertheless been changed (W.Wittek) to correspond
268 // to the centers of these bins. Only in the first bin is the difference big:
269 // the data were produced at theta = 15 degrees, whreas the bin center is at
270 // 8.75 degrees. Howeverm at such low z.a. the shower characteristics change
271 // very slowly with theta.
272 //
273 //
274 //
275 // Only for the binning taken from D. Kranich :
276 //
277
278 for (Int_t thetabin = 1; thetabin <= fHistAll->GetNbinsY(); thetabin++)
279 {
280 // This theta is not exactly the one of the MC events, just about
281 // the same (bins have been selected so):
282
283 Float_t theta = fHistAll->GetYaxis()->GetBinCenter(thetabin);
284
285 Float_t emin[4]; // Minimum energy in MC sample
286 Float_t emax[4]; // Maximum energy in MC sample
287 Float_t index[4]; // Spectral index
288 Float_t numevts[4]; // Number of events
289 Float_t multfactor[4]; // Factor by which the original number of events in an MC
290 // sample has been multiplied to account for the differences
291 // in the generation areas of the various samples.
292 Float_t rmax; // Maximum impact parameter range (on ground up to 45 degrees,
293 // on a plane perpendicular to Shower axis for 55 and 65 deg).
294
295 memset(emin, 0, 4*sizeof(Float_t));
296 memset(emax, 0, 4*sizeof(Float_t));
297 memset(index, 0, 4*sizeof(Float_t));
298 memset(numevts, 0, 4*sizeof(Float_t));
299 rmax = 0.;
300
301 multfactor[0] = 1.;
302 multfactor[1] = 1.;
303 multfactor[2] = 1.;
304 multfactor[3] = 1.;
305
306 //
307 // rmin and rmax are the minimum and maximum values of the impact
308 // parameter of the shower on the ground (horizontal plane).
309 //
310
311 Int_t num_MC_samples = 0;
312
313 if (theta > 8 && theta < 9) // 8.75 deg
314 {
315 emin[0] = 300.;
316 emax[0] = 400.; // Energies in GeV.
317 index[0] = 1.5;
318 numevts[0] = 4000.;
319
320 emin[1] = 400.;
321 emax[1] = 30000.;
322 index[1] = 1.5;
323 numevts[1] = 25740.;
324
325 rmax = 250.; //meters
326 num_MC_samples = 2;
327 }
328 else if (theta > 20 && theta < 21) // 20.5 deg
329 {
330 emin[0] = 300.;
331 emax[0] = 400.; // Energies in GeV.
332 index[0] = 1.5;
333 numevts[0] = 6611.;
334
335 emin[1] = 400.;
336 emax[1] = 30000.;
337 index[1] = 1.5;
338 numevts[1] = 24448.;
339
340 rmax = 263.;
341 num_MC_samples = 2;
342 }
343 else if (theta > 26 && theta < 27) // 26.5 degrees
344 {
345 emin[0] = 300.;
346 emax[0] = 400.; // Energies in GeV.
347 index[0] = 1.5;
348 numevts[0] = 4000.;
349
350 emin[1] = 400.;
351 emax[1] = 30000.;
352 index[1] = 1.5;
353 numevts[1] = 26316.;
354
355 rmax = 290.; //meters
356 num_MC_samples = 2;
357 }
358 else if (theta > 32 && theta < 33) // 32.5 degrees
359 {
360 emin[0] = 300.;
361 emax[0] = 30000.; // Energies in GeV.
362 index[0] = 1.5;
363 numevts[0] = 33646.;
364
365 rmax = 350.; //meters
366 num_MC_samples = 1;
367 }
368 else if (theta > 38 && theta < 39) // 38.75 degrees
369 {
370 emin[0] = 300.;
371 emax[0] = 30000.; // Energies in GeV.
372 index[0] = 1.5;
373 numevts[0] = 38415.;
374
375 rmax = 380.; //meters
376 num_MC_samples = 1;
377 }
378 else if (theta > 45 && theta < 47) // 46 degrees
379 {
380 emin[0] = 300.;
381 emax[0] = 50000.; // Energies in GeV.
382 index[0] = 1.5;
383 numevts[0] = 30197.;
384
385 rmax = 565.; //meters
386 num_MC_samples = 1;
387 }
388 else if (theta > 54 && theta < 56) // 55 degrees
389 {
390 //
391 // The value of numevts in the first sample (below) has been
392 // changed to simplify calculations. We have multiplied it
393 // times 1.2808997 to convert it to the number it would be if
394 // the generation area was equal to that of the other samples
395 // at 55 degrees (pi*600**2 m2). This has to be taken into account
396 // in the error in the number of events.
397 //
398
399 emin[0] = 500.;
400 emax[0] = 50000.; // Energies in GeV.
401 index[0] = 1.5;
402 numevts[0] = 3298.;
403 multfactor[0] = 1.2808997;
404
405 emin[1] = 1500.;
406 emax[1] = 50000.; // Energies in GeV.
407 index[1] = 1.5;
408 numevts[1] = 22229.;
409
410 emin[2] = 1500.;
411 emax[2] = 50000.; // Energies in GeV.
412 index[2] = 1.7;
413 numevts[2] = 7553.;
414
415 rmax = 600; //meters
416 num_MC_samples = 3;
417 }
418
419 else if (theta > 64 && theta < 66) // 65 degrees
420 {
421 emin[0] = 2000.;
422 emax[0] = 50000.; // Energies in GeV.
423 index[0] = 1.5;
424 numevts[0] = 16310.;
425
426 emin[1] = 2000.;
427 emax[1] = 50000.; // Energies in GeV.
428 index[1] = 1.7;
429 numevts[1] = 3000.;
430
431 //
432 // The value of numevts in the next two samples (below) has been
433 // changed to simplify calculations. We have converted them to the
434 // number it would be if the generation area was equal to that of
435 // the first two samples at 65 degrees (pi*800**2 m2) (four times
436 // as many, since the original maximum impact parameter was 400
437 // instead of 800. This is taken into account in the error too.
438 //
439
440 emin[2] = 5000.;
441 emax[2] = 50000.; // Energies in GeV.
442 index[2] = 1.5;
443 numevts[2] = 56584.;
444 multfactor[2] = 4;
445
446 emin[3] = 5000.;
447 emax[3] = 50000.; // Energies in GeV.
448 index[3] = 1.7;
449 numevts[3] = 11464;
450 multfactor[3] = 4;
451
452 rmax = 800; // meters
453 num_MC_samples = 4;
454 }
455
456
457 for (Int_t i=1; i <= fHistAll->GetNbinsX(); i++)
458 {
459 Float_t e1;
460 Float_t e2;
461
462 if (fEaxis == kLog10)
463 {
464 e1 = pow(10.,fHistAll->GetXaxis()->GetBinLowEdge(i));
465 e2 = pow(10.,fHistAll->GetXaxis()->GetBinLowEdge(i+1));
466 }
467 else
468 {
469 e1 = fHistAll->GetXaxis()->GetBinLowEdge(i);
470 e2 = fHistAll->GetXaxis()->GetBinLowEdge(i+1);
471 }
472
473 Float_t events = 0.;
474 Float_t errevents = 0.;
475
476 for (Int_t sample = 0; sample < num_MC_samples; sample++)
477 {
478 Float_t expo = 1.-index[sample];
479 Float_t k = numevts[sample] / (pow(emax[sample],expo) - pow(emin[sample],expo));
480
481 if (e2 < emin[sample] || e1 > emax[sample])
482 continue;
483
484 if (emin[sample] > e1)
485 e1 = emin[sample];
486
487 if (emax[sample] < e2)
488 e2 = emax[sample];
489
490 events += k * (pow(e2, expo) - pow(e1, expo));
491 errevents += multfactor[sample] * events;
492 }
493
494 errevents= sqrt(errevents);
495
496 fHistAll->SetBinContent(i, thetabin, events);
497 fHistAll->SetBinError(i, thetabin, errevents);
498 }
499
500 // -----------------------------------------------------------
501
502 const Float_t dr = TMath::Pi() * rmax * rmax;
503
504 for (Int_t ix = 1; ix <= fHistAll->GetNbinsX(); ix++)
505 {
506 const Float_t Na = fHistAll->GetBinContent(ix,thetabin);
507
508 if (Na <= 0)
509 {
510 //
511 // If energy is large, this case means that no or very few events
512 // were generated at this energy bin. In this case we assign it
513 // the effective area of the bin below it in energy. If energy is
514 // below 1E4, it means that no events triggered -> eff area = 0
515 //
516 // NOW DISABLED: because collection area after analysis does not
517 // saturate at high E!
518 //
519
520 /*
521 if (fHistSel->GetXaxis()->GetBinLowEdge(ix) > 4.)
522 {
523 fHistCol->SetBinContent(ix, thetabin, fHistCol->GetBinContent(ix-1, thetabin));
524 fHistCol->SetBinError(ix, thetabin, fHistCol->GetBinError(ix-1, thetabin));
525 }
526 */
527 continue;
528 }
529
530 const Float_t Ns = fHistSel->GetBinContent(ix,thetabin);
531
532 // Since Na is an estimate of the total number of showers generated
533 // in the energy bin, it may happen that Ns (triggered showers) is
534 // larger than Na. In that case, the bin is skipped:
535
536 if (Na < Ns)
537 continue;
538
539 const Double_t eff = Ns/Na;
540 const Double_t efferr = sqrt((1.-eff)*Ns)/Na;
541
542 //
543 // Now we get the total area, perpendicular to the observation direction
544 // in which the events were generated (correct for cos theta):
545 //
546
547 Float_t area = dr;
548
549 if (theta < 50)
550 area *= cos(theta*TMath::Pi()/180.);
551
552 // Above 50 degrees MC was generated with Corsika 6.xx, and the cores
553 // were distributed on a circle perpendicular to the observation direction,
554 // and not on ground, hence the correction for cos(theta) is not necessary.
555 //
556
557
558 fHistCol->SetBinContent(ix, thetabin, eff*area);
559 fHistCol->SetBinError(ix, thetabin, efferr*area);
560
561 }
562 }
563
564 SetReadyToSave();
565}
Note: See TracBrowser for help on using the repository browser.