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

Last change on this file since 7143 was 7142, checked in by tbretz, 20 years ago
*** empty log message ***
File size: 17.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::SetEdges(const Int_t nbins, const Axis_t lo, Axis_t up)
245{
246 const Double_t binsize = nbins<=0 ? 0 : (up-lo)/nbins;
247 fEdges.Set(nbins+1);
248 for (int i=0; i<=nbins; i++)
249 fEdges[i] = binsize*i + lo;
250
251 fType = kIsLinear;
252}
253
254// --------------------------------------------------------------------------
255//
256// Set edged from text. With the following structure:
257//
258// n lo hi [type [title]]
259//
260// n: number of bins
261// lo: lowest edge
262// hi: highest edge
263// type: "lin" <default>, "log", "cos", "asin" (without quotationmarks)
264// title: Whatever the title might be
265//
266// For example:
267// SetEdgesRaw("12 0 1 lin This is the title");
268//
269Bool_t MBinning::SetEdgesRaw(const char *txt)
270{
271 Int_t nbins = 0;
272 Float_t loedge = 0;
273 Float_t upedge = 0;
274 Int_t len = 0;
275 if (3!=sscanf(txt, " %d %f %f %n", &nbins, &loedge, &upedge, &len))
276 {
277 *fLog << warn << GetDescriptor() << "::SetEdges: Not enough arguments... ignored." << endl;
278 return kFALSE;
279 }
280
281 if (loedge>=upedge)
282 {
283 *fLog << warn << GetDescriptor() << "::SetEdges: Lowest edge >= highest edge... ignored." << endl;
284 return kFALSE;
285 }
286
287 TString str(txt);
288 str.Remove(0, len);
289 str = str.Strip(TString::kBoth);
290
291 TString typ(str);
292 Ssiz_t pos = str.First(' ');
293 if (pos>=0)
294 {
295 typ = str(0, pos);
296 str.Remove(0, pos);
297 str = str.Strip(TString::kBoth);
298 if (typ!=(TString)"lin" && typ!=(TString)"log" && typ!=(TString)"cos" && typ!=(TString)"asin")
299 {
300 *fLog << warn << GetDescriptor() << "::SetEdges: Type " << typ << " unknown... ignored." << endl;
301 return kFALSE;
302 }
303 }
304
305 SetEdges(nbins, loedge, upedge, typ.Data());
306
307 if (!str.IsNull())
308 fTitle = str;
309
310 return kTRUE;
311}
312/*
313// --------------------------------------------------------------------------
314//
315// Set edged from text. With the following structure:
316//
317// n= lo= hi= type= title="my title"
318//
319// n: number of bins
320// lo: lowest edge
321// hi: highest edge
322// type: "lin" <default>, "log", "cos" (without quotationmarks)
323// title: Whatever the title might be
324//
325// For example:
326// SetEdgesRaw("12 0 1 lin This is the title");
327//
328Bool_t MBinning::SetEdgesRaw(const char *txt)
329{
330 Int_t nbins = 0;
331 Float_t loedge = 0;
332 Float_t upedge = 0;
333 Int_t len = 0;
334 if (3!=sscanf(txt, " %d %f %f %n", &nbins, &loedge, &upedge, &len))
335 {
336 *fLog << warn << GetDescriptor() << "::SetEdges: Not enough arguments... ignored." << endl;
337 return kFALSE;
338 }
339
340 if (loedge>=upedge)
341 {
342 *fLog << warn << GetDescriptor() << "::SetEdges: Lowest edge >= highest edge... ignored." << endl;
343 return kFALSE;
344 }
345
346 TString str(txt);
347 str.Remove(0, len);
348 str = str.Strip(TString::kBoth);
349
350 TString typ;
351 Ssiz_t pos = str.First(' ');
352 if (pos>=0)
353 {
354 typ = str(0, pos);
355 if (typ!=(TString)"lin" && typ!=(TString)"log" && typ!=(TString)"cos")
356 {
357 *fLog << warn << GetDescriptor() << "::SetEdges: Type " << typ << " unknown... ignored." << endl;
358 return kFALSE;
359 }
360 }
361
362 SetEdges(nbins, loedge, upedge, typ.Data());
363
364 str = str.Strip(TString::kBoth);
365
366 if (!str.IsNull())
367 fTitle = str;
368
369 return kTRUE;
370}
371*/
372// --------------------------------------------------------------------------
373//
374// Calls SetEdgesLog if opt contains "log"
375// Calls SetEdgesCos if opt contains "cos"
376// Calls SetEdges in all other cases
377//
378void MBinning::SetEdges(const Int_t nbins, const Axis_t lo, Axis_t up, const char *opt)
379{
380 const TString o(opt);
381 if (o.Contains("log", TString::kIgnoreCase))
382 {
383 SetEdgesLog(nbins, lo, up);
384 return;
385 }
386 if (o.Contains("asin", TString::kIgnoreCase))
387 {
388 SetEdgesASin(nbins, lo, up);
389 return;
390 }
391 if (o.Contains("cos", TString::kIgnoreCase))
392 {
393 SetEdgesCos(nbins, lo, up);
394 return;
395 }
396 SetEdges(nbins, lo, up);
397}
398
399// --------------------------------------------------------------------------
400//
401// Specify the number of bins <nbins> (not the number of edges), the
402// lowest <lo> and highest <up> Edge (of your histogram)
403//
404void MBinning::SetEdgesLog(const Int_t nbins, const Axis_t lo, Axis_t up)
405{
406 // if (lo==0) ...
407
408 const Double_t binsize = log10(up/lo)/nbins;
409 fEdges.Set(nbins+1);
410 for (int i=0; i<=nbins; i++)
411 fEdges[i] = pow(10, binsize*i) * lo;
412
413 fType = kIsLogarithmic;
414}
415
416// --------------------------------------------------------------------------
417//
418// Specify the number of bins <nbins> (not the number of edges), the
419// lowest [deg] <lo> and highest [deg] <up> Edge (of your histogram)
420//
421void MBinning::SetEdgesCos(const Int_t nbins, const Axis_t lo, Axis_t up)
422{
423 // if (lo==0) ...
424 const Axis_t ld = lo/kRad2Deg;
425 const Axis_t ud = up/kRad2Deg;
426
427 const Double_t cld = ld<0 ? cos(ld)-1 : 1-cos(ld);
428 const Double_t cud = ud<0 ? cos(ud)-1 : 1-cos(ud);
429
430 SetEdgesASin(nbins, ld, ud);
431 /*
432 const Double_t binsize = (cld-cud)/nbins;
433 fEdges.Set(nbins+1);
434 for (int i=0; i<=nbins; i++)
435 {
436 const Double_t a = cld-binsize*i;
437 fEdges[i] = a<0 ? -acos(1+a)*kRad2Deg : acos(1-a)*kRad2Deg;
438 cout << a << " " << fEdges[i] << endl;
439 }
440
441 fType = kIsCosinic;*/
442}
443
444// --------------------------------------------------------------------------
445//
446// Specify the number of bins <nbins> (not the number of edges), the
447// lowest [deg] <lo> and highest [deg] <up> Edge (of your histogram)
448//
449void MBinning::SetEdgesASin(const Int_t nbins, Axis_t lo, Axis_t up)
450{
451 const Double_t binsize = nbins<=0 ? 0 : (up-lo)/nbins;
452 fEdges.Set(nbins+1);
453 for (int i=0; i<=nbins; i++)
454 {
455 const Double_t a = binsize*i + lo;
456 fEdges[i] = a<0 ? -acos(1+a)*kRad2Deg : acos(1-a)*kRad2Deg;
457 }
458
459 fType = kIsCosinic;
460}
461
462// --------------------------------------------------------------------------
463//
464// Apply this binning to the given histogram.
465// (By definition this works only for 1D-histograms. For 2D- and 3D-
466// histograms use MH::SetBinning directly)
467//
468void MBinning::Apply(TH1 &h) const
469{
470 if (h.InheritsFrom("TH2") || h.InheritsFrom("TH3"))
471 {
472 *fLog << warn << "MBinning::Apply: '" << h.GetName() << "' is not a basic TH1 object... no binning applied." << endl;
473 return;
474 }
475
476 MH::SetBinning(&h, this);
477}
478
479// --------------------------------------------------------------------------
480//
481// Print binning.
482//
483void MBinning::Print(Option_t *o) const
484{
485 *fLog << all;
486 *fLog << GetDescriptor() << ": nbins=" << GetNumBins() << " [";
487 *fLog << GetEdgeLo() << ", " << GetEdgeHi() << "] <";
488 switch (fType)
489 {
490 case kIsDefault: *fLog << "default"; break;
491 case kIsLinear: *fLog << "linear"; break;
492 case kIsLogarithmic: *fLog << "logarithmic"; break;
493 case kIsCosinic: *fLog << "consinic"; break;
494 case kIsUserArray: *fLog << "user-array"; break;
495 }
496 *fLog << ">";
497
498 if (fTitle!=gsDefTitle)
499 *fLog << " title=" << fTitle;
500
501 *fLog << endl;
502}
503
504// --------------------------------------------------------------------------
505//
506// Implementation of SavePrimitive. Used to write the call to a constructor
507// to a macro. In the original root implementation it is used to write
508// gui elements to a macro-file.
509//
510void MBinning::StreamPrimitive(ofstream &out) const
511{
512 out << " MBinning " << GetUniqueName();
513 if (fName!=gsDefName || fTitle!=gsDefTitle)
514 {
515 out << "(\"" << fName << "\"";
516 if (fTitle!=gsDefTitle)
517 out << ", \"" << fTitle << "\"";
518 out <<")";
519 }
520 out << ";" << endl;
521
522 if (IsDefault())
523 return;
524
525 if (IsLinear() || IsLogarithmic() || IsCosinic())
526 {
527 out << " " << GetUniqueName() << ".SetEdges";
528 if (IsLogarithmic())
529 out << "Log";
530 if (IsCosinic())
531 out << "Cos";
532 out << "(" << GetNumBins() << ", " << GetEdgeLo() << ", " << GetEdgeHi() << ");" << endl;
533 return;
534 }
535
536 out << " {" << endl;
537 out << " TArrayD dummy;" << endl;
538 for (int i=0; i<GetNumEdges(); i++)
539 out << " dummy[" << i << "]=" << GetEdges()[i] << ";" << endl;
540 out << " " << GetUniqueName() << ".SetEdges(dummy);" << endl;
541 out << " }" << endl;
542}
543
544// --------------------------------------------------------------------------
545//
546// Allows reading a binning from resource files. The structure is as follows
547//
548Int_t MBinning::ReadEnv(const TEnv &env, TString prefix, Bool_t print)
549{
550 Bool_t rc = kFALSE;
551
552 UInt_t nbins = GetNumBins();
553 Float_t edgelo = GetEdgeLo();
554 Float_t edgehi = GetEdgeHi();
555 TString type;
556 if (IsEnvDefined(env, prefix, "NumBins", print))
557 {
558 nbins = GetEnvValue(env, prefix, "NumBins", GetNumBins());
559 rc = kTRUE;
560 }
561 if (IsEnvDefined(env, prefix, "EdgeLo", print))
562 {
563 edgelo = GetEnvValue(env, prefix, "EdgeLo", GetEdgeLo());
564 rc = kTRUE;
565 }
566 if (IsEnvDefined(env, prefix, "EdgeHi", print))
567 {
568 edgehi = GetEnvValue(env, prefix, "EdgeHi", GetEdgeHi());
569 rc = kTRUE;
570 }
571 if (rc==kTRUE && (type==kIsUserArray || type==kIsDefault))
572 type = kIsLinear;
573
574 if (IsEnvDefined(env, prefix, "Type", print))
575 {
576 type = GetEnvValue(env, prefix, "Type", "lin");
577 if (type!=(TString)"lin" && type!=(TString)"log" && type!=(TString)"cos" && type!=(TString)"acos")
578 {
579 *fLog << warn << GetDescriptor() << "::ReadEnv - WARNING: Type is not lin, log nor cos... assuming lin." << endl;
580 type = "lin";
581 }
582 rc = kTRUE;
583 }
584 if (IsEnvDefined(env, prefix, "Edges", print))
585 {
586 if (rc==kTRUE)
587 *fLog << warn << GetDescriptor() << "::ReadEnv - WARNING: 'Edges' found... ignoring any 'NumBins', 'EdgeLo' and 'EdgeHi'" << endl;
588
589 const TString type = GetEnvValue(env, prefix, "Edges", "");
590 //type = kIsUserArray;
591 /* MISSING */
592 rc = kTRUE;
593 *fLog << err << " SORRY USER ARRAY NOT YET IMPLEMENTED" << endl;
594 return kERROR;
595 }
596
597 const Bool_t raw = IsEnvDefined(env, prefix, "Raw", print);
598 //const Bool_t fullbins = IsEnvDefined(env, prefix, "Binning", print);
599 if (!raw && /*!fullbins &&*/ rc==kTRUE)
600 SetEdges(nbins, edgelo, edgehi, type.Data());
601
602 if (rc==kTRUE)
603 *fLog << warn << GetDescriptor() << "::ReadEnv - WARNING: 'Binning' found... ignoring any 'NumBins', 'EdgeLo', 'EdgeHi' and 'Edges'" << endl;
604
605 if (IsEnvDefined(env, prefix, "Title", print))
606 {
607 fTitle = GetEnvValue(env, prefix, "Title", gsDefTitle.Data());
608 rc = kTRUE;
609 }
610
611 if (raw)
612 {
613 const TString txt = GetEnvValue(env, prefix, "Raw", "");
614 if (!SetEdgesRaw(txt.Data()))
615 return kERROR;
616 }
617/*
618 if (fullbins)
619 {
620 TString txt = GetEnvValue(env, prefix, "Binning", "");
621 SetEdgesRaw(txt.Data());
622 }
623 */
624
625 return rc;
626}
Note: See TracBrowser for help on using the repository browser.