source: trunk/MagicSoft/Mars/mhist/MH.cc@ 1502

Last change on this file since 1502 was 1484, checked in by tbretz, 22 years ago
*** empty log message ***
File size: 13.4 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 07/2001 <mailto:tbretz@astro.uni-wuerzburg.de>
19!
20! Copyright: MAGIC Software Development, 2000-2002
21!
22!
23\* ======================================================================== */
24
25//////////////////////////////////////////////////////////////////////////////
26// //
27// MH //
28// //
29// This is a base tasks for mars histograms. It defines a common interface //
30// for filling the histograms with events (MH::Fill) which is used by a //
31// common 'filler' And a SetupFill member function which may be used //
32// by MFillH. The idea is: //
33// 1) If your Histogram can become filled by one single container //
34// (like MHHillas) you overload MH::Fill and it gets called with //
35// a pointer to the container with which it should be filled. //
36// //
37// 2) You histogram needs several containers to get filled. Than you //
38// have to overload MH::SetupFill and get the necessary objects from //
39// the parameter list. Use this objects in Fill to fill your //
40// histogram. //
41// //
42// If you want to create your own histogram class the new class must be //
43// derived from MH (instead of the base MParContainer) and you must //
44// the fill function of MH. This is the function which is called to fill //
45// the histogram(s) by the data of a corresponding parameter container. //
46// //
47//////////////////////////////////////////////////////////////////////////////
48
49#include "MH.h"
50
51#include <TH1.h>
52#include <TH2.h>
53#include <TH3.h>
54#include <TGaxis.h>
55#include <TCanvas.h>
56
57#include "MLog.h"
58#include "MLogManip.h"
59
60#include "MParList.h"
61#include "MParContainer.h"
62
63#include "MBinning.h"
64
65ClassImp(MH);
66
67// --------------------------------------------------------------------------
68//
69// Default Constructor. It sets name and title only. Typically you won't
70// need to change this.
71//
72MH::MH(const char *name, const char *title)
73{
74 //
75 // set the name and title of this object
76 //
77 fName = name ? name : "MH";
78 fTitle = title ? title : "Base class for Mars histograms";
79}
80
81// --------------------------------------------------------------------------
82//
83// If you want to use the automatic filling of your derived class you
84// must overload this function. If it is not overloaded you cannot use
85// FillH with this class. The argument is a pointer to a container
86// in your paremeter list which is specified in the MFillH constructor.
87// If you are not going to use it you should at least add
88// Bool_t MH::Fill(const MParContainer *) { return kTRUE; }
89// to your class definition.
90//
91Bool_t MH::Fill(const MParContainer *par)
92{
93 *fLog << GetDescriptor() << ": Fill not overloaded! Can't be used!" << endl;
94 return kFALSE;
95}
96
97// --------------------------------------------------------------------------
98//
99// This is a function which should replace the creation of default
100// canvases like root does. Because this is inconvinient in some aspects.
101// need to change this.
102// You can specify a name for the default canvas and a title. Also
103// width and height can be given.
104// MakeDefCanvas looks for a canvas with the given name. If now name is
105// given the DefCanvasName of root is used. If no such canvas is existing
106// it is created and returned. If such a canvas already exists a new canvas
107// with a name plus anumber is created (the number is calculated by the
108// number of all existing canvases plus one)
109//
110TCanvas *MH::MakeDefCanvas(TString name, const char *title,
111 const UInt_t w, const UInt_t h)
112{
113 const TList *list = (TList*)gROOT->GetListOfCanvases();
114
115 if (name.IsNull())
116 name = gROOT->GetDefCanvasName();
117
118 if (list->FindObject(name))
119 name += Form(" <%d>", list->GetSize()+1);
120
121 return new TCanvas(name, title, w, h);
122}
123
124// --------------------------------------------------------------------------
125//
126// This function works like MakeDefCanvas(name, title, w, h) but name
127// and title are retrieved from the given TObject.
128//
129TCanvas *MH::MakeDefCanvas(const TObject *obj,
130 const UInt_t w, const UInt_t h)
131{
132 return MakeDefCanvas(obj->GetName(), obj->GetTitle(), w, h);
133}
134
135void MH::SetBinning(TH1 *h, const MBinning *binsx)
136{
137 //
138 // Another strange behaviour: TAxis::Set deletes the axis title!
139 //
140 TAxis &x = *h->GetXaxis();
141
142#if ROOT_VERSION_CODE < ROOT_VERSION(3,03,03)
143 TString xtitle = x.GetTitle();
144#endif
145
146 //
147 // This is a necessary workaround if one wants to set
148 // non-equidistant bins after the initialization
149 // TH1D::fNcells must be set correctly.
150 //
151 h->SetBins(binsx->GetNumBins(), 0, 1);
152
153 //
154 // Set the binning of the current histogram to the binning
155 // in one of the two given histograms
156 //
157 x.Set(binsx->GetNumBins(), binsx->GetEdges());
158#if ROOT_VERSION_CODE < ROOT_VERSION(3,03,03)
159 x.SetTitle(xtitle);
160#endif
161}
162
163void MH::SetBinning(TH2 *h, const MBinning *binsx, const MBinning *binsy)
164{
165 TAxis &x = *h->GetXaxis();
166 TAxis &y = *h->GetYaxis();
167
168 //
169 // Another strange behaviour: TAxis::Set deletes the axis title!
170 //
171#if ROOT_VERSION_CODE < ROOT_VERSION(3,03,03)
172 TString xtitle = x.GetTitle();
173 TString ytitle = y.GetTitle();
174#endif
175
176 //
177 // This is a necessary workaround if one wants to set
178 // non-equidistant bins after the initialization
179 // TH1D::fNcells must be set correctly.
180 //
181 h->SetBins(binsx->GetNumBins(), 0, 1,
182 binsy->GetNumBins(), 0, 1);
183
184 //
185 // Set the binning of the current histogram to the binning
186 // in one of the two given histograms
187 //
188 x.Set(binsx->GetNumBins(), binsx->GetEdges());
189 y.Set(binsy->GetNumBins(), binsy->GetEdges());
190#if ROOT_VERSION_CODE < ROOT_VERSION(3,03,03)
191 x.SetTitle(xtitle);
192 y.SetTitle(ytitle);
193#endif
194}
195
196void MH::SetBinning(TH3 *h, const MBinning *binsx, const MBinning *binsy, const MBinning *binsz)
197{
198 //
199 // Another strange behaviour: TAxis::Set deletes the axis title!
200 //
201 TAxis &x = *h->GetXaxis();
202 TAxis &y = *h->GetYaxis();
203 TAxis &z = *h->GetZaxis();
204
205#if ROOT_VERSION_CODE < ROOT_VERSION(3,03,03)
206 TString xtitle = x.GetTitle();
207 TString ytitle = y.GetTitle();
208 TString ztitle = z.GetTitle();
209#endif
210
211 //
212 // This is a necessary workaround if one wants to set
213 // non-equidistant bins after the initialization
214 // TH1D::fNcells must be set correctly.
215 //
216 h->SetBins(binsx->GetNumBins(), 0, 1,
217 binsy->GetNumBins(), 0, 1,
218 binsz->GetNumBins(), 0, 1);
219
220 //
221 // Set the binning of the current histogram to the binning
222 // in one of the two given histograms
223 //
224 x.Set(binsx->GetNumBins(), binsx->GetEdges());
225 y.Set(binsy->GetNumBins(), binsy->GetEdges());
226 z.Set(binsz->GetNumBins(), binsz->GetEdges());
227#if ROOT_VERSION_CODE < ROOT_VERSION(3,03,03)
228 x.SetTitle(xtitle);
229 y.SetTitle(ytitle);
230 z.SetTitle(ztitle);
231#endif
232}
233
234void MH::SetBinning(TH1 *h, const TArrayD &binsx)
235{
236 MBinning bx;
237 bx.SetEdges(binsx);
238 SetBinning(h, &bx);
239}
240
241void MH::SetBinning(TH2 *h, const TArrayD &binsx, const TArrayD &binsy)
242{
243 MBinning bx;
244 MBinning by;
245 bx.SetEdges(binsx);
246 by.SetEdges(binsy);
247 SetBinning(h, &bx, &by);
248}
249
250void MH::SetBinning(TH3 *h, const TArrayD &binsx, const TArrayD &binsy, const TArrayD &binsz)
251{
252 MBinning bx;
253 MBinning by;
254 MBinning bz;
255 bx.SetEdges(binsx);
256 by.SetEdges(binsy);
257 bz.SetEdges(binsz);
258 SetBinning(h, &bx, &by, &bz);
259}
260
261void MH::SetBinning(TH1 *h, const TAxis *binsx)
262{
263 const Int_t nx = binsx->GetNbins();
264
265 TArrayD bx(nx+1);
266 for (int i=0; i<nx; i++) bx[i] = binsx->GetBinLowEdge(i+1);
267 bx[nx] = binsx->GetXmax();
268
269 SetBinning(h, bx);
270}
271
272void MH::SetBinning(TH2 *h, const TAxis *binsx, const TAxis *binsy)
273{
274 const Int_t nx = binsx->GetNbins();
275 const Int_t ny = binsy->GetNbins();
276
277 TArrayD bx(nx+1);
278 TArrayD by(ny+1);
279 for (int i=0; i<nx; i++) bx[i] = binsx->GetBinLowEdge(i+1);
280 for (int i=0; i<ny; i++) by[i] = binsy->GetBinLowEdge(i+1);
281 bx[nx] = binsx->GetXmax();
282 by[ny] = binsy->GetXmax();
283
284 SetBinning(h, bx, by);
285}
286
287void MH::SetBinning(TH3 *h, const TAxis *binsx, const TAxis *binsy, const TAxis *binsz)
288{
289 const Int_t nx = binsx->GetNbins();
290 const Int_t ny = binsy->GetNbins();
291 const Int_t nz = binsz->GetNbins();
292
293 TArrayD bx(nx+1);
294 TArrayD by(ny+1);
295 TArrayD bz(nz+1);
296 for (int i=0; i<nx; i++) bx[i] = binsx->GetBinLowEdge(i+1);
297 for (int i=0; i<ny; i++) by[i] = binsy->GetBinLowEdge(i+1);
298 for (int i=0; i<nz; i++) bz[i] = binsz->GetBinLowEdge(i+1);
299 bx[nx] = binsx->GetXmax();
300 by[ny] = binsy->GetXmax();
301 bz[nz] = binsz->GetXmax();
302
303 SetBinning(h, bx, by, bz);
304}
305
306void MH::SetBinning(TH1 *h, TH1 *x)
307{
308 if (h->InheritsFrom(TH3::Class()) && x->InheritsFrom(TH3::Class()))
309 {
310 SetBinning((TH3*)h, x->GetXaxis(), x->GetYaxis(), x->GetZaxis());
311 return;
312 }
313 if (h->InheritsFrom(TH2::Class()) && x->InheritsFrom(TH2::Class()))
314 {
315 SetBinning((TH2*)h, x->GetXaxis(), x->GetYaxis());
316 return;
317 }
318 if (h->InheritsFrom(TH1::Class()) && x->InheritsFrom(TH1::Class()))
319 {
320 SetBinning(h, x->GetXaxis());
321 return;
322 }
323}
324
325void MH::ScaleArray(TArrayD &bins, Double_t f)
326{
327 for (int i=0; i<bins.GetSize(); i++)
328 bins[i] *= f;
329}
330
331TArrayD MH::ScaleAxis(TAxis &axe, Double_t f)
332{
333 TArrayD arr(axe.GetNbins()+1);
334
335 for (int i=1; i<=axe.GetNbins()+1; i++)
336 arr[i-1] = axe.GetBinLowEdge(i);
337
338 ScaleArray(arr, f);
339
340 return arr;
341}
342
343void MH::ScaleAxis(TH1 *h, Double_t fx, Double_t fy, Double_t fz)
344{
345 if (h->InheritsFrom(TH3::Class()))
346 {
347 SetBinning((TH3*)h,
348 ScaleAxis(*h->GetXaxis(), fx),
349 ScaleAxis(*h->GetYaxis(), fy),
350 ScaleAxis(*h->GetZaxis(), fz));
351 return;
352 }
353
354 if (h->InheritsFrom(TH2::Class()))
355 {
356 SetBinning((TH2*)h,
357 ScaleAxis(*h->GetXaxis(), fx),
358 ScaleAxis(*h->GetYaxis(), fy));
359 return;
360 }
361
362 if (h->InheritsFrom(TH1::Class()))
363 SetBinning(h, ScaleAxis(*h->GetXaxis(), fx));
364}
365
366Bool_t MH::ApplyBinning(const MParList &plist, TString name, TH1 *h)
367{
368 if (h->InheritsFrom(TH2::Class()) || h->InheritsFrom(TH3::Class()))
369 {
370 gLog << warn << "MH::ApplyBinning: '" << h->GetName() << "' is not a basic TH1 object... no binning applied." << endl;
371 return kFALSE;
372 }
373
374 const MBinning *bins = (MBinning*)plist.FindObject("Binning"+name);
375 if (!bins)
376 {
377 gLog << warn << "Object 'Binning" << name << "' [MBinning] not found... no binning applied." << endl;
378 return kFALSE;
379 }
380
381 SetBinning(h, bins);
382 return kTRUE;
383}
384
385void MH::FindGoodLimits(Int_t nbins, Int_t &newbins, Double_t &xmin, Double_t &xmax, Bool_t isInteger)
386{
387//*-*-*-*-*-*-*-*-*Find reasonable bin values*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
388//*-* ==========================
389
390 Double_t dx = 0.1*(xmax-xmin);
391 Double_t umin = xmin - dx;
392 Double_t umax = xmax + dx;
393
394 if (umin < 0 && xmin >= 0)
395 umin = 0;
396
397 if (umax > 0 && xmax <= 0)
398 umax = 0;
399
400 Int_t n=0;
401 Double_t binlow =0;
402 Double_t binhigh =0;
403 Double_t binwidth=0;
404 TGaxis::Optimize(umin, umax, nbins, binlow, binhigh, n, binwidth, "");
405
406 if (binwidth <= 0 || binwidth > 1.e+39)
407 {
408 xmin = -1;
409 xmax = 1;
410 }
411 else
412 {
413 xmin = binlow;
414 xmax = binhigh;
415 }
416
417 if (isInteger)
418 {
419 Int_t ixmin = (Int_t)xmin;
420 Int_t ixmax = (Int_t)xmax;
421 Double_t dxmin = (Double_t)ixmin;
422 Double_t dxmax = (Double_t)ixmax;
423
424 xmin = xmin<0 && xmin!=dxmin ? dxmin - 1 : dxmin;
425 xmax = xmax>0 && xmax!=dxmax ? dxmax + 1 : dxmax;
426
427 if (xmin>=xmax)
428 xmax = xmin+1;
429
430 Int_t bw = 1 + (Int_t)((xmax-xmin)/nbins);
431
432 nbins = (Int_t)((xmax-xmin)/bw);
433
434 if (xmin+nbins*bw < xmax)
435 {
436 nbins++;
437 xmax = xmin +nbins*bw;
438 }
439 }
440
441 newbins = nbins;
442}
443
444Double_t MH::GetMinimumGT(const TH1 &h, Double_t gt)
445{
446 Double_t min = FLT_MAX;
447
448 const TAxis &axe = *((TH1&)h).GetXaxis();
449
450 for (int i=1; i<=axe.GetNbins(); i++)
451 {
452 Double_t x = h.GetBinContent(i);
453 if (gt<x && x<min)
454 min = x;
455 }
456 return min;
457}
Note: See TracBrowser for help on using the repository browser.