Print

Print


Author: mccaky
Date: Wed Oct 29 21:25:20 2014
New Revision: 1336

Log:
Added documentation to particle reconstruction drivers and improved code efficiency.

Modified:
    java/trunk/recon/src/main/java/org/hps/recon/particle/HpsReconParticleDriver.java
    java/trunk/recon/src/main/java/org/hps/recon/particle/ReconParticleDriver.java
    java/trunk/recon/src/main/java/org/hps/recon/particle/TestRunReconParticleDriver.java

Modified: java/trunk/recon/src/main/java/org/hps/recon/particle/HpsReconParticleDriver.java
 =============================================================================
--- java/trunk/recon/src/main/java/org/hps/recon/particle/HpsReconParticleDriver.java	(original)
+++ java/trunk/recon/src/main/java/org/hps/recon/particle/HpsReconParticleDriver.java	Wed Oct 29 21:25:20 2014
@@ -20,147 +20,188 @@
 import org.hps.recon.vertexing.BilliorVertex;
 import org.hps.recon.vertexing.BilliorVertexer;
 
-
 /**
- * The Main HPS implementation of ReconParticleDriver...makes V0 candidates and does vertex fits
+ * The main HPS implementation of ReconParticleDriver. Method generates
+ * V0 candidates and does vertex fits.
+ * 
  * @author Omar Moreno <[log in to unmask]>
  * @version $Id$
  */
 public class HpsReconParticleDriver extends ReconParticleDriver {
-	
-	private enum Constraint { 
-		UNCONSTRAINED, 
-		BS_CONSTRAINED, 
-		TARGET_CONSTRAINED
-	}
-	
-	public HpsReconParticleDriver(){}		
-
-	@Override
-	protected void startOfData(){
-		
-//		unconstrainedV0CandidatesColName    = "UnconstrainedV0Candidates";
-//		beamConV0CandidatesColName   		= "BeamspotConstrainedV0Candidates";
-//		targetConV0CandidatesColName 		= "TargetConstrainedV0Candidates";	
-//		unconstrainedV0VerticesColName 		= "UnconstrainedV0Vertices";
-//		beamConV0VerticesColName 			= "BeamspotConstrainedV0Vertices";
-//		targetConV0VerticesColName			= "TargetConstrainedV0Vertices";
-	}
-
-	/**
-	 * 
-	 */
-	@Override
-	void findVertices(List<ReconstructedParticle> electrons, List<ReconstructedParticle> positrons) {
-		
-		ReconstructedParticle candidate = null; 
-		BilliorVertex vtxFit = null;
-		// Loop through both electrons and positrons and try to find a common vertex
-		for(ReconstructedParticle positron : positrons){
-			for(ReconstructedParticle electron : electrons){
-				
-				// Get the tracks associated with the electron and the positron
-				Track electronTrack = electron.getTracks().get(0); 
-				Track positronTrack = positron.getTracks().get(0); 
-				
-				// Covert the tracks to BilliorTracks used by the vertexer
-				BilliorTrack electronBTrack = toBilliorTrack(electronTrack); 
-				BilliorTrack positronBTrack = toBilliorTrack(positronTrack);
-			
-				for(Constraint constraint : Constraint.values()){
-					
-					vtxFit = fitVertex(constraint, electronBTrack, positronBTrack);
-				
-					candidate = makeReconstructedParticle(electron, positron, vtxFit); 
-					
-					
-					switch(constraint){
-						case UNCONSTRAINED: 
-							unconstrainedV0Vertices.add(vtxFit);
-							unconstrainedV0Candidates.add(candidate); 
-							break;
-						case BS_CONSTRAINED:
-							beamConV0Vertices.add(vtxFit);
-							beamConV0Candidates.add(candidate);
-							break;
-						case TARGET_CONSTRAINED:
-							targetConV0Vertices.add(vtxFit);
-							targetConV0Candidates.add(candidate);
-							break;
-					}
-				}
-			}
-		}
-	}
-	
-	/**
-	 * 
-	 */
-	BilliorVertex fitVertex(Constraint constraint, BilliorTrack electron, BilliorTrack positron){
-		
-		BilliorVertexer vtxFitter = new BilliorVertexer(bField);
-		// TODO: The beam size should come from the conditions database
-		vtxFitter.setBeamSize(beamsize);
-		
-		switch(constraint){
-			case UNCONSTRAINED: 
-				vtxFitter.doBeamSpotConstraint(false); 
-				break;
-			case BS_CONSTRAINED:
-				vtxFitter.doBeamSpotConstraint(true); 
-				break;
-			case TARGET_CONSTRAINED:
-				vtxFitter.doTargetConstraint(true);
-				break;
-		}
-				
-		List<BilliorTrack> billiorTracks = new ArrayList<BilliorTrack>();
-		billiorTracks.add(electron);
-		billiorTracks.add(positron);
-		
-		return vtxFitter.fitVertex(billiorTracks);
-	}
-	
-	/**
-	 * 
-	 */
-	ReconstructedParticle makeReconstructedParticle(ReconstructedParticle electron, ReconstructedParticle positron, BilliorVertex vtxFit){
-		
-		ReconstructedParticle candidate = new BaseReconstructedParticle();
-		((BaseReconstructedParticle) candidate).setStartVertex(vtxFit);
-		candidate.addParticle(electron);
-		candidate.addParticle(positron);
-					
-		// TODO: The calculation of the total fitted momentum should be done within 
-		// 		 BilloirVertex
-		((BaseReconstructedParticle) candidate).setMass(vtxFit.getParameters().get("invMass"));
-		Hep3Vector fittedMomentum = new BasicHep3Vector(vtxFit.getParameters().get("p1X"), 
-		   											    vtxFit.getParameters().get("p1Y"), 
-														vtxFit.getParameters().get("p1Z"));
-		fittedMomentum = VecOp.add(fittedMomentum, new BasicHep3Vector(vtxFit.getParameters().get("p2X"), 
-																   	   vtxFit.getParameters().get("p2Y"),
-																       vtxFit.getParameters().get("p2Z")));
-		this.printDebug("Fitted momentum in tracking frame: " + fittedMomentum.toString());
-		fittedMomentum = CoordinateTransformations.transformVectorToDetector(fittedMomentum);
-		this.printDebug("Fitted momentum in detector frame: " + fittedMomentum.toString());
-		HepLorentzVector fourVector = new BasicHepLorentzVector(0, 0, 0, 0); 
-		((BasicHepLorentzVector) fourVector).setV3(fourVector.t(), fittedMomentum);
-		((BaseReconstructedParticle) candidate).set4Vector(fourVector);
-		
-		// Add the ReconstructedParticle to the Vertex 
-		vtxFit.setAssociatedParticle(candidate);
-		
-		return candidate;
-		
-	}
-	
-
-	/**
-	 * 
-	 */
+    /**
+     * Represents a type of constraint for vertex fitting.
+     * 
+     * @author Omar Moreno <[log in to unmask]>
+     */
+    private enum Constraint { 
+        /** Represents a fit with no constraints. */
+        UNCONSTRAINED, 
+        /** Represents a fit with beam spot constraints. */
+        BS_CONSTRAINED, 
+        /** Represents a fit with target constraints. */
+        TARGET_CONSTRAINED
+    }
+    
+    /**
+     * Creates reconstructed V0 candidate particles and vertices for
+     * electron positron pairs using no constraints, beam constraints,
+     * and target constraints. These are saved to the appropriate lists
+     * in the super class.
+     * @param electrons - The list of electrons.
+     * @param positrons - The list of positrons.
+     */
+    @Override
+    protected void findVertices(List<ReconstructedParticle> electrons, List<ReconstructedParticle> positrons) {
+        // Iterate over the positrons and electrons to perform vertexing
+        // on the pairs.
+        for(ReconstructedParticle positron : positrons) {
+            for(ReconstructedParticle electron : electrons) {
+                // Get the tracks associated with the electron and
+                // the positron.
+                Track electronTrack = electron.getTracks().get(0); 
+                Track positronTrack = positron.getTracks().get(0); 
+                
+                // Covert the tracks to BilliorTracks.
+                BilliorTrack electronBTrack = toBilliorTrack(electronTrack); 
+                BilliorTrack positronBTrack = toBilliorTrack(positronTrack);
+                
+                // Create candidate particles for each constraint.
+                for(Constraint constraint : Constraint.values()) {
+                    // Generate a candidate vertex and particle.
+                    BilliorVertex vtxFit = fitVertex(constraint, electronBTrack, positronBTrack);
+                    ReconstructedParticle candidate = makeReconstructedParticle(electron, positron, vtxFit); 
+                    
+                    // Add the candidate vertex and particle to the
+                    // appropriate LCIO collection.
+                    switch(constraint){
+                        case UNCONSTRAINED: 
+                            unconstrainedV0Vertices.add(vtxFit);
+                            unconstrainedV0Candidates.add(candidate); 
+                            break;
+                        case BS_CONSTRAINED:
+                            beamConV0Vertices.add(vtxFit);
+                            beamConV0Candidates.add(candidate);
+                            break;
+                        case TARGET_CONSTRAINED:
+                            targetConV0Vertices.add(vtxFit);
+                            targetConV0Candidates.add(candidate);
+                            break;
+                    }
+                }
+            }
+        }
+    }
+    
+    /**
+     * Sets the default LCIO collection names if they are not already
+     * defined previously.
+     */
+    @Override
+    protected void startOfData(){
+        // If the LCIO collection names have not been defined, assign
+        // them to the default names.
+        if(unconstrainedV0CandidatesColName == null) { unconstrainedV0CandidatesColName = "UnconstrainedV0Candidates"; }
+        if(beamConV0CandidatesColName == null) { beamConV0CandidatesColName = "BeamspotConstrainedV0Candidates"; }
+        if(targetConV0CandidatesColName == null) { targetConV0CandidatesColName = "TargetConstrainedV0Candidates";     }
+        if(unconstrainedV0VerticesColName == null) { unconstrainedV0VerticesColName = "UnconstrainedV0Vertices"; }
+        if(beamConV0VerticesColName == null) { beamConV0VerticesColName = "BeamspotConstrainedV0Vertices"; }
+        if(targetConV0VerticesColName == null) { targetConV0VerticesColName = "TargetConstrainedV0Vertices"; }
+    }
+    
+    /**
+     * Fits a vertex from an electron/positron track pair using the
+     * indicated constraint.
+     * @param constraint - The constraint type to use.
+     * @param electron - The electron track.
+     * @param positron - The positron track.
+     * @return Returns the reconstructed vertex as a <code>BilliorVertex
+     * </code> object.
+     */
+    private BilliorVertex fitVertex(Constraint constraint, BilliorTrack electron, BilliorTrack positron){
+        // Create a vertex fitter from the magnetic field.
+        BilliorVertexer vtxFitter = new BilliorVertexer(bField);
+        // TODO: The beam size should come from the conditions database.
+        vtxFitter.setBeamSize(beamSize);
+        
+        // Perform the vertexing based on the specified constraint.
+        switch(constraint){
+            case UNCONSTRAINED: 
+                vtxFitter.doBeamSpotConstraint(false); 
+                break;
+            case BS_CONSTRAINED:
+                vtxFitter.doBeamSpotConstraint(true); 
+                break;
+            case TARGET_CONSTRAINED:
+                vtxFitter.doTargetConstraint(true);
+                break;
+        }
+        
+        // Add the electron and positron tracks to a track list for
+        // the vertex fitter.
+        List<BilliorTrack> billiorTracks = new ArrayList<BilliorTrack>();
+        billiorTracks.add(electron);
+        billiorTracks.add(positron);
+        
+        // Find and return a vertex based on the tracks.
+        return vtxFitter.fitVertex(billiorTracks);
+    }
+    
+    /**
+     * Creates a reconstructed V0 candidate particle from an electron,
+     * positron, and billior vertex.
+     * @param electron - The electron.
+     * @param positron - The positron.
+     * @param vtxFit - The billior vertex.
+     * @return Returns a reconstructed particle with properties generated
+     * from the child particles and vertex given as an argument.
+     */
+    private ReconstructedParticle makeReconstructedParticle(ReconstructedParticle electron, ReconstructedParticle positron, BilliorVertex vtxFit){
+        // Create a new reconstructed particle to represent the V0
+        // candidate and populate it with the electron and positron.
+        ReconstructedParticle candidate = new BaseReconstructedParticle();
+        ((BaseReconstructedParticle) candidate).setStartVertex(vtxFit);
+        candidate.addParticle(electron);
+        candidate.addParticle(positron);
+        
+        // TODO: The calculation of the total fitted momentum should be
+        //       done within BilloirVertex.
+        // Calculate the candidate particle momentum and associate it
+        // with the reconstructed candidate particle.
+        ((BaseReconstructedParticle) candidate).setMass(vtxFit.getParameters().get("invMass"));
+        Hep3Vector fittedMomentum = new BasicHep3Vector(vtxFit.getParameters().get("p1X"), 
+                                                           vtxFit.getParameters().get("p1Y"), 
+                                                        vtxFit.getParameters().get("p1Z"));
+        fittedMomentum = VecOp.add(fittedMomentum, new BasicHep3Vector(vtxFit.getParameters().get("p2X"), 
+                                                                          vtxFit.getParameters().get("p2Y"),
+                                                                       vtxFit.getParameters().get("p2Z")));
+        fittedMomentum = CoordinateTransformations.transformVectorToDetector(fittedMomentum);
+        HepLorentzVector fourVector = new BasicHepLorentzVector(0, 0, 0, 0); 
+        ((BasicHepLorentzVector) fourVector).setV3(fourVector.t(), fittedMomentum);
+        ((BaseReconstructedParticle) candidate).set4Vector(fourVector);
+        
+        // VERBOSE :: Output the fitted momentum data.
+        printDebug("Fitted momentum in tracking frame: " + fittedMomentum.toString());
+        printDebug("Fitted momentum in detector frame: " + fittedMomentum.toString());
+        
+        // Add the ReconstructedParticle to the vertex.
+        vtxFit.setAssociatedParticle(candidate);
+        
+        // Return the V0 candidate.
+        return candidate;
+    }
+    
+    /**
+     * Converts a <code>Track</code> object to a <code>BilliorTrack
+     * </code> object.
+     * @param track - The original track.
+     * @return Returns the original track as a <code>BilliorTrack
+     * </code> object.
+     */
     private BilliorTrack toBilliorTrack(Track track) {
-    	
-    	HelicalTrackFit trackFit = ((SeedTrack) track).getSeedCandidate().getHelix();
-    	return new BilliorTrack(trackFit);
+        // Convert the track to a helical track fit.
+        HelicalTrackFit trackFit = ((SeedTrack) track).getSeedCandidate().getHelix();
+        
+        // Generate and return the billior track.
+        return new BilliorTrack(trackFit);
     }
 }

Modified: java/trunk/recon/src/main/java/org/hps/recon/particle/ReconParticleDriver.java
 =============================================================================
--- java/trunk/recon/src/main/java/org/hps/recon/particle/ReconParticleDriver.java	(original)
+++ java/trunk/recon/src/main/java/org/hps/recon/particle/ReconParticleDriver.java	Wed Oct 29 21:25:20 2014
@@ -21,150 +21,318 @@
 import org.hps.recon.tracking.TrackUtils;
 
 /**
- * Driver that matches SVT Tracks and Ecal Clusters and creates
- * ReconstructedParticles.
+ * Driver framework for generating reconstructed particles and matching
+ * clusters and tracks.
  *
  * @author Mathew Graham <[log in to unmask]>
  * @author Omar Moreno <[log in to unmask]>
  * @version $Id$
  */
 public abstract class ReconParticleDriver extends Driver {
-
-    // Flags
-    boolean debug = false;
-
-    // Reconstructed particle collections
-    List<ReconstructedParticle> finalStateParticles;
-    List<ReconstructedParticle> unconstrainedV0Candidates;
-    List<ReconstructedParticle> beamConV0Candidates;
-    List<ReconstructedParticle> targetConV0Candidates;
-    List<ReconstructedParticle> electrons;
-    List<ReconstructedParticle> positrons;
-    List<Vertex> unconstrainedV0Vertices;
-    List<Vertex> beamConV0Vertices;
-    List<Vertex> targetConV0Vertices;
-
-    // Collections
-    String ecalClustersCollectionName = "EcalClusters";
-    String tracksCollectionName = "MatchedTracks";
-    String finalStateParticlesColName = "FinalStateParticles";
-    String unconstrainedV0CandidatesColName = "UnconstrainedV0Candidates";
-    String beamConV0CandidatesColName = "BeamspotConstrainedV0Candidates";
-    String targetConV0CandidatesColName = "TargetConstrainedV0Candidates";
-    String unconstrainedV0VerticesColName = "UnconstrainedV0Vertices";
-    String beamConV0VerticesColName = "BeamspotConstrainedV0Vertices";
-    String targetConV0VerticesColName = "TargetConstrainedV0Vertices";
-//    String unconstrainedV0CandidatesColName = null;
-//    String beamConV0CandidatesColName = null;
-//    String targetConV0CandidatesColName = null;
-//    String vertexCandidatesColName = null;
-//    String vertexBeamConsCandidatesName = null;
-//	String unconstrainedV0VerticesColName = null;
-//	String beamConV0VerticesColName = null;
-//	String targetConV0VerticesColName = null;
-
-    // The beamsize array is in the tracking frame
-    /* TODO  mg-May 14, 2014:  the the beam size from the conditions db...also beam position!  */
-    double[] beamsize = {0.001, 0.2, 0.02};
-    double maxTrackClusterDistance = 10000; // [mm] 
-    double bField;
-
-    //  flipSign is a kludge...
-    //  HelicalTrackFitter doesn't deal with B-fields in -ive Z correctly
-    //  so we set the B-field in +iveZ and flip signs of fitted tracks
-    //  
-    //  Note:  This should be -1 for test run configurations and +1 for 
-    //         prop-2014 configurations 
-    int flipSign = 1;
-
-    public ReconParticleDriver() {
-    }
-
-    public void setDebug(boolean debug) {
-        this.debug = debug;
-    }
-
-    public void setMaxTrackClusterDistance(double maxTrackClusterDistance) {
-        this.maxTrackClusterDistance = maxTrackClusterDistance;
-    }
-
-    public void setBeamSigmaX(double sigma_x) {
-        beamsize[1] = sigma_x;
-    }
-
-    public void setBeamSigmaY(double sigma_y) {
-        beamsize[2] = sigma_y;
-    }
-
+    /**
+     * Sets the name of the LCIO collection for beam spot constrained
+     * V0 candidate particles.
+     * @param beamConV0CandidatesColName - The LCIO collection name.
+     */
+    public void setBeamConV0CandidatesColName(String beamConV0CandidatesColName) {
+        this.beamConV0CandidatesColName = beamConV0CandidatesColName;
+    }
+    
+    /**
+     * Sets the name of the LCIO collection for beam spot constrained
+     * V0 candidate vertices.
+     * @param beamConV0VerticesColName - The LCIO collection name.
+     */
+    public void setBeamConV0VerticesColName(String beamConV0VerticesColName) {
+        this.beamConV0VerticesColName = beamConV0VerticesColName;
+    }
+    
+    /**
+     * Sets the beam size sigma in the x-direction.
+     * @param sigmaX - The standard deviation of the beam width in the
+     * x-direction.
+     */
+    public void setBeamSigmaX(double sigmaX) { beamSize[1] = sigmaX; }
+    
+    /**
+     * Sets the beam size sigma in the y-direction.
+     * @param sigmaY - The standard deviation of the beam width in the
+     * y-direction.
+     */
+    public void setBeamSigmaY(double sigmaY) { beamSize[2] = sigmaY; }
+    
+    /**
+     * Indicates whether verbose debug text should be written out during
+     * runtime or note. Defaults to <code>false</code>.
+     * @param debug - <code>true</code> indicates that debug text should
+     * be written and <code>false</code> that it should be suppressed.
+     */
+    public void setDebug(boolean debug) { this.debug = debug; }
+    
+    /**
+     * Sets the maximum allowed separation distance between a matched
+     * cluster and track pair.
+     * @param dxCut - The maximum separation distance in the x-direction.
+     */
+    public void setDxCut(double dxCut) {
+        this.dxCut = dxCut;
+    }
+    
+    /**
+     * Sets the maximum allowed separation distance between a matched
+     * cluster and track pair.
+     * @param dyCut - The maximum separation distance in the y-direction.
+     */
+    public void setDyCut(double dyCut) {
+        this.dyCut = dyCut;
+    }
+    
+    /**
+     * Sets the LCIO collection name for calorimeter cluster data.
+     * @param ecalClustersCollectionName - The LCIO collection name.
+     */
     public void setEcalClusterCollectionName(String ecalClustersCollectionName) {
         this.ecalClustersCollectionName = ecalClustersCollectionName;
     }
-
+    
+    /**
+     * Sets the name of the LCIO collection for reconstructed particles.
+     * @param finalStateParticlesColName - The LCIO collection name.
+     */
+    public void setFinalStateParticlesColName(String finalStateParticlesColName) {
+        this.finalStateParticlesColName = finalStateParticlesColName;
+    }
+    
+    /**
+     * Sets the name of the LCIO collection for target constrained V0
+     * candidate particles.
+     * @param targetConV0CandidatesColName - The LCIO collection name.
+     */
+    public void setTargetConV0CandidatesColName(String targetConV0CandidatesColName) {
+        this.targetConV0CandidatesColName = targetConV0CandidatesColName;
+    }
+    
+    /**
+     * Sets the name of the LCIO collection for target constrained V0
+     * candidate vertices.
+     * @param targetConV0VerticesColName - The LCIO collection name.
+     */
+    public void setTargetConV0VerticesColName(String targetConV0VerticesColName) {
+        this.targetConV0VerticesColName = targetConV0VerticesColName;
+    }
+    
+    /**
+     * Sets the LCIO collection name for particle track data.
+     * @param tracksCollectionName - The LCIO collection name.
+     */
     public void setTracksCollectionName(String tracksCollectionName) {
         this.tracksCollectionName = tracksCollectionName;
     }
     
-    public void setFinalStateParticlesColName(String finalStateParticlesColName) {
-        this.finalStateParticlesColName = finalStateParticlesColName;
-    }
-    
-     
+    /**
+     * Sets the name of the LCIO collection for unconstrained V0
+     * candidate particles.
+     * @param unconstrainedV0CandidatesColName - The LCIO collection name.
+     */
     public void setUnconstrainedV0CandidatesColName(String unconstrainedV0CandidatesColName) {
         this.unconstrainedV0CandidatesColName = unconstrainedV0CandidatesColName;
     }
     
-    
-    public void setBeamConV0CandidatesColName(String beamConV0CandidatesColName) {
-        this.beamConV0CandidatesColName = beamConV0CandidatesColName;
-    }
-    
-     
-    public void setTargetConV0CandidatesColName(String targetV0CandidatesColName) {
-        this.targetConV0CandidatesColName = targetConV0CandidatesColName;
-    }
-    
-    
+    /**
+     * Sets the name of the LCIO collection for unconstrained V0
+     * candidate vertices.
+     * @param unconstrainedV0VerticesColName - The LCIO collection name.
+     */
     public void setUnconstrainedV0VerticesColName(String unconstrainedV0VerticesColName) {
         this.unconstrainedV0VerticesColName = unconstrainedV0VerticesColName;
     }
     
-    
-    public void setBeamConV0VerticesColName(String beamConV0VerticesColName) {
-        this.beamConV0VerticesColName = beamConV0VerticesColName;
-    }
-    
-     
-    public void setTargetConV0VerticesColName(String targetV0VerticesColName) {
-        this.targetConV0VerticesColName = targetConV0VerticesColName;
-    }
-
+    /**
+     * Updates the magnetic field parameters to match the appropriate
+     * values for the current detector settings.
+     */
     @Override
     protected void detectorChanged(Detector detector) {
-
+        // Set the magnetic field parameters to the appropriate values.
         Hep3Vector ip = new BasicHep3Vector(0., 0., 1.);
         bField = detector.getFieldMap().getField(ip).y();
-        if (bField < 0)
-            flipSign = -1;
-
-    }
-
-    public void process(EventHeader event) {
-
-        // All events should have a collection of Ecal clusters.  If the event 
-        // doesn't have one, skip the event.
-        if (!event.hasCollection(Cluster.class, ecalClustersCollectionName))
+        if (bField < 0) { flipSign = -1; }
+    }
+    
+    /**
+     * Generates reconstructed V0 candidate particles and vertices from
+     * sets of positrons and electrons. Implementing methods should
+     * place the reconstructed vertices and candidate particles into the
+     * appropriate class variable lists in <code>ReconParticleDriver
+     * </code>.
+     * @param electrons - The list of electrons.
+     * @param positrons - The list of positrons.
+     */
+    protected abstract void findVertices(List<ReconstructedParticle> electrons, List<ReconstructedParticle> positrons);
+    
+    /**
+     * Create the set of final state particles from the event tracks
+     * and clusters. Clusters will be matched with tracks when this
+     * is possible.
+     * @param clusters - The list of event clusters.
+     * @param tracks - The list of event tracks.
+     * @return Returns a <code>List</code> collection containing all
+     * of the <code>ReconstructedParticle</code> objects generated from
+     * the argument data.
+     */
+    protected List<ReconstructedParticle> makeReconstructedParticles(List<Cluster> clusters, List<Track> tracks) {
+        // Create a list in which to store reconstructed particles.
+        List<ReconstructedParticle> particles = new ArrayList<ReconstructedParticle>();
+        
+        // Create a list of unmatched clusters. A cluster should be
+        // removed from the list if a matching track is found.
+        //List<Cluster> unmatchedClusters = new ArrayList<Cluster>(clusters);
+        java.util.Set<Cluster> unmatchedClusters = new java.util.HashSet<Cluster>(clusters);
+        
+        // Iterate over all of the tracks and generate reconstructed
+        // particles for each one. If possible, match a cluster to the
+        // track as well.
+        for (Track track : tracks) {
+            // Create a reconstructed particle to represent the track.
+            ReconstructedParticle particle = new BaseReconstructedParticle();
+            HepLorentzVector fourVector = new BasicHepLorentzVector(0, 0, 0, 0);
+            
+            // Store the track in the particle.
+            particle.addTrack(track);
+            
+            // Store the momentum derived from the track in the particle.
+            Hep3Vector momentum = new BasicHep3Vector(track.getTrackStates().get(0).getMomentum());
+            momentum = CoordinateTransformations.transformVectorToDetector(momentum);
+            ((BasicHepLorentzVector) fourVector).setV3(fourVector.t(), momentum);
+            
+            // Derive the charge of the particle from the track.
+            ((BaseReconstructedParticle) particle).setCharge(track.getCharge() * flipSign);
+            
+            // Extrapolate the particle ID from the track. Positively
+            // charged particles are assumed to be positrons and those
+            // with negative charges are assumed to be electrons.
+            if (particle.getCharge() > 0) {
+                ((BaseReconstructedParticle) particle).setParticleIdUsed(new SimpleParticleID(-11, 0, 0, 0));
+            }
+            else if (particle.getCharge() < 0) {
+                ((BaseReconstructedParticle) particle).setParticleIdUsed(new SimpleParticleID(11, 0, 0, 0));
+            }
+            
+            // Track the best matching cluster for the track. A null
+            // value indicates that no cluster matches the track to
+            // within the maximum displacement limits.
+            Cluster matchedCluster = null;
+            
+            // Loop through all the unmatched clusters and select the
+            // cluster, if any, that best fits with the track.
+            clusterLoop:
+            for (Cluster cluster : unmatchedClusters) {
+                // Check if the cluster and track are a valid match.
+                if (isMatch(cluster, track)) {
+                    // Store the matched cluster.
+                    matchedCluster = cluster;
+                    
+                    // Since a match has been found, the loop can be
+                    // terminated.
+                    break clusterLoop;
+                }
+            }
+            
+            // If a cluster was found that matches the track...
+            if (matchedCluster != null) {
+                // Update the reconstructed particle with the data from
+                // the cluster.
+                particle.addCluster(matchedCluster);
+                ((BasicHepLorentzVector) fourVector).setT(matchedCluster.getEnergy());
+                
+                // Remove the cluster from the set of unmatched clusters.
+                unmatchedClusters.remove(matchedCluster);
+            }
+            
+            // Store the momentum vector in the reconstructed particle.
+            ((BaseReconstructedParticle) particle).set4Vector(fourVector);
+            
+            // Add the particle to the list of reconstructed particles.
+            particles.add(particle);
+        }
+        
+        // If any cluster remain unmatched after the tracks are finished,
+        // they should be processed into additional reconstructed particles.
+        if (!unmatchedClusters.isEmpty())
+            // Iterate over the remaining unmatched clusters.
+            for (Cluster unmatchedCluster : unmatchedClusters) {
+                // Create a reconstructed particle to represent the
+                // unmatched cluster.
+                ReconstructedParticle particle = new BaseReconstructedParticle();
+                HepLorentzVector fourVector = new BasicHepLorentzVector(0, 0, 0, 0);
+                
+                // Add the cluster to the particle.
+                particle.addCluster(unmatchedCluster);
+                
+                // Set the reconstructed particle properties based on
+                // the cluster properties.
+                ((BasicHepLorentzVector) fourVector).setT(unmatchedCluster.getEnergy());
+                ((BaseReconstructedParticle) particle).setCharge(0);
+                ((BaseReconstructedParticle) particle).set4Vector(fourVector);
+                
+                // The particle is assumed to be a photon, since it
+                // did not leave any track.
+                ((BaseReconstructedParticle) particle).setParticleIdUsed(new SimpleParticleID(22, 0, 0, 0));
+                
+                // Add the particle to the reconstructed particle list.
+                particles.add(particle);
+            }
+        
+        // Return the list of reconstructed particles.
+        return particles;
+    }
+
+    /**
+     * Prints a message as per <code>System.out.println</code> to the
+     * output stream if the verbose debug output option is enabled.
+     * @param debugMessage - The message to print.
+     */
+    protected void printDebug(String debugMessage) {
+        // If verbose debug mode is enabled, print out the message.
+        if(debug) { System.out.printf("%s :: %s%n", simpleName, debugMessage); }
+    }
+    
+    /**
+     * Processes the track and cluster collections in the event into
+     * reconstructed particles and V0 candidate particles and vertices.
+     * These reconstructed particles are then stored in the event.
+     * @param event - The event to process.
+     */
+    @Override
+    protected void process(EventHeader event) {
+        // All events are required to contain calorimeter clusters. If
+        // the event lacks these, then it should be skipped.
+        if (!event.hasCollection(Cluster.class, ecalClustersCollectionName)) {
             return;
-
-        // Get the collection of Ecal clusters from the event. A triggered 
-        // event should have Ecal clusters.  If it doesn't, skip the event.
+        }
+        
+        // VERBOSE :: Note that a new event is being read.
+        printDebug("\nProcessing Event...");
+        
+        // Otherwise, get the list of calorimeter clusters.
         List<Cluster> clusters = event.get(Cluster.class, ecalClustersCollectionName);
-        //if(clusters.isEmpty()) return;  
-        this.printDebug("Number of Ecal clusters: " + clusters.size());
-
-        // Get the collection of tracks from the event
-        List<Track> tracks = event.get(Track.class, tracksCollectionName);
-        this.printDebug("Number of Tracks in "+tracksCollectionName+" : " + tracks.size());
-
+        
+        // VERBOSE :: Output the number of clusters in the event.
+        printDebug("Clusters :: " + clusters.size());
+        
+        // Get the set of tracks from the event. If no such collection
+        // exists, initialize an empty list instead.
+        List<Track> tracks;
+        if(event.hasCollection(Track.class, tracksCollectionName)) {
+            tracks = event.get(Track.class, tracksCollectionName);
+        }
+        else { tracks = new ArrayList<Track>(0); }
+        
+        // VERBOSE :: Output the number of tracks in the event.
+        printDebug("Tracks :: " + tracks.size());
+        
+        // Instantiate new lists to store reconstructed particles and
+        // V0 candidate particles and vertices.
         finalStateParticles = new ArrayList<ReconstructedParticle>();
         electrons = new ArrayList<ReconstructedParticle>();
         positrons = new ArrayList<ReconstructedParticle>();
@@ -174,193 +342,227 @@
         unconstrainedV0Vertices = new ArrayList<Vertex>();
         beamConV0Vertices = new ArrayList<Vertex>();
         targetConV0Vertices = new ArrayList<Vertex>();
-
-        // 
-        finalStateParticles = this.makeReconstructedParticles(clusters, tracks);
-        this.printDebug("Total number of Final State Particles: " + finalStateParticles.size());
-
-        // Put all the reconstructed particles in the event
+        
+        // Generate the reconstructed particles.
+        finalStateParticles = makeReconstructedParticles(clusters, tracks);
+        
+        // VERBOSE :: Output the number of reconstructed particles.
+        printDebug("Final State Particles :: " + finalStateParticles.size());
+        
+        // Store the reconstructed particles collection.
         event.put(finalStateParticlesColName, finalStateParticles, ReconstructedParticle.class, 0);
-
-        // Loop through the list of final state particles and separate the
-        // charged particles to either electrons or positrons.  These lists
-        // will be used for vertexing purposes.
-        for (ReconstructedParticle finalStateParticle : finalStateParticles)
-            if (finalStateParticle.getCharge() > 0)
-                positrons.add(finalStateParticle);
-            else if (finalStateParticle.getCharge() < 0)
-                electrons.add(finalStateParticle);
-        this.printDebug("Number of Electrons: " + electrons.size());
-        this.printDebug("Number of Positrons: " + positrons.size());
-
-        // Vertex electron and positron candidates 
+        
+        // Separate the reconstructed particles into electrons and
+        // positrons so that V0 candidates can be generated from them.
+        for (ReconstructedParticle finalStateParticle : finalStateParticles) {
+            // If the charge is positive, assume an electron.
+            if(finalStateParticle.getCharge() > 0) { positrons.add(finalStateParticle); }
+            
+            // Otherwise, assume the particle is a positron.
+            else if(finalStateParticle.getCharge() < 0) { electrons.add(finalStateParticle); }
+        }
+        
+        // VERBOSE :: Output the number of reconstructed positrons
+        // and electrons.
+        printDebug("Number of Electrons: " + electrons.size());
+        printDebug("Number of Positrons: " + positrons.size());
+        
+        // Form V0 candidate particles and vertices from the electron
+        // and positron reconstructed particles.
         findVertices(electrons, positrons);
-
-        // If the list exist, put the vertexed candidates and vertices into the event
+        
+        // Store the V0 candidate particles and vertices for each type
+        // of constraint in the appropriate collection in the event,
+        // as long as a collection name is defined.
         if (unconstrainedV0CandidatesColName != null) {
-            this.printDebug("Total number of unconstrained V0 candidates: " + unconstrainedV0Candidates.size());
+            printDebug("Unconstrained V0 Candidates: " + unconstrainedV0Candidates.size());
             event.put(unconstrainedV0CandidatesColName, unconstrainedV0Candidates, ReconstructedParticle.class, 0);
         }
         if (beamConV0CandidatesColName != null) {
-            this.printDebug("Total number of beam constrained V0 candidates: " + unconstrainedV0Candidates.size());
+            printDebug("Beam-Constrained V0 Candidates: " + unconstrainedV0Candidates.size());
             event.put(beamConV0CandidatesColName, beamConV0Candidates, ReconstructedParticle.class, 0);
         }
         if (targetConV0CandidatesColName != null) {
-            this.printDebug("Total number of target constrained V0 candidates: " + unconstrainedV0Candidates.size());
+            printDebug("Target-Constrained V0 Candidates: " + unconstrainedV0Candidates.size());
             event.put(targetConV0CandidatesColName, targetConV0Candidates, ReconstructedParticle.class, 0);
         }
         if (unconstrainedV0VerticesColName != null) {
-            this.printDebug("Total number of unconstrained V0 vertices: " + unconstrainedV0Vertices.size());
+            printDebug("Unconstrained V0 Vertices: " + unconstrainedV0Vertices.size());
             event.put(unconstrainedV0VerticesColName, unconstrainedV0Vertices, Vertex.class, 0);
         }
         if (beamConV0VerticesColName != null) {
-            this.printDebug("Total number of beam constrained V0 vertices: " + beamConV0Vertices.size());
+            printDebug("Beam-Constrained V0 Vertices: " + beamConV0Vertices.size());
             event.put(beamConV0VerticesColName, beamConV0Vertices, Vertex.class, 0);
         }
         if (targetConV0VerticesColName != null) {
-            this.printDebug("Total number of target constrained V0 vertices: " + beamConV0Vertices.size());
+            printDebug("Target-Constrained V0 Vertices: " + beamConV0Vertices.size());
             event.put(targetConV0VerticesColName, targetConV0Vertices, Vertex.class, 0);
         }
     }
-
-    /**
-     *
-     */
-    abstract void findVertices(List<ReconstructedParticle> electrons, List<ReconstructedParticle> positrons);
-
-    /**
-     * make the final state particles from clusters & tracks
-     * loop over the tracks first and try to match with clusters
-     */
-    protected List<ReconstructedParticle> makeReconstructedParticles(List<Cluster> clusters, List<Track> tracks) {
-
-        // Instantiate the list of reconstructed particles
-        List<ReconstructedParticle> particles = new ArrayList<ReconstructedParticle>();
-
-        // Instantiate the list of unmatched  clusters.  Remove if we find track match
-        List<Cluster> unmatchedClusters = new ArrayList<Cluster>(clusters);
-
-        for (Track track : tracks) {
-
-            ReconstructedParticle particle = new BaseReconstructedParticle();
-            HepLorentzVector fourVector = new BasicHepLorentzVector(0, 0, 0, 0);
-
-            //
-            // Add all track information to the ReconstructedParticle
-            //
-            particle.addTrack(track);
-
-            // Set the momentum of the ReconstructedParticle
-            Hep3Vector momentum = new BasicHep3Vector(track.getTrackStates().get(0).getMomentum());
-            momentum = CoordinateTransformations.transformVectorToDetector(momentum);
-            ((BasicHepLorentzVector) fourVector).setV3(fourVector.t(), momentum);
-            // Set the charge of the ReconstructedParticle
-            ((BaseReconstructedParticle) particle).setCharge(track.getCharge() * flipSign);
-            // Set the particle ID
-            if (particle.getCharge() > 0)
-                ((BaseReconstructedParticle) particle).setParticleIdUsed(new SimpleParticleID(-11, 0, 0, 0));
-            else if (particle.getCharge() < 0)
-                ((BaseReconstructedParticle) particle).setParticleIdUsed(new SimpleParticleID(11, 0, 0, 0));
-
-            Cluster matchedCluster = null;
-            // Loop through all of the clusters and find the one that best matches
-            // the track.
-            for (Cluster cluster : unmatchedClusters) {
-
-                // Get the position of the Ecal cluster
-                Hep3Vector clusterPosition = new BasicHep3Vector(cluster.getPosition());
-
-                // Extrapolate the track to the Ecal cluster position
-                Hep3Vector trackPosAtEcal = TrackUtils.extrapolateTrack(track, clusterPosition.z());
-                this.printDebug("Ecal cluster position: " + clusterPosition.toString());
-
-                double rMax = Double.MAX_VALUE;
-
-                // Check if any of the extrapolated values are invalid.
-                // TODO: There are some track whose extrapolated coordinates
-                //        are NaN. The problem seems to be that the y-coordinate
-                //        of the extrapolated helix is found to be non-real. This
-                //        needs to be fixed.
-                if (Double.isNaN(trackPosAtEcal.x()) || Double.isNaN(trackPosAtEcal.y()))
-                    continue;
-                this.printDebug("Track position at shower max: " + trackPosAtEcal.toString());
-
-//                double r = VecOp.sub(trackPosAtEcal, clusterPosition).magnitude();
-                // Don't trust extrapolation...just do y-difference for now
-                double r = Math.abs(clusterPosition.y() - trackPosAtEcal.y());
-                this.printDebug("Distance between Ecal cluster and track position: " + r + " mm");
-
-                // Check if the Ecal cluster and track are within the same 
-                // detector volume i.e. both top or bottom
-                if (clusterPosition.y() * trackPosAtEcal.y() < 0) {
-                    this.printDebug("Track and Ecal cluster are in opposite volumes. Track Y @ ECAL = " + trackPosAtEcal.z());
-                    continue;
-                }
-
-                // TODO: Checking whether r < rMax should be occuring within isMatch.  isMatch 
-                // 		 is basically repeating a lot of the same code as above.
-                if (r < rMax && isMatch(cluster, track)) {
-                    rMax = r;
-                    matchedCluster = cluster;
-                }
-            }
-
-            if (matchedCluster != null) {
-                particle.addCluster(matchedCluster);
-                ((BasicHepLorentzVector) fourVector).setT(matchedCluster.getEnergy());
-                unmatchedClusters.remove(matchedCluster);
-            }
-            ((BaseReconstructedParticle) particle).set4Vector(fourVector);
-            particles.add(particle);
-        }
-
-        if (!unmatchedClusters.isEmpty())
-            for (Cluster unmatchedCluster : unmatchedClusters) {
-                // Create a reconstructed particle and add it to the 
-                // collection of particles
-                ReconstructedParticle particle = new BaseReconstructedParticle();
-                HepLorentzVector fourVector = new BasicHepLorentzVector(0, 0, 0, 0);
-
-                particle.addCluster(unmatchedCluster);
-                ((BasicHepLorentzVector) fourVector).setT(unmatchedCluster.getEnergy());
-                ((BaseReconstructedParticle) particle).setCharge(0);
-                ((BaseReconstructedParticle) particle).set4Vector(fourVector);
-                ((BaseReconstructedParticle) particle).setParticleIdUsed(new SimpleParticleID(22, 0, 0, 0));
-                particles.add(particle);
-            }
-
-        return particles;
-    }
-
-    /**
-     *
-     * @param debugMessage
-     */
-    protected void printDebug(String debugMessage) {
-        if (debug)
-            System.out.println(this.getClass().getSimpleName() + ": " + debugMessage);
-    }
-
-    /**
-     *
-     */
-    boolean isMatch(Cluster cluster, Track track) {
-
-        // Get the position of the Ecal cluster
+    
+    /**
+     * Sets the LCIO collection names to their default values if they
+     * are not already defined.
+     */
+    @Override
+    protected void startOfData() {
+        // If any of the LCIO collection names are not properly defined, define them now.
+        if(ecalClustersCollectionName == null) { ecalClustersCollectionName = "EcalClusters"; }
+        if(tracksCollectionName == null) { tracksCollectionName = "MatchedTracks"; }
+        if(finalStateParticlesColName == null) { finalStateParticlesColName = "FinalStateParticles"; }
+        if(unconstrainedV0CandidatesColName == null) { unconstrainedV0CandidatesColName = "UnconstrainedV0Candidates"; }
+        if(beamConV0CandidatesColName == null) { beamConV0CandidatesColName = "BeamspotConstrainedV0Candidates"; }
+        if(targetConV0CandidatesColName == null) { targetConV0CandidatesColName = "TargetConstrainedV0Candidates"; }
+        if(unconstrainedV0VerticesColName == null) { unconstrainedV0VerticesColName = "UnconstrainedV0Vertices"; }
+        if(beamConV0VerticesColName == null) { beamConV0VerticesColName = "BeamspotConstrainedV0Vertices"; }
+        if(targetConV0VerticesColName == null) { targetConV0VerticesColName = "TargetConstrainedV0Vertices"; }
+    }
+    
+    /**
+     * Determines if a cluster is a potential match for a given track.
+     * If it is, returns the distance between the extrapolation of the
+     * track to the z-position of the cluster and the cluster position.
+     * Otherwise, returns <code>null</code> to indicate that the pair
+     * is not a valid match.
+     * @param cluster - The cluster to check.
+     * @param track - The track to check.
+     * @return Returns the distance between the cluster and extrapolated
+     * track position in millimeters as a <code>Double</code> if the
+     * pair is a potential match. Returns <code>null</code> otherwise.
+     */
+    private boolean isMatch(Cluster cluster, Track track) {
+        // Get the position of the cluster and extrapolate the position
+        // of the track at the z-position of the cluster.
         Hep3Vector clusterPosition = new BasicHep3Vector(cluster.getPosition());
-
-        // Extrapolate the track to the Ecal cluster position
         Hep3Vector trackPosAtEcal = TrackUtils.extrapolateTrack(track, clusterPosition.z());
-
-        double dxCut = 20.0;
-        double dyCut = 20.0;
-
-        if (Math.abs(trackPosAtEcal.x() - clusterPosition.x()) > dxCut)
+        
+        // TODO: There are some track whose extrapolated coordinates
+        //       are NaN. The problem seems to be that the y-coordinate
+        //       of the extrapolated helix is found to be non-real. This
+        //       needs to be fixed.
+        // There is an issue with track extrapolation that sometimes
+        // yields NaN for extrapolated track parameters. Tracks with
+        // this issue are not usable and thusly the check should be
+        // skipped.
+        if (Double.isNaN(trackPosAtEcal.x()) || Double.isNaN(trackPosAtEcal.y())) {
+            // VERBOSE :: Indicate the reason for the match failing.
+            printDebug("\tFailure :: Track extrapolation error.");
+
+            // Return false to indicate that the pair do not match.
             return false;
-
-        if (Math.abs(trackPosAtEcal.y() - clusterPosition.y()) > dyCut)
+        }
+        
+        // VERBOSE :: Output the position of the extrapolated track
+        //            and the cluster.
+        printDebug("\tCluster Position :: " + clusterPosition.toString());
+        printDebug("\tTrack Position   :: " + trackPosAtEcal.toString());
+        
+        // If one of either the cluster or extrapolated track fall on
+        // one volume of the detector and the other is in the other
+        // volume, then they can not be a match. (i.e. both parts of
+        // the pair must be on the top or bottom of the detector.)
+        if (clusterPosition.y() * trackPosAtEcal.y() < 0) {
+            // VERBOSE :: Indicate the reason for the match failing.
+            printDebug("\tFailure :: Cluster/Track pair in opposite volumes.");
+
+            // Return false to indicate that the pair do not match.
             return false;
-
+        }
+        
+        // Check to make sure that the x and y displacements between
+        // the extrapolated track position and cluster position are
+        // within the allowed bounds. If they are not, this pair is
+        // not a match.
+        if (Math.abs(trackPosAtEcal.x() - clusterPosition.x()) > dxCut) {
+            // VERBOSE :: Indicate the reason for the match failing.
+            printDebug("\tFailure :: Pair x-displacement exceeds allowed threshold.");
+
+            // Return false to indicate that the pair do not match.
+            return false;
+        }
+        
+        if (Math.abs(trackPosAtEcal.y() - clusterPosition.y()) > dyCut) {
+            // VERBOSE :: Indicate the reason for the match failing.
+            printDebug("\tFailure :: Pair y-displacement exceeds allowed threshold.");
+            
+            // Return false to indicate that the pair do not match.
+            return false;
+        }
+        
+        // VERBOSE :: Indicate the reason for the match failing.
+        printDebug("\tSuccess :: Cluster/track pair match!.");
+        
+        // A pair that has reached this point is a potential match.
+        // Return true to indicate a match.
         return true;
     }
+    
+    // ==============================================================
+    // ==== Class Variables =========================================
+    // ==============================================================
+    // Local variables.
+    /** The maximum separation distance in the x-direction beyond which
+     * a cluster and track will be rejected for pairing. */
+    private double dxCut = 20.0;
+    /** The maximum separation distance in the y-direction beyond which
+     * a cluster and track will be rejected for pairing. */
+    private double dyCut = 20.0;
+    /** Indicates whether debug text should be output or not. */
+    private boolean debug = false;
+    /** The simple name of the class used for debug print statements. */
+    private final String simpleName = getClass().getSimpleName();
+    
+    // Reconstructed Particle Lists
+    /** Stores reconstructed electron particles. */
+    private List<ReconstructedParticle> electrons;
+    /** Stores reconstructed positron particles. */
+    private List<ReconstructedParticle> positrons;
+    /** Stores particles reconstructed from an event. */
+    protected List<ReconstructedParticle> finalStateParticles;
+    /** Stores reconstructed V0 candidate particles generated without constraints. */
+    protected List<ReconstructedParticle> unconstrainedV0Candidates;
+    /** Stores reconstructed V0 candidate particles generated with beam spot constraints. */
+    protected List<ReconstructedParticle> beamConV0Candidates;
+    /** Stores reconstructed V0 candidate particles generated with target constraints. */
+    protected List<ReconstructedParticle> targetConV0Candidates;
+    /** Stores reconstructed V0 candidate vertices generated without constraints. */
+    protected List<Vertex> unconstrainedV0Vertices;
+    /** Stores reconstructed V0 candidate vertices generated with beam spot constraints. */
+    protected List<Vertex> beamConV0Vertices;
+    /** Stores reconstructed V0 candidate vertices generated with target constraints. */
+    protected List<Vertex> targetConV0Vertices;
+    
+    // LCIO Collection Names
+    /** LCIO collection name for calorimeter clusters. */
+    private String ecalClustersCollectionName = "EcalClusters";
+    /** LCIO collection name for tracks. */
+    private String tracksCollectionName = "MatchedTracks";
+    /** LCIO collection name for reconstructed particles. */
+    private String finalStateParticlesColName = "FinalStateParticles";
+    /** LCIO collection name for V0 candidate particles generated without constraints. */
+    protected String unconstrainedV0CandidatesColName = null;
+    /** LCIO collection name for V0 candidate particles generated with beam spot constraints. */
+    protected String beamConV0CandidatesColName = null;
+    /** LCIO collection name for V0 candidate particles generated with target constraints. */
+    protected String targetConV0CandidatesColName = null;
+    /** LCIO collection name for V0 candidate vertices generated without constraints. */
+    protected String unconstrainedV0VerticesColName = null;
+    /** LCIO collection name for V0 candidate vertices generated with beam spot constraints. */
+    protected String beamConV0VerticesColName = null;
+    /** LCIO collection name for V0 candidate vertices generated with target constraints. */
+    protected String targetConV0VerticesColName = null;
+    
+    // Beam size variables.
+    // The beamsize array is in the tracking frame
+    /* TODO  mg-May 14, 2014:  the the beam size from the conditions db...also beam position!  */
+    protected double[] beamSize = {0.001, 0.2, 0.02};
+    protected double bField;
+    
+    //  flipSign is a kludge...
+    //  HelicalTrackFitter doesn't deal with B-fields in -ive Z correctly
+    //  so we set the B-field in +iveZ and flip signs of fitted tracks
+    //  
+    //  Note:  This should be -1 for test run configurations and +1 for 
+    //         prop-2014 configurations 
+    private int flipSign = 1;
 }

Modified: java/trunk/recon/src/main/java/org/hps/recon/particle/TestRunReconParticleDriver.java
 =============================================================================
--- java/trunk/recon/src/main/java/org/hps/recon/particle/TestRunReconParticleDriver.java	(original)
+++ java/trunk/recon/src/main/java/org/hps/recon/particle/TestRunReconParticleDriver.java	Wed Oct 29 21:25:20 2014
@@ -10,41 +10,59 @@
 import org.hps.recon.vertexing.TwoTrackVertexer;
 
 /**
+ * Method creates reconstructed particles from tracks and clusters for
+ * test run data. Also generates candidate A' reconstructed particles.
+ * This method does not generate a separate vertex collection.
  * 
  * @author Omar Moreno <[log in to unmask]>
  * @version $Id$
  */
 public class TestRunReconParticleDriver extends ReconParticleDriver {
-
-	public TestRunReconParticleDriver(){}; 
-	
-	@Override
-	protected void startOfData(){
-		unconstrainedV0CandidatesColName = "V0Candidates";
-	}
-	
-	@Override
-	void findVertices(List<ReconstructedParticle> electrons, List<ReconstructedParticle> positrons) {
-		
-		TwoTrackVertexer vtxFitter = new TwoTrackVertexer(); 
-	
-		// Loop through both electrons and positrons and try to vertex them
-		for(ReconstructedParticle positron : positrons){
-			for(ReconstructedParticle electron : electrons){
-				
-				// Get the tracks associated with the electrons and positrons
-				Track electronTrack = electron.getTracks().get(0); 
-				Track positronTrack = positron.getTracks().get(0); 
-				vtxFitter.setTracks(electronTrack, positronTrack);
-				vtxFitter.fitVertex();
-				Vertex vertex = vtxFitter.getFittedVertex();
-				
-				ReconstructedParticle candidate = new BaseReconstructedParticle(); 
-				((BaseReconstructedParticle) candidate).setStartVertex(vertex);
-				candidate.addParticle(electron);
-				candidate.addParticle(positron);
-				unconstrainedV0Candidates.add(candidate); 
-			}
-		}
-	}
+    /**
+     * Generates reconstructed V0 candidate particles from electron
+     * and positron pairs.
+     * @param electrons - The list of electrons.
+     * @param positrons - The list of positrons.
+     */
+    @Override
+    protected void findVertices(List<ReconstructedParticle> electrons, List<ReconstructedParticle> positrons) {
+        // Create a vertex fitter.
+        TwoTrackVertexer vtxFitter = new TwoTrackVertexer();
+        
+        // Iterate over the electrons and positrons and try to generate
+        // an A' candidate from them.
+        for(ReconstructedParticle positron : positrons){
+            for(ReconstructedParticle electron : electrons){
+                // Get the electron and positron tracks.
+                Track electronTrack = electron.getTracks().get(0);
+                Track positronTrack = positron.getTracks().get(0);
+                
+                // Feed the tracks to the vertex fitter.
+                vtxFitter.setTracks(electronTrack, positronTrack);
+                vtxFitter.fitVertex();
+                
+                // Get the reconstructed vertex.
+                Vertex vertex = vtxFitter.getFittedVertex();
+                
+                // Create a reconstructed particle for the candidate
+                // particle generated from the electron/positron pair.
+                ReconstructedParticle candidate = new BaseReconstructedParticle(); 
+                ((BaseReconstructedParticle) candidate).setStartVertex(vertex);
+                candidate.addParticle(electron);
+                candidate.addParticle(positron);
+                
+                // Add the candidate particle to list.
+                unconstrainedV0Candidates.add(candidate); 
+            }
+        }
+    }
+    
+    /**
+     * Sets the unconstrained A' candidate particle collection name if
+     * it has not already been defined.
+     */
+    @Override
+    protected void startOfData(){
+        if(unconstrainedV0CandidatesColName == null) { unconstrainedV0CandidatesColName = "V0Candidates"; }
+    }
 }