Home | News | Documentation | Download

How to create vector<Vector3D> branch w/o dictionary?

I am trying to create a branch with a vector <Vector3D>.

Why this works using XYZVector, but not using TVector3 or dd4hep::rec::Vector3D?

#include "TFile.h"
#include "TTree.h"
#include <vector>
#include "Math/Vector3D.h"
using namespace ROOT::Math;

int test(){
    TFile f("test.root", "RECREATE");
    TTree* t = new TTree("Test", "Test Tree");
    std::vector <XYZVector> xyz;
    t->Branch("xyz", &xyz);
    xyz.push_back(XYZVector(42., 42.*42., 42.*42.+42.));
    t->Fill();
    f.Write();

    return 0;
}

works fine, but using

#include "TVector3.h"
...
    std::vector <TVector3> xyz;
    xyz.push_back(TVector3(42., 42.*42., 42.*42.+42.));
...

or

#include "DDRec/Vector3D.h"
using dd4hep::rec::Vector3D;
...
    std::vector <Vector3D> xyz;
    xyz.push_back(Vector3D(42., 42.*42., 42.*42.+42.));
...

Output:

Error in <TTree::Branch>: The class requested (vector<dd4hep::rec::Vector3D>) for the branch "xyz" is an instance of an stl collection and does not have a compiled CollectionProxy. Please generate the dictionary for this collection (vector<dd4hep::rec::Vector3D>) to avoid to write corrupted data.

with an empty ROOT file. Which I couldn’t fix.

thanks and cheers

ROOT Version: 6.22/00
Platform: Centos 7

@pcanal correct me if I’m wrong - no, where I’m wrong, but:

  • it doesn’t work for dd4hep::rec::Vector3D because we don’t have a dictionary;
  • it doesn’t work for TVector3 because that has a custom streamer and thus vector<TVector3> needs a dictionary (is that the case, Philippe?)
  • it works for XYZVector because we have a dictionary and it has a default streamer, and so we know how to stream a vector<XYZVector>.

In short: please create a dictionary for dd4hep::rec::Vector3D and it should work.

It works only because we generate dictionary for std::vector<ROOT::Math::XYZVector > in the GenVector library. To do I/O on an item (including collections) you need to generate a dictionary (for collection the dictionary is often generated implicit alongside the dictionary for a class that uses that collection)

Cheers,
Philippe.

PS. If you are adventurous it “might” work without a dictionary because all std::vector have the same layout in memory by disabling the warning:

t->Branch("xyz", , "std::vector<dd4hep::rec::Vector3D>", (void*)&xyz);

but your mileage may vary so use this solution solely for quick debugging session not for ‘production’ work.

@Axel , @pcanal
Thanks!

Is there one-line way to generate a dictionary without complicated DictDef.h and cling things?

I have tried to add line:
gInterpreter->GenerateDictionary("vector<Vector3D>","vector;DDRec/Vector3D.h");

But the same error occurs, though some Dictionary files appear in the directory…

Is there one-line way to generate a dictionary without complicated DictDef.h and cling things?

humm … the full solution is not “that” complicated:

// File ContLinkDef.h
#pragma link C++ class std::vector<dd4hep::rec::Vector3D>+;

and

rootcling -f ContDict.cxx -Iheader_directory vector DDRec/Vector3D.h ContLinkDef.h

and then compile and link ContDict.cxx as usual.

I have tried to add line:

You must use the fully qualified names (except for std:: which is optional):

gInterpreter->GenerateDictionary("std::vector<dd4hep::rec::Vector3D>","vector;DDRec/Vector3D.h");

Cheers,
Philippe.

1 Like

Is there a way to do “full solution” without compiling? E.g if I use root cpp script with just root test.cpp, without any compilation…

Because if I use this macro for the analysis, the code is changing every second, and recompiling all the time, is just annoying and adds time for every “save file” and “test launch”

cheers,
Bohdan

Create a simple “rootlogon.C” file (in your current working directory):

{ // rootlogon.C
  // gInterpreter->AddIncludePath("/path/to/include"); // where "DDRec/Vector3D.h" resides
  gInterpreter->GenerateDictionary("std::vector<dd4hep::rec::Vector3D>", "vector;DDRec/Vector3D.h");
  // gSystem->Load("/path/to/libMyClasses");
  // gInterpreter->AddIncludePath("/path/to/MyClasses/include");
  // gROOT->ProcessLine(".L /path/to/MyClasses.C+");
}
1 Like

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