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

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