source: trunk/MagicSoft/Mars/mhbase/MBinning.cc@ 8698

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