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

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