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

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