Project

General

Profile

Feature #16546

Updated by Kyle Knoepfel over 3 years ago

This isn't exactly needed, since I can hack it from the user level, but it might be useful to others.

I want to be able to get all data products of type recob::Wire from the current file.

Here's how I can hack it with custom code:

<pre><code class="cpp">
template<typename T>
vector<std::pair<string,art::InputTag>> findByType(TTree* fTree)
{
vector<std::pair<string,art::InputTag>> retval;
// Leaf names for std::vector<recob::Wire> get renamed
// to the art version of "recob::Wires" by this.
std::string pattern = art::TypeID(typeid(T)).friendlyClassName();
std::cout << "Looking for leaf of type " << pattern << "_label_instance_process." << endl;
TObjArray* list = fTree->GetListOfBranches();

// Look through every branch name.

// We're looking for:
// OBJ_LABEL_INSTANCE_PROCESSNAME.obj_
// Where OBJ is something like "recob::Wires"
// Where LABEL is something like "pandora"
// INSTANCE is usually (always?) blank
// Where PROCESSNAME is something like "McRecoAprStage1"

for(int i=0;i<list->GetEntriesFast();i++) {
TObject* o = list->At(i);
TBranch* br = dynamic_cast<TBranch*>(o);
std::string found = br->GetName();

// Does it start with our object type?
if(found.find(pattern)!=0) continue;
// std::cout << "--Candidate: " << found << std::endl;

// Does it end with '.'?
string::size_type p3 = found.find_last_of('.');
if(p3!=found.length()-1 || p3==0) continue;
// std::cout << "p3 " << found.substr(p3) << std::endl;

// Tokenize by underscore.
string::size_type p2 = found.rfind("_",p3-1);
if(p2==string::npos || p2==0) continue;
// std::cout << "p2 " << found.substr(p2) << std::endl;

string::size_type p1 = found.rfind("_",p2-1);
if(p1==string::npos || p1 ==0 ) continue;
// std::cout << "p1 " << found.substr(p1) << std::endl;

string::size_type p0 = found.rfind("_",p1-1);
if(p0==string::npos || p0==0) continue;
// std::cout << "p0 " << found.substr(p0) << std::endl;

art::InputTag tag(found.substr(p0+1,p1-p0-1), found.substr(p1+1,p2-p1-1), found.substr(p2+1,p3-p2-1));
retval.push_back( make_pair( found, tag ));
}
return retval;

}
</code></pre>


This code simply parses the Event tree branch list to find matching objects, and parses out the label/instance/process handles to create art::InputTags as a list. Then the calling code can do something like the following:

<pre><code class="cpp">


typedef vector<recob::Wire> thing_t;

for(auto item: findByType<thing_t>(ev.getTTree())) {

cout<< "Branch: " << item.first << std::endl;

cout<< "Tag : " << item.second << std::endl;

gallery::Handle< thing_t > handle;

ev.getByLabel(item.second,handle);

if(handle.isValid())

std::cout << "Found " << handle->size() << " wires." << std::endl;

}
</code></pre>



Looking at the ART source code, it would appear that this sort of parsing should be robust, since underscores are otherwise not allowed in InputTag elements.

Back