LDMX-Software / fire

Event-by-event processing framework using HDF5 and C++17
https://ldmx-software.github.io/fire/
GNU General Public License v3.0
1 stars 0 forks source link

io::root::Reader::copy implementation #46

Open tomeichlersmith opened 2 years ago

tomeichlersmith commented 2 years ago

Is your feature request related to a problem? Please describe. We want to ensure that all event objects that pass the drop/keep rules will be persisted into the output file. Even if they are not access by Event::get. The implementation of this for h5::Reader was done in #45 ; however, implementing this for root::Readeris delayed due to the necessary complexity.

Describe the solution you'd like An implementation of root::Reader::copy which silently reformats a branch of the LDMX_Events tree into the new HDF5 style. This would effectively open the door to a full reformat program which does nothing except move data from a ROOT file into the new fire/HDF5 files.

Describe alternatives you've considered A medium-term alternative is just to include a processor in the sequence which accesses all of the objects that the user wishes to transport from the input ROOT file into the output HDF5 file. This is annoying because then the user needs to write this producer and make sure to link the producer with the object definitions and ROOT dictionary. The objects in the processor do not need to be processed at all, the Event::get call is all that is necessary.

Additional context Copying over notes from #45 ...

Sneaking a look at how uproot identifies branch types, I wrote a quick ROOT macro to test it out and it is printing a type name. The key is to retrieve the TLeaf rather than try to use the TBranch::GetClassName directly. I think I can use this to construct a copy mechanism for ROOT files.

// in file: introspect.C
std::vector<TBranch*> flatten(TObjArray* list) {
  std::vector<TBranch*> flattened;
  for (unsigned int i{0}; i < list->GetEntries(); i++) {
    TBranch* sub_branch = (TBranch*)list->At(i);
    if (sub_branch->GetListOfBranches()->GetEntries() > 0) {
      std::vector<TBranch*> sub_list{flatten(sub_branch->GetListOfBranches())};
      flattened.insert(flattened.end(), sub_list.begin(), sub_list.end());
    } else {
      flattened.push_back(sub_branch);
    }
  }
  return flattened;
}   

void introspect() {
  TFile f{"test.root"};

  auto t{dynamic_cast<TTree*>(f.Get("LDMX_Events"))};

  if (not t) {
    std::cerr << "No tree"<< std::endl;
    return;
  }

  auto branches{flatten(t->GetListOfBranches())};
  for (TBranch* br : branches) {
    std::cout << br->GetFullName() << " : " << br->GetTitle();
    if (br->GetListOfLeaves()->GetEntries() > 0) {
      auto leaf{(TLeaf*)br->GetListOfLeaves()->At(0)};
      std::cout << " leaf: " 
        << leaf->GetTypeName() << " "
        << leaf->GetFullName() << " " 
        << leaf->GetTitle();
    }
    std::cout << std::endl; 
  }
}