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

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