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

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