source: trunk/MagicSoft/Mars/mbase/MParContainer.cc@ 1912

Last change on this file since 1912 was 1902, checked in by tbretz, 22 years ago
*** empty log message ***
File size: 17.1 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 12/2000 <mailto:tbretz@uni-sw.gwdg.de>
19!
20! Copyright: MAGIC Software Development, 2000-2002
21!
22!
23\* ======================================================================== */
24
25//////////////////////////////////////////////////////////////////////////////
26// //
27// MParContainer //
28// //
29// The MParContainer class is the base class for all MARS parameter //
30// containers. At the moment it is almost the same than ROOT's TNamed. //
31// A TNamed contains the essential elements (name, title) //
32// to identify a derived object in lists like our MParList or MTaskList. //
33// The main difference is that the name and title isn't stored and read //
34// to and from root files ("//!") //
35// //
36//////////////////////////////////////////////////////////////////////////////
37#include "MParContainer.h"
38
39#include <ctype.h> // isdigit
40#include <fstream.h> // ofstream, AsciiWrite
41
42#include <TEnv.h> // Env::Lookup
43#include <TClass.h> // IsA
44#include <TObjArray.h> // TObjArray
45#include <TBaseClass.h> // GetClassPointer
46#include <TMethodCall.h> // TMethodCall, AsciiWrite
47#include <TDataMember.h> // TDataMember, AsciiWrite
48#include <TVirtualPad.h> // gPad
49
50#include "MLog.h"
51#include "MLogManip.h"
52
53#ifndef __COSY__
54#include "MEvtLoop.h" // gListOfPrimitives
55#else
56TList *gListOfPrimitives; // forard declaration in MParContainer.h
57#endif
58
59ClassImp(MParContainer);
60
61// --------------------------------------------------------------------------
62//
63// MParContainer copy ctor
64//
65MParContainer::MParContainer(const MParContainer &named)
66{
67 fName = named.fName;
68 fTitle = named.fTitle;
69
70 fLog = named.fLog;
71
72 fReadyToSave = named.fReadyToSave;
73}
74
75// --------------------------------------------------------------------------
76//
77// MParContainer assignment operator.
78//
79MParContainer& MParContainer::operator=(const MParContainer& rhs)
80{
81 if (this == &rhs)
82 return *this;
83
84 TObject::operator=(rhs);
85
86 fName = rhs.fName;
87 fTitle = rhs.fTitle;
88
89 fLog = rhs.fLog;
90 fReadyToSave = rhs.fReadyToSave;
91
92 return *this;
93}
94
95// --------------------------------------------------------------------------
96//
97// Make a clone of an object using the Streamer facility.
98// If newname is specified, this will be the name of the new object
99//
100TObject *MParContainer::Clone(const char *newname) const
101{
102
103 MParContainer *named = (MParContainer*)TObject::Clone();
104 if (newname && strlen(newname)) named->SetName(newname);
105 return named;
106}
107
108// --------------------------------------------------------------------------
109//
110// Compare two MParContainer objects. Returns 0 when equal, -1 when this is
111// smaller and +1 when bigger (like strcmp).
112//
113Int_t MParContainer::Compare(const TObject *obj) const
114{
115 if (this == obj) return 0;
116 return fName.CompareTo(obj->GetName());
117}
118
119// --------------------------------------------------------------------------
120//
121// Copy this to obj.
122//
123void MParContainer::Copy(TObject &obj)
124#if ROOT_VERSION_CODE > ROOT_VERSION(3,04,01)
125const
126#endif
127{
128 MParContainer &cont = (MParContainer&)obj;
129
130 TObject::Copy(obj);
131
132 cont.fName = fName;
133 cont.fTitle = fTitle;
134
135 cont.fLog = fLog;
136 cont.fReadyToSave = fReadyToSave;
137}
138
139// --------------------------------------------------------------------------
140//
141// Encode MParContainer into output buffer.
142//
143void MParContainer::FillBuffer(char *&buffer)
144{
145 fName.FillBuffer(buffer);
146 fTitle.FillBuffer(buffer);
147}
148
149// --------------------------------------------------------------------------
150//
151// Return a unique name for this container. It is created from
152// the container name and the unique Id. (This is mostly used
153// in the StreamPrimitive member functions)
154//
155const TString MParContainer::GetUniqueName() const
156{
157 TString ret = ToLower(fName);
158
159 if (isdigit(ret[ret.Length()-1]))
160 ret+="_";
161
162 ret+=GetUniqueID();
163
164 return ret;
165}
166
167// --------------------------------------------------------------------------
168//
169// List MParContainer name and title.
170//
171void MParContainer::ls(Option_t *) const
172{
173 TROOT::IndentLevel();
174 *fLog << all << GetDescriptor() << " " << GetTitle() << ": kCanDelete=";
175 *fLog << Int_t(TestBit(kCanDelete)) << endl;
176}
177
178// --------------------------------------------------------------------------
179//
180// Print MParContainer name and title.
181//
182void MParContainer::Print(Option_t *) const
183{
184 *fLog << all << GetDescriptor() << " " << GetTitle() << endl;
185}
186
187// --------------------------------------------------------------------------
188//
189// Change (i.e. set) the name of the MParContainer.
190// WARNING !!
191// If the object is a member of a THashTable, THashList container
192// The HashTable must be Rehashed after SetName
193// For example the list of objects in the current directory is a THashList
194//
195void MParContainer::SetName(const char *name)
196{
197 fName = name;
198 ResetBit(kIsSavedAsPrimitive);
199 if (gPad && TestBit(kMustCleanup)) gPad->Modified();
200}
201
202// --------------------------------------------------------------------------
203//
204// Change (i.e. set) all the MParContainer parameters (name and title).
205// See also WARNING in SetName
206//
207void MParContainer::SetObject(const char *name, const char *title)
208{
209 fName = name;
210 fTitle = title;
211 ResetBit(kIsSavedAsPrimitive);
212 if (gPad && TestBit(kMustCleanup)) gPad->Modified();
213}
214
215// --------------------------------------------------------------------------
216//
217// Change (i.e. set) the title of the MParContainer.
218//
219void MParContainer::SetTitle(const char *title)
220{
221 fTitle = title;
222 ResetBit(kIsSavedAsPrimitive);
223 if (gPad && TestBit(kMustCleanup)) gPad->Modified();
224}
225
226// --------------------------------------------------------------------------
227//
228// Return size of the MParContainer part of the TObject.
229//
230Int_t MParContainer::Sizeof() const
231{
232 Int_t nbytes = fName.Sizeof() + fTitle.Sizeof();
233 return nbytes;
234}
235
236// --------------------------------------------------------------------------
237//
238// If you want to use Ascii-Input/-Output (eg. MWriteAsciiFile) of a
239// container, overload this function.
240//
241void MParContainer::AsciiRead(ifstream &fin)
242{
243 *fLog << warn << "To use the the ascii input of " << GetName();
244 *fLog << " you have to overload " << ClassName() << "::AsciiRead." << endl;
245}
246
247// --------------------------------------------------------------------------
248//
249// Write out a data member given as a TDataMember object to an output stream.
250//
251Bool_t MParContainer::WriteDataMember(ostream &out, const TDataMember *member, Double_t scale) const
252{
253 if (!member)
254 return kFALSE;
255
256 if (!member->IsPersistent() || member->Property()&kIsStatic)
257 return kFALSE;
258
259 /*const*/ TMethodCall *call = ((TDataMember*)member)->GetterMethod(); //FIXME: Root
260 if (!call)
261 {
262 *fLog << warn << "Sorry, no getter method found for " << member->GetName() << endl;
263 return kFALSE;
264 }
265
266 // For debugging: out << member->GetName() << ":";
267
268 switch (call->ReturnType())
269 {
270 case TMethodCall::kLong:
271 Long_t l;
272 call->Execute((void*)this, l); // FIXME: const, root
273 out << l << " ";
274 return kTRUE;
275
276 case TMethodCall::kDouble:
277 Double_t d;
278 call->Execute((void*)this, d); // FIXME: const, root
279 out << (scale*d) << " ";
280 return kTRUE;
281
282 default:
283 //case TMethodCall::kString:
284 //case TMethodCall::kOther:
285 /* someone may want to enhance this? */
286 return kFALSE;
287 }
288}
289
290// --------------------------------------------------------------------------
291//
292// Write out a data member given by name to an output stream.
293//
294Bool_t MParContainer::WriteDataMember(ostream &out, const char *member, Double_t scale) const
295{
296 /*const*/ TClass *cls = IsA()->GetBaseDataMember(member);
297 if (!cls)
298 return kFALSE;
299
300 return WriteDataMember(out, cls->GetDataMember(member), scale);
301}
302
303// --------------------------------------------------------------------------
304//
305// Write out a data member from a given TList of TDataMembers.
306// returns kTRUE when at least one member was successfully written
307//
308Bool_t MParContainer::WriteDataMember(ostream &out, const TList *list) const
309{
310 Bool_t rc = kFALSE;
311
312 TDataMember *data = NULL;
313
314 TIter Next(list);
315 while ((data=(TDataMember*)Next()))
316 rc |= WriteDataMember(out, data);
317
318 return rc;
319}
320
321// --------------------------------------------------------------------------
322//
323// If you want to use Ascii-Input/-Output (eg. MWriteAsciiFile) of a
324// container, you may overload this function. If you don't overload it
325// the data member of a class are written to the file in the order of
326// appearance in the class header (be more specfic: root dictionary)
327// Only data members which are of integer (Bool_t, Int_t, ...) or
328// floating point (Float_t, Double_t, ...) type are written.
329// returns kTRUE when at least one member was successfully written
330//
331Bool_t MParContainer::AsciiWrite(ostream &out) const
332{
333 // *fLog << warn << "To use the the ascii output of " << GetName();
334 // *fLog << " you have to overload " << ClassName() << "::AsciiWrite." << endl;
335
336 Bool_t rc = WriteDataMember(out, IsA()->GetListOfDataMembers());
337
338 TIter NextBaseClass(IsA()->GetListOfBases());
339 TBaseClass *base;
340 while ((base = (TBaseClass*) NextBaseClass()))
341 {
342 /*const*/ TClass *cls = base->GetClassPointer();
343
344 if (!cls)
345 continue;
346
347 if (cls->GetClassVersion())
348 rc |= WriteDataMember(out, cls->GetListOfDataMembers());
349 }
350
351 return rc;
352}
353
354TMethodCall *MParContainer::GetterMethod(const char *name) const
355{
356 TClass *cls = IsA()->GetBaseDataMember(name);
357 if (cls)
358 {
359 TDataMember *member = cls->GetDataMember(name);
360 if (!member)
361 {
362 *fLog << err << "Datamember '" << name << "' not in " << GetDescriptor() << endl;
363 return NULL;
364 }
365
366 TMethodCall *call = member->GetterMethod();
367 if (call)
368 return call;
369 }
370
371 *fLog << warn << "No standard access for '" << name << "' in ";
372 *fLog << GetDescriptor() << " or one of its base classes." << endl;
373
374 TMethodCall *call = NULL;
375
376 *fLog << warn << "Trying to find MethodCall '" << IsA()->GetName();
377 *fLog << "::Get" << name << "' instead <LEAKS MEMORY>" << endl;
378 call = new TMethodCall(IsA(), (TString)"Get"+name, "");
379 if (call->GetMethod())
380 return call;
381
382 delete call;
383
384 *fLog << warn << "Trying to find MethodCall '" << IsA()->GetName();
385 *fLog << "::" << name << "' instead <LEAKS MEMORY>" << endl;
386 call = new TMethodCall(IsA(), name, "");
387 if (call->GetMethod())
388 return call;
389
390 delete call;
391
392 *fLog << err << "Sorry, no getter method found for " << name << endl;
393 return NULL;
394}
395
396// --------------------------------------------------------------------------
397//
398// Implementation of SavePrimitive. Used to write the call to a constructor
399// to a macro. In the original root implementation it is used to write
400// gui elements to a macro-file.
401//
402void MParContainer::SavePrimitive(ofstream &out, Option_t *o)
403{
404 static UInt_t uid = 0;
405
406 if (IsSavedAsPrimitive())
407 return;
408
409 SetUniqueID(uid++);
410 SetBit(kIsSavedAsPrimitive);
411
412 if (gListOfPrimitives && !gListOfPrimitives->FindObject(this))
413 gListOfPrimitives->Add(this);
414
415 StreamPrimitive(out);
416}
417
418// --------------------------------------------------------------------------
419//
420// Creates the string written by SavePrimitive and returns it.
421//
422void MParContainer::StreamPrimitive(ofstream &out) const
423{
424 out << " // Using MParContainer::StreamPrimitive" << endl;
425 out << " " << ClassName() << " " << GetUniqueName() << "(\"";
426 out << fName << "\", \"" << fTitle << "\");" << endl;
427}
428
429void MParContainer::GetNames(TObjArray &arr) const
430{
431 arr.AddLast(new TNamed(fName, fTitle));
432}
433
434void MParContainer::SetNames(TObjArray &arr)
435{
436 TNamed *name = (TNamed*)arr.First();
437
438 fName = name->GetName();
439 fTitle = name->GetTitle();
440
441 delete arr.Remove(name);
442 arr.Compress();
443}
444
445// --------------------------------------------------------------------------
446//
447// Creates a new instance of this class. The idea is to create a clone of
448// this class in its initial state.
449//
450MParContainer *MParContainer::New() const
451{
452 return (MParContainer*)IsA()->New();
453}
454
455// --------------------------------------------------------------------------
456//
457// Read the contents/setup of a parameter container/task from a TEnv
458// instance (steering card/setup file).
459// The key to search for in the file should be of the syntax:
460// prefix.vname
461// While vname is a name which is specific for a single setup date
462// (variable) of this container and prefix is something like:
463// evtloopname.name
464// While name is the name of the containers/tasks in the parlist/tasklist
465//
466// eg. Job4.MImgCleanStd.CleaningLevel1: 3.0
467// Job4.MImgCleanStd.CleaningLevel2: 2.5
468//
469// If this cannot be found the next step is to search for
470// MImgCleanStd.CleaningLevel1: 3.0
471// And if this doesn't exist, too, we should search for:
472// CleaningLevel1: 3.0
473//
474// Warning: The programmer is responsible for the names to be unique in
475// all Mars classes.
476//
477Bool_t MParContainer::ReadEnv(const TEnv &env, TString prefix, Bool_t print)
478{
479 if (!IsEnvDefined(env, prefix, "", print))
480 return kFALSE;
481
482 *fLog << warn << "WARNING - Resource " << prefix+fName << " found, but no " << IsA()->GetName() << "::ReadEnv." << endl;
483 return kTRUE;
484}
485
486// --------------------------------------------------------------------------
487//
488// Write the contents/setup of a parameter container/task to a TEnv
489// instance (steering card/setup file).
490// The key to search for in the file should be of the syntax:
491// prefix.vname
492// While vname is a name which is specific for a single setup date
493// (variable) of this container and prefix is something like:
494// evtloopname.name
495// While name is the name of the containers/tasks in the parlist/tasklist
496//
497// eg. Job4.MImgCleanStd.CleaningLevel1: 3.0
498// Job4.MImgCleanStd.CleaningLevel2: 2.5
499//
500// If this cannot be found the next step is to search for
501// MImgCleanStd.CleaningLevel1: 3.0
502// And if this doesn't exist, too, we should search for:
503// CleaningLevel1: 3.0
504//
505// Warning: The programmer is responsible for the names to be unique in
506// all Mars classes.
507//
508Bool_t MParContainer::WriteEnv(TEnv &env, TString prefix, Bool_t print) const
509{
510 if (!IsEnvDefined(env, prefix, "", print))
511 return kFALSE;
512
513 *fLog << warn << "WARNING - Resource " << prefix+fName << " found, but " << IsA()->GetName() << "::WriteEnv not overloaded." << endl;
514 return kTRUE;
515}
516
517Bool_t MParContainer::IsEnvDefined(const TEnv &env, TString prefix, TString postfix, Bool_t print) const
518{
519 if (!postfix.IsNull())
520 postfix.Insert(0, ".");
521
522 return IsEnvDefined(env, prefix+postfix, print);
523}
524
525Bool_t MParContainer::IsEnvDefined(const TEnv &env, TString name, Bool_t print) const
526{
527 if (print)
528 *fLog << all << GetDescriptor() << " - " << name << "... " << flush;
529
530 if (!((TEnv&)env).Defined(name))
531 {
532 if (print)
533 *fLog << "not found." << endl;
534 return kFALSE;
535 }
536
537 if (print)
538 *fLog << "found." << endl;
539
540 return kTRUE;
541}
542
543Int_t MParContainer::GetEnvValue(const TEnv &env, TString prefix, TString postfix, Int_t dflt) const
544{
545 return GetEnvValue(env, prefix+"."+postfix, dflt);
546}
547
548Double_t MParContainer::GetEnvValue(const TEnv &env, TString prefix, TString postfix, Double_t dflt) const
549{
550 return GetEnvValue(env, prefix+"."+postfix, dflt);
551}
552
553const char *MParContainer::GetEnvValue(const TEnv &env, TString prefix, TString postfix, const char *dflt) const
554{
555 return GetEnvValue(env, prefix+"."+postfix, dflt);
556}
557
558Int_t MParContainer::GetEnvValue(const TEnv &env, TString prefix, Int_t dflt) const
559{
560 return ((TEnv&)env).GetValue(prefix, dflt);
561}
562
563Double_t MParContainer::GetEnvValue(const TEnv &env, TString prefix, Double_t dflt) const
564{
565 return ((TEnv&)env).GetValue(prefix, dflt);
566}
567
568const char *MParContainer::GetEnvValue(const TEnv &env, TString prefix, const char *dflt) const
569{
570 return ((TEnv&)env).GetValue(prefix, dflt);
571}
Note: See TracBrowser for help on using the repository browser.