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

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