Realtime root dictionary generation

Saving stl containers to the tree is very usual in REST. We can simply write in the process, for example:

map<int, double> mm{{1,3},{2,5},{3,7}};
SetObservableValue("map_value", mm);

to add a branch in the tree.

Acutally for some stl containers it is not possible to do this in pure root environment:

root [0] map<int,double> mm
(std::map<int, double> &) {}
root [1] TTree*tree=new TTree();
root [2] tree->Branch("map",&mm)
Error in <TTree::Branch>: The class requested (map<int,double>) for the branch "map" is an instance of an stl collection and does not have a compiled CollectionProxy. Please generate the dictionary for this collection (map<int,double>) to avoid to write corrupted data.
(TBranch *) nullptr

The “dictionary” mentioned in the above error message tells ROOT how to find the data from the object, and save to the disk. The dictionaries would be generated in chain when we run rootcling. For example if there is a Class “AAA” containing data member “aaa” with type “map<int,double>”, the dictionary will be generated both for “AAA” and “map<int,double>”. Therefore, in REST environment, the above code will execute normally, since there is a map<int,double> data member in TRestDetectorSingleChannelAnalysisProcess:

In case that no dictionary is available for the custom typed observable, REST provides realtime root dict generation. The idea is to call rootcling and gcc from the code to compile a library containing root dictionary for this stl container. For the previous map<int,double> type, the command is:

rootcling -f map_int_double_.cxx -c LinkDef.h
gcc map_int_double_.cxx -std=c++11 -I`root-config --incdir` `root-config --libs` -lGui -lGeom -lGdml -lMinuit -L/usr/lib64 -lstdc++ -shared -fPIC -o Dict_map_int_double_.so

Where the first command generates map_int_double_.cxx from LinkDef.h and the second command compiles the cxx file into our needed library. The LinkDef.h is like:

#include <map>
#include <vector>
#include <map>
#include <set>
#include <list>
#include <array>
#ifdef __ROOTCLING__
#pragma link C++ class map<int,double>;
#endif

Finally we call gSystem to load the compiled library, and refresh the reflected TClass object. This feature helps to a easy life for us to add observables.