source: trunk/Mars/mhbase/MBinning.cc@ 12876

Last change on this file since 12876 was 10166, checked in by tbretz, 14 years ago
Removed the old obsolete cvs header line.
File size: 19.0 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, 01/2002 <mailto:tbretz@astro.uni-wuerzburg.de>
19!
20! Copyright: MAGIC Software Development, 2000-2004
21!
22!
23\* ======================================================================== */
24
25//////////////////////////////////////////////////////////////////////////////
26//
27// MBinning
28//
29// This is a MParCOntainer storing a binning for a histogram. Doing this
30// you are able to distribute a single binning to several histograms
31// in your parameter list.
32//
33// In some classes the title of the container is used to set the
34// axis-title of the corresponding axis in your histogram.
35//
36// For all the features supported see the function descriptions in
37// MBinning and MH
38//
39//////////////////////////////////////////////////////////////////////////////
40#include "MBinning.h"
41
42#include <ctype.h> // tolower
43#include <fstream>
44
45#include <TH1.h> // InheritsFrom
46#include <TMath.h>
47
48#include "MLog.h"
49#include "MLogManip.h"
50
51#include "MParList.h"
52
53#include "MH.h"
54
55ClassImp(MBinning);
56
57using namespace std;
58
59const TString MBinning::gsDefName = "MBinning";
60const TString MBinning::gsDefTitle = "Container describing the binning of an axis";
61
62// --------------------------------------------------------------------------
63//
64// Default Constructor. It sets name and title only. Typically you won't
65// need to change this.
66//
67MBinning::MBinning(const char *name, const char *title)
68{
69 //
70 // set the name and title of this object
71 //
72 fName = name ? name : gsDefName.Data();
73 fTitle = title ? title : gsDefTitle.Data();
74
75 SetEdges(10, 0, 1);
76 fType = kIsDefault;
77}
78
79// --------------------------------------------------------------------------
80//
81// Copy Constructor. If necessary give also name and title.
82//
83MBinning::MBinning(const MBinning &bins, const char *name, const char *title)
84{
85 fName = name ? name : gsDefName.Data();
86 fTitle = title ? title : gsDefTitle.Data();
87
88 SetEdges(bins);
89}
90
91// --------------------------------------------------------------------------
92//
93// Instantiate MBinning with nbins number of bins between lo (lower edge)
94// and hi (upper edge), name name and title title.
95//
96MBinning::MBinning(Int_t nbins, Axis_t lo, Axis_t hi, const char *name, const char *opt, const char *title)
97{
98 fName = name ? name : gsDefName.Data();
99 fTitle = title ? title : gsDefTitle.Data();
100
101 SetEdges(nbins, lo, hi, opt);
102}
103
104// --------------------------------------------------------------------------
105//
106// Initialize Binning from an axis of a TH1. If no title given,
107// a title combined from the axis titles and the TH1 title is
108// used.
109//
110MBinning::MBinning(const TH1 &h, const Char_t axis, const char *name, const char *title)
111{
112 fName = name ? name : gsDefName.Data();
113 fTitle = title ? Form("%s;%s;%s;%s", h.GetTitle(),
114 h.GetXaxis()->GetTitle(),
115 h.GetYaxis()->GetTitle(),
116 h.GetZaxis()->GetTitle()) : gsDefTitle.Data();
117
118 SetEdges(h, axis);
119}
120
121// --------------------------------------------------------------------------
122//
123// Initialize Binning from TAxis.
124//
125MBinning::MBinning(const TAxis &axis, const char *name, const char *title)
126{
127 fName = name ? name : gsDefName.Data();
128 fTitle = title ? title : gsDefTitle.Data();
129
130 SetEdges(axis);
131}
132
133// --------------------------------------------------------------------------
134//
135// Initialize Binning from TArrayD.
136//
137MBinning::MBinning(const TArrayD &axis, const char *name, const char *title)
138{
139 fName = name ? name : gsDefName.Data();
140 fTitle = title ? title : gsDefTitle.Data();
141
142 SetEdges(axis);
143}
144
145// --------------------------------------------------------------------------
146//
147// Search in the parameter list for the binning with name "name". If found,
148// set the edges and title accordingly. Default is name of object.
149// return kTRUE if object found, kFALSE otherwise.
150//
151Bool_t MBinning::SetEdges(const MParList &list, const char *name)
152{
153 MBinning *bins = (MBinning*)list.FindObject(name ? name : fName.Data(), "MBinning");
154 if (!bins)
155 return kFALSE;
156
157 SetEdges(*bins);
158 return kTRUE;
159}
160
161// --------------------------------------------------------------------------
162//
163// Setup the edges stored in MBinning from the TAxis axe
164//
165void MBinning::SetEdges(const TAxis &axe)
166{
167 const TArrayD &arr = *axe.GetXbins();
168 if (arr.GetSize()>0)
169 {
170 SetEdges(arr);
171 return;
172 }
173
174 SetEdges(axe.GetNbins(), axe.GetXmin(), axe.GetXmax());
175}
176
177// --------------------------------------------------------------------------
178//
179// Add a new upper edge to the edges stored in MBinning. The new upper
180// edge must be greater than the current greatest. Using this you can
181// enhance a histogram bin-by-bin, eg:
182// TH1F h("", "", 2, 0, 1);
183// MBinning b;
184// b.SetEdges(h);
185// b.AddEdge(2);
186// b.Apply(h);
187// b.AddEdge(3);
188// b.Apply(h);
189// [...]
190//
191void MBinning::AddEdge(Axis_t up)
192{
193 const UInt_t n = fEdges.GetSize();
194
195 if (up<=fEdges[n-1])
196 {
197 *fLog << warn << dbginf << "WARNING - New upper edge not greater than old upper edge... ignored." << endl;
198 return;
199 }
200
201 fEdges.Set(n+1);
202 fEdges[n] = up;
203
204 fType = kIsUserArray;
205}
206
207// --------------------------------------------------------------------------
208//
209// Removes the first edge
210//
211void MBinning::RemoveFirstEdge()
212{
213 const Int_t n = fEdges.GetSize();
214 for (int i=0; i<n-1; i++)
215 fEdges[i] = fEdges[i+1];
216 fEdges.Set(n-1);
217}
218
219// --------------------------------------------------------------------------
220//
221// Removes the last edge
222//
223void MBinning::RemoveLastEdge()
224{
225 fEdges.Set(fEdges.GetSize()-1);
226}
227
228// --------------------------------------------------------------------------
229//
230// Set the edges in MBinning from a histogram-axis. Which axis is
231// specified by axis ('x', 'y', 'z')
232//
233void MBinning::SetEdges(const TH1 &h, const Char_t axis)
234{
235 switch (tolower(axis))
236 {
237 case 'x':
238 SetEdges(*h.GetXaxis());
239 return;
240 case 'y':
241 SetEdges(*h.GetYaxis());
242 return;
243 case 'z':
244 SetEdges(*h.GetZaxis());
245 return;
246 default:
247 *fLog << warn << "MBinning::SetEdges: Axis '" << axis << "' unknown... using x." << endl;
248 SetEdges(*h.GetXaxis());
249 }
250}
251
252// --------------------------------------------------------------------------
253//
254// Specify the number of bins <nbins> (not the number of edges), the
255// lowest <lo> and highest <up> Edge (of your histogram)
256//
257void MBinning::SetEdgesLin(Int_t nbins, Axis_t lo, Axis_t up)
258{
259 if (nbins<=0)
260 {
261 *fLog << warn << "WARNING - Number of bins cannot be <= 0... reset to 1." << endl;
262 nbins = 1;
263 }
264
265 if (up<lo)
266 {
267 *fLog << warn << "WARNING - Upper edge must be greater than lower edge... exchanging." << endl;
268
269 const Axis_t dummy(lo);
270 lo = up;
271 up = dummy;
272 }
273
274 const Double_t binsize = nbins<=0 ? 0 : (up-lo)/nbins;
275 fEdges.Set(nbins+1);
276 for (int i=0; i<=nbins; i++)
277 fEdges[i] = binsize*i + lo;
278
279 fType = kIsLinear;
280}
281
282// --------------------------------------------------------------------------
283//
284// Set edged from text. With the following structure:
285//
286// n lo hi [type [title]]
287//
288// n: number of bins
289// lo: lowest edge
290// hi: highest edge
291// type: "lin" <default>, "log", "cos", "asin" (without quotationmarks)
292// title: Whatever the title might be
293//
294// For example:
295// SetEdgesRaw("12 0 1 lin This is the title");
296//
297Bool_t MBinning::SetEdgesRaw(const char *txt)
298{
299 Int_t nbins = 0;
300 Float_t loedge = 0;
301 Float_t upedge = 0;
302 Int_t len = 0;
303 if (3!=sscanf(txt, " %d %f %f %n", &nbins, &loedge, &upedge, &len))
304 {
305 *fLog << warn << GetDescriptor() << "::SetEdges: Not enough arguments... ignored." << endl;
306 return kFALSE;
307 }
308
309 if (loedge>=upedge)
310 {
311 *fLog << warn << GetDescriptor() << "::SetEdges: Lowest edge >= highest edge... ignored." << endl;
312 return kFALSE;
313 }
314
315 TString str(txt);
316 str.Remove(0, len);
317 str = str.Strip(TString::kBoth);
318
319 TString typ(str);
320 Ssiz_t pos = str.First(' ');
321 if (pos>=0)
322 {
323 typ = str(0, pos);
324 str.Remove(0, pos);
325 str = str.Strip(TString::kBoth);
326 if (typ!=(TString)"lin" && typ!=(TString)"log" && typ!=(TString)"cos" && typ!=(TString)"asin")
327 {
328 *fLog << warn << GetDescriptor() << "::SetEdges: Type " << typ << " unknown... ignored." << endl;
329 return kFALSE;
330 }
331 }
332
333 SetEdges(nbins, loedge, upedge, typ.Data());
334
335 if (!str.IsNull())
336 fTitle = str;
337
338 return kTRUE;
339}
340/*
341// --------------------------------------------------------------------------
342//
343// Set edged from text. With the following structure:
344//
345// n= lo= hi= type= title="my title"
346//
347// n: number of bins
348// lo: lowest edge
349// hi: highest edge
350// type: "lin" <default>, "log", "cos" (without quotationmarks)
351// title: Whatever the title might be
352//
353// For example:
354// SetEdgesRaw("12 0 1 lin This is the title");
355//
356Bool_t MBinning::SetEdgesRaw(const char *txt)
357{
358 Int_t nbins = 0;
359 Float_t loedge = 0;
360 Float_t upedge = 0;
361 Int_t len = 0;
362 if (3!=sscanf(txt, " %d %f %f %n", &nbins, &loedge, &upedge, &len))
363 {
364 *fLog << warn << GetDescriptor() << "::SetEdges: Not enough arguments... ignored." << endl;
365 return kFALSE;
366 }
367
368 if (loedge>=upedge)
369 {
370 *fLog << warn << GetDescriptor() << "::SetEdges: Lowest edge >= highest edge... ignored." << endl;
371 return kFALSE;
372 }
373
374 TString str(txt);
375 str.Remove(0, len);
376 str = str.Strip(TString::kBoth);
377
378 TString typ;
379 Ssiz_t pos = str.First(' ');
380 if (pos>=0)
381 {
382 typ = str(0, pos);
383 if (typ!=(TString)"lin" && typ!=(TString)"log" && typ!=(TString)"cos")
384 {
385 *fLog << warn << GetDescriptor() << "::SetEdges: Type " << typ << " unknown... ignored." << endl;
386 return kFALSE;
387 }
388 }
389
390 SetEdges(nbins, loedge, upedge, typ.Data());
391
392 str = str.Strip(TString::kBoth);
393
394 if (!str.IsNull())
395 fTitle = str;
396
397 return kTRUE;
398}
399*/
400// --------------------------------------------------------------------------
401//
402// Calls SetEdgesLog if opt contains "log"
403// Calls SetEdgesCos if opt contains "cos"
404// Calls SetEdges in all other cases
405//
406void MBinning::SetEdges(const Int_t nbins, const Axis_t lo, Axis_t up, const char *opt)
407{
408 const TString o(opt);
409 if (o.Contains("log", TString::kIgnoreCase))
410 {
411 SetEdgesLog(nbins, lo, up);
412 return;
413 }
414 if (o.Contains("asin", TString::kIgnoreCase))
415 {
416 SetEdgesASin(nbins, lo, up);
417 return;
418 }
419 if (o.Contains("cos", TString::kIgnoreCase))
420 {
421 SetEdgesCos(nbins, lo, up);
422 return;
423 }
424 SetEdges(nbins, lo, up);
425}
426
427// --------------------------------------------------------------------------
428//
429// Specify the number of bins <nbins> (not the number of edges), the
430// lowest <lo> and highest <up> Edge (of your histogram)
431//
432void MBinning::SetEdgesLog(Int_t nbins, Axis_t lo, Axis_t up)
433{
434 // if (lo==0) ...
435 if (nbins<=0)
436 {
437 *fLog << warn << "WARNING - Number of bins cannot be <= 0... reset to 1." << endl;
438 nbins = 1;
439 }
440
441 if (up<lo)
442 {
443 *fLog << warn << "WARNING - Upper edge must be greater than lower edge... exchanging." << endl;
444
445 const Axis_t dummy(lo);
446 lo = up;
447 up = dummy;
448 }
449
450 const Double_t binsize = log10(up/lo)/nbins;
451 fEdges.Set(nbins+1);
452 for (int i=0; i<=nbins; i++)
453 fEdges[i] = pow(10, binsize*i) * lo;
454
455 fType = kIsLogarithmic;
456}
457
458// --------------------------------------------------------------------------
459//
460// Specify the number of bins <nbins> (not the number of edges), the
461// lowest [deg] <lo> and highest [deg] <up> Edge (of your histogram)
462//
463void MBinning::SetEdgesCos(Int_t nbins, Axis_t lo, Axis_t up)
464{
465 if (nbins<=0)
466 {
467 *fLog << warn << "WARNING - Number of bins cannot be <= 0... reset to 1." << endl;
468 nbins = 1;
469 }
470
471 if (up<lo)
472 {
473 *fLog << warn << "WARNING - Upper edge must be greater than lower edge... exchanging." << endl;
474
475 const Axis_t dummy(lo);
476 lo = up;
477 up = dummy;
478 }
479
480 // if (lo==0) ...
481 const Axis_t ld = lo/kRad2Deg;
482 const Axis_t ud = up/kRad2Deg;
483
484 const Double_t cld = ld<0 ? cos(ld)-1 : 1-cos(ld);
485 const Double_t cud = ud<0 ? cos(ud)-1 : 1-cos(ud);
486
487 SetEdgesASin(nbins, cld, cud);
488}
489
490// --------------------------------------------------------------------------
491//
492// Specify the number of bins <nbins> (not the number of edges), the
493// lowest [deg] <lo> and highest [deg] <up> Edge (of your histogram)
494//
495void MBinning::SetEdgesASin(Int_t nbins, Axis_t lo, Axis_t up)
496{
497 if (nbins<=0)
498 {
499 *fLog << warn << "WARNING - Number of bins cannot be <= 0... reset to 1." << endl;
500 nbins = 1;
501 }
502
503 if (up<lo)
504 {
505 *fLog << warn << "WARNING - Upper edge must be greater than lower edge... exchanging." << endl;
506
507 const Axis_t dummy(lo);
508 lo = up;
509 up = dummy;
510 }
511
512 const Double_t binsize = nbins<=0 ? 0 : (up-lo)/nbins;
513 fEdges.Set(nbins+1);
514 for (int i=0; i<=nbins; i++)
515 {
516 const Double_t a = binsize*i + lo;
517 fEdges[i] = a<0 ? -acos(1+a)*kRad2Deg : acos(1-a)*kRad2Deg;
518 }
519
520 fType = kIsCosinic;
521}
522
523// --------------------------------------------------------------------------
524//
525// Apply this binning to the given histogram.
526// (By definition this works only for 1D-histograms. For 2D- and 3D-
527// histograms use MH::SetBinning directly)
528//
529void MBinning::Apply(TH1 &h) const
530{
531 if (h.InheritsFrom("TH2") || h.InheritsFrom("TH3"))
532 {
533 *fLog << warn << "MBinning::Apply: '" << h.GetName() << "' is not a basic TH1 object... no binning applied." << endl;
534 return;
535 }
536
537 MH::SetBinning(h, *this);
538}
539
540// --------------------------------------------------------------------------
541//
542// Print binning.
543//
544void MBinning::Print(Option_t *o) const
545{
546 *fLog << all;
547 *fLog << GetDescriptor() << ": nbins=" << GetNumBins() << " [";
548 *fLog << GetEdgeLo() << ", " << GetEdgeHi() << "] <";
549 switch (fType)
550 {
551 case kIsDefault: *fLog << "default"; break;
552 case kIsLinear: *fLog << "linear"; break;
553 case kIsLogarithmic: *fLog << "logarithmic"; break;
554 case kIsCosinic: *fLog << "consinic"; break;
555 case kIsUserArray: *fLog << "user-array"; break;
556 }
557 *fLog << ">";
558
559 if (fTitle!=gsDefTitle)
560 *fLog << " title=" << fTitle;
561
562 *fLog << endl;
563}
564
565// --------------------------------------------------------------------------
566//
567// Implementation of SavePrimitive. Used to write the call to a constructor
568// to a macro. In the original root implementation it is used to write
569// gui elements to a macro-file.
570//
571void MBinning::StreamPrimitive(ostream &out) const
572{
573 out << " MBinning " << GetUniqueName();
574 if (fName!=gsDefName || fTitle!=gsDefTitle)
575 {
576 out << "(\"" << fName << "\"";
577 if (fTitle!=gsDefTitle)
578 out << ", \"" << fTitle << "\"";
579 out <<")";
580 }
581 out << ";" << endl;
582
583 if (IsDefault())
584 return;
585
586 if (IsLinear() || IsLogarithmic() || IsCosinic())
587 {
588 out << " " << GetUniqueName() << ".SetEdges";
589 if (IsLogarithmic())
590 out << "Log";
591 if (IsCosinic())
592 out << "Cos";
593 out << "(" << GetNumBins() << ", " << GetEdgeLo() << ", " << GetEdgeHi() << ");" << endl;
594 return;
595 }
596
597 out << " {" << endl;
598 out << " TArrayD dummy;" << endl;
599 for (int i=0; i<GetNumEdges(); i++)
600 out << " dummy[" << i << "]=" << GetEdges()[i] << ";" << endl;
601 out << " " << GetUniqueName() << ".SetEdges(dummy);" << endl;
602 out << " }" << endl;
603}
604
605// --------------------------------------------------------------------------
606//
607// Allows reading a binning from resource files. The structure is as follows
608//
609Int_t MBinning::ReadEnv(const TEnv &env, TString prefix, Bool_t print)
610{
611 Bool_t rc = kFALSE;
612
613 UInt_t nbins = GetNumBins();
614 Float_t edgelo = GetEdgeLo();
615 Float_t edgehi = GetEdgeHi();
616 TString type;
617 if (IsEnvDefined(env, prefix, "NumBins", print))
618 {
619 nbins = GetEnvValue(env, prefix, "NumBins", GetNumBins());
620 rc = kTRUE;
621 }
622 if (IsEnvDefined(env, prefix, "EdgeLo", print))
623 {
624 edgelo = GetEnvValue(env, prefix, "EdgeLo", GetEdgeLo());
625 rc = kTRUE;
626 }
627 if (IsEnvDefined(env, prefix, "EdgeHi", print))
628 {
629 edgehi = GetEnvValue(env, prefix, "EdgeHi", GetEdgeHi());
630 rc = kTRUE;
631 }
632 if (rc==kTRUE && (type==kIsUserArray || type==kIsDefault))
633 type = kIsLinear;
634
635 if (IsEnvDefined(env, prefix, "Type", print))
636 {
637 type = GetEnvValue(env, prefix, "Type", "lin");
638 if (type!=(TString)"lin" && type!=(TString)"log" && type!=(TString)"cos" && type!=(TString)"acos")
639 {
640 *fLog << warn << GetDescriptor() << "::ReadEnv - WARNING: Type is not lin, log nor cos... assuming lin." << endl;
641 type = "lin";
642 }
643 rc = kTRUE;
644 }
645 if (IsEnvDefined(env, prefix, "Edges", print))
646 {
647 if (rc==kTRUE)
648 *fLog << warn << GetDescriptor() << "::ReadEnv - WARNING: 'Edges' found... ignoring any 'NumBins', 'EdgeLo' and 'EdgeHi'" << endl;
649
650 const TString etype = GetEnvValue(env, prefix, "Edges", "");
651 //type = kIsUserArray;
652 /* MISSING */
653 rc = kTRUE;
654 *fLog << err << " SORRY USER ARRAY NOT YET IMPLEMENTED" << endl;
655 return kERROR;
656 }
657
658 const Bool_t raw = IsEnvDefined(env, prefix, "Raw", print);
659 //const Bool_t fullbins = IsEnvDefined(env, prefix, "Binning", print);
660 if (!raw && /*!fullbins &&*/ rc==kTRUE)
661 SetEdges(nbins, edgelo, edgehi, type.Data());
662
663 if (rc==kTRUE)
664 *fLog << warn << GetDescriptor() << "::ReadEnv - WARNING: 'Binning' found... ignoring any 'NumBins', 'EdgeLo', 'EdgeHi' and 'Edges'" << endl;
665
666 if (IsEnvDefined(env, prefix, "Title", print))
667 {
668 fTitle = GetEnvValue(env, prefix, "Title", gsDefTitle.Data());
669 rc = kTRUE;
670 }
671
672 if (raw)
673 {
674 const TString txt = GetEnvValue(env, prefix, "Raw", "");
675 if (!SetEdgesRaw(txt.Data()))
676 return kERROR;
677 }
678/*
679 if (fullbins)
680 {
681 TString txt = GetEnvValue(env, prefix, "Binning", "");
682 SetEdgesRaw(txt.Data());
683 }
684 */
685
686 return rc;
687}
Note: See TracBrowser for help on using the repository browser.