source: trunk/MagicSoft/Mars/mhbase/MFillH.cc@ 3392

Last change on this file since 3392 was 3226, checked in by tbretz, 21 years ago
*** empty log message ***
File size: 19.1 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-2003
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// To use a weight for each event filled in a histogram call //
53// SetWeight(). You can eithe use the name of a MWeight container stored //
54// in the parameter list or a pointer to it as an argument. //
55// //
56// //
57// WARNING: //
58// Because MFillH is a generalized task to fill histograms it doesn't //
59// know about which branches from a file are necessary to fill the //
60// histograms. If you are reading data from a file which is directly //
61// filled into a histogram via MFillH, please call either //
62// MReadTree::DisableAutoScheme() or enable the necessary branches by //
63// yourself, using MReadTree::EnableBranch() //
64// //
65// Checkout the Warning in MTaskList. //
66// //
67// Input Containers: //
68// A parameter container //
69// //
70// Output Containers: //
71// A histogram container //
72// //
73//////////////////////////////////////////////////////////////////////////////
74#include "MFillH.h"
75
76#include <fstream>
77
78#include <TClass.h>
79#include <TCanvas.h>
80
81#include "MDataChain.h"
82
83#include "MLog.h"
84#include "MLogManip.h"
85
86#include "MH.h"
87#include "MHArray.h"
88
89#include "MWeight.h"
90
91#include "MParList.h"
92#include "MStatusDisplay.h"
93
94ClassImp(MFillH);
95
96using namespace std;
97
98// --------------------------------------------------------------------------
99//
100// Initializes name and title of the object. It is called by all
101// constructors.
102//
103void MFillH::Init(const char *name, const char *title)
104{
105 fName = name ? name : "MFillH";
106 fTitle = title ? title : "Task to fill Mars histograms";
107
108 fH = NULL;
109 fParContainer = NULL;
110
111 fIndex = NULL;
112 fCanvas = NULL;
113
114 fWeight = NULL;
115 fWeightName = "";
116}
117
118// --------------------------------------------------------------------------
119//
120// Default Constructor. This is to support some root-stuff.
121// Never try to use it yourself!
122//
123MFillH::MFillH()
124{
125 Init(NULL, NULL);
126}
127
128// --------------------------------------------------------------------------
129//
130// Constructor.
131//
132// 1) - par is the name of the parameter container which should be filled into
133// the histogram
134// - hist is the name of the histogram container (which must have been
135// derived from MH)
136//
137// In this case MH::Fill is called with a pointer to the corresponding
138// histogram instance.
139//
140// 2) - hist is the name and/or type of the histogram.
141// 1) The name and type is identical, eg: "MHHillas"
142// 2) They are not identical, eg: "MyHistogram [MHHillas]"
143// This searches for a class instance of MHHillas with the name
144// "MyHistogram". If it doesn't exist one is created.
145//
146// In this case PreProcess calls MH::SetupFill with a pointer to the
147// parameter list and MH::Fill is called with a NULL-pointer.
148//
149MFillH::MFillH(const char *hist, const char *par, const char *name, const char *title)
150{
151 Init(name, title);
152
153 fHName = hist;
154 fParContainerName = par;
155
156 AddToBranchList(Form("%s.*", (const char*)ExtractName(hist)));
157 if (par)
158 AddToBranchList(Form("%s.*", (const char*)ExtractName(par)));
159
160 if (title)
161 return;
162
163 fTitle = "Fill " + fHName;
164 if (fParContainerName.IsNull())
165 return;
166
167 fTitle += " from " + fParContainerName;
168}
169
170// --------------------------------------------------------------------------
171//
172// Constructor.
173//
174// 1) - par is a pointer to the instance of your parameter container from which
175// the data should be used to fill the histogram.
176// - hist is the name of the histogram container (which must have been
177// derived from MH)
178//
179// In this case MH::Fill is called with a pointer to the corresponding
180// histogram instance.
181//
182// 2) - hist is the name and/or type of the histogram.
183// 1) The name and type is identical, eg: "MHHillas"
184// 2) They are not identical, eg: "MyHistogram [MHHillas]"
185// This searches for a class instance of MHHillas with the name
186// "MyHistogram". If it doesn't exist one is created. Everything
187// which is between the first '[' and the last ']' in the string
188// is used as the histogram type.
189//
190// In this case PreProcess calls MH::SetupFill with a pointer to the
191// parameter list and MH::Fill is called with a NULL-pointer.
192//
193//
194MFillH::MFillH(const char *hist, MParContainer *par, const char *name, const char *title)
195{
196 Init(name, title);
197
198 fHName = hist;
199 fParContainer = par;
200 fParContainerName = par->GetName();
201
202 AddToBranchList(Form("%s.*", (const char*)ExtractName(hist)));
203 AddToBranchList(Form("%s.*", par->GetName()));
204
205 if (!title)
206 fTitle = "Fill " + fHName + " from " + par->GetDescriptor();
207}
208
209// --------------------------------------------------------------------------
210//
211// Constructor.
212//
213// - par is a pointer to the instance of your parameter container from which
214// the data should be used to fill the histogram.
215// - hist is a pointer to the instance of your histogram container (which must
216// have been derived from MH) into which the data should flow
217//
218MFillH::MFillH(MH *hist, const char *par, const char *name, const char *title)
219{
220 Init(name, title);
221
222 fH = hist;
223 fHName = hist->GetName();
224 fParContainerName = par;
225
226 AddToBranchList(fH->GetDataMember());
227 if (par)
228 AddToBranchList(Form("%s.*", (const char*)ExtractName(par)));
229
230 if (title)
231 return;
232
233 fTitle = (TString)"Fill " + hist->GetDescriptor();
234 if (!par)
235 return;
236
237 fTitle += " from " + fParContainerName;
238}
239
240// --------------------------------------------------------------------------
241//
242// Constructor.
243//
244// - par is a pointer to the instance of your parameter container from which
245// the data should be used to fill the histogram.
246// - hist is the name of the histogram container (which must have been
247// derived from MH)
248//
249MFillH::MFillH(MH *hist, MParContainer *par, const char *name, const char *title)
250{
251 Init(name, title);
252
253 fH = hist;
254 fHName = hist->GetName();
255 fParContainer = par;
256 fParContainerName = par->GetName();
257
258 AddToBranchList(fH->GetDataMember());
259 AddToBranchList(Form("%s.*", par->GetName()));
260
261 if (!title)
262 fTitle = (TString)"Fill " + hist->GetDescriptor() + " from " + par->GetDescriptor();
263}
264
265// --------------------------------------------------------------------------
266//
267// Destructor. Delete fData if existing and kCanDelete is set.
268//
269MFillH::~MFillH()
270{
271 if (fIndex)
272 if (fIndex->TestBit(kCanDelete))
273 delete fIndex;
274}
275
276// --------------------------------------------------------------------------
277//
278// If the histogram to be filles is a MHArray you can specify a 'rule'
279// This rule is used to create an MDataChain. The return value of the chain
280// is casted to int. Each int acts as a key. For each (new) key a new
281// histogram is created in the array. (eg for the rule
282// "MRawEvtHeader::fRunNumber" you would get one histogram per run-number)
283//
284void MFillH::SetRuleForIdx(const TString rule)
285{
286 fIndex = new MDataChain(rule);
287 fIndex->SetBit(kCanDelete);
288}
289
290// --------------------------------------------------------------------------
291//
292// If the histogram to be filles is a MHArray you can specify a MData-object
293// The return value of the object is casted to int. Each int acts as a key.
294// For each (new) key a new histogram is created in the array. (eg for
295// MDataMember("MRawEvtHeader::fRunNumber") you would get one histogram per
296// run-number)
297//
298void MFillH::SetRuleForIdx(MData *data)
299{
300 fIndex = data;
301}
302
303// --------------------------------------------------------------------------
304//
305// Extracts the name of the histogram from the MFillH argument
306//
307TString MFillH::ExtractName(const char *name) const
308{
309 TString type = name;
310
311 const Ssiz_t first = type.First('[');
312 const Ssiz_t last = type.First(']');
313
314 if (!first || !last || first>=last)
315 return type;
316
317 return type.Remove(first).Strip(TString::kBoth);
318}
319
320// --------------------------------------------------------------------------
321//
322// Extracts the class-name of the histogram from the MFillH argument
323//
324TString MFillH::ExtractClass(const char *name) const
325{
326 TString type = name;
327
328 const Ssiz_t first = type.First('[');
329 const Ssiz_t last = type.First(']');
330
331 if (!first || !last || first>=last)
332 return type;
333
334 const Ssiz_t length = last-first-1;
335
336 TString strip = fHName(first+1, length);
337 return strip.Strip(TString::kBoth);
338}
339
340// --------------------------------------------------------------------------
341//
342// Creates a new tab in a status display with the name of the MH class,
343// if fDisplay is set and the MH-class overwrites the Draw function
344//
345Bool_t MFillH::DrawToDisplay()
346{
347 fCanvas = NULL;
348
349 if (!fDisplay)
350 return kTRUE;
351
352 if (!fH->OverwritesDraw())
353 return kTRUE;
354
355 if (TestBit(kDoNotDisplay))
356 return kTRUE;
357
358 fCanvas = &fDisplay->AddTab(fH->GetName());
359 fH->Draw();
360
361 return kTRUE;
362}
363
364// --------------------------------------------------------------------------
365//
366// Checks the parameter list for the existance of the parameter container. If
367// the name of it was given in the constructor. It checks also for the
368// existance of the histogram container in the parameter list if a name was
369// given. If it is not available it tried to create a histogram container
370// with the same type as the given object name.
371//
372Int_t MFillH::PreProcess(MParList *pList)
373{
374 if (fIndex)
375 {
376 if (!fIndex->PreProcess(pList))
377 {
378 *fLog << all << "PreProcessing of Index rule failed... aborting." << endl;
379 return kFALSE;
380 }
381
382 if (!fIndex->IsValid())
383 {
384 *fLog << all << "Given Index rule invalid... aborting." << endl;
385 return kFALSE;
386 }
387 }
388
389 //
390 // If the user defined the use of a weight: search for it.
391 //
392 if (!fWeight && !fWeightName.IsNull())
393 {
394 fWeight = (MWeight*)pList->FindObject(fWeightName, "MWeight");
395
396 if (!fWeight)
397 {
398 *fLog << err << fWeightName << " [MWeight] not found... aborting." << endl;
399 return kFALSE;
400 }
401 }
402
403 //
404 // Try to get the histogram container with name fHName from list
405 // or create one with this name
406 //
407 if (!fH)
408 {
409 const TString cls = ExtractClass(fHName);
410 const TString name = ExtractName(fHName);
411
412 TObject *obj=NULL;
413 if (cls==name)
414 obj = pList->FindObject(fHName);
415
416 if (!obj)
417 {
418 /*
419 if (cls==name)
420 *fLog << inf << "Object '" << fHName << "' not found in parlist... creating." << endl;
421 */
422 obj = pList->FindCreateObj(cls, name);
423 }
424
425 if (!obj)
426 return kFALSE;
427
428 //
429 // We were successfull getting it. Check whether it really inherits
430 // from MH, FindCreateObj does only check for inheritance from
431 // 'type'.
432 //
433 TClass *tcls = fIndex ? MHArray::Class() : MH::Class();
434 if (!obj->InheritsFrom(tcls))
435 {
436 *fLog << err << obj->GetName() << " doesn't inherit ";
437 *fLog << "from " << tcls->GetName() << " - cannot be used for MFillH...";
438 *fLog << "aborting." << endl;
439 return kFALSE;
440 }
441
442 fH = (MH*)obj;
443 }
444
445 //
446 // Now we have the histogram container available. Try to Setup Fill.
447 //
448 fH->SetSerialNumber(GetSerialNumber());
449 if (!fH->SetupFill(pList))
450 {
451 *fLog << (TestBit(kCanSkip) ? warn : err);
452 *fLog << (TestBit(kCanSkip) ? "WARNING" : "ERROR");
453 *fLog << " Calling SetupFill for " << fH->GetDescriptor() << "...";
454 *fLog << (TestBit(kCanSkip) ? "skipped." : "aborting.");
455
456 return TestBit(kCanSkip) ? kSKIP : kFALSE;
457 }
458
459 //
460 // If also a parameter container is already set we are done.
461 //
462 if (fParContainer)
463 return DrawToDisplay();
464
465 //
466 // This case means, that the MH sets up its container to be filled
467 // by itself. Check there if it has something to be filled with!
468 //
469 if (fParContainerName.IsNull())
470 {
471 fParContainer = NULL;
472 return DrawToDisplay();
473 }
474
475 fParContainer = (MParContainer*)pList->FindObject(fParContainerName);
476 if (fParContainer)
477 return DrawToDisplay();
478
479 if (TestBit(kCanSkip))
480 {
481 *fLog << warn << fParContainerName << " [MParContainer] not found... skipped." << endl;
482 return kSKIP;
483 }
484
485 *fLog << err << fParContainerName << " [MParContainer] not found... aborting." << endl;
486 return kFALSE;
487}
488
489// --------------------------------------------------------------------------
490//
491// Call the ReInit function of the contained Histogram
492//
493Bool_t MFillH::ReInit(MParList *pList)
494{
495 return fH->ReInit(pList);
496}
497
498// --------------------------------------------------------------------------
499//
500// Fills the data from the parameter conatiner into the histogram container
501//
502Int_t MFillH::Process()
503{
504 if (fIndex)
505 ((MHArray*)fH)->SetIndexByKey(fIndex->GetValue());
506 /*
507 const Int_t key = (Int_t)fIndex->GetValue();
508 const Int_t idx = fMapIdx->Add(key);
509 ((MHArray*)fH)->SetIndex(idx);
510 */
511
512 TVirtualPad *save = gPad;
513 if (fCanvas)
514 fCanvas->cd();
515
516 Bool_t rc = fH->Fill(fParContainer, fWeight?fWeight->GetWeight():1);
517
518 if (save && fCanvas)
519 save->cd();
520
521 return rc;
522}
523
524// --------------------------------------------------------------------------
525//
526// Set the ReadyToSave flag of the histogram container, because now all data
527// has been filled into the histogram.
528//
529Int_t MFillH::PostProcess()
530{
531 //
532 // Now all data is in the histogram. Maybe some final action is
533 // necessary.
534 //
535 if (!fH->Finalize())
536 {
537 *fLog << err << "ERROR - Calling Finalize for ";
538 *fLog << fH->GetDescriptor() << "... aborting." << endl;
539 return kFALSE;
540 }
541
542 fH->SetReadyToSave();
543
544 //
545 // Check whether fDisplay has previously been used (fCanvas),
546 // fDisplay is still open and the corresponding Canvas/Tab is
547 // still existing.
548 //
549 if (fDisplay && fDisplay->HasCanvas(fCanvas))
550 {
551 fCanvas->cd();
552 fH->DrawClone("nonew");
553 fCanvas->Modified();
554 fCanvas->Update();
555 }
556
557 return kTRUE;
558}
559
560// --------------------------------------------------------------------------
561//
562// Implementation of SavePrimitive. Used to write the call to a constructor
563// to a macro. In the original root implementation it is used to write
564// gui elements to a macro-file.
565//
566void MFillH::StreamPrimitive(ofstream &out) const
567{
568 if (fH)
569 fH->SavePrimitive(out);
570
571 if (fParContainer)
572 fParContainer->SavePrimitive(out);
573
574 if (fWeight)
575 fWeight->SavePrimitive(out);
576
577 out << " MFillH " << GetUniqueName() << "(";
578
579 if (fH)
580 out << "&" << fH->GetUniqueName();
581 else
582 out << "\"" << fHName << "\"";
583
584 if (fParContainer)
585 out << ", &" << fParContainer->GetUniqueName();
586 else
587 if (!fParContainerName.IsNull())
588 out << ", \"" << fParContainerName << "\"";
589
590 out << ");" << endl;
591
592 if (fWeight || !fWeightName.IsNull())
593 {
594 out << " " << GetUniqueName() << ".SetWeight(";
595 if (fWeight)
596 out << "&" << fWeight->GetUniqueName() << ");" << endl;
597 else
598 if (!fWeightName.IsNull())
599 out << "\"" << fWeightName << "\");" << endl;
600 }
601
602 if (fIndex)
603 {
604 out << " " << GetUniqueName() << ".SetRuleForIdx(\"";
605 out << fIndex->GetRule() << "\");" << endl;
606 }
607}
Note: See TracBrowser for help on using the repository browser.