|
sPHENIX_tutorial
Basic information useful for those working on sPHENIX
example codetest_sPHENIX.cpp provides an example of running the helixhough tracking over simulated data. This particular program runs over toy MC files generated by fastTrackMC, which is included in the svn repository. Classes to be used for sPHENIX trackingSimpleHit3DSimpleHit3D is the basic representation of a detector hit for the helixhough package. It contains x,y,z positions and uncertainties, a detector layer (counting starts at 0), and a unique index. SimpleTrack3DSimpleTrack3D contains information about reconstructed tracks. It stores a vector of SimpleHit3D for a track, the 5 helix parameters, and a unique index. HelixResolutionHelixResolution contains, for each of the 5 helix parameters, the maximum resolution (minimum value) that the hough transform will try to distinguish. This is passed to each instance of the HelixHough class HelixRangeHelixRange contains, for each helix parameter, a minimum and maximum value between which the hough transform will search for tracks. sPHENIXTrackersPHENIXTracker, which derives from HelixHough, is the class which actually performs the pattern recognition. It implements HelixHough::findTracks to do combinatorial tracking on groups of hits passed from the hough transform routines, and fits tracks using a Kalman Filter. VertexFitFuncVertexFitFunc represents a function to be minimized in order to find the collision vertex. It derives from the FitNewton::FunctionGradHessian class from fitnewton. Overview of how the sPHENIX tracking worksThe basic philosophy of the helixhough package is to use a recursive hough transform to find small groups of hits which are likely to contains tracks, and then pass those groups of hits to another tracking routine to actually find and fit the tracks. In the case that the second routine simply calls each group of hits a track, the algorithm performs like a standard hough transform. However, interaction of particles with the detector renders the helical tracks model incomplete, and in the limit of few, thick layers (like that proposed for sPHENIX), further evaluation past the level of a hough transform is needed. The sPHENIXTracker class is also written to have the option of doing the tracking in two stages, and this option has so far given better runtime speed for the default sPHENIX geometry. In the first stage, tracks are found using the inner 4 layers only. In the second stage, those tracks are combined with hits from the outer layers to make further tracks. This approach has a few advantages :
Vertex findingVertexing works by minimizing a function of reconstructed tracks. However, it is good to have a vertex before tracking. The recommended way around this circular problem is to perform tracking with very loose constraints on the vertex position until a specified number of tracks have been found, and using those tracks to find the vertex. After further tracking is done, the vertex can be found even more precisely. When a target number of tracks to be found is given to an instance of HelixHough, the class attempts to find that that number of tracks uniformly distributed in angular space. Helix ParametersThe helix parameters used by the Hough Transform are
The color-coded image below shows the parameters in 2D space, and also explains a bit of how the hough voting works.
A Walkthrough of an Example Tracking Routinetest_sPHENIX.cpp provides a basic example of running the tracking. In this example, no vertex finding is performed, and a vertex is implicitly assumed to be at 0,0,0. This is by no means necessary, but this example is meant to be as simple as possible. The range of helix parameters which will be considered by the hough transform needs to be decided. This information is encapsulated by the class HelixRange. In the code below, all phi are considered, tracks with d and z0 in between += 1 mm are considered, dzdl between +- 0.9 is considered, and tracks with kappa between 0 and 0.03 cm-1 are considered : float kappa_max = 0.03; float rho_max = pow(kappa_max,1.); // the parameter order is phi,d,kappa,dzdl,z0 HelixRange top_range(0.,2.*M_PI, -0.1, 0.1, 0.0, rho_max, -0.9, 0.9, -0.1, 0.1); A HelixHough instance requires a recursive binning strategy. One way to specify this is with a vector<vector<unsigned int> > which specifies how many bins to use for each of the 5 helix parameters at each recursion level. For example vector<unsigned int> onezoom(5,0);
vector<vector<unsigned int> > zoomprofile;
zoomprofile.assign(6,onezoom);
// the parameter order is phi,d,kappa,dzdl,z0
for(unsigned int i=0;i<=2;++i)
{
zoomprofile[i][0] = 5;
zoomprofile[i][1] = 1;
zoomprofile[i][2] = 2;
zoomprofile[i][3] = 4;
zoomprofile[i][4] = 1;
}Here, there are a maximum of 6 recursion steps. At each step, the phi variable is split into 5 bins, kappa into 2 bins, dzdl into 4 bins, and d and z0 just have one bin for all steps. Now we can specify an instance of sPHENIXTracker, giving it a binning and parameter range, as above, as well as a minimum level of recursion to use. sPHENIXTracker tracker(zoomprofile, 3, top_range); In this example, the sPHENIX tracker constructed above will be used for finding track seeds from the 4 inner layers. We specify some more parameters below for the tracker below : // only the first 4 layers are used for this tracker tracker.setNLayers(4); unsigned int max_hits_seed = 36; unsigned int min_hits_seed = 4; // no ghost rejection : that will be done after seeding tracker.setRejectGhosts(false); tracker.setChi2Cut(10.0); tracker.setPrintTimings(true); tracker.setVerbosity(1); tracker.setCutOnDca(false); // we want our seeds to use all 4 layers tracker.requireLayers(4); // don't smooth back the Kalman Filter to near the collision : since we are seeding we want the track parameters at the outer-most hit tracker.setSmoothBack(false); max_hits_seed and max_hits_seed will be used later when the tracking routine is actually called. This specifies that at most 36 and at least 4 hits must be in a parameter bin before any combinatorial algorithm is called on that group of hits. See the comments in the above code snippet for explanations of the other parameters set to the tracker. Next we will set up another instance of sPHENIXTracker to add hits from the outer two layers to the seeds. HelixRange top_range_2(0., 2.*M_PI, -0.2, 0.2, 0.0, rho_max, -0.9, 0.9, -0.3, 0.3); sPHENIXTracker tracker_seeded(zoomprofile, 3, top_range_2); unsigned int max_hits = 36; unsigned int min_hits = 2; tracker_seeded.setRejectGhosts(true); tracker_seeded.setChi2Cut(4.0); tracker_seeded.setPrintTimings(true); tracker_seeded.setVerbosity(1); tracker_seeded.setCutOnDca(false); tracker_seeded.setSmoothBack(true); Here we have expanded the d and z0 range, to account a bit more for multiple scattering. The next step in the tracking routine, not fully expanded here, is to read over the input file and convert the data there to a std::vector<SimpleHit3D>. Two vectors are filled, one for the first 4 layer called hits_0_3 and the other for the outer layers called hits_4_5. Each SimpleHit3D corresponds to one detector hit, or cluster of hits, and needs the following public variables filled :
Once the input files have been converted, we can run the tracking : vector<SimpleTrack3D> tracks_seed; tracker.findHelices(hits_0_3, min_hits_seed, max_hits_seed, tracks_seed); tracker_seeded.setSeedStates(tracker.getKalmanStates()); Now tracks_seed is filled with some 4-hit track candidates, and the Kalman covariance matrices for those candidates are set to the seeded tracker. And finally, the outer layers can be added to the track candidates : vector<SimpleTrack3D> tracks; tracker_seeded.findSeededHelices(tracks_seed, hits_4_5, min_hits, max_hits, tracks); tracks is a list of the final tracks for this event. The rest of the example converts the tracks to a format more suitable for output to a ROOT file. |