Commit in lcsim/src/org/lcsim/contrib/uiowa on MAIN
ReclusterDriver.java+108-11.24 -> 1.25
MJC: (contrib) Add support for cone-based linking within main reconstruction pass of PFA

lcsim/src/org/lcsim/contrib/uiowa
ReclusterDriver.java 1.24 -> 1.25
diff -u -r1.24 -r1.25
--- ReclusterDriver.java	2 Jul 2008 20:49:42 -0000	1.24
+++ ReclusterDriver.java	8 Jul 2008 16:34:19 -0000	1.25
@@ -37,7 +37,7 @@
   *
   * This version is PRELIMINARY.
   *
-  * @version $Id: ReclusterDriver.java,v 1.24 2008/07/02 20:49:42 mcharles Exp $
+  * @version $Id: ReclusterDriver.java,v 1.25 2008/07/08 16:34:19 mcharles Exp $
   * @author Mat Charles
   */
 
@@ -1008,6 +1008,111 @@
 	}
     }
 
+    // Special!
+    // May over-ride some previous links, giving them a better score
+    protected void initPotentialLinks_Cone(Collection<Cluster> seeds, Collection<Cluster> linkableClusters, Map<Cluster, Track> clustersMatchedToTweakedTracks, double scaleOK, double scaleMin) {
+	SteveMipWrapper tmpWrapper = new SteveMipWrapper();
+	tmpWrapper.process(m_event);
+	SteveMIPReassignmentAlgorithm mipAlg = new SteveMIPReassignmentAlgorithm(m_event, 1.0);
+	for (Cluster seed : seeds) {
+	    // Setup: Find what track the seed is connected to.
+	    Track tr = clustersMatchedToTweakedTracks.get(seed);
+	    if (tr == null) {
+		throw new AssertionError("Seed with "+seed.getCalorimeterHits().size()+" hits (from list of "+seeds.size()+" seeds) has a null track!");
+	    }
+	    if (tr.getTracks() == null) {
+		throw new AssertionError("Track.getTracks() is null!");
+	    }
+	    // Now loop over other clusters and assign scores if they're in a tight downstream cone
+	    for (Cluster clus : linkableClusters) {
+		if (seeds.contains(clus)) {
+		    // Don't link seeds to themselves or to other seeds
+		    continue;
+		}
+
+		// Check if a link already exists, and if so with what score
+		ScoredLink previousLink = null;
+		boolean linkAlreadyExists = checkForLink(seed, clus);
+		if (linkAlreadyExists) {
+		    List<ScoredLink> linksForSeed = m_potentialLinks.get(seed);
+		    for (ScoredLink link : linksForSeed) {
+			Cluster candidate = link.counterpart(seed);
+			if (candidate == clus) {
+			    // Found it
+			    previousLink = link;
+			    break;
+			}
+		    }
+		}
+
+		// Compute cone and score it
+		Double coneAngle = mipAlg.computeFigureOfMerit(tr, clus);
+		if (coneAngle == null) {
+		    // Extrapolation failed or angle way too large
+		    // Skip this link
+		    continue;
+		} else {
+		    double coneAngleCosTheta = Math.cos(coneAngle);
+		    // Compute score based on scales
+		    // Score drops linearly from (1.0 to 0.7) over the range (1.0, scaleOK)
+		    // Score drops linearly from (0.7 to 0.0) over the range (scaleOK, scaleMin)
+		    // Anything below scaleMin has zero score
+		    double score = 0.0;
+		    boolean newLinkValid = false;
+		    if (coneAngleCosTheta <= 1.0 && coneAngleCosTheta > scaleOK) {
+			// In "good" region, scoring 1.0 to 0.7
+			double offset = (1.0 - coneAngleCosTheta);
+			double normalizedOffset = offset / (1.0 - scaleOK);
+			score = 1.0 - 0.3*normalizedOffset;
+			if (score > 1.0 || score < 0.7) { throw new AssertionError("Calculation error"); }
+			newLinkValid = true;
+		    } else if (coneAngleCosTheta >= scaleOK && coneAngleCosTheta < scaleMin) {
+			// In "poor" region, scoring 0.7 to 0.0
+			double offset = (scaleOK - coneAngleCosTheta);
+			double normalizedOffset = offset / (scaleOK - scaleMin);
+			score = 0.7 - 0.7*normalizedOffset;
+			if (score > 0.7 || score < 0.0) { throw new AssertionError("Calculation error"); }
+			newLinkValid = true;
+		    } else {
+			// Angle too large to score
+			newLinkValid = false;
+		    }
+
+		    // Make link if needed
+		    if (newLinkValid) {
+			if (!linkAlreadyExists) {
+			    // No pre-existing link
+			    addPotentialLink(seed, clus, score);
+			} else {
+			    // Pre-existing link
+			    double oldScore = previousLink.score();
+			    if (score > oldScore) {
+				// New link is better!
+				// Replace old one.
+				List<ScoredLink> list1 = m_potentialLinks.get(seed);
+				List<ScoredLink> list2 = m_potentialLinks.get(clus);
+				list1.remove(previousLink);
+				list2.remove(previousLink);
+				// Check that it was removed OK
+				boolean linkExistsAfterRemove1 = checkForLink(seed, clus);
+				boolean linkExistsAfterRemove2 = checkForLink(clus, seed);
+				if (linkExistsAfterRemove1) { throw new AssertionError("Book-keeping error!"); }
+				if (linkExistsAfterRemove2) { throw new AssertionError("Book-keeping error!"); }
+				// Add new link
+				addPotentialLink(clus, seed, score);
+				// Check that it was added OK
+				boolean linkExistsAfterAdd1 = checkForLink(seed, clus);
+				boolean linkExistsAfterAdd2 = checkForLink(clus, seed);
+				if (!linkExistsAfterAdd1) { throw new AssertionError("Book-keeping error!"); }
+				if (!linkExistsAfterAdd2) { throw new AssertionError("Book-keeping error!"); }
+			    }
+			}
+		    }
+		}
+	    }
+	}
+    }
+
     protected void initPotentialLinks_MipMip(List<Cluster> mips, double scaleFactorTrackToTrack, boolean applyPenaltyFactor)
     {
 	for (int i=0; i<mips.size(); i++) {
@@ -2290,6 +2395,8 @@
     Map<Cluster, List<ScoredLink>> m_potentialLinks = null;
     protected void resetPotentialLinks() { m_potentialLinks = new HashMap<Cluster, List<ScoredLink>>(); }
     private void addPotentialLink(Cluster clus1, Cluster clus2, double score) {
+	boolean linkAlreadyExists = checkForLink(clus1, clus2);
+	if (linkAlreadyExists) { throw new AssertionError("Book-keeping error"); }
 	List<ScoredLink> linksForClus1 = m_potentialLinks.get(clus1);
 	List<ScoredLink> linksForClus2 = m_potentialLinks.get(clus2);
 	if (linksForClus1 == null) { linksForClus1 = new Vector<ScoredLink>(); m_potentialLinks.put(clus1, linksForClus1); }
CVSspam 0.2.8