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

Last change on this file since 2415 was 2414, checked in by tbretz, 21 years ago
*** empty log message ***
File size: 18.7 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// 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 if (title)
157 return;
158
159 fTitle = "Fill " + fHName;
160 if (fParContainerName.IsNull())
161 return;
162
163 fTitle += " from " + fParContainerName;
164}
165
166// --------------------------------------------------------------------------
167//
168// Constructor.
169//
170// 1) - par is a pointer to the instance of your parameter container from which
171// the data should be used to fill the histogram.
172// - hist is the name of the histogram container (which must have been
173// derived from MH)
174//
175// In this case MH::Fill is called with a pointer to the corresponding
176// histogram instance.
177//
178// 2) - hist is the name and/or type of the histogram.
179// 1) The name and type is identical, eg: "MHHillas"
180// 2) They are not identical, eg: "MyHistogram [MHHillas]"
181// This searches for a class instance of MHHillas with the name
182// "MyHistogram". If it doesn't exist one is created. Everything
183// which is between the first '[' and the last ']' in the string
184// is used as the histogram type.
185//
186// In this case PreProcess calls MH::SetupFill with a pointer to the
187// parameter list and MH::Fill is called with a NULL-pointer.
188//
189//
190MFillH::MFillH(const char *hist, MParContainer *par, const char *name, const char *title)
191{
192 Init(name, title);
193
194 fHName = hist;
195 fParContainer = par;
196 fParContainerName = par->GetName();
197
198 if (!title)
199 fTitle = "Fill " + fHName + " from " + par->GetDescriptor();
200}
201
202// --------------------------------------------------------------------------
203//
204// Constructor.
205//
206// - par is a pointer to the instance of your parameter container from which
207// the data should be used to fill the histogram.
208// - hist is a pointer to the instance of your histogram container (which must
209// have been derived from MH) into which the data should flow
210//
211MFillH::MFillH(MH *hist, const char *par, const char *name, const char *title)
212{
213 Init(name, title);
214
215 fH = hist;
216 fHName = hist->GetName();
217 fParContainerName = par;
218
219 AddToBranchList(fH->GetDataMember());
220
221 if (title)
222 return;
223
224 fTitle = (TString)"Fill " + hist->GetDescriptor();
225 if (!par)
226 return;
227
228 fTitle += " from " + fParContainerName;
229}
230
231// --------------------------------------------------------------------------
232//
233// Constructor.
234//
235// - par is a pointer to the instance of your parameter container from which
236// the data should be used to fill the histogram.
237// - hist is the name of the histogram container (which must have been
238// derived from MH)
239//
240MFillH::MFillH(MH *hist, MParContainer *par, const char *name, const char *title)
241{
242 Init(name, title);
243
244 fH = hist;
245 fHName = hist->GetName();
246 fParContainer = par;
247 fParContainerName = par->GetName();
248
249 AddToBranchList(fH->GetDataMember());
250
251 if (!title)
252 fTitle = (TString)"Fill " + hist->GetDescriptor() + " from " + par->GetDescriptor();
253}
254
255// --------------------------------------------------------------------------
256//
257// Destructor. Delete fData if existing and kCanDelete is set.
258//
259MFillH::~MFillH()
260{
261 if (fIndex)
262 if (fIndex->TestBit(kCanDelete))
263 delete fIndex;
264}
265
266// --------------------------------------------------------------------------
267//
268// If the histogram to be filles is a MHArray you can specify a 'rule'
269// This rule is used to create an MDataChain. The return value of the chain
270// is casted to int. Each int acts as a key. For each (new) key a new
271// histogram is created in the array. (eg for the rule
272// "MRawEvtHeader::fRunNumber" you would get one histogram per run-number)
273//
274void MFillH::SetRuleForIdx(const TString rule)
275{
276 fIndex = new MDataChain(rule);
277 fIndex->SetBit(kCanDelete);
278}
279
280// --------------------------------------------------------------------------
281//
282// If the histogram to be filles is a MHArray you can specify a MData-object
283// The return value of the object is casted to int. Each int acts as a key.
284// For each (new) key a new histogram is created in the array. (eg for
285// MDataMember("MRawEvtHeader::fRunNumber") you would get one histogram per
286// run-number)
287//
288void MFillH::SetRuleForIdx(MData *data)
289{
290 fIndex = data;
291}
292
293// --------------------------------------------------------------------------
294//
295// Extracts the name of the histogram from the MFillH argument
296//
297TString MFillH::ExtractName(const char *name) const
298{
299 TString type = name;
300
301 const Ssiz_t first = type.First('[');
302 const Ssiz_t last = type.First(']');
303
304 if (!first || !last || first>=last)
305 return type;
306
307 return type.Remove(first).Strip(TString::kBoth);
308}
309
310// --------------------------------------------------------------------------
311//
312// Extracts the class-name of the histogram from the MFillH argument
313//
314TString MFillH::ExtractClass(const char *name) const
315{
316 TString type = name;
317
318 const Ssiz_t first = type.First('[');
319 const Ssiz_t last = type.First(']');
320
321 if (!first || !last || first>=last)
322 return type;
323
324 const Ssiz_t length = last-first-1;
325
326 //
327 // Make a copy before stripping leading and trailing White Spaces.
328 //
329 TString strip = fHName(first+1, length);
330 return strip.Strip(TString::kBoth);
331}
332
333// --------------------------------------------------------------------------
334//
335// Creates a new tab in a status display with the name of the MH class,
336// if fDisplay is set and the MH-class overwrites the Draw function
337//
338Bool_t MFillH::DrawToDisplay()
339{
340 fCanvas = NULL;
341
342 if (!fDisplay)
343 return kTRUE;
344
345 if (TestBit(kDoNotDisplay))
346 return kTRUE;
347
348 const Bool_t dr = fH->OverwritesDraw();
349 const Bool_t ts = fH->OverwritesDraw(NULL, "TS");
350 if (!dr && !ts)
351 return kTRUE;
352
353 if (!ts)
354 {
355 *fLog << warn << "You overwrote " << fH->ClassName() << "::";
356 *fLog << "Draw instead of " << fH->ClassName() << "::DrawTS" << endl;
357 *fLog << "This is not thread safe and might result in trouble using" << endl;
358 *fLog << "multithreaded programs like MONA." << endl;
359 *fLog << "" << endl;
360 return kTRUE;
361 }
362
363 fCanvas = &fDisplay->AddTab(fH->GetName());
364 fH->DrawTS(fCanvas);
365
366 return kTRUE;
367}
368
369// --------------------------------------------------------------------------
370//
371//
372Bool_t MFillH::DrawCloneToDisplay()
373{
374 fH->DrawCloneTS(fCanvas);
375 fCanvas->Modified();
376 fCanvas->Update();
377
378 return kTRUE;
379}
380
381// --------------------------------------------------------------------------
382//
383// Checks the parameter list for the existance of the parameter container. If
384// the name of it was given in the constructor. It checks also for the
385// existance of the histogram container in the parameter list if a name was
386// given. If it is not available it tried to create a histogram container
387// with the same type as the given object name.
388//
389Int_t MFillH::PreProcess(MParList *pList)
390{
391 if (fIndex)
392 {
393 if (!fIndex->PreProcess(pList))
394 {
395 *fLog << all << "PreProcessing of Index rule failed... aborting." << endl;
396 return kFALSE;
397 }
398
399 if (!fIndex->IsValid())
400 {
401 *fLog << all << "Given Index rule invalid... aborting." << endl;
402 return kFALSE;
403 }
404 }
405
406 //
407 // If the user defined the use of a weight: search for it.
408 //
409 if (!fWeight && !fWeightName.IsNull())
410 {
411 fWeight = (MWeight*)pList->FindObject(fWeightName, "MWeight");
412 *fLog << err << fWeightName << " [MWeight] not found... aborting." << endl;
413 return kFALSE;
414 }
415
416 //
417 // Try to get the histogram container with name fHName from list
418 // or create one with this name
419 //
420 if (!fH)
421 {
422 const TString cls = ExtractClass(fHName);
423 const TString name = ExtractName(fHName);
424
425 TObject *obj=NULL;
426 if (cls==name)
427 obj = pList->FindObject(fHName);
428
429 if (!obj)
430 {
431 /*
432 if (cls==name)
433 *fLog << inf << "Object '" << fHName << "' not found in parlist... creating." << endl;
434 */
435 obj = pList->FindCreateObj(cls, name);
436 }
437
438 if (!obj)
439 return kFALSE;
440
441 //
442 // We were successfull getting it. Check whether it really inherits
443 // from MH, FindCreateObj does only check for inheritance from
444 // 'type'.
445 //
446 TClass *tcls = fIndex ? MHArray::Class() : MH::Class();
447 if (!obj->InheritsFrom(tcls))
448 {
449 *fLog << err << obj->GetName() << " doesn't inherit ";
450 *fLog << "from " << tcls->GetName() << " - cannot be used for MFillH...";
451 *fLog << "aborting." << endl;
452 return kFALSE;
453 }
454
455 fH = (MH*)obj;
456 }
457
458 //
459 // Now we have the histogram container available. Try to Setup Fill.
460 //
461 if (!fH->SetupFill(pList))
462 {
463 *fLog << err << "ERROR - Calling SetupFill for ";
464 *fLog << fH->GetDescriptor() << "... aborting." << endl;
465 return kFALSE;
466 }
467
468 //
469 // If also a parameter container is already set we are done.
470 //
471 if (fParContainer)
472 return DrawToDisplay();
473
474 //
475 // This case means, that the MH sets up its container to be filled
476 // by itself. Check there if it has something to be filled with!
477 //
478 if (fParContainerName.IsNull())
479 {
480 fParContainer = NULL;
481 return DrawToDisplay();
482 }
483
484 fParContainer = (MParContainer*)pList->FindObject(fParContainerName);
485 if (fParContainer)
486 return DrawToDisplay();
487
488 *fLog << err << fParContainerName << " [MParContainer] not found... aborting." << endl;
489 return kFALSE;
490}
491
492// --------------------------------------------------------------------------
493//
494// Fills the data from the parameter conatiner into the histogram container
495//
496Int_t MFillH::Process()
497{
498 if (fIndex)
499 ((MHArray*)fH)->SetIndexByKey(fIndex->GetValue());
500 /*
501 const Int_t key = (Int_t)fIndex->GetValue();
502 const Int_t idx = fMapIdx->Add(key);
503 ((MHArray*)fH)->SetIndex(idx);
504 */
505
506 return fH->Fill(fParContainer, fWeight?fWeight->GetWeight():1);
507}
508
509// --------------------------------------------------------------------------
510//
511// Set the ReadyToSave flag of the histogram container, because now all data
512// has been filled into the histogram.
513//
514Int_t MFillH::PostProcess()
515{
516 //
517 // Now all data is in the histogram. Maybe some final action is
518 // necessary.
519 //
520 if (!fH->Finalize())
521 {
522 *fLog << err << "ERROR - Calling Finalize for ";
523 *fLog << fH->GetDescriptor() << "... aborting." << endl;
524 return kFALSE;
525 }
526
527 fH->SetReadyToSave();
528
529 //
530 // Check whether fDisplay has previously been used (fCanvas),
531 // fDisplay is still open and the corresponding Canvas/Tab is
532 // still existing.
533 //
534 if (fDisplay && fDisplay->HasCanvas(fCanvas))
535 DrawCloneToDisplay();
536
537 return kTRUE;
538}
539
540// --------------------------------------------------------------------------
541//
542// Implementation of SavePrimitive. Used to write the call to a constructor
543// to a macro. In the original root implementation it is used to write
544// gui elements to a macro-file.
545//
546void MFillH::StreamPrimitive(ofstream &out) const
547{
548 if (fH)
549 fH->SavePrimitive(out);
550
551 if (fParContainer)
552 fParContainer->SavePrimitive(out);
553
554 if (fWeight)
555 fWeight->SavePrimitive(out);
556
557 out << " MFillH " << GetUniqueName() << "(";
558
559 if (fH)
560 out << "&" << fH->GetUniqueName();
561 else
562 out << "\"" << fHName << "\"";
563
564 if (fParContainer)
565 out << ", &" << fParContainer->GetUniqueName();
566 else
567 if (!fParContainerName.IsNull())
568 out << ", \"" << fParContainerName << "\"";
569
570 out << ");" << endl;
571
572 if (fWeight || !fWeightName.IsNull())
573 {
574 out << " " << GetUniqueName() << ".SetWeight(";
575 if (fWeight)
576 out << "&" << fWeight->GetUniqueName() << ");" << endl;
577 else
578 if (!fWeightName.IsNull())
579 out << "\"" << fWeightName << "\");" << endl;
580 }
581
582 if (fIndex)
583 {
584 out << " " << GetUniqueName() << ".SetRuleForIdx(\"";
585 out << fIndex->GetRule() << "\");" << endl;
586 }
587}
Note: See TracBrowser for help on using the repository browser.