Print

Print


Commit in lcsim/src/org/lcsim/contrib/uiowa/template on MAIN
FragmentIdentifier.java+20added 1.1
FragmentMergeDriver.java+91added 1.1
FragmentMerger.java+10added 1.1
SimpleFragmentIdentifier.java+112added 1.1
SimpleFragmentMerger.java+120added 1.1
+353
5 added files
Tools to identify & merge fragments

lcsim/src/org/lcsim/contrib/uiowa/template
FragmentIdentifier.java added at 1.1
diff -N FragmentIdentifier.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ FragmentIdentifier.java	4 Feb 2006 01:23:34 -0000	1.1
@@ -0,0 +1,20 @@
+package template;
+
+import org.lcsim.event.Cluster;
+import org.lcsim.event.EventHeader;
+
+/**
+ * Determine whether a cluster is a fragment or not.
+ *
+ * @version $Id: FragmentIdentifier.java,v 1.1 2006/02/04 01:23:34 mcharles Exp $
+ */
+
+public interface FragmentIdentifier 
+{
+    /**
+     * Attempt to determine whether the cluster is a fragment.
+     *
+     * @return true if we think it is a fragment, false if not.
+     */
+    public boolean isFragment(Cluster clus, EventHeader event);
+}

lcsim/src/org/lcsim/contrib/uiowa/template
FragmentMergeDriver.java added at 1.1
diff -N FragmentMergeDriver.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ FragmentMergeDriver.java	4 Feb 2006 01:23:34 -0000	1.1
@@ -0,0 +1,91 @@
+package template;
+
+import java.util.*; 
+import org.lcsim.util.*;
+import org.lcsim.event.*;
+import org.lcsim.recon.cluster.util.BasicCluster;
+
+/**
+ * A Driver to merge fragments into clusters.
+ */
+
+public class FragmentMergeDriver extends Driver
+{
+    public FragmentMergeDriver() {}
+
+    public void process(EventHeader event) 
+    {
+	// Input Clusters
+	List<Cluster> inputClusters = new Vector<Cluster>();
+	for (String name : m_inputClusterListNames) {
+	    List<Cluster> clist = event.get(Cluster.class, name);
+	    inputClusters.addAll(clist);
+	}
+
+	// Initially, fill the output hitmap with all hits
+	Map<Long,CalorimeterHit> leftoverHits = new HashMap<Long,CalorimeterHit>();
+	for (Cluster clus : inputClusters) {
+	    for (CalorimeterHit hit : clus.getCalorimeterHits()) {
+		Long id = new Long(hit.getCellID());
+		leftoverHits.put(id,hit);
+	    }
+	}
+
+	// Sort the input clusters into fragments and non-fragments
+	List<Cluster> fragments = new Vector<Cluster>();
+	List<Cluster> nonFragments = new Vector<Cluster>();
+	for (Cluster clus : inputClusters) {
+	    boolean isFragment = m_fragmentID.isFragment(clus, event);
+	    if (isFragment) {
+		fragments.add(clus);
+	    } else {
+		nonFragments.add(clus);
+	    }
+	}
+
+	// Add in any loose hits (treat as one-hit clusters)
+	for (String name : m_inputHitMapNames) {
+	    Map<Long,CalorimeterHit> map = (Map<Long,CalorimeterHit>)(event.get(name));
+	    leftoverHits.putAll(map);
+	    for (CalorimeterHit hit : map.values()) {
+		BasicCluster cl = new BasicCluster();
+		cl.addHit(hit);
+		fragments.add(cl);
+	    }
+	}
+	
+	// Merge:
+	List<Cluster> mergedClusters = m_fragmentMerger.mergeFragments(fragments, nonFragments);
+	    
+	// Take used hits out of the "leftoverHits" hitmap. Whatever is
+	// left is the set of unused hits.
+	for (Cluster clus : mergedClusters) {
+	    for (CalorimeterHit hit : clus.getCalorimeterHits()) {
+		Long id = new Long(hit.getCellID());		
+		leftoverHits.remove(id);
+	    }
+	}
+
+	// Output
+	event.put(m_outputClusterListName, mergedClusters);
+	event.put(m_outputHitMapName, leftoverHits);
+    }
+
+    public void addInputClusterList(String name) {m_inputClusterListNames.add(name);}
+    public void addInputParticleList(String name) {m_inputParticleListNames.add(name);}
+    public void addInputHitMap(String name) {m_inputHitMapNames.add(name);}
+    public void setOutputClusterList(String name) {m_outputClusterListName=name;}
+    public void setOutputHitMap(String name) {m_outputHitMapName=name;}
+    public void setFragmentIdentifier(FragmentIdentifier id) {m_fragmentID=id;}
+    public void setFragmentMerger(FragmentMerger merger) {m_fragmentMerger=merger;}
+
+    List<String> m_inputClusterListNames = new Vector<String>();
+    List<String> m_inputParticleListNames = new Vector<String>();
+    List<String> m_inputHitMapNames = new Vector<String>();
+    
+    String m_outputClusterListName;
+    String m_outputHitMapName;
+    FragmentIdentifier m_fragmentID;
+    FragmentMerger m_fragmentMerger;
+				
+}

lcsim/src/org/lcsim/contrib/uiowa/template
FragmentMerger.java added at 1.1
diff -N FragmentMerger.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ FragmentMerger.java	4 Feb 2006 01:23:34 -0000	1.1
@@ -0,0 +1,10 @@
+package template;
+
+import java.util.List;
+import org.lcsim.event.Cluster;
+import org.lcsim.event.EventHeader;
+
+public interface FragmentMerger
+{
+    public List<Cluster> mergeFragments(List<Cluster> fragments, List<Cluster> nonFragments);
+}

lcsim/src/org/lcsim/contrib/uiowa/template
SimpleFragmentIdentifier.java added at 1.1
diff -N SimpleFragmentIdentifier.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ SimpleFragmentIdentifier.java	4 Feb 2006 01:23:34 -0000	1.1
@@ -0,0 +1,112 @@
+package template;
+
+import java.util.*;
+import hep.physics.vec.*;
+
+import org.lcsim.event.*;
+import org.lcsim.recon.cluster.util.BasicCluster;
+import org.lcsim.recon.cluster.util.TensorClusterPropertyCalculator;
+
+public class SimpleFragmentIdentifier implements FragmentIdentifier
+{
+    public SimpleFragmentIdentifier() {}
+
+    public boolean isFragment(Cluster clus, EventHeader event)
+    {
+	// Look up the particles:
+	List<ReconstructedParticle> particleList = new Vector<ReconstructedParticle> ();
+	for (String name : m_particleListName) {
+	    List<ReconstructedParticle> currentList = event.get(ReconstructedParticle.class, name);
+	    particleList.addAll(currentList);
+	}
+
+        // Is there a track associated with this cluster?
+        boolean hasTrack = false;
+	for (ReconstructedParticle part : particleList) {
+	    if ( Math.abs(part.getCharge()) > 0.5 ) {
+		List<Cluster> clustersAssociatedWithTrack = recursivelyFindSubClusters(part);
+		if (clustersAssociatedWithTrack.contains(clus)) {
+		    hasTrack = true;
+		    break;
+		}
+	    }
+	}
+
+        // Check # hits
+        int nHits = clus.getCalorimeterHits().size();
+        boolean nHitsGood = (nHits > 10);
+
+        if (nHits<4) {
+            // If too few hits (1, 2, maybe 3), DOCA is undefined.
+            // Treat these cases as fragments always (unless there's a track)
+            if (!hasTrack) {
+                return true; // fragment
+            } else {
+                return false; // has track => tiny but real cluster
+            }
+        } else {
+            // Enough hits to check DOCA.
+            BasicHep3Vector originPoint = new BasicHep3Vector(0,0,0);
+            Hep3Vector[] linePosAndDir = getPositionAndDirection(clus);
+            double DOCA = findDOCAToPoint(linePosAndDir[0], linePosAndDir[1], originPoint);
+            boolean docaGood = (DOCA < 100.0);
+            // It's a fragment if there's no track AND not enough hits AND doesn't point back to IP:
+            boolean isFragment = !hasTrack && !nHitsGood && !docaGood;  
+            return isFragment;
+        }
+    }
+
+    protected List<Cluster> recursivelyFindSubClusters(ReconstructedParticle part) 
+    {
+	List<Cluster> allSubClusters = new Vector<Cluster>();
+	for (Cluster clus : part.getClusters()) {
+	    List<Cluster> subClusters = recursivelyFindSubClusters(clus);
+	    allSubClusters.addAll(subClusters);
+	}
+	return allSubClusters;
+    }
+    protected List<Cluster> recursivelyFindSubClusters(Cluster clus) 
+    {
+        List<Cluster> output = new Vector<Cluster>();
+        for (Cluster dau : clus.getClusters()) {
+            output.addAll(recursivelyFindSubClusters(dau));
+        }
+        output.add(clus);
+        return output;
+    }
+
+    // Belongs in another class:
+    protected double findDOCAToPoint(Hep3Vector linePoint, Hep3Vector lineDirection, Hep3Vector point) 
+    {
+        Hep3Vector displacement = new BasicHep3Vector(point.x() - linePoint.x(), point.y() - linePoint.y(), point.z() - linePoint.z());
+        double dotProduct = VecOp.dot(displacement, lineDirection);
+        double doca = Math.sqrt(displacement.magnitudeSquared() - dotProduct*dotProduct);
+        return doca;
+    }
+    // Belongs in another class:
+    protected Hep3Vector[] getPositionAndDirection(Cluster clus)
+    {
+        if (clus.getCalorimeterHits().size() < 4) {
+            // Too few hits to calculate the tensor
+            return null;
+        }
+
+        BasicCluster copy = new BasicCluster();
+        copy.addCluster(clus);
+        TensorClusterPropertyCalculator calc = new TensorClusterPropertyCalculator();
+        copy.setPropertyCalculator(calc);
+        copy.calculateProperties();
+        double[][]axes = calc.getPrincipleAxis();
+        if (axes == null) {
+            throw new AssertionError("Principal axes not calculated");
+        }
+        Hep3Vector[] posAndDir = new Hep3Vector[2];
+        posAndDir[0] = new BasicHep3Vector(copy.getPosition());
+        posAndDir[1] = new BasicHep3Vector(axes[0][0], axes[0][1], axes[0][2]);
+        return posAndDir;
+    }
+
+    public void addParticleList(String name) {m_particleListName.add(name);}
+
+    List<String> m_particleListName = new Vector<String>();
+}

lcsim/src/org/lcsim/contrib/uiowa/template
SimpleFragmentMerger.java added at 1.1
diff -N SimpleFragmentMerger.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ SimpleFragmentMerger.java	4 Feb 2006 01:23:34 -0000	1.1
@@ -0,0 +1,120 @@
+package template;
+
+import java.util.*;
+import hep.physics.vec.*;
+
+import org.lcsim.event.Cluster;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.CalorimeterHit;
+import org.lcsim.recon.cluster.util.BasicCluster;
+
+public class SimpleFragmentMerger implements FragmentMerger
+{
+    public List<Cluster> mergeFragments(List<Cluster> fragments, List<Cluster> nonFragments)
+    {
+	// Our output will be a new set of clusters that contain the old ones.
+	// So we'll need wrapped output:
+	Map<Cluster,BasicCluster> mapToWrappedClusters = new HashMap<Cluster,BasicCluster> ();
+	for (Cluster nonfrag : nonFragments) {
+	    BasicCluster newCluster = new BasicCluster();
+	    newCluster.addCluster(nonfrag);
+	    mapToWrappedClusters.put(nonfrag,newCluster);
+	}
+
+	// First pass: loop over fragments and find the best merge...
+	Map<Cluster,Cluster> mapFragmentsToParents = new HashMap<Cluster,Cluster> ();
+	List<Cluster> unmappedFragments = new Vector<Cluster>();
+        for (Cluster fragment : fragments) {
+            Cluster target = findBestMerge(fragment, nonFragments, fragments);
+            if (target != null) {
+		mapFragmentsToParents.put(fragment, target);
+	    } else {
+		unmappedFragments.add(fragment);
+	    }
+	}
+
+	// Second pass: Do the merges.
+	//   If this implementation can merge fragments into other fragments,
+	//   there is a danger that we will wind up with fragments that are
+	//   never merged into a non-fragment and hence never written out.
+	for (Cluster fragment : mapFragmentsToParents.keySet()) {
+	    Cluster target = mapFragmentsToParents.get(fragment);
+	    BasicCluster wrappedTarget = mapToWrappedClusters.get(target);
+	    wrappedTarget.addCluster(fragment);
+        }
+
+	// Return output, which is the wrapped non-fragments with fragments merged in.
+	List<Cluster> output = new Vector<Cluster>();
+	output.addAll(mapToWrappedClusters.values());
+	return output;
+    }
+
+    protected Cluster findBestMerge(Cluster fragment, List<Cluster> nonFragments, List<Cluster> fragments)
+    {
+        // This is kind of dumb.
+        // What's the nearest non-fragment using hit-hit distance?
+        Cluster nearest = null;
+        double minDistance = 0;
+        for (Cluster nonFragment : nonFragments) {
+            double dist = distance(fragment, nonFragment);
+            if (dist<minDistance || nearest==null) {
+                nearest = nonFragment;
+                minDistance = dist;
+            }
+        }
+        if (nearest == null) {
+            if (nonFragments.size() != 0) {
+                throw new AssertionError("BUG: There are non-fragments, but none is the nearest");
+            } else {
+                return null;
+            }
+        } else {
+            return nearest;
+        }
+    }
+
+
+    // This belongs outside this class.
+    private double distance(Cluster clus1, Cluster clus2)
+    {
+        // Loop over hits...
+        boolean firstCheck = true;
+        double minDistance = Double.NaN; // Will stay NaN if a cluster is empty
+        List<CalorimeterHit> hits = clus1.getCalorimeterHits();
+        for (CalorimeterHit hit : hits) {
+            double dist = distance(clus2, hit);
+            if (firstCheck || dist<minDistance) {
+                minDistance = dist;
+                firstCheck = false;
+            }
+        }
+
+        return minDistance;
+    }   
+    // This belongs outside this class.
+    private double distance(Cluster clus, CalorimeterHit hit)
+    {
+        // Loop over hits...
+        boolean firstCheck = true;
+        double minDistance = Double.NaN; // Will stay NaN if clus is empty
+        List<CalorimeterHit> hits = clus.getCalorimeterHits();
+        for (CalorimeterHit hitInCluster : hits) {
+            double dist = distance(hit, hitInCluster);
+            if (firstCheck || dist<minDistance) {
+                minDistance = dist;
+                firstCheck = false;
+            }
+        }
+
+        return minDistance;
+    }   
+    // This belongs outside this class.
+    private double distance(CalorimeterHit hit1, CalorimeterHit hit2)
+    {
+        Hep3Vector vect1 = new BasicHep3Vector(hit1.getPosition());
+        Hep3Vector vect2 = new BasicHep3Vector(hit2.getPosition());
+        Hep3Vector displacement = VecOp.sub(vect1, vect2);
+        return displacement.magnitude();
+    }
+
+}
CVSspam 0.2.8