CLHEP and root united

From: stefan kluth (skluth@mh1.lbl.gov)
Date: Sat Jul 04 1998 - 03:12:56 MEST


Dear Rooters!

I have managed to compile and link the more useful parts of CLHEP into
a shared library, which can be loaded into root. It contains the following
pieces:
Hep3Vector, HepRotation HepTranslation HepTransformation, HepPoint
HepLorentzVector, HepLorentzRotation
HepGenMatrix HepMatrix HepSymMatrix HepDiagMatrix HepVector
HepAList<T>, HepConstAList<T>, HepAListR<T>
HepAIterator<T>, ConstAIterator<T>

The 3 and Lorentzvectors together with the transformation classes provide
a quite complete command set for many calculation typical in HEP. 

The HepMatrix and Co. classes contain a convenient set of linear algebra
functions including inversion, diagonalisation and solving of sets of
linear equations. Compared to the root-matrix classes one wins on ease of
use (IMHO) and the lack of efficiency doesn't really matter for small to
medium scale computations performed on the command line or in a macro. 
For large computations in batch jobs one might suffer from a performance
penalty. 

The CLHEP template based lists and corresponding iterators can be used
only with instantiated templates in a separate precompiled shared library. 
The template class HepAListR<T> is ready for root-IO, such that one can
write lists of any root-streamable objects to root files. 

The CLHEP package can be found in by anonymous ftp to persil.lbl.gov in
pub/CLHEP-root. You find there also an example application of using the 
HepAListR<T> template container to contruct a ntuple-like tree in the
archive streamCLHEP.tar.gz. 

Please let me know of any comments, questions or additions you might have. 

cheers, Stefan


PS: Below I append my root-template-howto:


It is possible to fully link precompiled instantiated template classes 
into root by following this recipie:

1) Insert the macros ClassDefT and ClassImpT in place of the normal
   root macros ClassDef and ClassImp in your template class code. 

Here is the ClassDefT and ClassImpT macro defintion I use:


#define ClassDefT(name,id) \
private: \
  static TClass *fgIsA; \
public: \
  static const char *DeclFileName() { return __FILE__; } \
  static int DeclFileLine() { return __LINE__; } \
  static const char *ImplFileName(); \
  static int ImplFileLine(); \
  static Version_t Class_Version() { return id; } \
  static TClass *Class(); \
  static const char* SetClassName(); \
  static void Dictionary(); \
  virtual TClass *IsA() const { return name::Class(); } \
  virtual void ShowMembers(TMemberInspector &insp, char *parent); \
  virtual void Streamer(TBuffer &b); \
  friend TBuffer &operator>> (TBuffer &buf, name *&obj);

#define _ClassImpT_(name,Tmpl) \
   template <class Tmpl> TClass* name<Tmpl>::Class() \
          { if (!fgIsA) name<Tmpl>::Dictionary(); return fgIsA; } \
   template <class Tmpl> const char* name<Tmpl>::ImplFileName() \
     { return __FILE__; } \
   template <class Tmpl> int name<Tmpl>::ImplFileLine() { return __LINE__; } \
   template <class Tmpl> TClass* name<Tmpl>::fgIsA = 0;
// Don't know how to deal with this yet
//   _ClassInit_(name)
#define ClassImpT(name,Tmpl) \
   template <class Tmpl> void name<Tmpl>::Dictionary() { \
      TClass *c = CreateClass(SetClassName(), Class_Version(), \
                              DeclFileName(), ImplFileName(), \
                              DeclFileLine(), ImplFileLine()); \
      fgIsA = c; \
   } \
   _ClassImpT_(name,Tmpl)
#endif


These could in principle be part of Rtypes.h. For the moment you will
have to put these in a private additional header file. The main difference
is the additional member function SetClassName() and the insertion of
"template <class Tmpl>" in front of member functions which depend on
the template parameter. 

I could not work out how to extend the statements in the macro
_ClassInit_(name), so I just don't use it. Empirically, it doesn't 
seem to do any harm. 


2) Produce some "application code", which instantiates the templates
you want to use in root. For example, a piece of code containing the 
line

  HepAListR<HepLorentzVector> vl;

will result in the instantiation of HepAListR<HepLorentzVector>. A simple 
but complete example is provided in the package streamCLHEP.tar.gz


3) Proceed as usual, i.e. create a linkdef.h file with a line for every
template instantiation you need, e.g.

#pragma link C++ class HepAListR<HepLorentzVector>-;

The "-" is there, because the streamable HepAListR<T> has a custom 
Streamer method. Now run rootcint in the usual way. This will produce
the defintions for some of the functions declared above in the macros
separately for every template instantiation. 

The definition for SetClassName() is produced by a special program which 
is run directly after the rootcint step. It produces e.g.

// Set the class name for HepAList<HepLorentzVector>:
const char* HepAListR<HepLorentzVector>::SetClassName() {
  return "HepAListR<HepLorentzVector>";
}

This step could be done by rootcint itself, of course. An example of the
program can be found in the CLHEP-root package CLHEP.tar.gz as clhepcint.cc. 


4) Compile and link your "application code" together with the output
from running rootcint and clhepcint into a shared lib in the usual way. 


5) Start root and load the shared lib. Now you can use your instantiated
template as a type and for example do:
root [1] HepAListR<HepLorentzVector> vlist;
root [2] HepLorentzVector l1=(1,2,3,4);
root [3] HepLorentzVector l2=(5,6,7,8);
root [4] vlist.append( l1 );
root [4] vlist.append( l2 );



---Stefan Kluth---------------Lynen Fellow----------------|\--|\-------
-  LBNL, MS 50A 2160       -  phone:  +1 510 495 2376  -  |/  |/      -
-  1 Cyclotron Rd.         -  fax:    +1 510 495 2957  -  |\/\|\/\|'  -
---Berkeley, CA94720, USA-----e-mail: SKluth@lbl.gov------|/\/|/\/|----



This archive was generated by hypermail 2b29 : Tue Jan 04 2000 - 00:34:34 MET