source: trunk/MagicSoft/Mars/mbase/MStatusArray.cc@ 8339

Last change on this file since 8339 was 8299, checked in by tbretz, 18 years ago
*** empty log message ***
File size: 11.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 03/2004 <mailto:tbretz@astro.uni-wuerzburg.de>
19!
20! Copyright: MAGIC Software Development, 2000-2004
21!
22!
23\* ======================================================================== */
24
25//////////////////////////////////////////////////////////////////////////////
26//
27// MStatusArray
28//
29// Helper class for MStatusDisplay
30//
31// If you want to read a MStatusArray (normally with name MStatusDisplay)
32// it is recommended to do it like this:
33// TFile f("myfile.root", "read");
34// MStatusArray arr;
35// arr.Read();
36//
37// If you want to use TFile::Get or TFile::GetObject you should switch off
38// addding Histograms automatically to the current directory first:
39// TFile f("myfile.root", "read");
40// TH1::AddDirectory(kFALSE);
41// f.Get("MStatusDisplay");
42//
43//////////////////////////////////////////////////////////////////////////////
44#include "MStatusArray.h"
45
46#include <TH1.h> // TH1::AddDirectoryStatus();
47#include <TClass.h>
48#include <TCanvas.h>
49
50#include "MLog.h"
51#include "MLogManip.h"
52
53#include "MStatusDisplay.h"
54
55ClassImp(MStatusArray);
56
57using namespace std;
58
59// --------------------------------------------------------------------------
60//
61// If o==NULL a new status display is created, otherwise the one with name o
62// is searched in gROOT->GetListOfSpecials().
63// In this display the contents of the MStatusArray is displayed.
64//
65TObject *MStatusArray::DisplayIn(Option_t *o) const
66{
67 MStatusDisplay *d = 0;
68 if (TString(o).IsNull())
69 d = new MStatusDisplay;
70
71 if (!d)
72 d = (MStatusDisplay*)gROOT->GetListOfSpecials()->FindObject(o);
73
74 if (!d)
75 return 0;
76
77 if (d->Display(*this))
78 return d;
79
80 delete d;
81 return 0;
82}
83
84// --------------------------------------------------------------------------
85//
86// Display the contents of the given tab in the display given as argument.
87//
88void MStatusArray::DisplayIn(MStatusDisplay &d, const char *tab) const
89{
90 d.Display(*this, tab);
91}
92
93TObject *MStatusArray::FindObjectInPad(TVirtualPad *pad, const char *object, TClass *cls) const
94{
95 TObject *o = pad->FindObject(object);
96 if (o && o->InheritsFrom(cls))
97 return o;
98
99 TIter Next(pad->GetListOfPrimitives());
100 while ((o=Next()))
101 {
102 if (o==pad || !o->InheritsFrom(TVirtualPad::Class()))
103 continue;
104
105 if ((o = FindObjectInPad((TVirtualPad*)o, object, cls)))
106 if (o->InheritsFrom(cls))
107 return o;
108 }
109 return 0;
110}
111
112// FIXME: Move to a general class MMARS (TROOT) and unify with MParContainer
113TClass *MStatusArray::GetClass(const char *name) const
114{
115 TClass *cls = gROOT->GetClass(name);
116 Int_t rc = 0;
117 if (!cls)
118 rc =1;
119 else
120 {
121 if (!cls->Property())
122 rc = 5;
123 if (!cls->Size())
124 rc = 4;
125 if (!cls->IsLoaded())
126 rc = 3;
127 if (!cls->HasDefaultConstructor())
128 rc = 2;
129 }
130
131 if (rc==0)
132 return cls;
133
134 gLog << err << dbginf << "Class '" << name << "' not in dictionary: ";
135 switch (rc)
136 {
137 case 1:
138 gLog << "gROOT->GetClass() returned NULL." << endl;
139 return NULL;
140 case 2:
141 gLog << "no default constructor." << endl;
142 return NULL;
143 case 3:
144 gLog << "not loaded." << endl;
145 return NULL;
146 case 4:
147 gLog << "zero size." << endl;
148 return NULL;
149 case 5:
150 gLog << "no property." << endl;
151 return NULL;
152 }
153
154 gLog << "THIS SHOULD NEVER HAPPEN!" << endl;
155
156 return 0;
157}
158
159TCanvas *MStatusArray::FindCanvas(const char *name) const
160{
161 TObject *o = TObjArray::FindObject(name);
162 if (!o)
163 return 0;
164
165 return o->InheritsFrom(TCanvas::Class()) ? (TCanvas*)o : 0;
166}
167
168
169TObject *MStatusArray::FindObjectInCanvas(const char *object, const char *base, const char *canvas) const
170{
171 TClass *cls = GetClass(base);
172 if (!cls)
173 return 0;
174
175 TCanvas *c = canvas ? FindCanvas(canvas) : 0;
176 if (canvas)
177 {
178 if (!c)
179 {
180 gLog << warn << "Canvas '" << canvas << "' not found..." << endl;
181 return 0;
182 }
183
184 TObject *o = FindObjectInPad(c, object, cls);
185 if (!o)
186 {
187 gLog << warn << "Object '" << object << "' [" << base << "] not found in canvas '" << canvas << "'..." << endl;
188 return 0;
189 }
190
191 return o; //o->InheritsFrom(cls) ? o : 0;
192 }
193
194 TObject *o=0;
195 TIter Next(this);
196 while ((o=Next()))
197 {
198 if (!o->InheritsFrom(TVirtualPad::Class()))
199 continue;
200
201 if ((o=FindObjectInPad((TVirtualPad*)c, object, cls)))
202 return o;
203 }
204
205 gLog << warn << "Object '" << object << "' [" << base << "] not found in canvas '" << canvas << "'..." << endl;
206 return NULL;
207}
208
209TObject *MStatusArray::FindObjectInCanvas(const char *object, const char *canvas) const
210{
211 return FindObjectInCanvas(object, object, canvas);
212}
213
214TObject *MStatusArray::FindObject(const char *object, const char *base) const
215{
216 return FindObjectInCanvas(object, base, 0);
217}
218
219TObject *MStatusArray::FindObject(const char *object) const
220{
221 return FindObjectInCanvas(object, object, 0);
222}
223
224// --------------------------------------------------------------------------
225//
226// Print recursively all objects in this and sub-pads
227//
228void MStatusArray::PrintObjectsInPad(const TCollection *list, const TString &name, Int_t lvl) const
229{
230 TIter Next(list);
231 TObject *o=0;
232 while ((o=Next()))
233 {
234 const Bool_t print = name.IsNull() || name==(TString)o->GetName();
235 if (print)
236 {
237 if (lvl>0)
238 gLog << setw(lvl) << ' ';
239 gLog << " " << o->ClassName() << ": " << o->GetName() << " <" << Next.GetOption() << "> (" << o << ") " << (int)o->TestBit(kCanDelete) << endl;
240 }
241
242 if (o->InheritsFrom(TVirtualPad::Class()))
243 PrintObjectsInPad(((TVirtualPad*)o)->GetListOfPrimitives(), print?TString():name, lvl+1);
244 }
245}
246
247// --------------------------------------------------------------------------
248//
249// Print recursively all objects in this and sub-pads. If !option.IsNull()
250// only objects in the corresponding pad are printed.
251//
252void MStatusArray::Print(Option_t *option) const
253{
254 const TString opt(option);
255
256 PrintObjectsInPad(this, opt);
257}
258
259/*
260// --------------------------------------------------------------------------
261//
262// Make sure that kCanDelete is properly set for all directly contained
263// objects. Some kCanDelete bits might not be properly set or get lost when
264// the MParContainer is stored.
265//
266void MStatusArray::SetCanDelete(const TCollection *list) const
267{
268 TIter Next(list);
269 TObject *o=0;
270 while ((o=Next()))
271 {
272 if (o->InheritsFrom(TVirtualPad::Class()))
273 SetCanDelete(((TVirtualPad*)o)->GetListOfPrimitives());
274 else
275 o->SetBit(kCanDelete|kMustCleanup);
276 }
277}
278*/
279
280// --------------------------------------------------------------------------
281//
282// Set kCanDelete for all objects for which kMyCanDelete is set. This
283// is a STUPID workaruond for an ANNOYING root bug which is that
284// the streamer function of TH1 resets the KCanDelete bit after reading.
285//
286void MStatusArray::SetCanDelete(const TCollection *list) const
287{
288 TIter Next(list);
289 TObject *o=0;
290 while ((o=Next()))
291 {
292 if (o->InheritsFrom(TVirtualPad::Class()))
293 SetCanDelete(((TVirtualPad*)o)->GetListOfPrimitives());
294 else
295 {
296 if (o->TestBit(kMyCanDelete) && o->InheritsFrom("TH1"))
297 {
298 o->SetBit(kCanDelete);
299 o->ResetBit(kMyCanDelete);
300 }
301 }
302 }
303}
304
305void MStatusArray::EnableTH1Workaround(const TCollection *list) const
306{
307 TIter Next(list?list:this);
308 TObject *o=0;
309 while ((o=Next()))
310 {
311 if (o->InheritsFrom(TVirtualPad::Class()))
312 EnableTH1Workaround(((TVirtualPad*)o)->GetListOfPrimitives());
313 else
314 if (o->InheritsFrom("TH1"))
315 o->SetBit(kCanDelete);
316 }
317}
318
319// --------------------------------------------------------------------------
320//
321// Set kMyCanDelete for all objects for which kCanDelete is set. This
322// is a STUPID workaruond for an ANNOYING root bug which is that
323// the streamer function of TH1 resets the KCanDelete bit after reading.
324//
325void MStatusArray::SetMyCanDelete(const TCollection *list) const
326{
327 TIter Next(list);
328 TObject *o=0;
329 while ((o=Next()))
330 {
331 if (o->InheritsFrom(TVirtualPad::Class()))
332 SetMyCanDelete(((TVirtualPad*)o)->GetListOfPrimitives());
333 else
334 {
335 if (o->TestBit(kMyCanDelete) && o->InheritsFrom("TH1"))
336 gLog << warn << "WARNING - MStatusArray::Write - " << o->GetName() << " [" << o->ClassName() << "] has BIT(30) already set!" << endl;
337
338 if (o->TestBit(kCanDelete) && o->InheritsFrom("TH1"))
339 o->SetBit(kMyCanDelete);
340 }
341 }
342}
343
344// --------------------------------------------------------------------------
345//
346// Reset kMyCanDelete for all objects for which kMyCanDelete is set. This
347// is a STUPID workaruond for an ANNOYING root bug which is that
348// the streamer function of TH1 resets the KCanDelete bit after reading.
349//
350void MStatusArray::ResetMyCanDelete(const TCollection *list) const
351{
352 TIter Next(list);
353 TObject *o=0;
354 while ((o=Next()))
355 {
356 if (o->InheritsFrom(TVirtualPad::Class()))
357 ResetMyCanDelete(((TVirtualPad*)o)->GetListOfPrimitives());
358 else
359 {
360 if (o->TestBit(kMyCanDelete) && o->InheritsFrom("TH1"))
361 o->ResetBit(kMyCanDelete);
362 }
363 }
364}
365
366// --------------------------------------------------------------------------
367//
368// Switch off adding histograms to current directory before reading.
369// Switch back
370//
371Int_t MStatusArray::Read(const char *name)
372{
373 // It seems that the contents are not properly deleted by TObjArray::Read
374 Delete();
375
376 // Make sure newly read histograms are not added to the current directory
377 const Bool_t store = TH1::AddDirectoryStatus();
378 TH1::AddDirectory(kFALSE);
379 const Int_t rc = TObjArray::Read(name?name:"MStatusDisplay");
380 TH1::AddDirectory(store);
381
382 // All objects in the list (TNamed, TCanvas, etc) do not have
383 // the kCanDelete bit set. Make sure that it is set to make
384 // them deleted by the destructor of this list
385 TIter Next(this);
386 TObject *o=0;
387 while ((o=Next()))
388 {
389 if (o->InheritsFrom(TVirtualPad::Class()))
390 {
391 TIter Next2(((TVirtualPad*)o)->GetListOfPrimitives());
392 TObject *o2=0;
393 while ((o2=Next2()))
394 if (o2->InheritsFrom("MParContainer"))
395 o2->SetBit(kCanDelete);
396 }
397 o->SetBit(kCanDelete);
398 }
399
400 // Make sure that all kCanDelete bits are properly set
401 SetCanDelete(this);
402 SetOwner();
403
404 return rc;
405}
406
407// --------------------------------------------------------------------------
408//
409// Switch off adding histograms to current directory before reading.
410// Switch back
411//
412Int_t MStatusArray::Write(const char *name, Int_t option, Int_t bufsize) const
413{
414 SetMyCanDelete(this);
415 const Int_t rc = TObjArray::Write(name, option, bufsize);
416 ResetMyCanDelete(this);
417
418 return rc;
419}
Note: See TracBrowser for help on using the repository browser.