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

Last change on this file since 7039 was 6954, checked in by tbretz, 20 years ago
*** empty log message ***
File size: 16.7 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" (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")
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("cos", TString::kIgnoreCase))
387 {
388 SetEdgesCos(nbins, lo, up);
389 return;
390 }
391 SetEdges(nbins, lo, up);
392}
393
394// --------------------------------------------------------------------------
395//
396// Specify the number of bins <nbins> (not the number of edges), the
397// lowest <lo> and highest <up> Edge (of your histogram)
398//
399void MBinning::SetEdgesLog(const Int_t nbins, const Axis_t lo, Axis_t up)
400{
401 // if (lo==0) ...
402
403 const Double_t binsize = log10(up/lo)/nbins;
404 fEdges.Set(nbins+1);
405 for (int i=0; i<=nbins; i++)
406 fEdges[i] = pow(10, binsize*i) * lo;
407
408 fType = kIsLogarithmic;
409}
410
411// --------------------------------------------------------------------------
412//
413// Specify the number of bins <nbins> (not the number of edges), the
414// lowest [deg] <lo> and highest [deg] <up> Edge (of your histogram)
415//
416void MBinning::SetEdgesCos(const Int_t nbins, const Axis_t lo, Axis_t up)
417{
418 // if (lo==0) ...
419 const Axis_t ld = lo/kRad2Deg;
420 const Axis_t ud = up/kRad2Deg;
421
422 const Double_t binsize = (cos(ld)-cos(ud))/nbins;
423 fEdges.Set(nbins+1);
424 for (int i=0; i<=nbins; i++)
425 fEdges[i] = acos(cos(ld)-binsize*i)*kRad2Deg;
426
427 fType = kIsCosinic;
428}
429
430// --------------------------------------------------------------------------
431//
432// Apply this binning to the given histogram.
433// (By definition this works only for 1D-histograms. For 2D- and 3D-
434// histograms use MH::SetBinning directly)
435//
436void MBinning::Apply(TH1 &h) const
437{
438 if (h.InheritsFrom("TH2") || h.InheritsFrom("TH3"))
439 {
440 *fLog << warn << "MBinning::Apply: '" << h.GetName() << "' is not a basic TH1 object... no binning applied." << endl;
441 return;
442 }
443
444 MH::SetBinning(&h, this);
445}
446
447// --------------------------------------------------------------------------
448//
449// Print binning.
450//
451void MBinning::Print(Option_t *o) const
452{
453 *fLog << all;
454 *fLog << GetDescriptor() << ": nbins=" << GetNumBins() << " [";
455 *fLog << GetEdgeLo() << ", " << GetEdgeHi() << "] <";
456 switch (fType)
457 {
458 case kIsDefault: *fLog << "default"; break;
459 case kIsLinear: *fLog << "linear"; break;
460 case kIsLogarithmic: *fLog << "logarithmic"; break;
461 case kIsCosinic: *fLog << "consinic"; break;
462 case kIsUserArray: *fLog << "user-array"; break;
463 }
464 *fLog << ">";
465
466 if (fTitle!=gsDefTitle)
467 *fLog << " title=" << fTitle;
468
469 *fLog << endl;
470}
471
472// --------------------------------------------------------------------------
473//
474// Implementation of SavePrimitive. Used to write the call to a constructor
475// to a macro. In the original root implementation it is used to write
476// gui elements to a macro-file.
477//
478void MBinning::StreamPrimitive(ofstream &out) const
479{
480 out << " MBinning " << GetUniqueName();
481 if (fName!=gsDefName || fTitle!=gsDefTitle)
482 {
483 out << "(\"" << fName << "\"";
484 if (fTitle!=gsDefTitle)
485 out << ", \"" << fTitle << "\"";
486 out <<")";
487 }
488 out << ";" << endl;
489
490 if (IsDefault())
491 return;
492
493 if (IsLinear() || IsLogarithmic() || IsCosinic())
494 {
495 out << " " << GetUniqueName() << ".SetEdges";
496 if (IsLogarithmic())
497 out << "Log";
498 if (IsCosinic())
499 out << "Cos";
500 out << "(" << GetNumBins() << ", " << GetEdgeLo() << ", " << GetEdgeHi() << ");" << endl;
501 return;
502 }
503
504 out << " {" << endl;
505 out << " TArrayD dummy;" << endl;
506 for (int i=0; i<GetNumEdges(); i++)
507 out << " dummy[" << i << "]=" << GetEdges()[i] << ";" << endl;
508 out << " " << GetUniqueName() << ".SetEdges(dummy);" << endl;
509 out << " }" << endl;
510}
511
512// --------------------------------------------------------------------------
513//
514// Allows reading a binning from resource files. The structure is as follows
515//
516Int_t MBinning::ReadEnv(const TEnv &env, TString prefix, Bool_t print)
517{
518 Bool_t rc = kFALSE;
519
520 UInt_t nbins = GetNumBins();
521 Float_t edgelo = GetEdgeLo();
522 Float_t edgehi = GetEdgeHi();
523 TString type;
524 if (IsEnvDefined(env, prefix, "NumBins", print))
525 {
526 nbins = GetEnvValue(env, prefix, "NumBins", GetNumBins());
527 rc = kTRUE;
528 }
529 if (IsEnvDefined(env, prefix, "EdgeLo", print))
530 {
531 edgelo = GetEnvValue(env, prefix, "EdgeLo", GetEdgeLo());
532 rc = kTRUE;
533 }
534 if (IsEnvDefined(env, prefix, "EdgeHi", print))
535 {
536 edgehi = GetEnvValue(env, prefix, "EdgeHi", GetEdgeHi());
537 rc = kTRUE;
538 }
539 if (rc==kTRUE && (type==kIsUserArray || type==kIsDefault))
540 type = kIsLinear;
541
542 if (IsEnvDefined(env, prefix, "Type", print))
543 {
544 type = GetEnvValue(env, prefix, "Type", "lin");
545 if (type!=(TString)"lin" && type!=(TString)"log" && type!=(TString)"cos")
546 {
547 *fLog << warn << GetDescriptor() << "::ReadEnv - WARNING: Type is not lin, log nor cos... assuming lin." << endl;
548 type = "lin";
549 }
550 rc = kTRUE;
551 }
552 if (IsEnvDefined(env, prefix, "Edges", print))
553 {
554 if (rc==kTRUE)
555 *fLog << warn << GetDescriptor() << "::ReadEnv - WARNING: 'Edges' found... ignoring any 'NumBins', 'EdgeLo' and 'EdgeHi'" << endl;
556
557 const TString type = GetEnvValue(env, prefix, "Edges", "");
558 //type = kIsUserArray;
559 /* MISSING */
560 rc = kTRUE;
561 *fLog << err << " SORRY USER ARRAY NOT YET IMPLEMENTED" << endl;
562 return kERROR;
563 }
564
565 const Bool_t raw = IsEnvDefined(env, prefix, "Raw", print);
566 //const Bool_t fullbins = IsEnvDefined(env, prefix, "Binning", print);
567 if (!raw && /*!fullbins &&*/ rc==kTRUE)
568 SetEdges(nbins, edgelo, edgehi, type.Data());
569
570 if (rc==kTRUE)
571 *fLog << warn << GetDescriptor() << "::ReadEnv - WARNING: 'Binning' found... ignoring any 'NumBins', 'EdgeLo', 'EdgeHi' and 'Edges'" << endl;
572
573 if (IsEnvDefined(env, prefix, "Title", print))
574 {
575 fTitle = GetEnvValue(env, prefix, "Title", gsDefTitle.Data());
576 rc = kTRUE;
577 }
578
579 if (raw)
580 {
581 const TString txt = GetEnvValue(env, prefix, "Raw", "");
582 if (!SetEdgesRaw(txt.Data()))
583 return kERROR;
584 }
585/*
586 if (fullbins)
587 {
588 TString txt = GetEnvValue(env, prefix, "Binning", "");
589 SetEdgesRaw(txt.Data());
590 }
591 */
592
593 return rc;
594}
Note: See TracBrowser for help on using the repository browser.