5 added files
lcsim/src/org/lcsim/contrib/uiowa/template
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
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
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
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
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