TKey, TObject and GetListOfKeys for only newest ttrees

Hi there,

I have the requirement that I have root files with a large number of trees that I need to loop over and insert a branch in each (systematics trees).
The problem arises if there are multiples trees of the same name (probably due to some autosave feature outside of my control), i.e.
treeA
treeA:1

I don’t want to loop and save both of them, so how do I just get the newest ones?

At the moment I have something like

     // Do a loop over all trees that are not nominal
      TList* list = oldFile->GetListOfKeys() ;
      if (!list) { printf("<E> No keys found in file\n") ; exit(1) ; }
      TIter next(list) ;
      TKey* key ;
      TObject* obj ;

      while ( key = (TKey*)next() ) {

        obj = key->ReadObj() ;
        // skip if not a TTree or sumWeights TTree
        if ( (strcmp(obj->IsA()->GetName(),"TTree")!=0) || (strcmp("sumWeights",obj->GetName()) == 0)) {
          printf("Not running over: %s \n",obj->GetName()); continue;
        }

        newtree = fChain->CloneTree(0);  // some stuff with tree
      }

but this will loop over ALL trees.

Thanks in for the help!
Josh

Aux;1 aux;2 aux3;

Try with something like:

   TString oldkeyname;

         while ( (key = (TKey*)nextkey())) {

            // Keep only the highest cycle number for each key for mergeable objects. They are stored
            // in the (hash) list consecutively and in decreasing order of cycles, so we can continue
            // until the name changes. We flag the case here and we act consequently later.
            bool alreadyseen = (oldkeyname == key->GetName());

            if (alreadyseen) continue;
           
           alreadyseen = key->GetName();
          
           ....
      }

Cheers,
Philippe.

Thanks for this, Philippe.

However, after testing, it seems alreadyseen will always evaluate to false given tree names I use, i.e.

treeA
treeA:1

I do not understand. What is the :1 suffix? ‘key->GetName()’ returns the name of the TTree without the cycle and should be self consistent (i.e. alreadyseen is assigned the value of key->GetName() and then it is compared with the same).

Cheers,
Philippe.

The trees look like the attached.
Yes, I’m also surprsed this isn’t working.

The loop looks like this. At no point do I ever reach “ERROR”.

 // Do a loop over all trees that are not nominal
      TList* list = oldFile->GetListOfKeys() ;
      if (!list) { printf("<E> No keys found in file\n") ; exit(1) ; }
      TIter next(list) ;
      TKey* key ;
      TObject* obj ;


      std::string oldkeyname;
      while ( (key = (TKey*)next()) ) {

        bool alreadyseen = (oldkeyname == key->GetName());

        std::cout <<alreadyseen <<std::endl;
        if (alreadyseen){
        std::cout << "ERROR"<<std::endl;
        continue;
        }
        alreadyseen = key->GetName();
        TChain *fChain=nullptr;
        TTree *newtree=nullptr;

        obj = key->ReadObj() ;
        if ( (strcmp(obj->IsA()->GetName(),"TTree")!=0) || (strcmp("sumWeights",obj->GetName()) == 0)
          || (strcmp("nominal",obj->GetName()) == 0) || (strcmp("nominal_Loose",obj->GetName()) == 0)) {
          printf("Not running over: %s \n",obj->GetName()); continue;
        }

        fChain = new TChain(obj->GetName());

        fChain->Add((file).c_str());

        newtree = fChain->CloneTree(0);
       if(fChain->GetEntries() == 0){
         std::cout<<"No events, skipping"<<std::endl;
         continue;
       }
        m_add_branches(fChain,newtree,m_neuralNet); // some external function

        newfile->cd();
        newtree->Write();

        delete newtree;
        delete fChain;

      } // end loop over trees

Cheers,
Josh

There was a fatal bug in my code snippet :frowning:
Replace

alreadyseen = key->GetName();

with

oldkeyname = key->GetName();

Cheers,
Philippe.

Wow. I should have seen that, sorry!
Thanks, it’s working now. :slight_smile:
Cheers,
Josh

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.