Ignore:
Timestamp:
01/03/05 12:02:16 (20 years ago)
Author:
tbretz
Message:
*** empty log message ***
Location:
trunk/MagicSoft/Mars/mfileio
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/MagicSoft/Mars/mfileio/MReadTree.cc

    r5160 r5692  
    1818!   Author(s): Thomas Bretz, 12/2000 <mailto:tbretz@astro.uni-wuerzburg.de>
    1919!
    20 !   Copyright: MAGIC Software Development, 2000-2003
     20!   Copyright: MAGIC Software Development, 2000-2005
    2121!
    2222!
     
    2424
    2525/////////////////////////////////////////////////////////////////////////////
    26 //                                                                         //
    27 // MReadTree                                                               //
    28 //                                                                         //
    29 // This tasks opens all branches in a specified tree and creates the       //
    30 // corresponding parameter containers if not already existing in the       //
    31 // parameter list.                                                         //
    32 //                                                                         //
    33 // The Process function reads one events from the tree. To go through the  //
    34 // events of one tree make sure that the event number is increased from    //
    35 // outside. It makes also possible to go back by decreasing the number.    //
    36 //                                                                         //
    37 // If you don't want to start reading the first event you have to call     //
    38 // MReadTree::SetEventNum after instantiating your MReadTree-object.       //
    39 //                                                                         //
    40 // To make reading much faster (up to a factor of 10 to 20) you can        //
    41 // ensure that only the data you are really processing is enabled by       //
    42 // calling MReadTree::UseLeaf.                                             //
    43 //                                                                         //
    44 // If the chain switches from one file to another file all                 //
    45 // TObject::Notify() functions are called of TObject objects which were    //
    46 // added to the Notifier list view MReadTree::AddNotify. If MReadTree      //
    47 // is the owner (viw MReadTree::SetOwner) all this objects are deleted     //
    48 // by the destructor of MReadTree                                          //
    49 //                                                                         //
     26//
     27// MReadTree
     28//
     29// This tasks opens all branches in a specified tree and creates the
     30// corresponding parameter containers if not already existing in the
     31// parameter list.
     32//
     33// The Process function reads one events from the tree. To go through the
     34// events of one tree make sure that the event number is increased from
     35// outside. It makes also possible to go back by decreasing the number.
     36//
     37// If you don't want to start reading the first event you have to call
     38// MReadTree::SetEventNum after instantiating your MReadTree-object.
     39//
     40// To make reading much faster (up to a factor of 10 to 20) you can
     41// ensure that only the data you are really processing is enabled by
     42// calling MReadTree::UseLeaf.
     43//
     44// If the chain switches from one file to another file all
     45// TObject::Notify() functions are called of TObject objects which were
     46// added to the Notifier list view MReadTree::AddNotify. If MReadTree
     47// is the owner (viw MReadTree::SetOwner) all this objects are deleted
     48// by the destructor of MReadTree
     49//
     50//
     51// ToDo:
     52// -----
     53//  - Auto Scheme and Branch choosing doesn't work for memory trees
     54//
    5055/////////////////////////////////////////////////////////////////////////////
    5156#include "MReadTree.h"
     
    7378// --------------------------------------------------------------------------
    7479//
    75 //  Default constructor. Don't use it.
    76 //
    77 MReadTree::MReadTree()
     80//  Default constructor. Use this constructor (ONLY) if you want to
     81//  access a memory tree (a TTree not stored in a file) created by
     82//  MWriteRootFile or manually.
     83//
     84MReadTree::MReadTree(TTree *tree)
    7885    : fNumEntry(0), fNumEntries(0), fBranchChoosing(kFALSE), fAutoEnable(kTRUE)
    7986{
     
    8188    fTitle = "Task to loop over all events in one single tree";
    8289
    83     fVetoList = NULL;
    84     fNotify = NULL;
     90    fVetoList = new TList;
     91    fVetoList->SetOwner();
     92
     93    fNotify = new TList;
    8594
    8695    fChain = NULL;
     96
     97    fTree = tree;
     98    SetBit(kChainWasChanged);
     99
     100    if (fTree)
     101        fAutoEnable = kFALSE;
     102    /*
     103    if (!fTree)
     104        return;
     105
     106    TIter Next(fTree->GetListOfBranches());
     107    TBranch *b=0;
     108    while ((b=(TBranch*)Next()))
     109        b->ResetAddress();
     110    */
    87111}
    88112
     
    114138    //
    115139    fChain = new MChain(tname);
     140    fTree = fChain;
    116141
    117142    // root 3.02:
     
    122147    if (fname)
    123148        AddFile(fname);
    124 //        if (fChain->Add(fname)>0)
    125 //            SetBit(kChainWasChanged);
    126149}
    127150
     
    137160    // creates a memory leak!
    138161    //
    139     TIter Next(fChain->GetStatus());
    140 
    141     TChainElement *element = NULL;
    142     while ((element=(TChainElement*)Next()))
    143         if (element->GetBaddress())
    144             delete (MParContainer**)element->GetBaddress();
    145 
    146     //
    147     // Delete the chain and the veto list
    148     //
     162    if (fChain) // FIXME: MEMORY LEAK for fTree!=0
     163    {
     164        TIter Next(fChain->GetStatus());
     165
     166        TChainElement *element = NULL;
     167        while ((element=(TChainElement*)Next()))
     168            if (element->GetBaddress())
     169                delete (MParContainer**)element->GetBaddress();
     170
     171        //
     172        // Delete the chain and the veto list
     173        //
    149174#if ROOT_VERSION_CODE < ROOT_VERSION(3,03,00)
    150     if (fChain->GetFile())
    151         delete fChain->GetFile();
     175        if (fChain->GetFile())
     176            delete fChain->GetFile();
    152177#endif
    153     delete fChain;
     178        delete fChain;
     179    }
     180
     181    /* This is AND MUST be done in PostProcess. See there for more details
     182    else
     183    {
     184        TIter Next(fTree->GetListOfBranches());
     185
     186        TBranch *element = NULL;
     187        while ((element=(TBranch*)Next()))
     188            if (element->GetAddress())
     189                delete (MParContainer**)element->GetAddress();
     190        }
     191    */
    154192
    155193    delete fNotify;
     
    179217Bool_t MReadTree::CheckBranchSize()
    180218{
    181     TArrayI entries(fChain->GetStatus()->GetSize());
     219    //if (!fChain) // >FIXME: fTree!=0
     220    //    return kTRUE;
     221
     222    TArrayI entries(fChain ? fChain->GetStatus()->GetSize() : fTree->GetListOfBranches()->GetSize());
    182223    Int_t num=0;
    183224
    184225    // Loop over all branches which have a corresponding container
    185     TIter Next(fChain->GetStatus());
    186 
    187     TChainElement *element = NULL;
    188     while ((element=(TChainElement*)Next()))
    189     {
    190         // Get branch name and find pointer to corresponding branch
    191         const TString name = element->GetName();
    192         const TBranch *b = fChain->FindBranch(name);
    193 
    194         // Skip element without corresponding branches (like "*")
    195         if (!b)
    196             continue;
    197 
    198         entries[num++] = (Int_t)b->GetEntries();
     226    /*
     227    if (fChain)
     228    {
     229        TIter Next(fChain->GetStatus());
     230
     231        TChainElement *element = NULL;
     232        while ((element=(TChainElement*)Next()))
     233        {
     234            // Get branch name and find pointer to corresponding branch
     235            const TString name = element->GetName();
     236            const TBranch *b = fChain->FindBranch(name);
     237
     238            // Skip element without corresponding branches (like "*")
     239            if (!b)
     240                continue;
     241
     242            entries[num++] = (Int_t)b->GetEntries();
     243        }
     244    }
     245    else */
     246    {
     247        TIter Next(fTree->GetListOfBranches());
     248
     249        TBranch *element = NULL;
     250        while ((element=(TBranch*)Next()))
     251            entries[num++] = (Int_t)element->GetEntries();
    199252    }
    200253
     
    209262            *fLog << "  Due to several circumstances (such at a bug in MReadTree or wrong" << endl;
    210263            *fLog << "  usage of the file UPDATE mode) you may have produced a file in which" << endl;
    211             *fLog << "  at least two branches in the same tree (" << fChain->GetName() << ") have different" << endl;
     264            *fLog << "  at least two branches in the same tree (" << fTree->GetName() << ") have different" << endl;
    212265            *fLog << "  number of entries. Sorry, but this file (" << GetFileName() << ")" << endl;
    213266            *fLog << "  is unusable." << endl;
     
    278331Int_t MReadTree::AddFile(const char *fname, Int_t entries)
    279332{
     333    if (!fChain)
     334    {
     335        *fLog << err << "MReadTree::AddFile - ERROR: You cannot add a file, because MReadTree" << endl;
     336        *fLog <<        "                            handles a memory based tree or its default" << endl;
     337        *fLog <<        "                            constructor was called." << endl;
     338        return 0;
     339    }
     340
    280341#if ROOT_VERSION_CODE < ROOT_VERSION(3,03,01)
    281342    //
     
    353414Int_t MReadTree::AddFiles(const MReadTree &read)
    354415{
     416    if (!fChain)
     417    {
     418        *fLog << err << "MReadTree::AddFiles - ERROR: You cannot add a file, because MReadTree" << endl;
     419        *fLog <<        "                             handles a memory based tree or its default" << endl;
     420        *fLog <<        "                             constructor was called." << endl;
     421        return 0;
     422    }
     423
    355424    const Int_t rc = fChain->Add(read.fChain);
    356425
     
    376445void MReadTree::SortFiles()
    377446{
    378     fChain->GetListOfFiles()->Sort();
     447    if (fChain)
     448        fChain->GetListOfFiles()->Sort();
    379449}
    380450
     
    392462
    393463    *fLog << inf << GetDescriptor() << ": Branch choosing enabled (only enabled branches are read)." << endl;
    394     fChain->SetBranchStatus("*", kFALSE);
     464    fTree->SetBranchStatus("*", kFALSE); // *CHANGED-fChain-to-fTree*
    395465    fBranchChoosing = kTRUE;
    396466}
     
    405475void MReadTree::EnableBranch(const char *name)
    406476{
     477    if (!fChain)
     478    {
     479        *fLog << warn << "MReadTree::EnableBranch - WARNING: EnableBranch doesn't work with memory based trees... ignored." << endl;
     480        return;
     481    }
     482
    407483    if (fChain->GetListOfFiles()->GetEntries()==0)
    408484    {
     
    424500void MReadTree::SetBranchStatus(const char *name, Bool_t status)
    425501{
    426     fChain->SetBranchStatus(name, status);
     502    fTree->SetBranchStatus(name, status); // *CHANGED-fChain-to-fTree*
    427503
    428504    *fLog << inf << (status ? "Enabled" : "Disabled");
     
    449525        bn.Remove(bn.Length()-1);
    450526
    451     if (fChain->GetBranch(bn))
     527    if (fTree->GetBranch(bn)) // *CHANGED-fChain-to-fTree*
    452528        SetBranchStatus(name, status);
    453529
     
    461537        return;
    462538
    463     if (fChain->GetBranch(dot+1))
     539    if (fTree->GetBranch(dot+1)) // *CHANGED-fChain-to-fTree*
    464540        SetBranchStatus(dot+1, status);
    465541}
     
    575651    if (TestBit(kChainWasChanged))
    576652    {
    577         *fLog << inf << "Scanning chain " << fChain->GetName() << "... " << flush;
    578         fNumEntries = (UInt_t)fChain->GetEntries();
     653        // *CHANGED-fChain-to-fTree*
     654        *fLog << inf << "Scanning chain " << fTree->GetName() << "... " << flush;
     655        fNumEntries = (UInt_t)fTree->GetEntries();
    579656        *fLog << fNumEntries << " events found." << endl;
    580657        ResetBit(kChainWasChanged);
     
    624701    // tasks are not preprocessed.
    625702    //
    626     fChain->SetNotify(NULL);
     703    fTree->SetNotify(NULL); //*CHANGED-fChain-to-fTree*
    627704
    628705    //
     
    633710    // it crashes. ResetTree makes sure, that the tree number is -1
    634711    //
    635     fChain->ResetTree();
     712    if (fChain) // *CHANGED-fChain-to-fTree*
     713        fChain->ResetTree();
    636714    // Maybe this would be enough, but the above might be safer...
    637715    //if (fChain->GetTreeNumber()==0)
     
    641719    // check for files and for the tree!
    642720    //
    643     if (!fChain->GetFile())
     721    if (fChain && !fChain->GetFile()) // *CHANGED-fChain-to-fTree*
    644722    {
    645723        *fLog << err << GetDescriptor() << ": No file or no tree with name " << fChain->GetName() << " in file." << endl;
     
    665743    // create the Iterator to loop over all branches
    666744    //
    667     TIter Next(fChain->GetListOfBranches());
     745    TIter Next(fTree->GetListOfBranches()); // *CHANGED-fChain-to-fTree*
    668746    TBranch *branch=NULL;
    669747
     
    728806        // If we created one already, delete it.
    729807        //
    730         TChainElement *element = (TChainElement*)fChain->GetStatus()->FindObject(bname);
    731         if (element)
    732             delete (MParContainer**)element->GetBaddress();
     808        // *CHANGED-fChain-to-fTree*
     809        if (fChain)
     810        {
     811            TChainElement *element = (TChainElement*)fChain->GetStatus()->FindObject(bname);
     812            if (element)
     813                delete (MParContainer**)element->GetBaddress();
     814        }
     815        /* This can't be done here for memory trees - see
     816           PostProcess for more details.
     817        else
     818        {
     819            TBranch *branch = (TBranch*)fTree->GetBranch(bname);
     820            if (branch)
     821            {
     822                *fLog << bname << " " << (void*)branch->GetAddress() << " " << pcont << endl;
     823                delete (MParContainer**)branch->GetAddress();
     824            }
     825        }
     826        */
    733827
    734828        //
     
    736830        // the actual branch should be stored - enable branch.
    737831        //
    738         fChain->SetBranchAddress(bname, pcont);
     832        fTree->SetBranchAddress(bname, pcont); // *CHANGED-fChain-to-fTree*
    739833
    740834        *fLog << inf << "Master branch address '" << bname << "' [";
     
    762856    // PreProcess-function.
    763857    //
    764     fChain->ResetTree();
    765     fChain->SetNotify(this);
    766 
    767     return GetSelector() ? GetSelector()->CallPreProcess(pList) : kTRUE;
     858    if (fChain)
     859        fChain->ResetTree(); // *CHANGED-fChain-to-fTree*
     860
     861    fTree->SetNotify(this); // *CHANGED-fChain-to-fTree*
     862
     863    const Int_t rc = GetSelector() ? GetSelector()->CallPreProcess(pList) : kTRUE;
     864    if (rc!=kTRUE || fChain)
     865        return rc;
     866
     867    return Notify();
    768868}
    769869
     
    775875void MReadTree::SetReadyToSave(Bool_t flag)
    776876{
     877    if (!fChain)
     878        return;
     879
    777880    TIter Next(fChain->GetStatus());
    778881
     
    870973    }
    871974
    872     const Bool_t rc = fChain->GetEntry(fNumEntry++) != 0;
     975    const Bool_t rc = fTree->GetEntry(fNumEntry++) != 0; // *CHANGED-fChain-to-fTree*
    873976
    874977    if (fTaskList)
    875         fTaskList->SetStreamId(fChain->GetName());
     978        fTaskList->SetStreamId(fTree->GetName()); // *CHANGED-fChain-to-fTree*
    876979
    877980    if (rc)
     
    887990Int_t MReadTree::PostProcess()
    888991{
     992    // In the case of a memory tree I don't know how we can
     993    // make a decision in PreProcess between a self allocated
     994    // memory address or a pending address set long before.
     995    // So we delete the stuff in PostProcess and not the destructor
     996    // (which might seg faullt if PreProcess has never been called)
     997    if (!fChain)
     998    {
     999        TIter Next(fTree->GetListOfBranches());
     1000        TBranch *b=0;
     1001        while ((b=(TBranch*)Next()))
     1002        {
     1003            if (b->GetAddress())
     1004            {
     1005                delete b->GetAddress();
     1006                b->ResetAddress();
     1007            }
     1008        }
     1009    }
     1010
    8891011    return GetSelector() ? GetSelector()->CallPostProcess() : kTRUE;
    8901012}
     
    8961018Bool_t MReadTree::GetEvent()
    8971019{
    898     Bool_t rc = fChain->GetEntry(fNumEntry) != 0;
     1020    Bool_t rc = fTree->GetEntry(fNumEntry) != 0; // *CHANGED-fChain-to-fTree*
    8991021
    9001022    if (rc)
     
    9811103TString MReadTree::GetFileName() const
    9821104{
    983     const TFile *file = fChain->GetFile();
     1105    const TFile *file = fChain ? fChain->GetFile() : fTree->GetCurrentFile();
    9841106
    9851107    if (!file)
     
    9971119Int_t MReadTree::GetFileIndex() const
    9981120{
    999     return fChain->GetTreeNumber();
     1121    return fChain ? fChain->GetTreeNumber() : 0;
    10001122    /*
    10011123    const TString filename = fChain->GetFile()->GetName();
  • trunk/MagicSoft/Mars/mfileio/MReadTree.h

    r5160 r5692  
    88class MChain;
    99class TBranch;
     10class TTree;
    1011class MTaskList;
    1112
     
    1516
    1617private:
    17     MChain *fChain;            // Pointer to tree
     18    MChain *fChain;            // Pointer to tree==fTree (only if fTree inherits from MChain)
     19    TTree  *fTree;             // Pointer to tree
    1820
    1921    UInt_t  fNumEntry;         // Number of actual entry in chain
     
    2325    Bool_t  fAutoEnable;       // Flag for auto enabeling scheme
    2426
    25     TList  *fVetoList;         // List of Branches which are not allowed to get enabled
    26     TList  *fNotify;           // List of TObjects to notify when switching files
     27    TList  *fVetoList;         //-> List of Branches which are not allowed to get enabled
     28    TList  *fNotify;           //-> List of TObjects to notify when switching files
    2729
    2830    MTaskList *fTaskList;      // Tasklist to set StreamId
     
    4749
    4850public:
    49     MReadTree();
     51    MReadTree(TTree *tree=0);
    5052    MReadTree(const char *treename, const char *filename=NULL, const char *name=NULL, const char *title=NULL);
    5153    ~MReadTree();
  • trunk/MagicSoft/Mars/mfileio/MWriteRootFile.cc

    r4826 r5692  
    1818!   Author(s): Thomas Bretz, 6/2001 <mailto:tbretz@astro.uni-wuerzburg.de>
    1919!
    20 !   Copyright: MAGIC Software Development, 2000-2004
     20!   Copyright: MAGIC Software Development, 2000-2005
    2121!
    2222!
     
    3737// ReInit()) For more details se the corresponding constructor.
    3838//
     39// Memory based trees
     40// ------------------
     41// It is possible to store the data into memory (TTrees) instead of
     42// writing the data into a file. To do this either call the default
     43// constructor or specify 'memory' as option in the constructor.
     44//
     45// Afterwards the tree can be found using gROOT->FindObject("treename")
     46//
     47// Currently(!) the tree is not deleted at all! Please make sure to
     48// delete it if it is not used anymore - otherwise you could wast a LOT
     49// of memory. Please consider that this behaviour might change in the
     50// future.
     51//
     52// Such trees are usefull if you want to use more basic root-tools
     53// like TMultiLayerPerceptron or TEventList.
     54//
     55// If you want to process such memory based Trees using Mars make sure,
     56// that you don't need data from the RunHeader tree because you can
     57// only use MReadTree but not MReadMarsFile with such a tree.
     58//
    3959/////////////////////////////////////////////////////////////////////////////
    4060#include "MWriteRootFile.h"
     
    7292
    7393    //
    74     // Believing the root user guide, TTree instanced are owned by the
     94    // Believing the root user guide, TTree instances are owned by the
    7595    // directory (file) in which they are. This means we don't have to
    7696    // care about their destruction.
     
    87107{
    88108    Init();
    89 
    90     //
    91     // Set the Arrays the owner of its entries. This means, that the
    92     // destructor of the arrays will delete all its entries.
    93     //
    94     fBranches.SetOwner();
    95109}
    96110
     
    133147//
    134148MWriteRootFile::MWriteRootFile(const char *fname,
    135                                const Option_t *opt,
     149                               const Option_t *option,
    136150                               const char *ftitle,
    137151                               const Int_t comp,
    138152                               const char *name,
    139                                const char *title)
     153                               const char *title) : fOut(NULL)
    140154{
    141155    Init(name, title);
     156
     157    TString opt(option);
     158    opt.ToLower();
     159
     160    //
     161    // Check if we are writing to memory
     162    //
     163    if (opt.Contains("memory"))
     164    {
     165        fSplitRule = fname;
     166        return;
     167    }
    142168
    143169    //
     
    172198    Print();
    173199
    174     //
    175     // If the file is still open (no error) write the keys. This is necessary
    176     // for appearance of the all trees and branches.
    177     //
    178     if (IsFileOpen())
    179         fOut->Write();
    180 
    181     //
    182     // Delete the file. This'll also close the file (if open)
    183     //
    184     delete fOut;
    185     fOut = 0;
     200    if (fOut)
     201    {
     202        //
     203        // If the file is still open (no error) write the keys. This is necessary
     204        // for appearance of the all trees and branches.
     205        //
     206        if (IsFileOpen())
     207            fOut->Write();
     208
     209        //
     210        // Delete the file. This'll also close the file (if open)
     211        //
     212        delete fOut;
     213        fOut = 0;
     214    }
    186215
    187216    //
     
    257286void MWriteRootFile::AddContainer(const char *cname, const char *tname, Bool_t must)
    258287{
     288    if (!fOut && !tname)
     289        tname = fSplitRule;
     290
    259291    TIter Next(&fBranches);
    260292    TObject *o=0;
     
    262294        if (TString(o->GetName())==TString(tname) && TString(o->GetTitle())==TString(cname))
    263295        {
     296            *fLog << warn;
    264297            *fLog << "WARNING - Container '" << cname << "' in Tree '" << tname << "' already scheduled... ignored." << endl;
    265298            return;
     
    290323                                  Bool_t must)
    291324{
     325    if (!fOut && !tname)
     326        tname = fSplitRule;
     327
    292328    TIter Next(&fBranches);
    293329    TObject *o=0;
     
    296332            static_cast<MRootFileBranch*>(o)->GetContainer()==cont)
    297333        {
     334            *fLog << warn;
    298335            *fLog << "WARNING - Container " << cont << " in Tree '" << tname << "' already scheduled... ignored." << endl;
    299336            return;
     
    378415
    379416        //
    380         // Check if the tree is already existing (part of the file)
    381         //
    382         TTree *tree = (TTree*)fOut->Get(tname);
     417        // Check if the tree is already existing (part of the file or memory)
     418        //
     419        TTree *tree = fOut ? (TTree*)fOut->Get(tname) : dynamic_cast<TTree*>(gROOT->FindObject(tname));
     420        if (!fOut && tree)
     421        {
     422            if (tree->GetCurrentFile())
     423            {
     424                *fLog << err;
     425                *fLog << "ERROR - You are trying to write data into a memory stored root tree," << endl;
     426                *fLog << "        because you either called the default constructor  or  have" << endl;
     427                *fLog << "        instantiated MWriteRootFile using the write option 'memory'." << endl;
     428                *fLog << "        This  tree   '" << tname << "'   is  already  existing  in" << endl;
     429                *fLog << "        memory  (gROOT->FindObject)  and is already belonging  to a" << endl;
     430                *fLog << "        file (" << tree->GetCurrentFile()->GetName() << ")." << endl;
     431                *fLog << "        This can  - for example -  happen if you are reading from a" << endl;
     432                *fLog << "        tree with the same name.  The easiest solution in this case" << endl;
     433                *fLog << "        is to change the name of the tree you want to write to." << endl;
     434                *fLog << endl;
     435                return kFALSE;
     436            }
     437            *fLog << inf << "Tree '" << tname << "' found already in Memory... using." << endl;
     438        }
     439
    383440        if (!tree)
    384441        {
     
    389446            //
    390447            TDirectory *save = gDirectory;
    391             fOut->cd();
    392 
    393             tree = new TTree(tname, ttitle);
     448            if (fOut)
     449                fOut->cd();
     450            else
     451                gROOT->cd();
     452
     453            tree = new TTree(tname, ttitle, fOut ? 99 : 1);
    394454            fTrees.AddLast(tree);
    395455
     
    567627
    568628    //
     629    // If we are writing into memory we don't split into seperate files
     630    //
     631    if (!fOut)
     632        return kTRUE;
     633
     634    //
    569635    // For more information see TTree:ChangeFile()
    570636    //
     
    774840// --------------------------------------------------------------------------
    775841//
    776 // return open state of the root file.
     842// return open state of the root file. If the file is 'memory' kTRUE is
     843// returned.
    777844//
    778845Bool_t MWriteRootFile::IsFileOpen() const
    779846{
     847    if (!fOut)
     848        return kTRUE;
     849
    780850    const char *n = fOut->GetName();
    781851    return n==0 || *n==0 ? kTRUE : fOut->IsOpen();
     
    784854// --------------------------------------------------------------------------
    785855//
    786 // return name of the root-file
     856// return name of the root-file. If the file is "memory" "<memory>" is
     857// returned.
    787858//
    788859const char *MWriteRootFile::GetFileName() const
    789860{
     861    if (!fOut)
     862        return "<memory>";
     863
    790864    const char *n = fOut->GetName();
    791865    return n==0 || *n==0 ? "<dummy>" : n;
     
    794868// --------------------------------------------------------------------------
    795869//
    796 // cd into file. See TFile::cd()
     870// cd into file. See TFile::cd(). If the file is "memory" kTRUE is returned.
    797871//
    798872Bool_t MWriteRootFile::cd(const char *path)
    799873{
    800     return fOut->cd(path);
     874    return fOut ? fOut->cd(path) : kTRUE;
    801875}
    802876
     
    809883void MWriteRootFile::StreamPrimitive(ofstream &out) const
    810884{
    811     out << "   MWriteRootFile " << GetUniqueName() << "(\"";
    812     out << fOut->GetName() << "\", \"";
    813     out << fOut->GetOption() << "\", \"";
    814     out << fOut->GetTitle() << "\", ";
    815     out << fOut->GetCompressionLevel();
    816 
    817     if (fName!=gsDefName || fTitle!=gsDefTitle)
    818     {
    819         out << ", \"" << fName << "\"";
    820         if (fTitle!=gsDefTitle)
    821             out << ", \"" << fTitle << "\"";
    822     }
    823     out << ");" << endl;
    824 
     885    out << "   MWriteRootFile " << GetUniqueName();
     886    if (fOut)
     887    {
     888        out << "(\"";
     889        out << fOut->GetName() << "\", \"";
     890        out << fOut->GetOption() << "\", \"";
     891        out << fOut->GetTitle() << "\", ";
     892        out << fOut->GetCompressionLevel();
     893        out << ")";
     894    }
     895    out << ";" << endl;
     896
     897    if (fName!=gsDefName)
     898        out << "   " << GetUniqueName() << ".SetName(\"" << fName << "\");" << endl;
     899    if (fTitle!=gsDefTitle)
     900        out << "   " << GetUniqueName() << ".SetTitle(\"" << fTitle << "\");" << endl;
    825901
    826902    MRootFileBranch *entry;
Note: See TracChangeset for help on using the changeset viewer.