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

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