Grover
(Generic
Reconstruction
Of
VERtices)
The person currently responsible for the Grover package is:
Dmitri Emeliyanov. Please send
all correspondence to him.
Click here for the latest version of
the manual (refers to Grover v2.01 in ARTE-03-08-r7).
Primary Vertex Reconstruction by Grover, Tracking meeting, March 27th 2002.
The New Primary Vertex Finder in Grover.
The documentation below is historical. Please use the postscript
manual above.
Introduction
Grover is a package for vertexing at HERA-B which tries to merge two
different tools - VT and Rover. VT was written by Thomas Lohse
before HERA-B was built and before the DST data structure was fixed.
It is a series of stand-alone FORTRAN routines and is rather complete.
A FORTRAN Arte interface was written a few years ago, but the
structure of the Arte tables and Arte itself has changed rather a lot.
In particular, most users are now using C++. Rover is a C++
package, started by Thomas Perschke and developed by Ivan Kisel and
others, which, at the time Grover was conceived, contained a primary
finder, a basic two-track secondary fit and a graphical display.
It was integrated with Arte from the start.
Grover is an attempt to allow the ordinary user to use both packages
in a transparent way from their usevnt() function.
I have tried to make
it as general as possible so that the package can be extended a lot.
It should be considered as under test for the moment!
VT can now be tuned on real and MC data. numbers such as
chi-squared cuts in the package which were PARAMETERs have now been
turned into 'cuts' which can be set inside Grover.
The immediate aim is to allow everybody to tune VT and compare
its performance with Rover's, and to allow the authors to extend Rover at
their leisure without interfering with or slowing down the vertexing
effort as a whole.
The following sections describe the structure very briefly. If you'd
rather, you can just download the tarball below and read the README file.
It should be fairly
obvious what's happening. When you need to change things read this page
completely and refer to the header file grover.hh
for complete specifications of the classes and functions.
Classes
There are four classes defined in Grover:
- GroverParticle
- GroverWire
- GroverVertex
- GroverCuts
The first three have a corresponding container - GroverParticleList,
GroverWireList, GroverVertexList. These are just typedef'ed to
a STL vector for the moment, although that might change if it
proves inadequate for you, the user. The containers provide the usual
functionality, including random-access iterators. For more STL
info see here (courtesy of SGI).
The documentation in the header file Grover.hh is more complete
A GroverParticle corresponds roughly to a RSEG entry, with additional
data and, of course, internal functionality, such as propagating the
beginning of the track to a plane in z, swapping it
between Global and Local VDS coordinates, finding the chi-squared distance
to another GroverParticle, GroverWire or GroverVertex, etc. It can
be constructed from RSEGs, RTRAs, other GroverParticles, etc. It can
even be constructed from vertices or MC tracks to provide more
flexibility. It also
possesses a type specifying what kind of object it was made from, and
a pointer to that object. In this way information is not lost. It also
possesses various numbers and flags that can be set and read by the user.
A GroverWire can be constructed from a GTAR entry and also has some
functionality - coordinate transformations, for example. It also has numbers
and flags for the user's convenience - number of primaries associated
to this wire, etc.
A GroverVertex is also designed to be rather flexible and can be constructed
from RVER entries, GroverParticleLists, etc. It possesses a GroverParticleList
which can be manipulated both by the user and internally.
The particles in the list can be fitted as as a primary or secondary using
one of the member functions (only one exists at the moment - the geometrical
primary vertex fitting routine vertex.RPGeoFit implemented in Rover1.05).
A GroverCuts object is basically a struct. It is constructed with all
the default values of VT and Rover already set, but they can be changed by
the user.
The contents of all Grover objects can be dumped to stdout using
GroverObject.Dump().
(*) Mavens please note: the classes are by no means bullet-proof, and
encapsulation is only partial. You can do lots of nonsensical things to
a Grover class and make it break without too much effort.
Vertexing is physics and the classes are there to make life easier.
If you switch your brain off you will get in a mess :-)
More Detail
GroverParticle
Constructors: There is a default constructor, which is not
very useful. Better are
GroverParticle fred(ArtePointer jim(0)) and the RTRA
equivalent which initialise the track parameters and coordinate system
flags correctly and set up the pointer to the parent RSEG/RTRA
and type flag.
Data Structure: The object contains the track parameters
(x,y,z,ax,ay) and their triangular covariance matrix at each of four
points. Two are fixed during construction - the start and end of the
parent object (e.g. RTRA entry). The other two are moveable
using the member functions PropagateXXXTo() described below.
The momentum and inverse momentum (plus errors) are also stored, as are
the mass (and its error), charge and total number of hits in the
Vertex Detector. Also stored are an index integer, a 'used in primary'
integer and a couple of floats for weights. There is also a 'parent type'
flag which tells you what kind of object its parent was, and a set
of pointers of appropriate type to allow you to always follow a trail
back to the DST or Clue object. All of these things are gettable and
settable. Remember that not all of them are meaningful at all times. For
example, you can't expect the mass to be set if you constructed from
an RSEG object.
Member Functions: There are member functions for finding
the spatial and chi-2 distances to other objects of type
GroverParticle, GroverWire or GroverVertex,
which take the pointer to that object as an argument. There are member
functions to swap all the track parameters between coordinate systems.
The covariances are not changed for the moment. This is probably not
such a problem since the rotations involved are small. There are two
member functions PropagateBeginTo(z) and PropagateEndTo(z)
which use the internally defined start and end points of the particle
and propagate the track upstream or downstream, respectively, to
a plane in z. The
Begin and End points accessed with BeginX(),
EndSlopeY() etc.
refer to these virtual points. The covariance matrices are also
adjusted. If you want to rediscover the original points of the
parent object (e.g. RTRA entry) you can find the original
z with OriginalBeginZ() or OriginalEndZ() and
then project to this plane. There is a Dump() function to
get a quick look at what's inside the object.
GroverWire
Constructors: The default is a 250um thick vertical wire
at 0,0,0 in global coordinates with number -1. The constructor for
a GTAR entry is the only one anybody would want to use, I suspect.
Data Structure:
Pretty much the same as GTAR. There are flags for horizontal
and vertical, and three integers to label the wire with number of particles,
number of primaries and number of secondaries. They are set by the user
and may be garbage!
Member Functions:
The wire can be swapped between coordinate systems and there is also
a Dump() and a full set of getters and setters.
GroverCuts
Constructors:Only one, which sets the members to their
default values.
Data Structure: An open c-style struct. Just a bunch of
integers and floats.
Member Functions:
Dump()
GroverVertex
Constructors:The standard way to construct a vertex is from
a GroverParticle or GroverParticleList. It can also
be constructed from an RVER entry, whereupon the internal
particle list (see below) is also filled correctly from RTRA
using the relations on the DST. The coordinate system is set to be the same
as the particle, or last on the list of particles, from which the vertex
was constructed. There is also a shortcut vertex(x,y,z) where
by default x,y,z are in local VDS coordinates.
Data Structure: The vertex position and momentum are stored.
The covariance matrix is a 6x6 triangular matrix. The first six elements
are the spatial covariances. It has not been decided which three parameters
to use for the momentum - {ax,ay,p} or {px,py,pz}. VT uses the former.
The Rover routines are all geometric so far, so the question remains
open for a few days until the VT interface is running.
There is an index integer and a couple of chi-squares which can be set by
the user or a major routine such as a GroverPrimaries.
The main data structures are two GroverParticleLists called
particles and trashcan which are publically accessible.
This makes the class less robust and people should not add or remove
particles unless absolutely necessary. This is dealt with below
Member Functions:
It would be unwise to allow all possible fitting procedures to become
member functions of the class, although conceptually that is where they
belong. In practice it could get very slow and messy to deal with
multiple GroverVertexLists if each GroverVertex in them
contained lots of matrices corresponding to the internal data structures
of each routine. In general it is better to keep such routines as separate
functions which operate on a GroverVertex, or list thereof.
This keeps the class small and efficient. Very useful and/or general
procedures - such as momentum or covariance estimation as starting points
for fits - can be added, of course. One or two are already there.
EstimateCov(z) projects all the tracks in particles
to a plane in z and estimates a diagonal covariance matrix according to
the scatter of the tracks in that plane. EstimateMomentum()
uses a method similar to VT's to estimate the momentum of
a vertex, taking into account all the covariance matrices of the tracks.
Now to the internal particle lists. Imagine I have a constrained fitting
routine. First I use Add(gp) or Add(gpl) (where gp
and gpl are pointers to a GroverParticle or
GroverParticleList, respectively. This copies the
particle(s) onto the internal particles list. The author of the
fit might do the following: 0) Clear the trashcan.
1) Do an unconstrained fit to see if all the
particles are compatible with the constraint. 2) use the standard
member functions of an STL vector to remove from the
particles list any which are not compatible
and add them to the trashcan list. 3)
Perform the fit again with the constraint, and update the parameters of the
particles in the particles list. 4) Write the chi-2 of the fit into
the appropriate variable in the vertex, and the contribution of each track
to the chi-2 into the appropriate place in the GroverParticles.
Aafter this procedure the user can
see the results of the fit, but also get access to the particles which were
excluded. In general, the author of a fit program will
clear()
the trashcan before starting, so the particles there are lost
unless the user accesses them immediately after the fit. The lists
are publically accessible, so the user can do nonsensical things like
wiping the particles list clean and asking for a momentum
estimate for a vertex with zero particles. This is the price we have to
pay for flexibility. The general user should not have to alter either
particles or trashcan. The Add() function
can be used to prepare a vertex candidate for fitting, and then pass it to
a carefully thought out fitting routine which does its own book-keeping.
In principle we could have one or more Remove() functions. For
example, "Remove all particles in the list with less than seven hits in
the VDS'. This might be feasible for certain common cases, but I think in
general it's better and safer to construct a new vertex and fill it with
the tracks you are interested in, then pass it to a general routine
like a J/psi finder. Mail me if you have any feelings on this.
Finally there are routines for swapping between coordinate systems. The
covariances are not changed. All the particles in both lists are also
transformed, to save you having to do it by hand.
STL vector commands: Elements in a list fred
can be accessed with an iterator:
for (GroverVertexList::iterator j = fred.begin(); j!=fred.end(); ++j)
p = j->Momentum();
// OR if fred is a pointer to a GroverVertexList
for (GroverVertexList::iterator j = fred->begin(); j!=fred->end(); ++j)
p = j->Momentum();
or via indexed access (index starts at 0, i.e C-style, not Fortran style!):
p = fred[i].Momentum();
// OR if fred is a pointer to a GroverVertexList
p = (*fred)[i].Momentum();
The lists behave as stacks. e.g. to get the momentum of the last on the stack
and then remove it, do something like:
p = fred.back().Momentum();
fred.pop_back();
You can also do fred.push_back(vtx) (where vtx is a
GroverVertex) to add a vertex to the stack. You can have multiple
iterators operating on the same list, and you can even add and remove
particles in the middle of a list, although this is should be done extremely
carefully in Grover as the indexing will get mixed up and any iterators
pointing to vertices after the one removed or added will be invalid and
could cause a segmentation fault if dereferenced.
Utility Routines
A few utility routines already exist. GroverFillFromRSEG and GroverFillFromRTRA
fill a GroverParticleList from the Arte banks, as does GroverFillLikeRover.
This latter routine fills the track list in the same way as Rover 1.0x, that is, using one RTRA
for each RSEG (when one or more exists) and all remaining RSEGs. This routine will change
quickly as the tracking situation improves.
GroverFillFromGTAR fills
a GroverWireList from GTAR. GroverAddToRVER writes a GroverVertexList
into the RVER table and updates the relations to RTRA. GroverFillVTInputs
fills the common blocks necessary for running VT with the GroverWireList,
GroverParticleList and GroverCuts specified by the user. See the
header file for a complete list of prototypes, and the corresponding source code
for comments and explanation. If you are still none the wiser, send me an email!
Primary Vertex Finding
Primary Vertex finding can be done with VT or Rover. Both are called
in the same way. Lists of wires, particles and cuts are passed as
inputs and a list of vertices is returned as output. If the appropriate flag
in the passed GroverCuts is set, a graphical display is started when
GroverPrimaries or GroverVTPrimaries is called. The
simplest way is simply to call GroverEvent(0). See the README file
in the tarball below.
Secondary Vertex Finding
Very primitive at the moment. Use it if you like, but I make no claims for it.
The situation is expected to improve rapidly in the next three weeks, so update
the tarball regularly and look here for documentation. The secondary finder
at the moment uses only VDS RSEGs, so you should specify TrackChoice = 2
in the cut file. The algorithm looks for secondaries consisting of the two
tracks identified online as the J/psi electrons, and tries to add anything
else which is not already in the primaries. It's added to RVER if
reasonably separated from the nearest primary.
Sven Schaller
Last modified: Mon Jul 8 16:24:24 MEST 2002