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

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