Commit in lcsim/src/org/lcsim/contrib/uiowa/template on MAIN
NonTrivialPFA.java+227-931.6 -> 1.7
Snapshot update

lcsim/src/org/lcsim/contrib/uiowa/template
NonTrivialPFA.java 1.6 -> 1.7
diff -u -r1.6 -r1.7
--- NonTrivialPFA.java	18 Jul 2006 00:45:05 -0000	1.6
+++ NonTrivialPFA.java	18 Aug 2006 00:13:55 -0000	1.7
@@ -4,6 +4,7 @@
 import hep.physics.vec.*;
 
 import org.lcsim.util.*;
+import org.lcsim.util.decision.*;
 import org.lcsim.util.hitmap.*;
 import org.lcsim.event.*;
 import org.lcsim.event.util.*;
@@ -20,7 +21,10 @@
 import org.lcsim.mc.fast.tracking.MCFastTracking;
 import org.lcsim.recon.pfa.identifier.SimpleNeutralParticleMaker;
 import org.lcsim.recon.pfa.identifier.SimpleChargedParticleMaker;
-//import org.lcsim.recon.pfa.identifier.DebugChargedParticleMaker;
+import org.lcsim.recon.pfa.identifier.MIPChargedParticleMaker;
+import org.lcsim.recon.pfa.identifier.SimpleTrackClusterMatcher;
+import org.lcsim.recon.pfa.identifier.SimpleTrackMIPClusterMatcher;
+import org.lcsim.recon.pfa.identifier.TrackClusterMatcher;
 import org.lcsim.recon.cluster.util.BothCalorimetersDecision;
 import org.lcsim.recon.cluster.util.ClusterListFilterDriver;
 import org.lcsim.recon.cluster.util.VetoClustersFromParticles;
@@ -32,6 +36,7 @@
 import org.lcsim.util.decision.ParticlePDGDecision;
 import org.lcsim.recon.cluster.cheat.PerfectClusterer;
 import org.lcsim.recon.cluster.structural.ChargedNeutralFragmentSeparator;
+import org.lcsim.recon.cluster.util.ClusterFirstLayerDecision;
 
 import org.lcsim.util.aida.AIDA;
 
@@ -45,6 +50,7 @@
 	// Book-keeping
 	HitBookKeeper accountant = new HitBookKeeper();
 	accountant.setDebug(false);
+	//accountant.setDebug(true);
 
 	// Set up the MC list
 	//
@@ -68,52 +74,149 @@
 	add( new SimCalorimeterHitsDriver() );
 
 	// Step 1: Set up input hit lists:
-	HitListToHitMapDriver hitmapEcal = new HitListToHitMapDriver();
-	hitmapEcal.addInputList("EcalBarrDigiHits");
-	hitmapEcal.addInputList("EcalEndcapDigiHits");
-	hitmapEcal.setOutput("input hit map ecal");
-	HitListToHitMapDriver hitmapHcal = new HitListToHitMapDriver();
-	hitmapHcal.addInputList("HcalBarrDigiHits");
-	hitmapHcal.addInputList("HcalEndcapDigiHits");
-	hitmapHcal.setOutput("input hit map hcal");
-	add(hitmapEcal);
-	add(hitmapHcal);
+	{
+	    HitListToHitMapDriver hitmapEcal = new HitListToHitMapDriver();
+	    hitmapEcal.addInputList("EcalBarrDigiHits");
+	    hitmapEcal.addInputList("EcalEndcapDigiHits");
+	    hitmapEcal.setOutput("input hit map ecal");
+	    HitListToHitMapDriver hitmapHcal = new HitListToHitMapDriver();
+	    hitmapHcal.addInputList("HcalBarrDigiHits");
+	    hitmapHcal.addInputList("HcalEndcapDigiHits");
+	    hitmapHcal.setOutput("input hit map hcal");
+	    add(hitmapEcal);
+	    add(hitmapHcal);
+	}
 	accountant.addListOfNamedLists( new String[] { "input hit map ecal", "input hit map hcal" } );
 
 	// Find tracks
-	// Output: List<Track> saved as EventHeader.TRACKS
+	// Non-cheating: Output: List<Track> saved as EventHeader.TRACKS
 	add (new MCFastTracking());
+	// Cheating: Output: CombinedTracks (type CheatTrack)
+	org.lcsim.recon.ztracking.cheater.TrackingCheater trackCheater = new org.lcsim.recon.ztracking.cheater.TrackingCheater();
+	trackCheater.setUseFinalStateParticles(true);
+	add(trackCheater);
+
+	String nonCheatingTrackList = EventHeader.TRACKS;
+	String cheatingTrackList = new String("CombinedTracks");
+	//String trackList = nonCheatingTrackList;
+	String trackList = cheatingTrackList;
+
+
+	// Finding photons and MIPs needs to be done carefully, since
+	// many photons look like MIPs and vice-versa.
+	// For now we do it in chunks.
+	
+	// Find MIP candidates in ECAL, starting near the front:
+	{
+	    TrackClusterDriver ecalFrontSideMIPs = new TrackClusterDriver("input hit map ecal", "front-side mips ecal", "hit map ecal without front-side mips");
+	    ecalFrontSideMIPs.filterOutputClusters(new ClusterFirstLayerDecision(4));
+	    add(ecalFrontSideMIPs);
+	}
+
+	// Check if they match a track (ugly... don't need to make the particles!)
+	{
+	    MIPChargedParticleMaker mipHadID = new MIPChargedParticleMaker();
+	    SimpleTrackMIPClusterMatcher mipMatch = new SimpleTrackMIPClusterMatcher();
+	    add(mipMatch);
+	    mipHadID.setTrackMatcher(mipMatch);
+	    mipHadID.setInputTrackList(trackList);
+	    mipHadID.setOutputTrackList("tracks left over from front-side mips");
+	    mipHadID.setInputMIPList("front-side mips ecal");
+	    mipHadID.setOutputMIPList("mips minus front-side mips ecal");
+	    mipHadID.setOutputParticleList("front-side mip particles");
+	    add(mipHadID);
+	}
+
+	// Isolate the genuine (charged) MIPs from the rest
+	{
+	    ClusterListFilterDriver filterRemoveChargedMIPs = new ClusterListFilterDriver();
+	    ClusterListFilterDriver filterSelectChargedMIPs = new ClusterListFilterDriver();
+	    VetoClustersFromParticles vetoChargedMIPs = new VetoClustersFromParticles("front-side mip particles"); // veto MIPs
+	    DecisionMakerSingle<Cluster> selectChargedMIPs = new NotDecisionMakerSingle<Cluster> (vetoChargedMIPs); // invert veto to select MIPs
+	    filterRemoveChargedMIPs.setInputDecision(vetoChargedMIPs);
+	    filterSelectChargedMIPs.setInputDecision(selectChargedMIPs);
+	    filterRemoveChargedMIPs.setInputList("front-side mips ecal");
+	    filterSelectChargedMIPs.setInputList("front-side mips ecal");
+	    filterRemoveChargedMIPs.setOutputList("neutral front-side mips ecal");
+	    filterSelectChargedMIPs.setOutputList("charged front-side mips ecal");
+	    add(vetoChargedMIPs);
+	    add(filterRemoveChargedMIPs);
+	    add(filterSelectChargedMIPs);
+	}
+	// Merge the non-charged "MIP" hits back in
+	{
+	    ClusterListToHitMapDriver convertFakeMIPsToHitMap = new ClusterListToHitMapDriver("neutral front-side mips ecal", "hit map ecal of neutral front-side mips");
+	    add(convertFakeMIPsToHitMap);
+	    HitMapAddDriver addFakeMIPHitsBack = new HitMapAddDriver();
+	    addFakeMIPHitsBack.addInputHitMap("hit map ecal of neutral front-side mips");
+	    addFakeMIPHitsBack.addInputHitMap("hit map ecal without front-side mips");
+	    addFakeMIPHitsBack.setOutputHitMap("hit map ecal without charged front-side mips");
+	    add(addFakeMIPHitsBack);
+	}
+	
+	// Find photons
+	{
+	    MSTPhotonFinderDriver photonFinder = new MSTPhotonFinderDriver();
+	    photonFinder.setCoreThreshold(7.5);
+	    photonFinder.setFragmentThreshold(7.5);
+	    photonFinder.setLayerProximityThreshold(2);
+	    photonFinder.setCoreSizeMinimum(10);
+	    photonFinder.setFragmentSizeMaximum(6);
+	    photonFinder.setInputHitMap("hit map ecal without charged front-side mips");
+	    photonFinder.setOutputHitMap("hit map ecal without photons or charged front-side mips");
+	    photonFinder.setOutputClusterList("photon clusters");
+	    //photonFinder.setDebug(true);
+	    add(photonFinder);
+	}
 
+	// Merge the charged MIP hits back in
+	{
+	    ClusterListToHitMapDriver convertRealMIPsToHitMap = new ClusterListToHitMapDriver("charged front-side mips ecal", "hit map ecal of charged front-side mips");
+	    add(convertRealMIPsToHitMap);
+	    HitMapAddDriver addRealMIPHitsBack = new HitMapAddDriver();
+	    addRealMIPHitsBack.addInputHitMap("hit map ecal of charged front-side mips");
+	    addRealMIPHitsBack.addInputHitMap("hit map ecal without photons or charged front-side mips");
+	    addRealMIPHitsBack.setOutputHitMap("hit map ecal without photons");
+	    add(addRealMIPHitsBack);
+	}
+	
 	// Find track segments in ECAL and HCAL
-	TrackClusterDriver ecalMIP = new TrackClusterDriver("input hit map ecal", "mips ecal", "hit map ecal without mips");
-	TrackClusterDriver hcalMIP = new TrackClusterDriver("input hit map hcal", "mips hcal", "hit map hcal without mips");
-	add(ecalMIP);
-	add(hcalMIP);
+	{
+	    TrackClusterDriver ecalMIP = new TrackClusterDriver("hit map ecal without photons", "mips ecal", "hit map ecal without mips or photons");
+	    TrackClusterDriver hcalMIP = new TrackClusterDriver("input hit map hcal", "mips hcal", "hit map hcal without mips");
+	    add(ecalMIP);
+	    add(hcalMIP);
+	}
         // Merge the two lists:
-	ListAddDriver<Cluster> mergeMIPs = new ListAddDriver<Cluster>();
-        mergeMIPs.addInputList("mips ecal");
-        mergeMIPs.addInputList("mips hcal");
-        mergeMIPs.setOutputList("mips");
-	add(mergeMIPs);
-	accountant.addListOfNamedLists( new String[] { "hit map ecal without mips", "hit map hcal without mips", "mips ecal", "mips hcal" } );
-	accountant.addListOfNamedLists( new String[] { "hit map ecal without mips", "hit map hcal without mips", "mips" } );
-
-	// Find photons in the ECAL (cheat for now)
-	add(new ListFilterDriver(new ParticlePDGDecision(22), mcListName, "MCParticles photons only"));
-	PerfectClusterer myCheatPhotonFinder = new PerfectClusterer();
-	myCheatPhotonFinder.setInputHitMap("hit map ecal without mips");
-	myCheatPhotonFinder.setOutputHitMap("hit map ecal without mips or photons");
-	myCheatPhotonFinder.setOutputClusterList("photon clusters");
-	myCheatPhotonFinder.setMCParticleList("MCParticles photons only");
-	myCheatPhotonFinder.allowHitSharing(false);
-	add(myCheatPhotonFinder);
-	accountant.addListOfNamedLists( new String[] { "hit map ecal without mips or photons", "hit map hcal without mips", "mips ecal", "mips hcal", "photon clusters" } );
-	// ID them
-	SimpleNeutralParticleMaker myPhotonIdentifier = new SimpleNeutralParticleMaker(22); // 22 = photon
-	myPhotonIdentifier.setInputClusterList("photon clusters");
-	myPhotonIdentifier.setOutputParticleList("photon particles");
-	add(myPhotonIdentifier);
-	accountant.addListOfNamedLists( new String[] { "hit map ecal without mips or photons", "hit map hcal without mips", "mips ecal", "mips hcal", "photon particles" } );
+	{
+	    ListAddDriver<Cluster> mergeMIPs = new ListAddDriver<Cluster>();
+	    mergeMIPs.addInputList("mips ecal");
+	    mergeMIPs.addInputList("mips hcal");
+	    mergeMIPs.setOutputList("mips");
+	    add(mergeMIPs);
+	    accountant.addListOfNamedLists( new String[] { "hit map ecal without mips or photons", "hit map hcal without mips", "mips ecal", "mips hcal", "photon clusters" } );
+	    accountant.addListOfNamedLists( new String[] { "hit map ecal without mips or photons", "hit map hcal without mips", "mips", "photon clusters" } );
+	}
+
+	//// Find photons in the ECAL (cheat for now)
+	//add(new ListFilterDriver(new ParticlePDGDecision(22), mcListName, "MCParticles photons only"));
+	//PerfectClusterer myCheatPhotonFinder = new PerfectClusterer();
+	//myCheatPhotonFinder.setInputHitMap("hit map ecal without mips");
+	//myCheatPhotonFinder.setOutputHitMap("hit map ecal without mips or photons");
+	//myCheatPhotonFinder.setOutputClusterList("photon clusters");
+	//myCheatPhotonFinder.setMCParticleList("MCParticles photons only");
+	//myCheatPhotonFinder.allowHitSharing(false);
+	//add(myCheatPhotonFinder);
+	//accountant.addListOfNamedLists( new String[] { "hit map ecal without mips or photons", "hit map hcal without mips", "mips ecal", "mips hcal", "photon clusters" } );
+
+	// ID photons
+	{
+	    SimpleNeutralParticleMaker myPhotonIdentifier = new SimpleNeutralParticleMaker(22); // 22 = photon
+	    myPhotonIdentifier.setInputClusterList("photon clusters");
+	    myPhotonIdentifier.setOutputParticleList("photon particles");
+	    add(myPhotonIdentifier);
+	    accountant.addListOfNamedLists( new String[] { "hit map ecal without mips or photons", "hit map hcal without mips", "mips ecal", "mips hcal", "photon particles" } );
+	}
 
 	// Find clumps in ECAL and HCAL
 	// Clumps are defined as contiguous sets of
@@ -201,6 +304,7 @@
 	    Driver checkpoint = new LikelihoodEvaluatorCheckpointDriver(eval, 10);
 	    add(checkpoint);
 	} else {
+
 	    // Step 6a: Structural algorithm
 	    // Inputs from event:
 	    //   * Big (MST) clusters
@@ -255,64 +359,62 @@
 	    accountant.addListOfNamedLists( new String[] { "ecal hit map after mst", "hcal hit map after mst", "skeletons plus halo", "structural unused hits minus halo", "mst clusters linked (<10 hits)", "photon particles" } );
 
 	    // Step 6c: Extrapolate tracks to ECAL surface, form charged particles
-	    // Inputs:
-	    //   * The tracks (which we'll extrapolate)
-	    //   * The MIPs (which are our best chance of a good association)
-	    //   * The fleshed-out skeletons (to match the tracks to -- or to their MIP components -- and form particles)
-	    // Outputs:
-	    //   * Any unused tracks
-	    //   * The reconstructed particles
-	    SimpleChargedParticleMaker hadID = new SimpleChargedParticleMaker();
-	    hadID.setInputTrackList(EventHeader.TRACKS);
-	    hadID.setOutputTrackList("leftover tracks");
-	    hadID.setInputMIPList("mips");
-	    hadID.setInputClusterList("skeletons plus halo");
-	    hadID.setOutputParticleList("charged hadron particles");
-	    hadID.setDebug(false);
-	    add(hadID);
+
+	    // First try the MIPs...
+	    {
+		MIPChargedParticleMaker hadIDmip = new MIPChargedParticleMaker();
+		SimpleTrackMIPClusterMatcher mipMatch = new SimpleTrackMIPClusterMatcher();
+		add(mipMatch);
+		hadIDmip.setTrackMatcher(mipMatch);
+		hadIDmip.setInputTrackList(trackList);
+		hadIDmip.setOutputTrackList("tracks minus mip associations");
+		hadIDmip.setInputMIPList("mips");
+		hadIDmip.setOutputParticleList("charged hadron particles with mip association");
+		hadIDmip.setOutputMIPList("unmatched mips");
+		hadIDmip.addClusterList("skeletons plus halo", "skeletons plus halo minus charged particles from mips");
+		hadIDmip.addClusterList("mst clusters linked (<10 hits)", "mst clusters linked (<10 hits) minus charged particles from mips");
+		add(hadIDmip);
+	    }
+
+	    // Then try the clusters generically:
+	    {
+		SimpleChargedParticleMaker hadID = new SimpleChargedParticleMaker();
+		SimpleTrackClusterMatcher clusMatch = new SimpleTrackClusterMatcher();
+		add(clusMatch);
+		hadID.setTrackMatcher(clusMatch);
+		hadID.setInputTrackList("tracks minus mip associations");
+		hadID.setOutputTrackList("leftover tracks");
+		hadID.setInputClusterList("skeletons plus halo minus charged particles from mips");
+		hadID.setOutputParticleList("charged hadron particles with non-mip association");
+		add(hadID);
+	    }
+
+	    // Merge the two particle lists:
+	    {
+		ListAddDriver<ReconstructedParticle> mergeParticles = new ListAddDriver<ReconstructedParticle>();
+		mergeParticles.addInputList("charged hadron particles with mip association");
+		mergeParticles.addInputList("charged hadron particles with non-mip association");
+		mergeParticles.setOutputList("charged hadron particles");
+		add(mergeParticles);
+	    }
 
 	    // Step 6d: Handle fragments
-	    // Here are the fragment/small neutrals we've accumulated:
-	    //    * Small clusters ("mst clusters linked (<10 hits)")
-	    //    * Unassigned structural hits, if any ("structural unused hits minus halo")
-	    // Convert the individual hits into clusters:
-	    add(new HitMapToClusterListDriver("structural unused hits minus halo", "structural unused hits minus halo (clusters)"));
-	    // Merge fragments into a single cluster list:
-	    ListAddDriver combineFragmentClusters = new ListAddDriver();
-	    combineFragmentClusters.addInputList("mst clusters linked (<10 hits)");
-	    combineFragmentClusters.addInputList("structural unused hits minus halo (clusters)");
-	    combineFragmentClusters.setOutputList("small clusters");
-	    add(combineFragmentClusters);
-
-	    // Test: Try to figure out which are charged and which are neutral
-	    ChargedNeutralFragmentSeparator testCharged = new ChargedNeutralFragmentSeparator(EventHeader.TRACKS);
-	    testCharged.initPlots();
-	    add(testCharged);
-	    add(new ClusterListFilterDriver(testCharged, "small clusters", "charged small clusters"));
-
-	    // FragmentHandler
-	    // Inputs:
-	    //    * Charged particles ("charged hadron particles")
-	    //    * Skeleton clusters ("skeletons plus halo")
-	    //    * Small clusters    ("small clusters")
-	    // Outputs:
-	    //    * Particles (one per merged cluster)
-	    //    * Clusters after merging in fragments ("merged clusters");
-	    //    * Any remaining unassigned hits("leftover hits after fragment merge")
+
 	    org.lcsim.recon.cluster.structural.FragmentHandler fragMergeDriver = new org.lcsim.recon.cluster.structural.FragmentHandler();
 	    fragMergeDriver.addInputClusterList("skeletons plus halo");
-	    fragMergeDriver.addInputClusterList("small clusters");
+	    fragMergeDriver.addInputClusterList("mst clusters linked (<10 hits)");
 	    fragMergeDriver.setOutputClusterList("clusters with fragments merged");
 	    fragMergeDriver.setOutputHitMap("hits left over after fragment merge");
 	    org.lcsim.recon.cluster.structural.SimpleFragmentIdentifier fragID = new org.lcsim.recon.cluster.structural.SimpleFragmentIdentifier(10, 100.0);
 	    fragID.addParticleList("charged hadron particles");
 	    fragMergeDriver.setFragmentIdentifier(fragID); // don't cheat
 	    accountant.addListOfNamedLists( new String[] { "ecal hit map after mst", "hcal hit map after mst", "clusters with fragments merged", "hits left over after fragment merge", "photon particles" } );
+
 	    // What if we want to cheat? Set it up...
 	    {
 		// Here are our cluster lists:
-		//   "skeletons plus halo"
-		//   "mst clusters linked (<10 hits)"
+		//   "skeletons plus halo plus orphan mips"
+		//   "mst clusters linked (<10 hits) minus orphan mips"
 		// Here is the MC list:
 		//   "GenFinalStateParticles" [or sim]
 		// Here are the output lists:
@@ -330,24 +432,56 @@
 		org.lcsim.recon.cluster.structural.CheatFragmentIdentifier cheatFragID = new org.lcsim.recon.cluster.structural.CheatFragmentIdentifier(hitListNames, clusterListNames, mcListName, "CheatFragmentIdentifier info P->C", "CheatFragmentIdentifier info C->P");
 		fragMergeDriver.setFragmentIdentifier(cheatFragID); // cheat
 	    }
+
 	    org.lcsim.recon.cluster.structural.SimpleFragmentMerger fragMerge = new org.lcsim.recon.cluster.structural.SimpleFragmentMerger();
 	    fragMergeDriver.setFragmentMerger(fragMerge); // don't cheat
 	    org.lcsim.recon.cluster.structural.CheatFragmentMerger cheatFragMerge = new org.lcsim.recon.cluster.structural.CheatFragmentMerger();
 	    cheatFragMerge.initializeAssociator("TmpHitList", "TmpClusterList", mcListName, "TmpMCCList", "TmpCMCList");
 	    add(cheatFragMerge);
-	    fragMergeDriver.setFragmentMerger(cheatFragMerge); // cheat
+	    //fragMergeDriver.setFragmentMerger(cheatFragMerge); // cheat [broken?]
 	    add(fragMergeDriver);
 
 	    accountant.addListOfNamedLists( new String[] { "ecal hit map after mst", "hcal hit map after mst", "clusters with fragments merged", "hits left over after fragment merge", "photon particles" } );
 
 	    // Repeat the hadron ID step with the revised cluster list:
-	    SimpleChargedParticleMaker hadID2 = new SimpleChargedParticleMaker();
-	    hadID2.setInputTrackList(EventHeader.TRACKS);
-	    hadID2.setOutputTrackList("leftover tracks 2");
-	    hadID2.setInputMIPList("mips");
-	    hadID2.setInputClusterList("clusters with fragments merged");
-	    hadID2.setOutputParticleList("charged hadron particles 2");
-	    add(hadID2);
+
+	    // First try the MIPs...
+	    {
+		MIPChargedParticleMaker hadIDmip2 = new MIPChargedParticleMaker();
+		SimpleTrackMIPClusterMatcher mipMatch = new SimpleTrackMIPClusterMatcher();
+		add(mipMatch);
+		hadIDmip2.setTrackMatcher(mipMatch);
+		hadIDmip2.setInputTrackList(trackList);
+		hadIDmip2.setOutputTrackList("tracks minus mip associations 2");
+		hadIDmip2.setInputMIPList("mips");
+		hadIDmip2.setOutputParticleList("charged hadron particles with mip association 2");
+		hadIDmip2.setOutputMIPList("unmatched mips 2");
+		hadIDmip2.addClusterList("clusters with fragments merged", "clusters with fragments merged minus charged particles from mips");
+		add(hadIDmip2);
+	    }
+
+	    // Then try the clusters generically:
+	    {
+		SimpleChargedParticleMaker hadID2 = new SimpleChargedParticleMaker();
+		SimpleTrackClusterMatcher clusMatch = new SimpleTrackClusterMatcher();
+		add(clusMatch);
+		hadID2.setTrackMatcher(clusMatch);
+		hadID2.setInputTrackList("tracks minus mip associations 2");
+		hadID2.setOutputTrackList("leftover tracks 2");
+		hadID2.setInputClusterList("clusters with fragments merged minus charged particles from mips");
+		hadID2.setOutputParticleList("charged hadron particles with non-mip association 2");
+		add(hadID2);
+	    }
+
+	    // Merge the two particle lists:
+	    {
+		ListAddDriver<ReconstructedParticle> mergeParticles = new ListAddDriver<ReconstructedParticle>();
+		mergeParticles.addInputList("charged hadron particles with mip association 2");
+		mergeParticles.addInputList("charged hadron particles with non-mip association 2");
+		mergeParticles.setOutputList("charged hadron particles 2");
+		add(mergeParticles);
+	    }
+
 	    // ... and then any remaining clusters should be neutral
 	    ClusterListFilterDriver removeChargedClusters = new ClusterListFilterDriver();
 	    VetoClustersFromParticles vetoCharged = new VetoClustersFromParticles("charged hadron particles 2");
CVSspam 0.2.8