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

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