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

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