Acessing custom class branches in python

Hi all,

My post is somewhat related to the difference between dd4hep::rec::Vector3D and XYZVector discussed here

I used to creating XYZVector branches without a dictionary, which allows me to immediately start to analyze output root file in python scripts, like e.g.:

df = ROOT.RDataFrame("tree_name", "output.root")
h = df.Define("pos_z", "my_vec.z()").Histo1D("pos_z")
h.Draw()

However, I couldn’t achieve the same with dd4hep::rec::Vector3D

I created a dictionary and compiled and linked it, so it successfully created output ROOT file.

But now, there are probably additional steps I need to make in my python script so everything works?

Cause it outputs an error:

input_line_68:2:38: error: use of undeclared identifier 'dd4hep'
auto lambda0 = [](ROOT::VecOps::RVec<dd4hep::rec::Vector3D>& var0){return var0.z

cheers,
Bohdan

Did you request a dictionary also for the namespaces?

Do I understand correctly that I need modify my ContLinkDef.h from

#pragma link C++ class std::vector<dd4hep::rec::Vector3D>+;

to

#pragma link C++ class dd4hep::rec::Vector3D+;
#pragma link C++ class std::vector<dd4hep::rec::Vector3D>+;

Will it also work for the namespaces? E.g. I should do:

#pragma link C++ class dd4hep::rec+;
#pragma link C++ class dd4hep::rec::Vector3D+;
#pragma link C++ class std::vector<dd4hep::rec::Vector3D>+;

?

Try:

#pragma link C++ nestedclass;
#pragma link C++ nestedtypedef;
#pragma link C++ namespace dd4hep;
#pragma link C++ defined_in namespace dd4hep;
#pragma link C++ namespace dd4hep::rec;
#pragma link C++ defined_in namespace dd4hep::rec;
#pragma link C++ class dd4hep::rec::Vector3D+;
#pragma link C++ class std::vector<dd4hep::rec::Vector3D>+;
1 Like

It works, thanks a lot.

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

Hi all,

During the discussion here I didn’t check thorough enough and now I can’t make it work again…

Is it possible to write methods of dd4hep::rec::Vector3D or is it impossible by design?

ROOT Version: 6.18
Platform: Centos 7
Compiler: g++ 8.2


Well, the dictionary created by “#pragma link C++ class dd4hep::rec::Vector3D+;” should (automatically) include all data members and all methods of this class.

Ok… Then I try to ask again attaching full examples as I should have done in the first place to not cause confusion and in hopes to finally understand this topic…

Setup

  • OS: Centos 7
  • ROOT: 6.18/04 Built for linuxx8664gcc on Sep 11 2019, 15:38:23
  • g++: 8.2.0
  • DD4hep: v01-11-02

Code example

I have the following script and the file for dictionaries in the same folder:
test.cpp (422 Bytes)
ContLinkDef.h (341 Bytes)

Steps

  1. I compile dictionaries with
    rootcling -f ContDict.cxx -I${PWD} vector DDRec/Vector3D.h ContLinkDef.h
    which creates me dictionary files:
    ContDict.cxx (11.3 KB)
    and ContDict_rdict.pcm (can’t attach)

  2. I compile both files with
    g++ test.cpp ContDict.cxx -I$DD4hep_DIR/include `root-config --cflags --glibs`
    and I obtain my compiled executable a.out.

  3. Run ./a.out which outputs me my root file:
    test.root (6.3 KB)

  4. Trying to look at the file via TBrowser:

$ root
root [0] new TBrowser
(TBrowser *) 0x21fb010
root [1]

After clicking and opening the file it produces a warning:

root [1] Warning in <TClass::Init>: no dictionary for class dd4hep::rec::Vector3D is available
(TFile *) 0x37c7460
  1. Looking inside the tree shows correct data stored inside _x, _y, _z variables of the Vector3D, but no other methods are written.
    For the std::vector however, branch @size for the method size() is present.

Expected behavior

I would expect Vector3D to be written with all the physical methods, e.g.: theta(), rho(), etc.

Trying to understand on my own

I was trying to read some documentation about dictionaries and stumbled upon this link.
which I don’t fully understand, but I see sentences like this:

Looking in the file eventdict.cxx we can see, theStreamer() andShowMembers()methods for the two classes. Streamer() is used to stream an object to/from a TBuffer and ShowMembers() is used by the Dump() and Inspect() methods of TObject. Here is the TEvent::Streamer method:

And I don’t see neither Streamer() nor ShowMembers() in my generated ContDict.cxx

Also this section:

The ShowMembers and Streamer method, as well as the >> operator overloads, are implemented !!!only!!! if you use ClassDef and ClassImp. See $ROOTSYS/include/Rtypes.h for the definition of ClassDef and ClassImp

indicated to me that it will not produce these methods if I don’t use ClassDef and ClassImp whatever that means.

Also this section:

Step 4: Compile the class using the Makefile.In the Makefile call rootcling to make the dictionary for the class. Call it SClassDict.cxx. The rootcling utility generates the methods Streamer, TBuffer &operator>>() and ShowMembers for ROOT classes.

Indicated to me that it creates these methods for ROOT classes making me understand that I cannot do that for outside ROOT classes like dd4hep::rec::Vector3D

And at this point I was completely frustrated and lost hope in using dictionaries.

minor notes

initially my question would be how to do that with cmake. But I switched to g++ to simplify the example, assuming that I will not have problem transferring working example to the cmake.

P.S. I have tried it with recent ROOT version as well and I believe it does not make any different and behavior stays the same. Only some verbose messages change if I call rootcint with -v flag.

cheers,
Bohdan

In principle, you would need to create a shared library:

`root-config --cxx --cflags` -fPIC -shared -I${DD4hep_DIR}/include ContDict.cxx -o libContDict.so `root-config --libs`

and then load it into ROOT before opening your file:

root [0] .L libContDict.so
root [1] new TBrowser()
1 Like

Thanks, it works.

And to access the file from python, I can use:
ROOT.gInterpreter.LoadFile("libContDict.so")

So, is it always the case that the end user which uses my root file also should have libContDict.so file? Is there a way of dealing with this w/o additional library file?

I assume it works for ROOT::Math::XYZVector w/o library file because the library is always read by default somewhere under the hood?

Maybe better: ROOT.gSystem.Load("libContDict")

@couet I don’t know any “guide” / “manual” which explicitly demonstrates how to achieve autoloading of ROOT classes (i.e., all steps needed without using CMake).

We will have soon a doc review . I Added your point as an issue for the ROOT manual. Thanks. https://github.com/root-project/web/issues/641

1 Like

So did I understand correctly that it possible to create a ROOT file with dd4hep::rec::Vector3D branch using cmake such that the output file can be read without preloading library?