source: trunk/MagicSoft/Mars/mhist/MFillH.cc@ 1600

Last change on this file since 1600 was 1574, checked in by tbretz, 22 years ago
*** empty log message ***
File size: 17.8 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 07/2001 <mailto:tbretz@astro.uni-wuerzburg.de>
19!
20! Copyright: MAGIC Software Development, 2000-2002
21!
22!
23\* ======================================================================== */
24
25//////////////////////////////////////////////////////////////////////////////
26// //
27// MFillH //
28// //
29// This is a common interface (task) to fill mars histograms. Every mars //
30// histogram which is derived from MH can be filled with this task. //
31// //
32// There are two options to use: //
33// //
34// 1) You specifiy the parameter container with which data the //
35// histogram container should be filled, and the histogram container //
36// which has to be filled. This can be done by either specifing the //
37// name of the objects in the parameter list or by specifiing a pointer //
38// to the object. (s. Constructor) // //
39// //
40// 2) You specify the name and/or type of the histogram to become filled. //
41// Any other action imust be taken by the histogram class. //
42// //
43// PreProcess: In the preprocessing of this task we setup all pointers //
44// to instances which are needed and call FillSetup of the //
45// histogram class with the parameter list as an argument. //
46// //
47// Process: The process function calls the Fill member function of the //
48// histogram class instance (inheriting from MH) with either //
49// a NULL pointer or a pointer to the corresponding container //
50// as an argument. //
51// //
52// WARNING: //
53// Because MFillH is a generalized task to fill histograms it doesn't //
54// know about which branches from a file are necessary to fill the //
55// histograms. If you are reading data from a file which is directly //
56// filled into a histogram via MFillH, please call either //
57// MReadTree::DisableAutoScheme() or enable the necessary branches by //
58// yourself, using MReadTree::EnableBranch() //
59// //
60// Checkout the Warning in MTaskList. //
61// //
62// Input Containers: //
63// A parameter container //
64// //
65// Output Containers: //
66// A histogram container //
67// //
68//////////////////////////////////////////////////////////////////////////////
69#include "MFillH.h"
70
71#include <fstream.h>
72
73#include <TClass.h>
74
75#include "MDataChain.h"
76
77#include "MLog.h"
78#include "MLogManip.h"
79
80#include "MH.h"
81#include "MHArray.h"
82
83#include "MParList.h"
84
85ClassImp(MFillH);
86
87//////////////////////////////////////////////////////////////////////////////
88//
89// MMap
90//
91// This class maps a key-value to a given value. In its simple versions it
92// maps a key to an index.
93//
94//////////////////////////////////////////////////////////////////////////////
95#include <TArrayI.h>
96
97class MMap
98{
99private:
100 TArrayI fKeys;
101 TArrayI fValues;
102
103 Int_t K(Int_t i) const { return ((TArrayI)fKeys)[i]; }
104 Int_t V(Int_t i) const { return ((TArrayI)fValues)[i]; }
105
106public:
107 // --------------------------------------------------------------------------
108 //
109 // Get the value which corresponds to the given key-value
110 //
111 Int_t GetValue(Int_t key) const
112 {
113 const Int_t n = fKeys.GetSize();
114 for (int i=0; i<n; i++)
115 {
116 if (K(i)==key)
117 return V(i);
118 }
119 return -1;
120 }
121
122 // --------------------------------------------------------------------------
123 //
124 // Adds a new pair key-value. While the key is the key to the value.
125 // if the key already exists the pair is ignored.
126 //
127 void Add(Int_t key, Int_t value)
128 {
129 if (GetValue(key)>=0)
130 return;
131
132 const Int_t n = fKeys.GetSize();
133
134 fKeys.Set(n+1);
135 fValues.Set(n+1);
136
137 fKeys[n] = key;
138 fValues[n] = value;
139 }
140
141 // --------------------------------------------------------------------------
142 //
143 // Adds a new pair key-value. While the key is the key to the value.
144 // In this case the value is an automatically sequential created index.
145 // if the key already exists the pair is ignored.
146 //
147 Int_t Add(Int_t key)
148 {
149 const Int_t k = GetValue(key);
150 if (k>=0)
151 return k;
152
153 const Int_t n = fKeys.GetSize();
154
155 fKeys.Set(n+1);
156 fValues.Set(n+1);
157
158 fKeys[n] = key;
159 fValues[n] = n;
160
161 return n;
162 }
163};
164
165// --------------------------------------------------------------------------
166//
167// Initializes name and title of the object. It is called by all
168// constructors.
169//
170void MFillH::Init(const char *name, const char *title)
171{
172 fName = name ? name : "MFillH";
173 fTitle = title ? title : "Task to fill Mars histograms";
174
175 fH = NULL;
176 fParContainer = NULL;
177
178 fIndex = NULL;
179 fMapIdx = new MMap;
180}
181
182// --------------------------------------------------------------------------
183//
184// Default Constructor. This is to support some root-stuff.
185// Never try to use it yourself!
186//
187MFillH::MFillH()
188{
189 Init(NULL, NULL);
190}
191
192// --------------------------------------------------------------------------
193//
194// Constructor.
195//
196// 1) - par is the name of the parameter container which should be filled into
197// the histogram
198// - hist is the name of the histogram container (which must have been
199// derived from MH)
200//
201// In this case MH::Fill is called with a pointer to the corresponding
202// histogram instance.
203//
204// 2) - hist is the name and/or type of the histogram.
205// 1) The name and type is identical, eg: "MHHillas"
206// 2) They are not identical, eg: "MyHistogram [MHHillas]"
207// This searches for a class instance of MHHillas with the name
208// "MyHistogram". If it doesn't exist one is created.
209//
210// In this case PreProcess calls MH::SetupFill with a pointer to the
211// parameter list and MH::Fill is called with a NULL-pointer.
212//
213MFillH::MFillH(const char *hist, const char *par, const char *name, const char *title)
214{
215 Init(name, title);
216
217 fHName = hist;
218 fParContainerName = par;
219
220 if (title)
221 return;
222
223 fTitle = "Fill " + fHName;
224 if (!par)
225 return;
226
227 fTitle += " from " + fParContainerName;
228}
229
230// --------------------------------------------------------------------------
231//
232// Constructor.
233//
234// 1) - par is a pointer to the instance of your parameter container from which
235// the data should be used to fill the histogram.
236// - hist is the name of the histogram container (which must have been
237// derived from MH)
238//
239// In this case MH::Fill is called with a pointer to the corresponding
240// histogram instance.
241//
242// 2) - hist is the name and/or type of the histogram.
243// 1) The name and type is identical, eg: "MHHillas"
244// 2) They are not identical, eg: "MyHistogram [MHHillas]"
245// This searches for a class instance of MHHillas with the name
246// "MyHistogram". If it doesn't exist one is created. Everything
247// which is between the first '[' and the last ']' in the string
248// is used as the histogram type.
249//
250// In this case PreProcess calls MH::SetupFill with a pointer to the
251// parameter list and MH::Fill is called with a NULL-pointer.
252//
253//
254MFillH::MFillH(const char *hist, MParContainer *par, const char *name, const char *title)
255{
256 Init(name, title);
257
258 fHName = hist;
259 fParContainer = par;
260 fParContainerName = par->GetName();
261
262 if (!title)
263 fTitle = "Fill " + fHName + " from " + par->GetDescriptor();
264}
265
266// --------------------------------------------------------------------------
267//
268// Constructor.
269//
270// - par is a pointer to the instance of your parameter container from which
271// the data should be used to fill the histogram.
272// - hist is a pointer to the instance of your histogram container (which must
273// have been derived from MH) into which the data should flow
274//
275MFillH::MFillH(MH *hist, const char *par, const char *name, const char *title)
276{
277 Init(name, title);
278
279 fH = hist;
280 fHName = hist->GetName();
281 fParContainerName = par;
282
283 AddToBranchList(fH->GetDataMember());
284
285 if (title)
286 return;
287
288 fTitle = (TString)"Fill " + hist->GetDescriptor();
289 if (!par)
290 return;
291
292 fTitle += " from " + fParContainerName;
293}
294
295// --------------------------------------------------------------------------
296//
297// Constructor.
298//
299// - par is a pointer to the instance of your parameter container from which
300// the data should be used to fill the histogram.
301// - hist is the name of the histogram container (which must have been
302// derived from MH)
303//
304MFillH::MFillH(MH *hist, MParContainer *par, const char *name, const char *title)
305{
306 Init(name, title);
307
308 fH = hist;
309 fHName = hist->GetName();
310 fParContainer = par;
311 fParContainerName = par->GetName();
312
313 AddToBranchList(fH->GetDataMember());
314
315 if (!title)
316 fTitle = (TString)"Fill " + hist->GetDescriptor() + " from " + par->GetDescriptor();
317}
318
319// --------------------------------------------------------------------------
320//
321// Destructor. Delete fData if existing and kCanDelete is set.
322//
323MFillH::~MFillH()
324{
325 if (fIndex)
326 if (fIndex->TestBit(kCanDelete))
327 delete fIndex;
328
329 delete fMapIdx;
330}
331
332// --------------------------------------------------------------------------
333//
334// If the histogram to be filles is a MHArray you can specify a 'rule'
335// This rule is used to create an MDataChain. The return value of the chain
336// is casted to int. Each int acts as a key. For each (new) key a new
337// histogram is created in the array. (eg for the rule
338// "MRawEvtHeader::fRunNumber" you would get one histogram per run-number)
339//
340void MFillH::SetRuleForIdx(const TString rule)
341{
342 fIndex = new MDataChain(rule);
343 fIndex->SetBit(kCanDelete);
344}
345
346// --------------------------------------------------------------------------
347//
348// If the histogram to be filles is a MHArray you can specify a MData-object
349// The return value of the object is casted to int. Each int acts as a key.
350// For each (new) key a new histogram is created in the array. (eg for
351// MDataMember("MRawEvtHeader::fRunNumber") you would get one histogram per
352// run-number)
353//
354void MFillH::SetRuleForIdx(MData *data)
355{
356 fIndex = data;
357}
358
359// --------------------------------------------------------------------------
360//
361// Extracts the name of the histogram from the MFillH argument
362//
363TString MFillH::ExtractName(const char *name) const
364{
365 TString type = name;
366
367 const Ssiz_t first = type.First('[');
368 const Ssiz_t last = type.First(']');
369
370 if (!first || !last || first>=last)
371 return type;
372
373 return type.Remove(first).Strip(TString::kBoth);
374}
375
376// --------------------------------------------------------------------------
377//
378// Extracts the class-name of the histogram from the MFillH argument
379//
380TString MFillH::ExtractClass(const char *name) const
381{
382 TString type = name;
383
384 const Ssiz_t first = type.First('[');
385 const Ssiz_t last = type.First(']');
386
387 if (!first || !last || first>=last)
388 return type;
389
390 const Ssiz_t length = last-first-1;
391
392 TString strip = fHName(first+1, length);
393 return strip.Strip(TString::kBoth);
394}
395
396// --------------------------------------------------------------------------
397//
398// Checks the parameter list for the existance of the parameter container. If
399// the name of it was given in the constructor. It checks also for the
400// existance of the histogram container in the parameter list if a name was
401// given. If it is not available it tried to create a histogram container
402// with the same type as the given object name.
403//
404Bool_t MFillH::PreProcess(MParList *pList)
405{
406 if (fIndex)
407 {
408 if (!fIndex->PreProcess(pList))
409 {
410 *fLog << all << "PreProcessing of Index rule failed... aborting." << endl;
411 return kFALSE;
412 }
413
414 if (!fIndex->IsValid())
415 {
416 *fLog << all << "Given Index rule invalid... aborting." << endl;
417 return kFALSE;
418 }
419 }
420
421 //
422 // Try to get the histogram container with name fHName from list
423 // or create one with this name
424 //
425 if (!fH)
426 {
427 const TString cls = ExtractClass(fHName);
428 const TString name = ExtractName(fHName);
429
430 TObject *obj=NULL;
431 if (cls==name)
432 obj = pList->FindObject(fHName);
433
434 if (!obj)
435 {
436 if (cls==name)
437 *fLog << inf << "Object '" << fHName << "' not found in parlist... trying to create one." << endl;
438 obj = pList->FindCreateObj(cls, name);
439 }
440
441 if (!obj)
442 return kFALSE;
443
444 //
445 // We were successfull getting it. Check whether it really inherits
446 // from MH, FindCreateObj does only check for inheritance from
447 // 'type'.
448 //
449 TClass *tcls = fIndex ? MHArray::Class() : MH::Class();
450 if (!obj->InheritsFrom(tcls))
451 {
452 *fLog << err << dbginf << obj->GetName() << " doesn't inherit ";
453 *fLog << "from " << tcls->GetName() << " - cannot be used for MFillH...";
454 *fLog << "aborting." << endl;
455 return kFALSE;
456 }
457
458 fH = (MH*)obj;
459 }
460
461 //
462 // Now we have the histogram container available. Try to Setup Fill.
463 //
464 if (!fH->SetupFill(pList))
465 {
466 *fLog << err << dbginf << "Error: calling SetupFill for ";
467 *fLog << fH->GetDescriptor() << "... aborting." << endl;
468 return kFALSE;
469 }
470
471 //
472 // If also a parameter container is already set we are done.
473 //
474 if (fParContainer)
475 return kTRUE;
476
477 //
478 // If a name is given try to find the input container in the
479 // list. If it could not be found we cannot proceed.
480 //
481 if (fParContainerName.IsNull())
482 {
483 fParContainer = pList;
484 return kTRUE;
485 }
486
487 fParContainer = (MParContainer*)pList->FindObject(fParContainerName);
488 if (fParContainer)
489 return kTRUE;
490
491 *fLog << err << dbginf << "'" << fParContainerName << "' [MParContainer] not found... aborting." << endl;
492 return kFALSE;
493}
494
495// --------------------------------------------------------------------------
496//
497// Fills the data from the parameter conatiner into the histogram container
498//
499Bool_t MFillH::Process()
500{
501 if (fIndex)
502 {
503 const Int_t key = (Int_t)fIndex->GetValue();
504 const Int_t idx = fMapIdx->Add(key);
505 ((MHArray*)fH)->SetIndex(idx);
506 }
507
508 return fH->Fill(fParContainer);
509}
510
511// --------------------------------------------------------------------------
512//
513// Set the ReadyToSave flag of the histogram container, because now all data
514// has been filled into the histogram.
515//
516Bool_t MFillH::PostProcess()
517{
518 //
519 // Now all data is in the histogram. Maybe some final action is
520 // necessary.
521 //
522 if (!fH->Finalize())
523 {
524 *fLog << err << dbginf << "Error: calling Finalize for ";
525 *fLog << fH->GetDescriptor() << "... aborting." << endl;
526 return kFALSE;
527 }
528
529 fH->SetReadyToSave();
530 return kTRUE;
531}
532
533// --------------------------------------------------------------------------
534//
535// Implementation of SavePrimitive. Used to write the call to a constructor
536// to a macro. In the original root implementation it is used to write
537// gui elements to a macro-file.
538//
539void MFillH::StreamPrimitive(ofstream &out) const
540{
541 if (fH)
542 fH->SavePrimitive(out);
543
544 if (fParContainer)
545 fParContainer->SavePrimitive(out);
546
547 out << " MFillH " << GetUniqueName() << "(";
548
549 if (fH)
550 out << "&" << fH->GetUniqueName();
551 else
552 out << "\"" << fHName << "\"";
553
554 if (fParContainer)
555 out << ", &" << fParContainer->GetUniqueName();
556 else
557 if (!fParContainerName.IsNull())
558 out << ", \"" << fParContainerName << "\"";
559
560 out << ");" << endl;
561
562 if (!fIndex)
563 return;
564
565 out << " " << GetUniqueName() << ".SetRuleForIdx(\"";
566 out << fIndex->GetRule() << "\");" << endl;
567}
Note: See TracBrowser for help on using the repository browser.