RDataFrame not processing TMap branch correctly

I am putting a TMap into a TTree branch. But the following minimal reproducer shows that when I ‘process’ my tree with a RDataFrame I don’t get the maps I was expecting:

TTree* t = new TTree("t","t");
    TMap* myMap = new TMap;
    t->Branch("myMap",&myMap);

    auto k = new TObjString("prop");
    myMap->Add(k, new TObjString("value"));
    myMap->Print();
    t->Fill();
    // replace with different value
    myMap->Remove(k);
    myMap->Add(k, new TParameter<int>("par",4));
    myMap->Print();
    t->Fill();
    
    t->ResetBranchAddresses(); // otherwise DataFrame will merge with existing obj

    ROOT::RDataFrame df(*t);

    auto selector = [](const TMap& m) {
        m.Print();
        return true;
    };
    df.Foreach(selector,{"myMap"});

This prints:

Collection name='TMap', class='TMap', size=1
 Key:   TObjString = prop
 Value: TObjString = value
Collection name='TMap', class='TMap', size=1
 Key:   TObjString = prop
 Value:  TParameter<int>        par = 4
Collection name='TMap', class='TMap', size=1
 Key:   TObjString = prop
 Value: TObjString = value
Collection name='TMap', class='TMap', size=2
 Key:   TObjString = prop
 Value: TObjString = value
 Key:   TObjString = prop
 Value: TObjString = value

Note that the last TMap print should have been a copy of the 2nd print, instead it seems to be some strange map of size 2, with two copies of the first entry (prop: value) in it. I was expecting it to be a map of size 1 with (prop: 4) in it.

What did I do wrong?

Thanks
Will

Hi Will,
I obtain the same printouts reading things back with TTree, so there is something wrong in the way TMap is written to file. I think we need the help of @pcanal .

Cheers,
Enrico

#include <ROOT/RDataFrame.hxx>
#include <TFile.h>
#include <TMap.h>
#include <TObjString.h>
#include <TParameter.h>
#include <TTree.h>

int main() {
  {
    TFile f("f.root", "recreate");
    TTree *t = new TTree("t", "t");
    TMap *myMap = new TMap;
    t->Branch("myMap", &myMap);

    auto k = new TObjString("prop");
    myMap->Add(k, new TObjString("value"));
    myMap->Print();
    t->Fill();
    // replace with different value
    myMap->Remove(k);
    myMap->Add(k, new TParameter<int>("par", 4));
    myMap->Print();
    t->Fill();
    t->Write();
  }

  TFile f("f.root");
  auto *t = f.Get<TTree>("t");
  TMap *m = nullptr;
  t->SetBranchAddress("myMap", &m);
  t->GetEntry(0);
  m->Print();
  t->GetEntry(1);
  m->Print();

  return 0;
}

Hi again,
@pcanal confirmed that this is a bug in TTree (which is now https://sft.its.cern.ch/jira/browse/ROOT-10990 ) and provided a workaround: calling Delete on the map at the end of each event processing:

  ROOT::RDataFrame df(*t);                                                                                                                                                    
                                                                                                                                                                              
  auto selector = [](TMap &m) {                                                                                                                                               
    m.Print();                                                                                                                                                                
    m.Delete();                                                                                                                                                               
    return true;                                                                                                                                                              
  };                                                                                                                                                                          
  df.Foreach(selector, {"myMap"}); 

Cheers,
Enrico

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