source: trunk/Mars/mhbase/MHn.cc@ 20095

Last change on this file since 20095 was 19345, checked in by tbretz, 6 years ago
Improves the behaviour with RecursiveRemove. Strictly speaking this change might only be necessary if a class contains more than one member which is bound to recursive remove. Onth other hand setting all members to NULL which might be affected by RecursiveRemove is not wrong either.
File size: 18.3 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 2002 <mailto:tbretz@astro.uni-wuerzburg.de>
19!
20! Copyright: MAGIC Software Development, 2000-2010
21!
22!
23\* ======================================================================== */
24
25/////////////////////////////////////////////////////////////////////////////
26//
27// MHn
28//
29//
30// Initialization
31// --------------
32//
33// MHn is a histogram class which derives from MH as all Mars histogram
34// classes do, i.e. to fill the histogram use MFillH. (Example below)
35//
36// After instantisation of MHn add the histograms of your interest using
37// AddHist. Before the next AddHist is called you can now set the options
38// of your histogram using InitName, InitTitle, SetLog, SetAutoRange,
39// SetScale and SetDrawOption.
40//
41//
42// Layout
43// ------
44//
45// The layout of the histograms on the screen depends on the number of
46// initialized histograms and the option SetLayout. For details see below.
47//
48// SetLayout(MHn::kSimple)
49// < default > SetLayout(MHn::kComplex)
50// ========================= ==========================
51// +-----------------+
52// |1 |
53// | |
54// | |
55// | |
56// | |
57// +-----------------+
58//
59// +-----------------+ +--------+--------+
60// |1 | |1 |2 |
61// | | | | |
62// +-----------------+ | | |
63// |2 | | | |
64// | | | | |
65// +-----------------+ +--------+--------+
66//
67// +--------+--------+ +-----+-----+-----+
68// |1 |2 | |1 |3 |
69// | | | | | |
70// +--------+--------+ +-----+ +
71// |3 | | |2 | |
72// | | | | | |
73// +--------+--------+ +-----+-----+-----+
74//
75// +--------+--------+ +------+----------+
76// |1 |2 | |1 |4 |
77// | | | +------+ |
78// +--------+--------+ |2 | |
79// |3 |4 | +------+ |
80// | | | |3 | |
81// +--------+--------+ +------+----------+
82//
83// +-----+-----+-----+ +--------+--------+
84// |1 |2 |3 | |1 |2 |
85// | | | | +--------+--------|
86// +-----+-----+-----+ |3 |4 |
87// |4 |5 | | +--------+ |
88// | | | | |5 | |
89// +-----+-----+-----+ +--------+--------+
90//
91// +-----+-----+-----+ +--------+--------+
92// |1 |2 |3 | |1 |2 |
93// | | | | +--------+--------+
94// +-----+-----+-----+ |3 |4 |
95// |4 |5 |6 | +--------+--------+
96// | | | | |5 |6 |
97// +-----+-----+-----+ +--------+--------+
98//
99//
100// For example:
101// ------------
102// // Instatiate the MHn class with default name and title
103// MHn hres("Energy2", "Energy Residual (lg E_{est} - lg E_{mc})");
104//
105// // Initialize your first histogram (here a 2D histogram with x- and y-axis)
106// hres.AddHist("MMcEvt.fEnergy", "log10(MEnergyEst.fVal)-log10(MMcEvt.fEnergy)");
107// // Initialize the name of the histogram (ResEmc) and the title of the
108// // binnings ((here BinningEnergy for x-axis and BinningEnergyResidual for y-axis)
109// hres.InitName("ResEmc;Energy;EnergyResidual");
110// // Initialize the title of the histogram and the axis titles
111// hres.InitTitle(";E_{mc} [GeV];\\Delta lg E;");
112// // Initialize the draw option for the histogram
113// hres.SetDrawOption("colz profx");
114// // for more details on the options and more options see below
115// // or the class reference of MH3
116//
117// // Initialize a second histogram
118// hres.AddHist("MPointingPos.fZd", "log10(MEnergyEst.fVal)-log10(MMcEvt.fEnergy)");
119// hres.InitName("ResTheta;Theta;EnergyResidual");
120// hres.InitTitle(";Zd [#circ];\\Delta lg E;");
121// hres.SetDrawOption("colz profx");
122//
123// // Note that only AddHist is mandatory. All other options can be omitted
124//
125// // Initialize the filling task which can now be added to the tasklist
126// MFillH fill(&hres);
127// ...
128//
129/////////////////////////////////////////////////////////////////////////////
130#include "MHn.h"
131
132#include <TCanvas.h>
133
134#include "MLog.h"
135#include "MLogManip.h"
136
137#include "MH3.h"
138#include "MString.h"
139
140ClassImp(MHn);
141
142using namespace std;
143
144MHn::MHn(const char *name, const char *title) : fLayout(kSimple), fNum(0)
145{
146 fName = name ? name : "MHn";
147 fTitle = title ? title : "Generalized histogram class for up to six histograms";
148
149 memset(fHist, 0, 6*sizeof(MH3*));
150}
151
152MHn::~MHn()
153{
154 for (int i=0; i<fNum; i++)
155 if (fHist[i])
156 {
157 delete fHist[i];
158 fHist[i] = 0;
159 }
160}
161
162// --------------------------------------------------------------------------
163//
164// If a histogram with the same name is found, the pad-number with a
165// training underscore is added.
166//
167// FIXME: How do we handle identical names with different axes?
168//
169void MHn::InitHist()
170{
171 TString name = fName;
172
173 for (int i=0; i<fNum; i++)
174 if (name==fHist[i]->GetName())
175 {
176 name += MString::Format("_%d", fNum);
177 break;
178 }
179
180 fHist[fNum]->SetName(fName);
181 fHist[fNum]->SetTitle(fTitle);
182
183 fHist[fNum]->SetAutoRangeX();
184
185 fNum++;
186}
187
188// --------------------------------------------------------------------------
189//
190// Add a new 1D-MH3 histogram. An internal pointer is set to it, so that
191// InitName and InitTitle can be used for this histogram until a new
192// histogram is added using AddHist
193//
194// e.g. AddHist("MHillas.fSize")
195//
196Bool_t MHn::AddHist(const char *memberx)
197{
198 if (fNum==8)
199 {
200 *fLog << err << "ERROR - MHn doesn't support more than six histograms... AddHist ignored." << endl;
201 return kFALSE;
202 }
203
204 fHist[fNum] = new MH3(memberx);
205
206 InitHist();
207
208 return kTRUE;
209}
210
211// --------------------------------------------------------------------------
212//
213// Add a new 2D-MH3 histogram. An internal pointer is set to it, so that
214// InitName and InitTitle can be used for this histogram until a new
215// histogram is added using AddHist
216//
217// e.g. AddHist("MHillas.fLength", "MHillas.fSize")
218//
219Bool_t MHn::AddHist(const char *memberx, const char *membery, MH3::Type_t type)
220{
221 if (fNum==8)
222 {
223 *fLog << err << "ERROR - MHn doesn't support more than six histograms... AddHist ignored." << endl;
224 return kFALSE;
225 }
226
227 fHist[fNum] = new MH3(memberx, membery, type);
228
229 InitHist();
230
231 return kTRUE;
232}
233
234// --------------------------------------------------------------------------
235//
236// Add a new 3D-MH3 histogram. An internal pointer is set to it, so that
237// InitName and InitTitle can be used for this histogram until a new
238// histogram is added using AddHist
239//
240// e.g. AddHist("MHillas.fWidth", "MHillas.fLength", "MHillas.fSize")
241//
242Bool_t MHn::AddHist(const char *memberx, const char *membery, const char *memberz, MH3::Type_t type)
243{
244 if (fNum==8)
245 {
246 *fLog << err << "ERROR - MHn doesn't support more than six histograms... AddHist ignored." << endl;
247 return kFALSE;
248 }
249
250 fHist[fNum] = new MH3(memberx, membery, memberz, type);
251
252 InitHist();
253
254 return kTRUE;
255}
256
257// --------------------------------------------------------------------------
258//
259// Add a new 3D-MH3 histogram. An internal pointer is set to it, so that
260// InitName and InitTitle can be used for this histogram until a new
261// histogram is added using AddHist
262//
263// e.g. AddHist("MHillas.fWidth", "MHillas.fLength", "MHillas.fSize", "MWeight.fVal")
264//
265Bool_t MHn::AddHist(const char *memberx, const char *membery, const char *memberz, const char *weight)
266{
267 if (fNum==8)
268 {
269 *fLog << err << "ERROR - MHn doesn't support more than six histograms... AddHist ignored." << endl;
270 return kFALSE;
271 }
272
273 fHist[fNum] = new MH3(memberx, membery, memberz, weight);
274
275 InitHist();
276
277 return kTRUE;
278}
279
280// --------------------------------------------------------------------------
281//
282// Set the draw option of the n-th MH3. See MH3 for more details of the
283// meaning of it.
284//
285Bool_t MHn::SetDrawOption(Int_t n, const char *opt)
286{
287 if (n<0 || n>=fNum)
288 {
289 *fLog << err << "ERROR - Histogram " << n << " not yet initialized... SetDrawOption ignored." << endl;
290 return kFALSE;
291 }
292
293 fDrawOption[n] = opt;
294
295 return kTRUE;
296}
297
298// --------------------------------------------------------------------------
299//
300// Set the name of the n-th MH3. See MH3 for more details of the meaning
301// of the name. If the given name starts with a semicolon fName is prepend
302// to the string.
303//
304Bool_t MHn::InitName(Int_t n, const char *nam)
305{
306 if (n<0 || n>=fNum)
307 {
308 *fLog << err << "ERROR - Histogram " << n << " not yet initialized... InitName ignored." << endl;
309 return kFALSE;
310 }
311
312 TString name = TString(nam).Strip(TString::kBoth);
313
314 if (name[0]==';')
315 name.Prepend(fName);
316
317 fHist[n]->SetName(name);
318
319 return kTRUE;
320}
321
322// --------------------------------------------------------------------------
323//
324// Set the title of the n-th MH3. See MH3 for more details of the meaning
325// of the title. If the given title starts with a semicolon fTitle is prepend
326// to the string.
327//
328Bool_t MHn::InitTitle(Int_t n, const char *tit)
329{
330 if (n<0 || n>=fNum)
331 {
332 *fLog << err << "ERROR - Histogram " << n << " not yet initialized... InitTitle ignored." << endl;
333 return kFALSE;
334 }
335
336 TString title = TString(tit).Strip(TString::kBoth);
337
338 if (title[0]==';')
339 title.Prepend(fTitle);
340
341 fHist[n]->SetTitle(title);
342
343 return kTRUE;
344}
345
346// --------------------------------------------------------------------------
347//
348// Set additional scale factors for the current histogram
349//
350void MHn::SetScale(Double_t x, Double_t y, Double_t z) const
351{
352 if (fHist[fNum-1])
353 fHist[fNum-1]->SetScale(x, y, z);
354}
355
356// --------------------------------------------------------------------------
357//
358// Enable or disable displaying log-scale for the current histogram.
359// Normally it is retrieved from the corresponding MBinning
360//
361void MHn::SetLog(Bool_t x, Bool_t y, Bool_t z) const
362{
363 if (fHist[fNum-1])
364 fHist[fNum-1]->SetLog(x, y, z);
365}
366
367// --------------------------------------------------------------------------
368//
369// Set the axis range in Finalize automatically to the histogram region
370// containing contents. This is the default for the x-axis.
371// This function can be used to enable this behaviour also for the other
372// axis, or disable it for the x-axis of the current histogram.
373//
374void MHn::SetAutoRange(Bool_t x, Bool_t y, Bool_t z) const
375{
376 if (fHist[fNum-1])
377 fHist[fNum-1]->SetAutoRange(x, y, z);
378}
379
380// --------------------------------------------------------------------------
381//
382// Call Sumw2 for trhe current histogram, enabling errors.
383//
384void MHn::Sumw2() const
385{
386 if (fHist[fNum-1])
387 fHist[fNum-1]->Sumw2();
388}
389
390// --------------------------------------------------------------------------
391//
392// Force the given binning(s) for the current histogram. The binnings
393// do not get owned. The user is responsible for deleting them.
394//
395void MHn::SetBinnings(MBinning *x, MBinning *y, MBinning *z) const
396{
397 if (fHist[fNum-1])
398 fHist[fNum-1]->SetBinnings(x, y, z);
399}
400
401// --------------------------------------------------------------------------
402//
403// call MH3::InitLabels for the current histogram
404//
405void MHn::InitLabels(MH3::Labels_t labels) const
406{
407 if (fHist[fNum-1])
408 fHist[fNum-1]->InitLabels(labels);
409}
410
411// --------------------------------------------------------------------------
412//
413// call MH3::DefaultLabelX for the current histogram
414//
415void MHn::DefaultLabelX(const char *name)
416{
417 if (fHist[fNum-1])
418 fHist[fNum-1]->DefaultLabelX(name);
419}
420
421// --------------------------------------------------------------------------
422//
423// call MH3::DefaultLabelY for the current histogram
424//
425void MHn::DefaultLabelY(const char *name)
426{
427 if (fHist[fNum-1])
428 fHist[fNum-1]->DefaultLabelY(name);
429}
430
431// --------------------------------------------------------------------------
432//
433// call MH3::DefaultLabelZ for the current histogram
434//
435void MHn::DefaultLabelZ(const char *name)
436{
437 if (fHist[fNum-1])
438 fHist[fNum-1]->DefaultLabelZ(name);
439}
440
441// --------------------------------------------------------------------------
442//
443// call MH3::DefineLabelX for the current histogram
444//
445void MHn::DefineLabelX(Int_t label, const char *name)
446{
447 if (fHist[fNum-1])
448 fHist[fNum-1]->DefineLabelX(label, name);
449}
450
451// --------------------------------------------------------------------------
452//
453// call MH3::DefineLabelY for the current histogram
454//
455void MHn::DefineLabelY(Int_t label, const char *name)
456{
457 if (fHist[fNum-1])
458 fHist[fNum-1]->DefineLabelY(label, name);
459}
460
461// --------------------------------------------------------------------------
462//
463// call MH3::DefineLabelZ for the current histogram
464//
465void MHn::DefineLabelZ(Int_t label, const char *name)
466{
467 if (fHist[fNum-1])
468 fHist[fNum-1]->DefineLabelZ(label, name);
469}
470
471// --------------------------------------------------------------------------
472//
473// call MH3::DefineLabelsX for the current histogram
474//
475void MHn::DefineLabelsX(const TString &labels)
476{
477 if (fHist[fNum-1])
478 fHist[fNum-1]->DefineLabelsX(labels);
479}
480
481// --------------------------------------------------------------------------
482//
483// call MH3::DefineLabelsY for the current histogram
484//
485void MHn::DefineLabelsY(const TString &labels)
486{
487 if (fHist[fNum-1])
488 fHist[fNum-1]->DefineLabelsY(labels);
489}
490
491// --------------------------------------------------------------------------
492//
493// call MH3::DefineLabelsZ for the current histogram
494//
495void MHn::DefineLabelsZ(const TString &labels)
496{
497 if (fHist[fNum-1])
498 fHist[fNum-1]->DefineLabelsZ(labels);
499}
500
501// --------------------------------------------------------------------------
502//
503// call MH3::SetWeight for the current histogram
504//
505void MHn::SetWeight(const char *phrase)
506{
507 if (fHist[fNum-1])
508 fHist[fNum-1]->SetWeight(phrase);
509}
510
511// --------------------------------------------------------------------------
512//
513// call MH3::SetConversion for the current histogram
514//
515void MHn::SetConversion(const char *func)
516{
517 if (fHist[fNum-1])
518 fHist[fNum-1]->SetConversion(func);
519}
520
521// --------------------------------------------------------------------------
522//
523// Call SetupFill for all initialized histograms
524//
525Bool_t MHn::SetupFill(const MParList *plist)
526{
527 for (int i=0; i<fNum; i++)
528 {
529 TestBit(kDoNotReset) ? fHist[i]->SetBit(kDoNotReset) : fHist[i]->ResetBit(kDoNotReset);
530
531 if (!fHist[i]->SetupFill(plist))
532 return kFALSE;
533 }
534
535 return kTRUE;
536}
537
538// --------------------------------------------------------------------------
539//
540// Call Fill for all initialized histograms
541//
542Int_t MHn::Fill(const MParContainer *par, const Stat_t w)
543{
544 for (int i=0; i<fNum; i++)
545 {
546 const Int_t rc = fHist[i]->Fill(par, w);
547 if (rc!=kTRUE)
548 return rc;
549 }
550
551 return kTRUE;
552}
553
554// --------------------------------------------------------------------------
555//
556// Call Finalize for all initialized histograms
557//
558Bool_t MHn::Finalize()
559{
560 for (int i=0; i<fNum; i++)
561 if (!fHist[i]->Finalize())
562 return kFALSE;
563
564 return kTRUE;
565}
566
567// --------------------------------------------------------------------------
568//
569void MHn::Draw(Option_t *opt)
570{
571 TVirtualPad *pad = gPad ? gPad : MakeDefCanvas(this);
572 pad->SetBorderMode(0);
573
574 const Bool_t same = TString(opt).Contains("same");
575
576 if (!same)
577 {
578 AppendPad();
579
580 const Int_t id = fNum + fLayout*10;
581
582 switch (id)
583 {
584 case 0: // 0
585 case 10: // 0
586 return;
587 case 1: // 1
588 case 11: // 1
589 break;
590
591 case 2: // 2
592 pad->Divide(1,2, 1e-5, 1e-5);
593 break;
594 case 3: // 3
595 pad->Divide(2,2, 1e-5, 1e-5);
596 delete pad->GetPad(4);
597 break;
598 case 4: // 4
599 pad->Divide(2,2, 1e-5, 1e-5);
600 break;
601 case 5: // 5
602 pad->Divide(3,2, 1e-5, 1e-5);
603 delete pad->GetPad(6);
604 break;
605 case 6: // 6
606 pad->Divide(3,2, 1e-5, 1e-5);
607 break;
608
609 case 12: // 2
610 pad->Divide(2,1, 1e-5, 1e-5);
611 break;
612 case 13: // 3
613 pad->Divide(2,2, 1e-5, 1e-5);
614 pad->GetPad(1)->SetPad(0.01, 0.505, 0.33, 0.99);
615 pad->GetPad(2)->SetPad(0.01, 0.01, 0.33, 0.495);
616 pad->GetPad(3)->SetPad(0.34, 0.01, 0.99, 0.99);
617 delete pad->GetPad(4);
618 break;
619 case 14: // 4
620 pad->Divide(2,2, 1e-5, 1e-5);
621 break;
622 case 15: // 5
623 pad->Divide(2,3, 1e-5, 1e-5);
624 pad->GetPad(4)->SetPad(0.51, 0.01, 0.99, 0.65);
625 delete pad->GetPad(6);
626 break;
627 case 16: // 6
628 pad->Divide(2,3);
629 break;
630 }
631 }
632
633 for (int i=0; i<fNum; i++)
634 {
635 TString dopt(fDrawOption[i]);
636 if (same)
637 dopt += " same";
638
639 pad->cd(i+1);
640 fHist[i]->Draw(dopt);
641 }
642}
643
644void MHn::RecursiveRemove(TObject *obj)
645{
646 for (int i=0; i<6; i++)
647 {
648 if (!fHist[i])
649 continue;
650
651 if (obj==fHist[i])
652 fHist[i] = 0;
653 else
654 fHist[i]->RecursiveRemove(obj);
655 }
656
657 MH::RecursiveRemove(obj);
658}
Note: See TracBrowser for help on using the repository browser.