TTree::SetBranchStatus does not have effect

Hi,

I’ve created a TTree with a set of branches: muons, jets, etc. and would like to read only some of them. So, I do it this way:

[code] TTree tree = 0;
// file() will return TFile *
//
file()->GetObject(“MyDir/TreeName”, tree);
tree->SetBranchStatus("
", 0);

std::auto_ptr<Jets>            jets(new Jets());
std::auto_ptr<Leptons>         electrons(new Leptons());
std::auto_ptr<Leptons>         muons(new Leptons());

s8::Jets *jetsPointer = jets.get();
tree->SetBranchAddress("jets", &jetsPointer);
if (_readJets)
{
    clog << " + Enable Jets branch" << endl;
    tree->SetBranchStatus("jets", 1);
}

s8::Leptons *electronsPointer = electrons.get();
tree->SetBranchAddress("electrons", &electronsPointer);
if (_readElectrons)
{
    clog << " + Enable Electrons branch" << endl;
    tree->SetBranchStatus("electrons", 1);
}

s8::Leptons *muonsPointer = muons.get();
tree->SetBranchAddress("muons", &muonsPointer);
if (_readMuons)
{
    clog << " + Enable Muons branch" << endl;
    tree->SetBranchStatus("muons", 1);
}

const int entries = tree->GetEntries();

// Loop over events
//
for(int entry = 0; entries > entry; ++entry)
{
    tree->GetEvent(entry);

    // Process event
    //
}

[/code]

Where Jets and Leptons are:

typedef std::vector<Jet *> Jets; typedef std::vector<Lepton *> Leptons;

So, non of the Branches is read !

On the other hand, if I do NOT disable all branches then they are read fine.

In the mean time, I tried to enable all branches and disable them one by one. It didn’t work too.

Am I missing something? What is wrong?

Any suggestions?

Hi,

SetBranchStatus does a wildcard match on the name of the branches. Doing SetBranchStatus on a top level branch only affects that top level branches and none of the subbranches. So try SetBranchStatus(“muon.*”,1)

Cheers,
Philippe.

Thanks for the reply, but SetBranchStatus(“muons.*”, 1) fails with error:

Hi,

In this case, it must mean that when creating the branches, the trailing dot was not added to the top level branch name. This means the top level branch name is not embedded in the sub-branches name and that using SetBranchStatus is going to be difficult (You would need to enumerate the sub-branches names).

Instead I recommend that you do not use SetBranchStatus but instead use the branch directly. So you would need to use something like:[code]
Tree *tree = 0;
// file() will return TFile *
//
file()->GetObject(“MyDir/TreeName”, tree);

std::auto_ptr<Jets>              jets(new Jets());
std::auto_ptr<Leptons>         electrons(new Leptons());
std::auto_ptr<Leptons>         muons(new Leptons());
TBranch *jetsBranch = 0;
TBranch *electonrsBranch = 0;
TBranch *muonsBranch = 0;

s8::Jets *jetsPointer = jets.get();
tree->SetBranchAddress("jets", &jetsPointer, &jetsBranch);
s8::Leptons *electronsPointer = electrons.get();
tree->SetBranchAddress("electrons", &electronsPointer, &electronsBranch);
s8::Leptons *muonsPointer = muons.get();
tree->SetBranchAddress("muons", &muonsPointer, &muonsBranch);

const int entries = tree->GetEntries();
// Loop over events
//
for(int entry = 0; entries > entry; ++entry)
{
    Long64_t treeEntry = tree->LoadEntry(entry);
    if (_readJets)
    {
        // clog << " + Enable Jets branch" << endl;
        jetsBranch->GetEntry(treeEntry);
    }
    if (_readElectrons)
    {
        // clog << " + Enable Electrons branch" << endl;
        electronsBranch->GetEntry(treeEntry);
    }
    if (_readMuons)
    {
        // clog << " + Enable Muons branch" << endl;
        muonsBranch->GetEntry(treeEntry);
    }

    // Process event
    //
}[/code]

Cheers,
Philippe.

What is this “trailing dot added to branches when Tree is generated” trick?

I can regenerate Trees if needed.

Hi,

Instead of tree->Branch("muons",&muons) use tree->Branch("muons.",&muons). See the TTree documentation for details.

Cheers,
Philippe.

Philippe,

thanks for your time and help. I appreciate it.

I’ve generated Tree with:

auto_ptr<Muons> muons(new Muons()); tree->Branch("muons.", muons.get()); ...

But, attempt to set Status (upon Tree read) with:

tree->SetBranchStatus("muons.*", 1);

produces error:

In the meantime, as I wrote before Muons is a std::vector<Muon *> where Muon is something like:

[code]class Muon
{
public:
Muon() { _p4 = new TLorentzVector(); }
~Muon() { delete _p4; }

//...

private:
TLorentzVector *_p4;
}[/code]

When I try to read Tree via Branches (explicitly), ROOT crashes b/c of the ~Muon(). I guess ROOT is doing some memory management and deletes _p4. So, attempt to manually destroy non-existing object leads to crash.

Is there a workaround?

[quote]produces error:[/quote]Humm strange. It might depends on the content of your muons branch. tree->SetBranchStatus("muons*", 1);should work better …

[quote]In the meantime, as I wrote before Muons is a std::vector<Muon *> where Muon is something like:[/quote]Humm do you really need a container of pointer (do you derive from Muon)? You should try vector it would be more efficient. private: TLorentzVector *_p4;It seems that the pointer is unnecessary since you always allocate it. Wouldn’t [code]class Muon
{
public:
Muon() { }
~Muon() { }

//...

private:
TLorentzVector _p4;
}[/code] work as well for you?

[quote]When I try to read Tree via Branches (explicitly), ROOT crashes b/c of the ~Muon().[/quote]A priori, it shouldn’t, so there is more to the sorry (to track this down, the best is to use valgrind).

Cheers,
Philippe.

The main reason for pointers is to reduce includes.

Finally, I’ve managed the solution. Honestly, I still do not know what is wrong, but disabling branches one by one did the trick.

In fact, I didn’t have to add any dots at the end of branch names, etc.

Thanks for help, Philippe.