/* ======================================================================== *\ ! ! * ! * This file is part of MARS, the MAGIC Analysis and Reconstruction ! * Software. It is distributed to you in the hope that it can be a useful ! * and timesaving tool in analysing Data of imaging Cerenkov telescopes. ! * It is distributed WITHOUT ANY WARRANTY. ! * ! * Permission to use, copy, modify and distribute this software and its ! * documentation for any purpose is hereby granted without fee, ! * provided that the above copyright notice appear in all copies and ! * that both that copyright notice and this permission notice appear ! * in supporting documentation. It is provided "as is" without express ! * or implied warranty. ! * ! ! ! Author(s): Thomas Bretz 03/2004 ! ! Copyright: MAGIC Software Development, 2000-2004 ! ! \* ======================================================================== */ ////////////////////////////////////////////////////////////////////////////// // // MStatusArray // // Helper class for MStatusDisplay // // If you want to read a MStatusArray (normally with name MStatusDisplay) // it is recommended to do it like this: // TFile f("myfile.root", "read"); // MStatusArray arr; // arr.Read(); // // If you want to use TFile::Get or TFile::GetObject you should switch off // addding Histograms automatically to the current directory first: // TFile f("myfile.root", "read"); // TH1::AddDirectory(kFALSE); // f.Get("MStatusDisplay"); // ////////////////////////////////////////////////////////////////////////////// #include "MStatusArray.h" #include // TH1::AddDirectoryStatus(); #include #include #include "MLog.h" #include "MLogManip.h" #include "MStatusDisplay.h" ClassImp(MStatusArray); using namespace std; // -------------------------------------------------------------------------- // // Initialize the MStatusArray from an MStatusDisplay. Note, the contents // still owned by MStatusDisplay and will vanish if the display changes // or is deleted without further notice. // MStatusArray::MStatusArray(const MStatusDisplay &d) : TObjArray() { d.FillArray(*this); } // -------------------------------------------------------------------------- // // If o==NULL a new status display is created, otherwise the one with name o // is searched in gROOT->GetListOfSpecials(). // In this display the contents of the MStatusArray is displayed. // TObject *MStatusArray::DisplayIn(Option_t *o) const { MStatusDisplay *d = 0; if (TString(o).IsNull()) d = new MStatusDisplay; if (!d) d = (MStatusDisplay*)gROOT->GetListOfSpecials()->FindObject(o); if (!d) return 0; if (d->Display(*this)) return d; delete d; return 0; } // -------------------------------------------------------------------------- // // Display the contents of the given tab in the display given as argument. // void MStatusArray::DisplayIn(MStatusDisplay &d, const char *tab) const { d.Display(*this, tab); } TObject *MStatusArray::FindObjectInPad(TVirtualPad *pad, const char *object, TClass *cls) const { TObject *o = NULL;//pad->FindObject(object); // if (o && o->InheritsFrom(cls)) // return o; TIter Next(pad->GetListOfPrimitives()); while ((o=Next())) { if (o->GetName()==(TString)object && o->InheritsFrom(cls)) return o; if (o==pad || !o->InheritsFrom(TVirtualPad::Class())) continue; if ((o = FindObjectInPad((TVirtualPad*)o, object, cls))) return o; // if (o->InheritsFrom(cls)) // return o; } return 0; } // FIXME: Move to a general class MMARS (TROOT) and unify with MParContainer TClass *MStatusArray::GetClass(const char *name) const { TClass *cls = gROOT->GetClass(name); Int_t rc = 0; if (!cls) rc =1; else { if (!cls->Property()) rc = 5; if (!cls->Size()) rc = 4; if (!cls->IsLoaded()) rc = 3; if (!cls->HasDefaultConstructor()) rc = 2; } if (rc==0) return cls; gLog << err << dbginf << "Class '" << name << "' not in dictionary: "; switch (rc) { case 1: gLog << "gROOT->GetClass() returned NULL." << endl; return NULL; case 2: gLog << "no default constructor." << endl; return NULL; case 3: gLog << "not loaded." << endl; return NULL; case 4: gLog << "zero size." << endl; return NULL; case 5: gLog << "no property." << endl; return NULL; } gLog << "THIS SHOULD NEVER HAPPEN!" << endl; return 0; } TCanvas *MStatusArray::FindCanvas(const char *name) const { TObject *o = TObjArray::FindObject(name); if (!o) return 0; return o->InheritsFrom(TCanvas::Class()) ? (TCanvas*)o : 0; } TObject *MStatusArray::FindObjectInCanvas(const char *object, const char *base, const char *canvas) const { TClass *cls = GetClass(base); if (!cls) return 0; TCanvas *c = canvas ? FindCanvas(canvas) : 0; if (canvas) { if (!c) { gLog << warn << "Canvas '" << canvas << "' not found..." << endl; return 0; } TObject *o = FindObjectInPad(c, object, cls); if (!o) { gLog << warn << "Object '" << object << "' [" << base << "] not found in canvas '" << canvas << "'..." << endl; return 0; } return o; //o->InheritsFrom(cls) ? o : 0; } TObject *o=0; TIter Next(this); while ((o=Next())) { if (!o->InheritsFrom(TVirtualPad::Class())) continue; if ((o=FindObjectInPad((TVirtualPad*)c, object, cls))) return o; } gLog << warn << "Object '" << object << "' [" << base << "] not found in canvas '" << canvas << "'..." << endl; return NULL; } TObject *MStatusArray::FindObjectInCanvas(const char *object, const char *canvas) const { return FindObjectInCanvas(object, object, canvas); } TObject *MStatusArray::FindObject(const char *object, const char *base) const { return FindObjectInCanvas(object, base, 0); } TObject *MStatusArray::FindObject(const char *object) const { return FindObjectInCanvas(object, object, 0); } // -------------------------------------------------------------------------- // // Print recursively all objects in this and sub-pads // void MStatusArray::PrintObjectsInPad(const TCollection *list, const TString &name, Int_t lvl) const { TIter Next(list); TObject *o=0; while ((o=Next())) { const Bool_t print = name.IsNull() || name==(TString)o->GetName(); if (print) { if (lvl>0) gLog << setw(lvl) << ' '; gLog << " " << o->ClassName() << ": " << o->GetName() << " <" << Next.GetOption() << "> (" << o << ") " << (int)o->TestBit(kCanDelete) << endl; } if (o->InheritsFrom(TVirtualPad::Class())) PrintObjectsInPad(((TVirtualPad*)o)->GetListOfPrimitives(), print?TString():name, lvl+1); } } // -------------------------------------------------------------------------- // // Print recursively all objects in this and sub-pads. If !option.IsNull() // only objects in the corresponding pad are printed. // void MStatusArray::Print(Option_t *option) const { gLog << all; PrintObjectsInPad(this, TString(option)); } /* // -------------------------------------------------------------------------- // // Make sure that kCanDelete is properly set for all directly contained // objects. Some kCanDelete bits might not be properly set or get lost when // the MParContainer is stored. // void MStatusArray::SetCanDelete(const TCollection *list) const { TIter Next(list); TObject *o=0; while ((o=Next())) { if (o->InheritsFrom(TVirtualPad::Class())) SetCanDelete(((TVirtualPad*)o)->GetListOfPrimitives()); else o->SetBit(kCanDelete|kMustCleanup); } } */ // -------------------------------------------------------------------------- // // Set kCanDelete for all objects for which kMyCanDelete is set. This // is a STUPID workaruond for an ANNOYING root bug which is that // the streamer function of TH1 resets the KCanDelete bit after reading. // void MStatusArray::SetCanDelete(const TCollection *list) const { TIter Next(list); TObject *o=0; while ((o=Next())) { if (o->InheritsFrom(TVirtualPad::Class())) SetCanDelete(((TVirtualPad*)o)->GetListOfPrimitives()); else { if (o->TestBit(kMyCanDelete) && o->InheritsFrom("TH1")) { o->SetBit(kCanDelete); o->ResetBit(kMyCanDelete); } } } } void MStatusArray::EnableTH1Workaround(const TCollection *list) const { TIter Next(list?list:this); TObject *o=0; while ((o=Next())) { if (o->InheritsFrom(TVirtualPad::Class())) EnableTH1Workaround(((TVirtualPad*)o)->GetListOfPrimitives()); else if (o->InheritsFrom("TH1")) o->SetBit(kCanDelete); } } // -------------------------------------------------------------------------- // // Set kMyCanDelete for all objects for which kCanDelete is set. This // is a STUPID workaruond for an ANNOYING root bug which is that // the streamer function of TH1 resets the KCanDelete bit after reading. // void MStatusArray::SetMyCanDelete(const TCollection *list) const { TIter Next(list); TObject *o=0; while ((o=Next())) { if (o->InheritsFrom(TVirtualPad::Class())) SetMyCanDelete(((TVirtualPad*)o)->GetListOfPrimitives()); else { if (o->TestBit(kMyCanDelete) && o->InheritsFrom("TH1")) gLog << warn << "WARNING - MStatusArray::Write - " << o->GetName() << " [" << o->ClassName() << "] has BIT(30) already set!" << endl; if (o->TestBit(kCanDelete) && o->InheritsFrom("TH1")) o->SetBit(kMyCanDelete); } } } // -------------------------------------------------------------------------- // // Reset kMyCanDelete for all objects for which kMyCanDelete is set. This // is a STUPID workaruond for an ANNOYING root bug which is that // the streamer function of TH1 resets the KCanDelete bit after reading. // void MStatusArray::ResetMyCanDelete(const TCollection *list) const { TIter Next(list); TObject *o=0; while ((o=Next())) { if (o->InheritsFrom(TVirtualPad::Class())) ResetMyCanDelete(((TVirtualPad*)o)->GetListOfPrimitives()); else { if (o->TestBit(kMyCanDelete) && o->InheritsFrom("TH1")) o->ResetBit(kMyCanDelete); } } } // -------------------------------------------------------------------------- // // Switch off adding histograms to current directory before reading. // Switch back // Int_t MStatusArray::Read(const char *name) { // It seems that the contents are not properly deleted by TObjArray::Read Delete(); // Make sure newly read histograms are not added to the current directory const Bool_t store = TH1::AddDirectoryStatus(); TH1::AddDirectory(kFALSE); const Int_t rc = TObjArray::Read(name?name:"MStatusDisplay"); TH1::AddDirectory(store); // All objects in the list (TNamed, TCanvas, etc) do not have // the kCanDelete bit set. Make sure that it is set to make // them deleted by the destructor of this list TIter Next(this); TObject *o=0; while ((o=Next())) { if (o->InheritsFrom(TVirtualPad::Class())) { TIter Next2(((TVirtualPad*)o)->GetListOfPrimitives()); TObject *o2=0; while ((o2=Next2())) if (o2->InheritsFrom("MParContainer")) o2->SetBit(kCanDelete); } o->SetBit(kCanDelete); } // Make sure that all kCanDelete bits are properly set SetCanDelete(this); SetOwner(); return rc; } // -------------------------------------------------------------------------- // // Switch off adding histograms to current directory before reading. // Switch back // Int_t MStatusArray::Write(const char *name, Int_t option, Int_t bufsize) const { SetMyCanDelete(this); const Int_t rc = TObjArray::Write(name, option, bufsize); ResetMyCanDelete(this); return rc; }