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

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