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

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