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

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