Commit in lcsim/src/org/lcsim/contrib/uiowa on MAIN
ReclusterDTreeDriver.java+93-51.4 -> 1.5
MJC: Reclusterer Mk II: Add final pass (over-rides for E/p); turn off a lot of debug by default.

lcsim/src/org/lcsim/contrib/uiowa
ReclusterDTreeDriver.java 1.4 -> 1.5
diff -u -r1.4 -r1.5
--- ReclusterDTreeDriver.java	19 Dec 2007 22:44:47 -0000	1.4
+++ ReclusterDTreeDriver.java	20 Dec 2007 04:07:05 -0000	1.5
@@ -32,7 +32,7 @@
 	m_dTreeClusterListName = dTreeClusterList;
 	m_inputTrackList = trackList;
 	m_mcList = mcList;
-	m_debugEoverP = true;
+	m_debugEoverP = false;
 	m_eval = new LikelihoodEvaluatorWrapper();
 	m_outputParticleListName = "DTreeReclusteredParticles";
     }
@@ -129,7 +129,9 @@
 	treeOfComponent.putAll(treeOfClump);
 	treeOfComponent.putAll(treeOfLeftoverHits);
 
-	System.out.println("Found "+mips.size()+" mips, "+clumps.size()+" clumps, "+photons.size()+" photons, "+leftoverHitClusters.size()+" leftover-hit-clusters, "+treesWithNoStructure.size()+" large DTrees with no structure, and "+trackList.size()+" tracks in event.");
+	if (m_debug) {
+	    System.out.println("Found "+mips.size()+" mips, "+clumps.size()+" clumps, "+photons.size()+" photons, "+leftoverHitClusters.size()+" leftover-hit-clusters, "+treesWithNoStructure.size()+" large DTrees with no structure, and "+trackList.size()+" tracks in event.");
+	}
 
 	// Match tracks
 	List<Cluster> allMatchableClusters = new Vector<Cluster>();
@@ -141,7 +143,7 @@
 	if (allMatchableClusters.contains(null)) { throw new AssertionError("Book-keeping error: null cluster in list allMatchableClusters"); }
 	Map<Track,Cluster> tracksMatchedToClusters = new HashMap<Track,Cluster>();
 	Map<Cluster, List<Track>> clustersMatchedToTracks = new HashMap<Cluster, List<Track>>();
-	System.out.println("Attempting to match "+allMatchableClusters.size()+" matchable clusters to "+trackList.size()+" tracks");
+	if (m_debug) { System.out.println("Attempting to match "+allMatchableClusters.size()+" matchable clusters to "+trackList.size()+" tracks"); }
 	for (Track tr : trackList) {
 	    Cluster matchedCluster = m_trackClusterMatcher.matchTrackToCluster(tr, allMatchableClusters);
 	    if (matchedCluster != null) {
@@ -385,8 +387,94 @@
 	    }
 	}
 
-	List<Cluster> tmp = new Vector<Cluster>();
-	printStatus("FINAL STATUS:", tracksSortedByMomentum, allSharedClusters, newMapTrackToShowerComponents, newMapShowerComponentToTrack, newMapTrackToThreshold, newMapTrackToTolerance, photons, mips, clumps, treesWithNoStructure, seedLeftoverHitClusters, newMapTrackToVetoedAdditions);
+	// Look for cases where we can see something went wrong and fix it.
+	// The easiest instance is where:
+	//   * A cluster C is not connected to any track
+	//   * The best potential link for cluster C was to a track T
+	//   * The E/p for track T is currently too low
+	//   * The E/p for track T would be OK if cluster C was added
+	// We could also generalize this to a group of clusters (C1+C2+...+Cn) to be connected to T.
+	boolean noOverridesOnPreviousPass = false;
+	while (!noOverridesOnPreviousPass) {
+	    noOverridesOnPreviousPass = true;
+	    for (Cluster clus : linkableClusters) {
+		if (photons.contains(clus)) {
+		    // Don't eat photons
+		    continue;
+		}
+		if (newMapShowerComponentToTrack.get(clus) == null) {
+		    // Cluster with no tracks connected.
+		    MCParticle domPartOfClus = quoteDominantParticle(clus);
+		    int domPDG = domPartOfClus.getPDGID();
+		    double domMom = domPartOfClus.getMomentum().magnitude();
+		    if (m_debug) { System.out.println("DEBUG: Considering a link over-ride for cluster ["+clus.getCalorimeterHits().size()+" hits] with no track."); }
+		    // What was the best-scoring link available?
+		    List<ScoredLink> potentialLinks = m_potentialLinks.get(clus);
+		    if (potentialLinks != null && potentialLinks.size()>0) {
+			ScoredLink bestLink = potentialLinks.get(0);
+			Cluster matchedClusterOfBestLink = bestLink.counterpart(clus);
+			Track trackOfMatchedClusterOfBestLink = newMapShowerComponentToTrack.get(matchedClusterOfBestLink);
+			if (m_debug) { System.out.println("DEBUG: Potential link from cluster ["+clus.getCalorimeterHits().size()+" hits] to a cluster ["+matchedClusterOfBestLink.getCalorimeterHits().size()+" hits] with score="+bestLink.score()); }
+			if (trackOfMatchedClusterOfBestLink != null) {
+			    // OK, there's a track. We might have vetoed this for E/p before... check that
+			    double trackMomentum = new BasicHep3Vector(trackOfMatchedClusterOfBestLink.getMomentum()).magnitude();
+			    if (newMapTrackToVetoedAdditions.get(trackOfMatchedClusterOfBestLink).contains(clus)) {
+				// We vetoed it before -- ignore it for now
+				if (m_debug) { System.out.println("DEBUG: Potential link from cluster ["+clus.getCalorimeterHits().size()+" hits] to a cluster ["+matchedClusterOfBestLink.getCalorimeterHits().size()+" hits] vetoed due to E/p"); }
+			    } else {
+				// OK, good to go.
+				Set<Cluster> currentShowerOfTrack = newMapTrackToShowerComponents.get(trackOfMatchedClusterOfBestLink);
+				Set<Cluster> newShowerOfTrack = new HashSet<Cluster>(currentShowerOfTrack);
+				newShowerOfTrack.add(clus);
+				double energyOfExistingShower = energy(currentShowerOfTrack, allSharedClusters);
+				double energyOfNewShower = energy(newShowerOfTrack, allSharedClusters);
+				double tolerance = newMapTrackToTolerance.get(trackOfMatchedClusterOfBestLink).doubleValue();
+				if (m_debug) { System.out.println("DEBUG: Potential link from cluster ["+clus.getCalorimeterHits().size()+" hits] to a cluster ["+matchedClusterOfBestLink.getCalorimeterHits().size()+" hits] would move shift energy "+energyOfExistingShower+" --> "+energyOfNewShower+" (p="+trackMomentum); }
+				if (testEoverP(energyOfNewShower, trackOfMatchedClusterOfBestLink, tolerance)) {
+				    // OK, add it
+				    newMapTrackToShowerComponents.put(trackOfMatchedClusterOfBestLink, newShowerOfTrack);
+				    newMapShowerComponentToTrack.put(clus, trackOfMatchedClusterOfBestLink);
+				    noOverridesOnPreviousPass = false;
+				    boolean truthMatch = false;
+				    if (trackOfMatchedClusterOfBestLink instanceof BaseTrackMC) {
+					MCParticle trackTruth = ((BaseTrackMC)(trackOfMatchedClusterOfBestLink)).getMCParticle();
+					truthMatch = (domPartOfClus == trackTruth);
+				    } else {
+					List<Track> tracks = trackOfMatchedClusterOfBestLink.getTracks();
+					for (Track tr : tracks) {
+					    MCParticle trackTruth = ((BaseTrackMC)(tr)).getMCParticle();
+					    if (domPartOfClus == trackTruth) { 
+						truthMatch = true;
+					    }
+					}
+				    }
+				    String mistake = new String(""); // Default: not a mistake
+				    if (!truthMatch) {
+					mistake += " -- MISTAKE"; 
+					boolean clusterComesFromReconstructedTrack = false;
+					for (Track eachTrack : tracksMatchedToClusters.keySet()) {
+					    MCParticle truthForEachTrack = ((BaseTrackMC)(eachTrack)).getMCParticle();
+					    if (domPartOfClus == truthForEachTrack) {
+						clusterComesFromReconstructedTrack = true;
+						break;
+					    }
+					}
+					if (clusterComesFromReconstructedTrack) {
+					    mistake += " [but no cost]";
+					}
+				    }
+				    if (m_debug) { System.out.println("DEBUG: Over-rode scoring to make a link: Track with p="+trackMomentum+" to clus with "+clus.getCalorimeterHits().size()+" hits from "+domPDG+" with p="+domMom+mistake); }
+				}
+			    }
+			}
+		    }
+		}
+	    }
+	}
+
+        if (m_debug) {
+	  printStatus("FINAL STATUS:", tracksSortedByMomentum, allSharedClusters, newMapTrackToShowerComponents, newMapShowerComponentToTrack, newMapTrackToThreshold, newMapTrackToTolerance, photons, mips, clumps, treesWithNoStructure, seedLeftoverHitClusters, newMapTrackToVetoedAdditions);
+	}
 
 	// Outputs
 
CVSspam 0.2.8