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

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