source: trunk/MagicSoft/Mars/mhbase/MH3.cc@ 9271

Last change on this file since 9271 was 9195, checked in by tbretz, 16 years ago
*** empty log message ***
File size: 35.5 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-2008
21!
22!
23\* ======================================================================== */
24
25/////////////////////////////////////////////////////////////////////////////
26//
27// MH3
28//
29// With this histogram you can fill a histogram with up to three
30// variables from Mars parameter containers in an eventloop.
31//
32// In the constructor you can give up to three variables which should be
33// filled in the histogram. Dependend on the number of given variables
34// (data members) a TH1D, TH2D or TH3D is created.
35// Specify the data mamber like the following:
36// "MHillas.fLength"
37// Where MHillas is the name of the parameter container in the parameter
38// list and fLength is the name of the data member which should be filled
39// in the histogram. Assuming that your MHillas container has a different
40// name (MyHillas) the name to give would be:
41// "MyHillas.fLength"
42//
43// If you want to use a different unit for histogramming use SetScaleX,
44// SetScaleY and SetScaleZ.
45//
46//
47// Binning/Binning name
48// =====================
49//
50// The axis binning is retrieved from the parameter list, too. Create a
51// MBinning with the name "Binning" plus the name of your MH3 container
52// plus the axis name ("X", "Y" or "Z") and add it to the parameter list.
53//
54// If the binning should have a different name than the histogram name
55// the binning name can be added to the name, eg.:
56// SetName("MyHistName;MyXBins;MyYBins")
57// Instead of BinningMyHistName[XYZ] the parameter list will be searched
58// for BinningMyXBinning, BinningMyYBins and BinningMyHistNameZ
59//
60// If you don't want to use a MBinning object from the parameter list
61// you can also set one directly, for example
62// MBinning bins(10, 0, 1);
63// mh3.SetBinningX(&bins);
64// You must not delete the MBinning object before the class has been
65// PreProcessed.
66//
67//
68// Axis titles
69// ===========
70//
71// 1) If no other title is given the rule for this axis is used.
72// 2) If the MBinning used for this axis has a non-default Title
73// (MBinning::HasTitle) this title is used for the corresponding axis
74// 3) If the MH3 has a non-default title (MH3::SetTitle called)
75// this title is set as the histogram title. It can be used to overwrite
76// the axis titles. For more information see TH1::SetTitle, eg.
77// SetTitle("MyHist;x[mm];y[cm];Counts");
78//
79//
80// Labels
81// ======
82//
83// To use labels at an axis you have to initialize this for the axis
84// by either calling InitLabels(Labels_t) or setiting a DefaultLabel.
85// For the axis for which the labels have been initialized the
86// number returned by the given corresponding phrase is converted
87// to int with TMath::Nint and used as a label. If you want to replace
88// this id by a named label you can call DefineLabel to do that.
89// Several ids can be replaced by the same label. If you define
90// named labels for every label which was not defined the default
91// is used, if any, otherwise an unnamed label is created.
92//
93// In the case of an axis with labels the axis-title cannot be
94// set via a MBinning, because the MBinning is not evaluated.
95//
96// Please note that for some reason not all combinations of
97// labels, dimensions and weights are available in the root-
98// histogram classes. Please check the MH3::Fill function to see
99// whether your combination is supported.
100//
101//
102// Examples:
103// =========
104//
105// 1) MH3 myhist("MHillas.fLength");
106// myhist.SetName("MyHist");
107// myhist.SetScaleX(geomcam.GetConvMm2Deg()); //convert length to degree
108// MBinning bins("BinningMyHistX", "Title for my x-axis [Hz]");
109// bins.SetEdges(10, 0, 150);
110// plist.AddToList(&bins);
111//
112// 2) MH3 myhist("MHillas.fLength");
113// myhist.SetName("MyHist;MyX");
114// myhist.SetTitle("Histogram Title;X-Title [mm];Counts");
115// MBinning bins("BinningMyX");
116// bins.SetEdges(10, 0, 150);
117// plist.AddToList(&bins);
118//
119// 3) MH3 myhist("MTriggerPatter.GetUnprescaled");
120// myhist.SetWeight("1./MRawRunHeader.GetRunLength");
121// myhist.SetTitle("Rate of the trigger pattern [Hz];Run Number;Trigger Pattern;Rate [Hz]");
122// myhist.InitLabels(MH3::kLabelsXY);
123// myhist.DefaultLabelY("UNKNOWN"); // Lvl1
124// myhist.DefineLabelY( 1, "Trig"); // Lvl1
125// myhist.DefineLabelY( 2, "Cal"); // Cal
126// myhist.DefineLabelY( 4, "Trig"); // Lvl2
127// myhist.DefineLabelY( 8, "Ped"); // Ped
128//
129//
130// Class Version 3:
131// ----------------
132// - MData *fData[3];
133// + MData *fData[4];
134//
135// Class Version 2:
136// ----------------
137// - MDataChain *fData[3]; // Object from which the data is filled
138// + MData *fData[3]; // Object from which the data is filled
139//
140// Class Version 3:
141// ----------------
142// - Byte_t fStyleBits
143// + MBinning fBins[3]
144//
145/////////////////////////////////////////////////////////////////////////////
146#include "MH3.h"
147
148#include <ctype.h> // tolower
149#include <stdlib.h> // atoi (Ubuntu 8.10)
150#include <fstream>
151
152#include <TMath.h>
153
154#include <THashList.h>
155#include <TObjString.h>
156
157//#include <TPad.h>
158#include <TStyle.h>
159#include <TCanvas.h>
160
161#include <TH2.h>
162#include <TH3.h>
163#include <TProfile.h>
164#include <TProfile2D.h>
165
166#include "MLog.h"
167#include "MLogManip.h"
168
169#include "MParList.h"
170#include "MBinning.h"
171#include "MDataPhrase.h"
172
173ClassImp(MH3);
174
175using namespace std;
176
177const TString MH3::gsDefName = "MH3";
178const TString MH3::gsDefTitle = "Container for a n-D Mars Histogram";
179
180// --------------------------------------------------------------------------
181//
182// Set fStyleBits to 0, Reset fBins to NULL, fScale to 1, set name and title
183// to gsDefName and gsDefTitle and if fHist!=NULL UseCurrentStyle and
184// SetDirectory(0)
185//
186void MH3::Init()
187{
188 fStyleBits = 0;
189
190 fData[3] = NULL;
191
192 fBins[0] = NULL;
193 fBins[1] = NULL;
194 fBins[2] = NULL;
195
196 fScale[0] = 1;
197 fScale[1] = 1;
198 fScale[2] = 1;
199
200 fName = gsDefName;
201 fTitle = gsDefTitle;
202
203 if (!fHist)
204 return;
205
206 fHist->UseCurrentStyle();
207 fHist->SetDirectory(NULL);
208}
209
210// --------------------------------------------------------------------------
211//
212// Default constructor.
213//
214MH3::MH3(const Int_t dim, Type_t type) : fDimension(dim), fHist(NULL)
215{
216 // FIXME?
217 switch (type)
218 {
219 case kHistogram:
220 if (fDimension>3)
221 fDimension=3;
222 break;
223 case kProfile:
224 fDimension = -TMath::Abs(fDimension);
225 if (fDimension<-2)
226 fDimension = -2;
227 break;
228 }
229
230 switch (fDimension)
231 {
232 case 1:
233 fHist = new TH1D;
234 fHist->SetYTitle("Counts");
235 break;
236 case -1:
237 fHist = new TProfile;
238 fHist->SetYTitle("Average");
239 break;
240 case 2:
241 fHist = new TH2D;
242 fHist->SetZTitle("Counts");
243 break;
244 case -2:
245 fHist = new TProfile2D;
246 fHist->SetZTitle("Average");
247 break;
248 case 3:
249 fHist = new TH3D;
250 break;
251 }
252
253 fData[0] = NULL;
254 fData[1] = NULL;
255 fData[2] = NULL;
256
257 Init();
258}
259
260// --------------------------------------------------------------------------
261//
262// Creates an TH1D. memberx is filled into the X-bins. For a more detailed
263// description see the class description above.
264//
265MH3::MH3(const char *memberx, Type_t type) : fDimension(1)
266{
267 fHist = new TH1D;
268 fHist->SetYTitle("Counts");
269
270 fData[0] = new MDataPhrase(memberx);
271 fData[1] = NULL;
272 fData[2] = NULL;
273
274 Init();
275}
276
277// --------------------------------------------------------------------------
278//
279// Adapt a given histogram
280//
281MH3::MH3(const TH1 &h1) : fDimension(1)
282{
283 if (h1.InheritsFrom(TH3::Class()))
284 fDimension = 3;
285 if (h1.InheritsFrom(TH2::Class()))
286 fDimension = 2;
287
288 if (h1.InheritsFrom(TProfile2D::Class()))
289 fDimension = -2;
290 if (h1.InheritsFrom(TProfile::Class()))
291 fDimension = -1;
292
293 fHist = (TH1*)h1.Clone();
294
295 fData[0] = NULL;
296 fData[1] = NULL;
297 fData[2] = NULL;
298
299 switch (fDimension)
300 {
301 case 3:
302 case -2:
303 fData[2] = new MDataPhrase(h1.GetZaxis()->GetTitle());
304 case 2:
305 case -1:
306 fData[1] = new MDataPhrase(h1.GetYaxis()->GetTitle());
307 case 1:
308 fData[0] = new MDataPhrase(h1.GetXaxis()->GetTitle());
309 }
310
311 Init(); // Before without SeUseCurrentStyle!
312}
313
314// --------------------------------------------------------------------------
315//
316// Creates an TH2D. memberx is filled into the X-bins. membery is filled
317// into the Y-bins. For a more detailed description see the class
318// description above.
319//
320MH3::MH3(const char *memberx, const char *membery, Type_t type)
321 : fDimension(type&kProfile?-1:2)
322{
323
324 switch (fDimension)
325 {
326 case 2:
327 fHist = static_cast<TH1*>(new TH2D);
328 break;
329 case -1:
330 fHist = static_cast<TH1*>(new TProfile);
331 break;
332 }
333
334 fHist->SetZTitle(fDimension>0?"Counts":"Average");
335
336 fData[0] = new MDataPhrase(memberx);
337 fData[1] = new MDataPhrase(membery);
338 fData[2] = NULL;
339
340 Init();
341}
342
343// --------------------------------------------------------------------------
344//
345// Creates an TH3D. memberx is filled into the X-bins. membery is filled
346// into the Y-bins. membery is filled into the Z-bins. For a more detailed
347// description see the class description above.
348//
349MH3::MH3(const char *memberx, const char *membery, const char *memberz, Type_t type)
350 : fDimension(type==kHistogram?3:-2)
351{
352 fHist = type&kProfile ? static_cast<TH1*>(new TProfile2D) : static_cast<TH1*>(new TH3D);
353
354 fData[0] = new MDataPhrase(memberx);
355 fData[1] = new MDataPhrase(membery);
356 fData[2] = new MDataPhrase(memberz);
357
358 Init();
359}
360
361// --------------------------------------------------------------------------
362//
363// Deletes the histogram
364//
365MH3::~MH3()
366{
367 delete fHist;
368
369 for (int i=0; i<4; i++)
370 if (fData[i])
371 delete fData[i];
372
373 for (int i=0; i<3; i++)
374 if (fLabels[i].GetDefault())
375 delete fLabels[i].GetDefault();
376}
377
378// --------------------------------------------------------------------------
379//
380// You can set a weight as a phrase additionally to the one given
381// as an argument to Fill (most likely from MFillH). The two weights
382// are multiplied together.
383//
384void MH3::SetWeight(const char *phrase)
385{
386 if (fData[3])
387 delete fData[3];
388 fData[3] = new MDataPhrase(phrase);
389}
390
391// --------------------------------------------------------------------------
392//
393// The axis label is centered and the labeling of the axis is initialized.
394//
395// This function must not be called after any label has been created!
396//
397void MH3::InitLabels(TAxis &x) const
398{
399 x.CenterTitle();
400 x.SetBinLabel(1, "");
401 x.LabelsOption("h"); // FIXME: Is "a" thread safe? (Paint and Fill?)
402 x.GetLabels()->Delete();
403}
404
405// --------------------------------------------------------------------------
406//
407// Depending on the bits set the InitLabels(TAxis&) function for
408// the corresponding axes are called. In any case the kCanRebin bit
409// is set.
410//
411// This function must not be called after any label has been created!
412//
413void MH3::InitLabels(Labels_t type) const
414{
415 if (!fHist)
416 return;
417
418 if (type&kLabelsX && fHist->GetXaxis())
419 InitLabels(*fHist->GetXaxis());
420
421 if (type&kLabelsY && fHist->GetYaxis())
422 InitLabels(*fHist->GetYaxis());
423
424 if (type&kLabelsZ && fHist->GetZaxis())
425 InitLabels(*fHist->GetZaxis());
426
427 if (type&kLabelsXYZ)
428 fHist->SetBit(TH1::kCanRebin);
429}
430
431// --------------------------------------------------------------------------
432//
433// Return the corresponding Labels_t describing for which axis
434// axis-labels are switched on.
435//
436MH3::Labels_t MH3::GetLabels() const
437{
438 UInt_t type = kNoLabels;
439 if (fHist->GetXaxis() && fHist->GetXaxis()->GetLabels())
440 type |= kLabelsX;
441 if (fHist->GetYaxis() && fHist->GetYaxis()->GetLabels())
442 type |= kLabelsY;
443 if (fHist->GetZaxis() && fHist->GetZaxis()->GetLabels())
444 type |= kLabelsZ;
445 return (Labels_t)type;
446}
447
448// --------------------------------------------------------------------------
449//
450// Calls the LabelsDeflate from the histogram for all axes.
451// LabelsDeflate will just do nothing if the axis has no labels
452// initialized.
453//
454void MH3::DeflateLabels() const
455{
456 fHist->LabelsDeflate("X");
457 fHist->LabelsDeflate("Y");
458 fHist->LabelsDeflate("Z");
459}
460
461// --------------------------------------------------------------------------
462//
463// Returns the named label corresponding to the given value
464// and the given axis. The names are defined with the
465// DefineLabel-functions. if no name is defined the value
466// is converted to a string with %d and TMath::Nint.
467// If names are defined, but not for the given value, the default
468// label is returned instead. If no default is defined the
469// %d-converted string is returned.
470//
471const char *MH3::GetLabel(Int_t axe, Double_t val) const
472{
473 const Int_t v = TMath::Nint(val);
474
475 if (fLabels[axe].GetSize())
476 {
477 const char *l = fLabels[axe].GetObjName(v);
478 if (l)
479 return l;
480 }
481
482 return Form("%d", v);
483}
484
485// --------------------------------------------------------------------------
486//
487// Return the data members used by the data chain to be used in
488// MTask::AddBranchToList
489//
490TString MH3::GetDataMember() const
491{
492 TString str=fData[0]->GetDataMember();
493
494 for (int i=1; i<4; i++)
495 if (fData[i])
496 {
497 str += ";";
498 str += fData[i]->GetDataMember();
499 }
500
501 return str;
502}
503
504// --------------------------------------------------------------------------
505//
506// Setup the Binning for the histograms automatically if the correct
507// instances of MBinning are found in the parameter list
508// For a more detailed description see class description above.
509//
510Bool_t MH3::SetupFill(const MParList *plist)
511{
512 // reset histogram (necessary if the same eventloop is run more than once)
513 fHist->Reset();
514
515 // Tokenize name into name and binnings names
516 TObjArray *tok = fName.Tokenize(";");
517
518 const TString name = (*tok)[0] ? (*tok)[0]->GetName() : fName.Data();
519
520 TString bx = (*tok)[1] ? (*tok)[1]->GetName() : Form("%sX", name.Data());
521 TString by = (*tok)[2] ? (*tok)[2]->GetName() : Form("%sY", name.Data());
522 TString bz = (*tok)[3] ? (*tok)[3]->GetName() : Form("%sZ", name.Data());
523
524 bx.Prepend("Binning");
525 by.Prepend("Binning");
526 bz.Prepend("Binning");
527
528 delete tok;
529
530 MBinning *binsx = NULL;
531 MBinning *binsy = NULL;
532 MBinning *binsz = NULL;
533
534 const Labels_t labels = GetLabels();
535
536 switch (TMath::Abs(fDimension))
537 {
538 case 3:
539 if (fData[2])
540 fHist->SetZTitle(fData[2]->GetTitle());
541 if (!(labels&kLabelsZ))
542 {
543 binsz = fBins[2] ? fBins[2] : (MBinning*)plist->FindObject(bz, "MBinning");
544 if (!binsz)
545 {
546 *fLog << err << dbginf << "MBinning '" << bz << "' not found... aborting." << endl;
547 return kFALSE;
548 }
549 if (binsz->HasTitle())
550 fHist->SetZTitle(binsz->GetTitle());
551 if (binsz->IsLogarithmic())
552 fHist->SetBit(kIsLogz);
553 }
554 case 2:
555 if (fData[1])
556 fHist->SetYTitle(fData[1]->GetTitle());
557 if (!(labels&kLabelsY))
558 {
559 binsy = fBins[1] ? fBins[1] : (MBinning*)plist->FindObject(by, "MBinning");
560 if (!binsy)
561 {
562 *fLog << err << dbginf << "MBinning '" << by << "' not found... aborting." << endl;
563 return kFALSE;
564 }
565 if (binsy->HasTitle())
566 fHist->SetYTitle(binsy->GetTitle());
567 if (binsy->IsLogarithmic())
568 fHist->SetBit(kIsLogy);
569 }
570 case 1:
571 if (fData[0]!=NULL)
572 fHist->SetXTitle(fData[0]->GetTitle());
573 if (!(labels&kLabelsX))
574 {
575 binsx = fBins[0] ? fBins[0] : (MBinning*)plist->FindObject(bx, "MBinning");
576 if (!binsx)
577 {
578 if (fDimension==1)
579 binsx = (MBinning*)plist->FindObject("Binning"+fName, "MBinning");
580
581 if (!binsx)
582 {
583 *fLog << err << dbginf << "Neither '" << bx << "' nor '" << fName << "' found... aborting." << endl;
584 return kFALSE;
585 }
586 }
587 if (binsx->HasTitle())
588 fHist->SetXTitle(binsx->GetTitle());
589 if (binsx->IsLogarithmic())
590 fHist->SetBit(kIsLogx);
591 }
592 }
593
594 // PreProcess existing fData members
595 for (int i=0; i<4; i++)
596 if (fData[i] && !fData[i]->PreProcess(plist))
597 return kFALSE;
598
599 TString title(fDimension>0?"Histogram":"Profile");
600 title += " for ";
601 title += name;
602 title += Form(" (%dD)", TMath::Abs(fDimension));
603
604 fHist->SetName(name);
605 fHist->SetTitle(fTitle==gsDefTitle ? title : fTitle);
606 fHist->SetDirectory(0);
607
608 // This is for the case we have set lables
609 const MBinning def(1, 0, 1);
610 if (!binsx)
611 binsx = const_cast<MBinning*>(&def);
612 if (!binsy)
613 binsy = const_cast<MBinning*>(&def);
614 if (!binsz)
615 binsz = const_cast<MBinning*>(&def);
616
617 // set binning
618 switch (TMath::Abs(fDimension))
619 {
620 case 1:
621 SetBinning(fHist, binsx);
622 return kTRUE;
623 case 2:
624 SetBinning(static_cast<TH2*>(fHist), binsx, binsy);
625 return kTRUE;
626 case 3:
627 SetBinning(static_cast<TH3*>(fHist), binsx, binsy, binsz);
628 return kTRUE;
629 }
630
631 *fLog << err << "ERROR - MH3 has " << TMath::Abs(fDimension) << " dimensions!" << endl;
632 return kFALSE;
633}
634
635// --------------------------------------------------------------------------
636//
637// Set the name of the histogram ant the MH3 container
638//
639void MH3::SetName(const char *name)
640{
641 if (fHist)
642 {
643 if (gPad)
644 {
645 const TString pfx(Form("%sProfX", fHist->GetName()));
646 const TString pfy(Form("%sProfY", fHist->GetName()));
647
648 TProfile *p = 0;
649 if ((p=dynamic_cast<TProfile*>(gPad->FindObject(pfx))))
650 p->SetName(Form("%sProfX", name));
651 if ((p=dynamic_cast<TProfile*>(gPad->FindObject(pfy))))
652 p->SetName(Form("%sProfY", name));
653 }
654
655 fHist->SetName(name);
656 fHist->SetDirectory(0);
657
658 }
659 MParContainer::SetName(name);
660}
661
662// --------------------------------------------------------------------------
663//
664// Set the title of the histogram ant the MH3 container
665//
666void MH3::SetTitle(const char *title)
667{
668 if (fHist)
669 fHist->SetTitle(title);
670 MParContainer::SetTitle(title);
671}
672
673// --------------------------------------------------------------------------
674//
675// Fills the one, two or three data members into our histogram
676//
677Int_t MH3::Fill(const MParContainer *par, const Stat_t ww)
678{
679 // Get Information about labels (UInt_t, to supress warning about
680 // unhandeled cases in switch)
681 const UInt_t type = GetLabels();
682
683 // Get values for axis
684 Double_t x=0;
685 Double_t y=0;
686 Double_t z=0;
687 Double_t w=ww;
688
689 switch (fDimension)
690 {
691 case -2:
692 case 3:
693 z = fData[2]->GetValue()*fScale[2];
694 case -1:
695 case 2:
696 y = fData[1]->GetValue()*fScale[1];
697 case 1:
698 x = fData[0]->GetValue()*fScale[0];
699 }
700
701 if (fData[3])
702 w *= fData[3]->GetValue();
703
704 // If label option is set, convert value to label
705 TString labelx, labely, labelz;
706 if (type&kLabelsX)
707 labelx = GetLabel(0, x);
708 if (type&kLabelsY)
709 labely = GetLabel(1, y);
710 if (type&kLabelsZ)
711 labelz = GetLabel(2, z);
712
713 // Fill histogram
714 switch (fDimension)
715 {
716 case 3:
717 switch (type)
718 {
719 case kNoLabels:
720 static_cast<TH3*>(fHist)->Fill(x, y, z, w);
721 return kTRUE;
722 case kLabelsX:
723 static_cast<TH3*>(fHist)->Fill(labelx, y, z);
724 return kTRUE;
725 case kLabelsY:
726 static_cast<TH3*>(fHist)->Fill(x, labely, z, w);
727 return kTRUE;
728 case kLabelsZ:
729 static_cast<TH3*>(fHist)->Fill(x, y, labelz, w);
730 return kTRUE;
731 case kLabelsXY:
732 static_cast<TH3*>(fHist)->Fill(labelx, labely, z, w);
733 return kTRUE;
734 case kLabelsXZ:
735 static_cast<TH3*>(fHist)->Fill(labelx, y, labelz, w);
736 return kTRUE;
737 case kLabelsYZ:
738 static_cast<TH3*>(fHist)->Fill(x, labely, labelz, w);
739 return kTRUE;
740 case kLabelsXYZ:
741 static_cast<TH3*>(fHist)->Fill(labelx, labely, labelz, w);
742 return kTRUE;
743 }
744 break;
745 case 2:
746 switch (type)
747 {
748 case kNoLabels:
749 static_cast<TH2*>(fHist)->Fill(x, y, w);
750 return kTRUE;
751 case kLabelsX:
752 static_cast<TH2*>(fHist)->Fill(x, labely, w);
753 return kTRUE;
754 case kLabelsY:
755 static_cast<TH2*>(fHist)->Fill(labelx, y, w);
756 return kTRUE;
757 case kLabelsXY:
758 static_cast<TH2*>(fHist)->Fill(labelx, labely, w);
759 return kTRUE;
760 }
761 break;
762 case 1:
763 switch (type)
764 {
765 case kNoLabels:
766 fHist->Fill(x, w);
767 return kTRUE;
768 case kLabelsX:
769 fHist->Fill(labelx, w);
770 return kTRUE;
771 }
772 break;
773 case -1:
774 switch (type)
775 {
776 case kNoLabels:
777 static_cast<TProfile*>(fHist)->Fill(x, y, w);
778 return kTRUE;
779 case kLabelsX:
780 static_cast<TProfile*>(fHist)->Fill(labelx, y, w);
781 return kTRUE;
782 }
783 break;
784 case -2:
785 switch (type)
786 {
787 case kNoLabels:
788 static_cast<TProfile2D*>(fHist)->Fill(x, y, z, w);
789 return kTRUE;
790 case kLabelsX:
791 static_cast<TProfile2D*>(fHist)->Fill(labelx, y, z);
792 return kTRUE;
793 case kLabelsY:
794 static_cast<TProfile2D*>(fHist)->Fill(x, labely, z);
795 return kTRUE;
796 case kLabelsXY:
797 static_cast<TProfile2D*>(fHist)->Fill(labelx, labely, z);
798 return kTRUE;
799 }
800 break;
801 }
802
803 *fLog << err << "MH3::Fill: ERROR - A fatal error occured." << endl;
804 return kERROR;
805}
806
807// --------------------------------------------------------------------------
808//
809// If an auto range bit is set the histogram range of the corresponding
810// axis is set to show only the non-empty bins (with a single empty bin
811// on both sides)
812//
813Bool_t MH3::Finalize()
814{
815 DeflateLabels();
816
817 Bool_t autorangex=TESTBIT(fStyleBits, 0);
818 Bool_t autorangey=TESTBIT(fStyleBits, 1);
819 //Bool_t autorangez=TESTBIT(fStyleBits, 2);
820
821 Int_t lo, hi;
822 if (autorangex)
823 {
824 GetRangeX(*fHist, lo, hi);
825 fHist->GetXaxis()->SetRange(lo-2, hi+1);
826 }
827 if (autorangey)
828 {
829 GetRangeY(*fHist, lo, hi);
830 fHist->GetYaxis()->SetRange(lo-2, hi+1);
831 }
832 /*
833 if (autorangez)
834 {
835 GetRangeZ(*fHist, lo, hi);
836 fHist->GetZaxis()->SetRange(lo-2, hi+1);
837 }
838 */
839 return kTRUE;
840}
841
842// --------------------------------------------------------------------------
843//
844// FIXME
845//
846void MH3::Paint(Option_t *o)
847{
848 TProfile *p=0;
849
850 if (TMath::Abs(fDimension)==2)
851 MH::SetPalette("pretty");
852
853 const TString pfx(Form("%sProfX", fHist->GetName()));
854 if ((p=dynamic_cast<TProfile*>(gPad->FindObject(pfx))))
855 {
856 Int_t col = p->GetLineColor();
857 p = ((TH2*)fHist)->ProfileX(pfx, -1, -1, "s");
858 p->SetLineColor(col);
859 }
860
861 const TString pfy(Form("%sProfY", fHist->GetName()));
862 if ((p=dynamic_cast<TProfile*>(gPad->FindObject(pfy))))
863 {
864 Int_t col = p->GetLineColor();
865 p = ((TH2*)fHist)->ProfileY(pfy, -1, -1, "s");
866 p->SetLineColor(col);
867 }
868/*
869 if (fHist->TestBit(kIsLogx) && fHist->GetEntries()>0) gPad->SetLogx();
870 if (fHist->TestBit(kIsLogy) && fHist->GetEntries()>0) gPad->SetLogy();
871 if (fHist->TestBit(kIsLogz) && fHist->GetEntries()>0) gPad->SetLogz();
872 */
873}
874
875// --------------------------------------------------------------------------
876//
877// If Xmax is < 3000*Xmin SetMoreLogLabels is called. If Xmax<5000
878// the exponent is switched off (SetNoExponent)
879//
880void MH3::HandleLogAxis(TAxis &axe) const
881{
882 if (axe.GetXmax()>3000*axe.GetXmin())
883 return;
884
885 axe.SetMoreLogLabels();
886 if (axe.GetXmax()<5000)
887 axe.SetNoExponent();
888}
889
890// --------------------------------------------------------------------------
891//
892// Creates a new canvas and draws the histogram into it.
893//
894// Possible options are:
895// PROFX: Draw a x-profile into the histogram (for 2D histograms only)
896// PROFY: Draw a y-profile into the histogram (for 2D histograms only)
897// ONLY: Draw the profile histogram only (for 2D histograms only)
898// BLUE: Draw the profile in blue color instead of the histograms
899// line color
900//
901// If the kIsLog?-Bit is set the axis is displayed lkogarithmically.
902// eg this is set when applying a logarithmic MBinning
903//
904// Be careful: The histogram belongs to this object and won't get deleted
905// together with the canvas.
906//
907void MH3::Draw(Option_t *opt)
908{
909 TVirtualPad *pad = gPad ? gPad : MakeDefCanvas(fHist);
910 pad->SetBorderMode(0);
911 pad->SetGridx();
912 pad->SetGridy();
913
914 if (fHist->TestBit(kIsLogx))
915 {
916 pad->SetLogx();
917 HandleLogAxis(*fHist->GetXaxis());
918 }
919 if (fHist->TestBit(kIsLogy))
920 {
921 pad->SetLogy();
922 HandleLogAxis(*fHist->GetYaxis());
923 }
924 if (fHist->TestBit(kIsLogz))
925 {
926 pad->SetLogz();
927 HandleLogAxis(*fHist->GetZaxis());
928 }
929
930 fHist->SetFillStyle(4000);
931
932 TString str(opt);
933 str.ToLower();
934
935 if (GetLabels())
936 {
937 if (str.IsNull() && fDimension==2)
938 str = "colz";
939
940 if (str.Contains("box", TString::kIgnoreCase) && fDimension==2)
941 fHist->SetLineColor(kBlue);
942 }
943
944 const Bool_t only = str.Contains("only") && TMath::Abs(fDimension)==2;
945 const Bool_t same = str.Contains("same") && TMath::Abs(fDimension)<3;
946 const Bool_t blue = str.Contains("blue") && TMath::Abs(fDimension)==2;
947 const Bool_t profx = str.Contains("profx") && TMath::Abs(fDimension)==2;
948 const Bool_t profy = str.Contains("profy") && TMath::Abs(fDimension)==2;
949
950 str.ReplaceAll("only", "");
951 str.ReplaceAll("blue", "");
952 str.ReplaceAll("profx", "");
953 str.ReplaceAll("profy", "");
954 str.ReplaceAll(" ", "");
955
956 if (same && TMath::Abs(fDimension)==1)
957 {
958 fHist->SetLineColor(kBlue);
959 fHist->SetMarkerColor(kBlue);
960 }
961
962 // FIXME: We may have to remove all our own options from str!
963 if (!only)
964 fHist->Draw(str);
965
966 AppendPad();
967
968 TProfile *p=0;
969 if (profx)
970 {
971 const TString pfx(Form("%sProfX", fHist->GetName()));
972
973 if (same && (p=dynamic_cast<TProfile*>(gPad->FindObject(pfx))))
974 *fLog << warn << "TProfile " << pfx << " already in pad." << endl;
975
976 p = ((TH2*)fHist)->ProfileX(pfx, -1, -1, "s");
977 p->UseCurrentStyle();
978 p->SetLineColor(blue ? kBlue : fHist->GetLineColor());
979 p->SetBit(kCanDelete);
980 p->SetDirectory(NULL);
981 p->SetXTitle(fHist->GetXaxis()->GetTitle());
982 p->SetYTitle(fHist->GetYaxis()->GetTitle());
983 p->Draw(only&&!same?"":"same");
984 }
985 if (profy)
986 {
987 const TString pfy(Form("%sProfY", fHist->GetName()));
988
989 if (same && (p=dynamic_cast<TProfile*>(gPad->FindObject(pfy))))
990 *fLog << warn << "TProfile " << pfy << " already in pad." << endl;
991
992 p = ((TH2*)fHist)->ProfileY(pfy, -1, -1, "s");
993 p->UseCurrentStyle();
994 p->SetLineColor(blue ? kBlue : fHist->GetLineColor());
995 p->SetBit(kCanDelete);
996 p->SetDirectory(NULL);
997 p->SetYTitle(fHist->GetXaxis()->GetTitle());
998 p->SetXTitle(fHist->GetYaxis()->GetTitle());
999 p->Draw(only&&!same?"":"same");
1000 }
1001
1002 //AppendPad("log");
1003}
1004
1005// --------------------------------------------------------------------------
1006//
1007// Implementation of SavePrimitive. Used to write the call to a constructor
1008// to a macro. In the original root implementation it is used to write
1009// gui elements to a macro-file.
1010//
1011void MH3::StreamPrimitive(ostream &out) const
1012{
1013 TString name = GetUniqueName();
1014
1015 out << " MH3 " << name << "(\"";
1016 out << fData[0]->GetRule() << "\"";
1017 if (fDimension>1 || fDimension<0)
1018 out << ", \"" << fData[1]->GetRule() << "\"";
1019 if (fDimension>2 || fDimension<-1)
1020 out << ", \"" << fData[2]->GetRule() << "\"";
1021
1022 out << ");" << endl;
1023
1024 if (fName!=gsDefName)
1025 out << " " << name << ".SetName(\"" << fName << "\");" << endl;
1026
1027 if (fTitle!=gsDefTitle)
1028 out << " " << name << ".SetTitle(\"" << fTitle << "\");" << endl;
1029
1030 if (fData[3])
1031 out << " " << name << ".SetWeight(\"" << fData[3]->GetRule() << "\");" << endl;
1032
1033 switch (fDimension)
1034 {
1035 case -2:
1036 case 3:
1037 if (fScale[2]!=1)
1038 out << " " << name << ".SetScaleZ(" << fScale[2] << ");" << endl;
1039 case -1:
1040 case 2:
1041 if (fScale[1]!=1)
1042 out << " " << name << ".SetScaleY(" << fScale[1] << ");" << endl;
1043 case 1:
1044 if (fScale[0]!=1)
1045 out << " " << name << ".SetScaleX(" << fScale[0] << ");" << endl;
1046 }
1047}
1048
1049// --------------------------------------------------------------------------
1050//
1051// Used to rebuild a MH3 object of the same type (data members,
1052// dimension, ...)
1053//
1054MParContainer *MH3::New() const
1055{
1056 // FIXME: TREAT THE NEW OPTIONS CORRECTLY (PROFILE, LABELS)
1057
1058 MH3 *h = NULL;
1059
1060 if (fData[0] == NULL)
1061 h=new MH3(fDimension);
1062 else
1063 switch (fDimension)
1064 {
1065 case 1:
1066 h=new MH3(fData[0]->GetRule());
1067 break;
1068 case 2:
1069 h=new MH3(fData[0]->GetRule(), fData[1]->GetRule());
1070 break;
1071 case -1:
1072 h=new MH3(fData[0]->GetRule(), fData[1]->GetRule(), MH3::kProfile);
1073 break;
1074 case 3:
1075 h=new MH3(fData[0]->GetRule(), fData[1]->GetRule(), fData[2]->GetRule());
1076 break;
1077 case -2:
1078 h=new MH3(fData[0]->GetRule(), fData[1]->GetRule(), fData[2]->GetRule(), MH3::kProfile);
1079 break;
1080 }
1081
1082 switch (fDimension)
1083 {
1084 case -2:
1085 case 3:
1086 h->SetScaleZ(fScale[2]);
1087 case 2:
1088 case -1:
1089 h->SetScaleY(fScale[1]);
1090 case 1:
1091 h->SetScaleX(fScale[0]);
1092 }
1093
1094 if (fData[3])
1095 h->SetWeight(fData[3]->GetRule());
1096
1097 return h;
1098}
1099
1100// --------------------------------------------------------------------------
1101//
1102// FIXME
1103//
1104TString MH3::GetRule(const Char_t axis) const
1105{
1106 switch (tolower(axis))
1107 {
1108 case 'x':
1109 case 'X':
1110 return fData[0] ? fData[0]->GetRule() : TString("");
1111 case 'y':
1112 case 'Y':
1113 return fData[1] ? fData[1]->GetRule() : TString("");
1114 case 'z':
1115 case 'Z':
1116 return fData[2] ? fData[2]->GetRule() : TString("");
1117 case 'w':
1118 case 'W':
1119 return fData[3] ? fData[3]->GetRule() : TString("");
1120 default:
1121 return "<n/a>";
1122 }
1123}
1124
1125// --------------------------------------------------------------------------
1126//
1127// Returns the total number of bins in a histogram (excluding under- and
1128// overflow bins)
1129//
1130Int_t MH3::GetNbins() const
1131{
1132 Int_t num = 1;
1133
1134 switch (TMath::Abs(fDimension))
1135 {
1136 case 3:
1137 num *= fHist->GetNbinsZ()+2;
1138 case 2:
1139 num *= fHist->GetNbinsY()+2;
1140 case 1:
1141 num *= fHist->GetNbinsX()+2;
1142 }
1143
1144 return num;
1145}
1146
1147// --------------------------------------------------------------------------
1148//
1149// Returns the total number of bins in a histogram (excluding under- and
1150// overflow bins) Return -1 if bin is underflow or overflow
1151//
1152Int_t MH3::FindFixBin(Double_t x, Double_t y, Double_t z) const
1153{
1154 const TAxis &axex = *fHist->GetXaxis();
1155 const TAxis &axey = *fHist->GetYaxis();
1156 const TAxis &axez = *fHist->GetZaxis();
1157
1158 Int_t binz = 0;
1159 Int_t biny = 0;
1160 Int_t binx = 0;
1161
1162 switch (fDimension)
1163 {
1164 case 3:
1165 case -2:
1166 binz = axez.FindFixBin(z);
1167 if (binz>axez.GetLast() || binz<axez.GetFirst())
1168 return -1;
1169 case 2:
1170 case -1:
1171 biny = axey.FindFixBin(y);
1172 if (biny>axey.GetLast() || biny<axey.GetFirst())
1173 return -1;
1174 case 1:
1175 binx = axex.FindFixBin(x);
1176 if (binx<axex.GetFirst() || binx>axex.GetLast())
1177 return -1;
1178 }
1179
1180 const Int_t nx = fHist->GetNbinsX()+2;
1181 const Int_t ny = fHist->GetNbinsY()+2;
1182
1183 return binx + nx*(biny +ny*binz);
1184}
1185
1186// --------------------------------------------------------------------------
1187//
1188// Return the MObjLookup corresponding to the axis/character.
1189// Note that only lower-case charecters (x, y, z) are supported.
1190// If for the axis no labels were set, the corresponding
1191// InitLabels is called.
1192//
1193MObjLookup *MH3::GetLabels(char axe)
1194{
1195 if (!fHist)
1196 return 0;
1197
1198 TAxis *x = 0;
1199
1200 switch (axe)
1201 {
1202 case 'x':
1203 x = fHist->GetXaxis();
1204 break;
1205 case 'y':
1206 x = fHist->GetYaxis();
1207 break;
1208 case 'z':
1209 x = fHist->GetZaxis();
1210 break;
1211 }
1212
1213 if (!x)
1214 return 0;
1215
1216 const Int_t idx = axe-'x';
1217
1218 if (!x->GetLabels())
1219 switch (idx)
1220 {
1221 case 0:
1222 InitLabels(kLabelsX);
1223 break;
1224 case 1:
1225 InitLabels(kLabelsY);
1226 break;
1227 case 2:
1228 InitLabels(kLabelsZ);
1229 break;
1230 }
1231
1232 return &fLabels[idx];
1233}
1234
1235// --------------------------------------------------------------------------
1236//
1237// Set a default label which is used if no other is found in the list
1238// of labels. if a default was set already it is overwritten. If the
1239// axis has not yet been initialized to use labels it it now.
1240//
1241void MH3::DefaultLabel(char axe, const char *name)
1242{
1243 MObjLookup *arr = GetLabels(axe);
1244 if (!arr)
1245 return;
1246
1247 if (arr->GetDefault())
1248 {
1249 delete arr->GetDefault();
1250 arr->SetDefault(0);
1251 }
1252
1253 if (name)
1254 arr->SetDefault(new TObjString(name));
1255}
1256
1257// --------------------------------------------------------------------------
1258//
1259// Define a name for a label. More than one label can have the same
1260// name. If the axis has not yet been initialized to use labels
1261// it it now.
1262//
1263void MH3::DefineLabel(char axe, Int_t label, const char *name)
1264{
1265 MObjLookup *arr = GetLabels(axe);
1266
1267 if (!arr || !name)
1268 return;
1269
1270 if (arr->GetObj(label)!=arr->GetDefault())
1271 return;
1272
1273 arr->Add(label, name);
1274}
1275
1276// --------------------------------------------------------------------------
1277//
1278// Define names for labels, like
1279// 1=Trig;2=Cal;4=Ped;8=Lvl2
1280// More than one label can have the same name. If the axis has not
1281// yet been initialized to use labels it it now.
1282//
1283// A default cannot be set here. Use DefaultLabel instead.
1284//
1285void MH3::DefineLabels(char axe, const TString &labels)
1286{
1287 TObjArray *arr = labels.Tokenize(';');
1288
1289 for (int i=0; i<arr->GetEntries(); i++)
1290 {
1291 const char *s = (*arr)[0]->GetName();
1292 const char *v = strchr(s, '=');
1293
1294 if (v)
1295 DefineLabel(axe, atoi(s), v+1);
1296 }
1297
1298 delete arr;
1299}
Note: See TracBrowser for help on using the repository browser.