We are having issues scanning and drawing branches of std::vector<std::vector<std::array<float, 2>>>.
In trying to create a simpler minimal working example of the problem, I see this error:
Error in <TBranchElement::InitializeOffsets>: Could not find the real data member '_M_elems[2]' when constructing the branch 'vector_array' [Likely missing ShowMember].
with the following short macro:
void mwe_no_dict() {
gInterpreter->GenerateDictionary("vector<array<float,2>>", "array;vector");
std::vector<std::array<float,2>> vector_array;
TTree* tree = new TTree();
tree->Branch("vector_array", &vector_array);
}
Thanks for the reply. I’ve attached a small file that we are having trouble with. After writing out this message, I found that I can’t post links as a new user so let me know if there’s another way for me to get this file to you.
As a bit of explanation, we should have (and do) have twice as many etimes as hits. The etimes are in pairs corresponding to two ends of a straw. So the first two lines (68217.414 and 68215.187) are from the same hit on a straw but at different ends. These pairs are represented by the inner-most std::array<float, 2>.
However, when we try to Scan each end separately, we get the same results (i.e. in the first row we get 68217.414 twice when we expect 68215.187 in the final column)
There are a couple more details on our experiment’s GitHub page (looks like I can’t post a direct link as a new user but it’s Mu2e/TrkAna issue #168). For example, we don’t have a problem when reading it in via python+uproot.
Anyway, if it would be easier that I break the problem down into a non-experiment specific example, then I’m happy to try. I would just have to get past the error in my iniital post.
@pcanal Maybe someone could have a look at the problem reported in the first post here (the newest ROOT 6.32.02 is also affected),
Moreover, this line breaks ACLiC (it really dies hard, not just issues some harmless warning): gInterpreter->GenerateDictionary("array<float,2>", "array");
However, std::vector of an std::array is not yet supported. You can however use the following pattern (the class ArrayWrapper and std::vector<ArrayWrapper> need a dictionary):
struct ArrayWrapper {
std::array<float,2> _values;
};
....
std::vector<ArrayWrapper> vector_array;
TTree* tree = new TTree("tree", "");
tree->Branch("vector_array", &vector_array);
I’m afraid I’m still having trouble. If I do the following on the command line:
struct ArrayWrapper { std::array<float,2> _values; };
gInterpreter->GenerateDictionary("ArrayWrapper");
gInterpreter->GenerateDictionary("vector<ArrayWrapper>", "vector");
std::vector<ArrayWrapper> vector_array;
TTree* tree = new TTree("tree", "");
tree->Branch("vector_array", &vector_array);
I get the following error:
Error in <TTree::Branch>: The class requested (vector<ArrayWrapper>) for the branch "vector_array" is an instance of an stl collection and does not have a compiled CollectionProxy. Please generate the dictionary for this collection (vector<ArrayWrapper>) to avoid to write corrupted data.
Is there a way to tell whether the dictionary was generated correctly?
.L ArrayWrapper.h
gInterpreter->GenerateDictionary("ArrayWrapper", "ArrayWrapper.h");
gInterpreter->GenerateDictionary("vector<ArrayWrapper>", "ArrayWrapper.h;vector");
std::vector<ArrayWrapper> vector_array;
TTree* tree = new TTree("tree", "");
tree->Branch("vector_array", &vector_array);
and I get the same error:
Error in <TTree::Branch>: The class requested (vector<ArrayWrapper>) for the branch "vector_array" is an instance of an stl collection and does not have a compiled CollectionProxy. Please generate the dictionary for this collection (vector<ArrayWrapper>) to avoid to write corrupted data.
humm … something is odd in your setup … with your exact file I get:
root [0] .L ArrayWrapper.h
root [1] gInterpreter->GenerateDictionary("ArrayWrapper", "ArrayWrapper.h");
In file included from AutoDict_ArrayWrapper_cxx_ACLiC_dict dictionary payload:8:
In file included from ./AutoDict_ArrayWrapper.cxx:1:
/private/var/tmp/arr/ArrayWrapper.h:5:8: error: redefinition of 'ArrayWrapper'
struct ArrayWrapper {
^
input_line_8:1:10: note: './ArrayWrapper.h' included multiple times, additional include site here
...
Thanks - it looks like there is something wrong with the setup. Your instructions work on a clean install on my laptop but not on the common machines we use for Mu2e…
Since vector<array> branches are not directly supported and the ArrayWrapper solution doesn’t do what we want, we’re looking into using a vector<vector<vector>> branch for our three-level branch.
Unfortunately, this seems to be working even less well…
The attached vec_vec_vec.C script produces the following output:
$ root -l vec_vec_vec.C
root [0]
Processing vec_vec_vec.C...
Entry #1:
vec_vec = [ (1,2) ]
vec_vec_vec = { [ (1,2) ], [ (3,4) ] }
Entry #2:
vec_vec = [ (5,7) ]
vec_vec_vec = { [ (20,25) ], [ (30,35) ] }
TTree::Scan of the vec_vec branch works as expected...
printing all values:
******************************************
* Row * Instance * vec_vec *
******************************************
* 0 * 0 * 1 *
* 0 * 1 * 2 *
* 1 * 0 * 5 *
* 1 * 1 * 7 *
******************************************
printing just first and second value of pair:
*******************************************************************************
* Row * Instance * vec_vec[][0] * vec_vec[][1] *
*******************************************************************************
* 0 * 0 * 1 * 2 *
* 1 * 0 * 5 * 7 *
*******************************************************************************
printing the difference between the first and second value of pair:
******************************************************************
* Row * Instance * vec_vec[][0]-vec_vec[][1] *
******************************************************************
* 0 * 0 * -1 *
* 1 * 0 * -2 *
******************************************************************
TTree:Scan of the vec_vec_vec branch *doesn't* work as expected for...
printing all values:
********************************************************
* Row * Instance * vec_vec_vec *
********************************************************
* 0 * 0 * 0 *
* 0 * 1 * 0 *
* 1 * 0 * 0 *
* 1 * 1 * 0 *
********************************************************
Thanks, @pcanal. We looked into RDataFrame and it doesn’t work for our branch structure either. We can still analyze with compiled macros and loops but for quick data exploriation, the ROOT command line was very useful. We’ll keep an eye on developments in case RDataFrame or TTreeFormula can do what we want in the future.