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

Last change on this file since 3789 was 3789, checked in by tbretz, 20 years ago
*** empty log message ***
File size: 19.5 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// Use this to set a draw option used when drawing automatically to the
343// status display.
344//
345void MFillH::SetDrawOption(Option_t *option)
346{
347 fDrawOption = option;
348}
349
350// --------------------------------------------------------------------------
351//
352// Creates a new tab in a status display with the name of the MH class,
353// if fDisplay is set and the MH-class overwrites the Draw function
354//
355Bool_t MFillH::DrawToDisplay()
356{
357 fCanvas = NULL;
358
359 if (!fDisplay)
360 return kTRUE;
361
362 if (!fH->OverwritesDraw())
363 return kTRUE;
364
365 if (TestBit(kDoNotDisplay))
366 return kTRUE;
367
368 fCanvas = &fDisplay->AddTab(fNameTab.IsNull() ? fH->GetName() : fNameTab.Data());
369 fH->Draw(fDrawOption);
370
371 return kTRUE;
372}
373
374// --------------------------------------------------------------------------
375//
376// Checks the parameter list for the existance of the parameter container. If
377// the name of it was given in the constructor. It checks also for the
378// existance of the histogram container in the parameter list if a name was
379// given. If it is not available it tried to create a histogram container
380// with the same type as the given object name.
381//
382Int_t MFillH::PreProcess(MParList *pList)
383{
384 if (fIndex)
385 {
386 if (!fIndex->PreProcess(pList))
387 {
388 *fLog << all << "PreProcessing of Index rule failed... aborting." << endl;
389 return kFALSE;
390 }
391
392 if (!fIndex->IsValid())
393 {
394 *fLog << all << "Given Index rule invalid... aborting." << endl;
395 return kFALSE;
396 }
397 }
398
399 //
400 // If the user defined the use of a weight: search for it.
401 //
402 if (!fWeight && !fWeightName.IsNull())
403 {
404 fWeight = (MWeight*)pList->FindObject(fWeightName, "MWeight");
405
406 if (!fWeight)
407 {
408 *fLog << err << fWeightName << " [MWeight] not found... aborting." << endl;
409 return kFALSE;
410 }
411 }
412
413 //
414 // Try to get the histogram container with name fHName from list
415 // or create one with this name
416 //
417 if (!fH)
418 {
419 const TString cls = ExtractClass(fHName);
420 const TString name = ExtractName(fHName);
421
422 TObject *obj=NULL;
423 if (cls==name)
424 obj = pList->FindObject(fHName);
425
426 if (!obj)
427 {
428 /*
429 if (cls==name)
430 *fLog << inf << "Object '" << fHName << "' not found in parlist... creating." << endl;
431 */
432 obj = pList->FindCreateObj(cls, name);
433 }
434
435 if (!obj)
436 return kFALSE;
437
438 //
439 // We were successfull getting it. Check whether it really inherits
440 // from MH, FindCreateObj does only check for inheritance from
441 // 'type'.
442 //
443 TClass *tcls = fIndex ? MHArray::Class() : MH::Class();
444 if (!obj->InheritsFrom(tcls))
445 {
446 *fLog << err << obj->GetName() << " doesn't inherit ";
447 *fLog << "from " << tcls->GetName() << " - cannot be used for MFillH...";
448 *fLog << "aborting." << endl;
449 return kFALSE;
450 }
451
452 fH = (MH*)obj;
453 }
454
455 //
456 // Now we have the histogram container available. Try to Setup Fill.
457 //
458 fH->SetSerialNumber(GetSerialNumber());
459 if (!fH->SetupFill(pList))
460 {
461 *fLog << (TestBit(kCanSkip) ? warn : err);
462 *fLog << (TestBit(kCanSkip) ? "WARNING" : "ERROR");
463 *fLog << " Calling SetupFill for " << fH->GetDescriptor() << "...";
464 *fLog << (TestBit(kCanSkip) ? "skipped." : "aborting.");
465
466 return TestBit(kCanSkip) ? kSKIP : kFALSE;
467 }
468
469 //
470 // If also a parameter container is already set we are done.
471 //
472 if (fParContainer)
473 return DrawToDisplay();
474
475 //
476 // This case means, that the MH sets up its container to be filled
477 // by itself. Check there if it has something to be filled with!
478 //
479 if (fParContainerName.IsNull())
480 {
481 fParContainer = NULL;
482 return DrawToDisplay();
483 }
484
485 fParContainer = (MParContainer*)pList->FindObject(fParContainerName);
486 if (fParContainer)
487 return DrawToDisplay();
488
489 if (TestBit(kCanSkip))
490 {
491 *fLog << warn << fParContainerName << " [MParContainer] not found... skipped." << endl;
492 return kSKIP;
493 }
494
495 *fLog << err << fParContainerName << " [MParContainer] not found... aborting." << endl;
496 return kFALSE;
497}
498
499// --------------------------------------------------------------------------
500//
501// Call the ReInit function of the contained Histogram
502//
503Bool_t MFillH::ReInit(MParList *pList)
504{
505 return fH->ReInit(pList);
506}
507
508// --------------------------------------------------------------------------
509//
510// Fills the data from the parameter conatiner into the histogram container
511//
512Int_t MFillH::Process()
513{
514 if (fIndex)
515 ((MHArray*)fH)->SetIndexByKey(fIndex->GetValue());
516 /*
517 const Int_t key = (Int_t)fIndex->GetValue();
518 const Int_t idx = fMapIdx->Add(key);
519 ((MHArray*)fH)->SetIndex(idx);
520 */
521
522 TVirtualPad *save = gPad;
523 if (fCanvas)
524 fCanvas->cd();
525
526 Bool_t rc = fH->Fill(fParContainer, fWeight?fWeight->GetWeight():1);
527
528 if (save && fCanvas)
529 save->cd();
530
531 return rc;
532}
533
534// --------------------------------------------------------------------------
535//
536// Set the ReadyToSave flag of the histogram container, because now all data
537// has been filled into the histogram.
538//
539Int_t MFillH::PostProcess()
540{
541 //
542 // Now all data is in the histogram. Maybe some final action is
543 // necessary.
544 //
545 if (!fH->Finalize())
546 {
547 *fLog << err << "ERROR - Calling Finalize for ";
548 *fLog << fH->GetDescriptor() << "... aborting." << endl;
549 return kFALSE;
550 }
551
552 fH->SetReadyToSave();
553
554 //
555 // Check whether fDisplay has previously been used (fCanvas),
556 // fDisplay is still open and the corresponding Canvas/Tab is
557 // still existing.
558 //
559 if (fDisplay && fDisplay->HasCanvas(fCanvas))
560 {
561 const TString opt(Form("nonew %s", fDrawOption));
562 fCanvas->cd();
563 fH->DrawClone(opt);
564 fCanvas->Modified();
565 fCanvas->Update();
566 }
567
568 return kTRUE;
569}
570
571// --------------------------------------------------------------------------
572//
573// Implementation of SavePrimitive. Used to write the call to a constructor
574// to a macro. In the original root implementation it is used to write
575// gui elements to a macro-file.
576//
577void MFillH::StreamPrimitive(ofstream &out) const
578{
579 if (fH)
580 fH->SavePrimitive(out);
581
582 if (fParContainer)
583 fParContainer->SavePrimitive(out);
584
585 if (fWeight)
586 fWeight->SavePrimitive(out);
587
588 out << " MFillH " << GetUniqueName() << "(";
589
590 if (fH)
591 out << "&" << fH->GetUniqueName();
592 else
593 out << "\"" << fHName << "\"";
594
595 if (fParContainer)
596 out << ", &" << fParContainer->GetUniqueName();
597 else
598 if (!fParContainerName.IsNull())
599 out << ", \"" << fParContainerName << "\"";
600
601 out << ");" << endl;
602
603 if (fWeight || !fWeightName.IsNull())
604 {
605 out << " " << GetUniqueName() << ".SetWeight(";
606 if (fWeight)
607 out << "&" << fWeight->GetUniqueName() << ");" << endl;
608 else
609 if (!fWeightName.IsNull())
610 out << "\"" << fWeightName << "\");" << endl;
611 }
612
613 if (fIndex)
614 {
615 out << " " << GetUniqueName() << ".SetRuleForIdx(\"";
616 out << fIndex->GetRule() << "\");" << endl;
617 }
618}
Note: See TracBrowser for help on using the repository browser.