7 added files
lcsim/src/org/lcsim/recon/pfa/identifier
diff -N MultipleTrackTrack.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ MultipleTrackTrack.java 22 Oct 2008 17:40:34 -0000 1.1
@@ -0,0 +1,53 @@
+package org.lcsim.recon.pfa.identifier;
+
+import java.util.*;
+import org.lcsim.util.*;
+import org.lcsim.event.*;
+import org.lcsim.event.base.*;
+
+/**
+ * Utility class for the case when multiple tracks point to the same
+ * cluster in the calorimeter and can't be disentangled.
+ *
+ * @version $Id: MultipleTrackTrack.java,v 1.1 2008/10/22 17:40:34 mcharles Exp $
+ * @author [log in to unmask]
+ */
+
+public class MultipleTrackTrack extends BaseTrack {
+ protected Collection<Track> m_tracks;
+
+ /** FIXME: Needs to be protected! Public for now while adjusting contrib... */
+ public MultipleTrackTrack(Collection<Track> tracks) {
+ m_tracks = tracks;
+ }
+ public List<Track> getTracks() { return new Vector<Track>(m_tracks); }
+ public int getCharge() {
+ int chargeSum = 0;
+ for (Track tr : m_tracks) {
+ chargeSum += tr.getCharge();
+ }
+ return chargeSum;
+ }
+ public double[] getMomentum() {
+ double[] mom = new double[3];
+ mom[0] = this.getPX();
+ mom[1] = this.getPY();
+ mom[2] = this.getPZ();
+ return mom;
+ }
+ public double getPX() {
+ double psum = 0.0;
+ for (Track tr : m_tracks) { psum += tr.getPX(); }
+ return psum;
+ }
+ public double getPY() {
+ double psum = 0.0;
+ for (Track tr : m_tracks) { psum += tr.getPY(); }
+ return psum;
+ }
+ public double getPZ() {
+ double psum = 0.0;
+ for (Track tr : m_tracks) { psum += tr.getPZ(); }
+ return psum;
+ }
+}
lcsim/src/org/lcsim/recon/pfa/identifier
diff -N AmbiguousTrackToClusterMapMaker.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ AmbiguousTrackToClusterMapMaker.java 22 Oct 2008 17:40:34 -0000 1.1
@@ -0,0 +1,118 @@
+package org.lcsim.recon.pfa.identifier;
+
+import java.util.*;
+import hep.physics.vec.*;
+import org.lcsim.util.*;
+import org.lcsim.event.*;
+import org.lcsim.event.util.*;
+import org.lcsim.recon.pfa.identifier.*;
+
+public class AmbiguousTrackToClusterMapMaker extends TrackToClusterMapMaker {
+ protected HelixExtrapolator m_findCluster;
+ public AmbiguousTrackToClusterMapMaker(HelixExtrapolator findCluster, String inputTrackList, String outputMap, String outputUnmatchedTrackList) {
+ super(inputTrackList, outputMap, outputUnmatchedTrackList);
+ m_findCluster = findCluster;
+ }
+
+ protected Map<String,String> m_mapInputNameToMatchedOutputName = new HashMap<String,String>();
+ protected Map<String,String> m_mapInputNameToUnmatchedOutputName = new HashMap<String,String>();
+ public void addInputList(String inputName, String matchedOutputName, String unmatchedOutputName) {
+ m_mapInputNameToMatchedOutputName.put(inputName, matchedOutputName);
+ m_mapInputNameToUnmatchedOutputName.put(inputName, unmatchedOutputName);
+ }
+
+ protected Map<Track,Cluster> makeMap(EventHeader event) {
+ // Read in inputs
+ List<Track> trackList = event.get(Track.class, m_inputTrackListName);
+ Map<String, List<Cluster>> inputLists = new HashMap<String, List<Cluster>>();
+ for (String str : m_mapInputNameToMatchedOutputName.keySet()) {
+ List<Cluster> currentList = event.get(Cluster.class, str);
+ inputLists.put(str, currentList);
+ }
+ if (inputLists.size() != m_mapInputNameToMatchedOutputName.size()) { throw new AssertionError("Book-keeping error"); }
+ if (inputLists.size() != m_mapInputNameToUnmatchedOutputName.size()) { throw new AssertionError("Book-keeping error"); }
+
+ // Set up matching
+ LocalHelixExtrapolationTrackMIPClusterMatcher mipMatch = new LocalHelixExtrapolationTrackMIPClusterMatcher(m_findCluster);
+ LocalHelixExtrapolationTrackClusterMatcher genMatch = new LocalHelixExtrapolationTrackClusterMatcher(m_findCluster);
+ DualActionTrackClusterMatcher dualMatch = new DualActionTrackClusterMatcher(mipMatch, genMatch);
+ mipMatch.process(event);
+ genMatch.process(event);
+ List<Cluster> allMatchableClusters = new Vector<Cluster>();
+ for (List<Cluster> inputList : inputLists.values()) {
+ allMatchableClusters.addAll(inputList);
+ }
+
+ // Do matching
+ Map<Track,Cluster> tracksMatchedToClusters = new HashMap<Track,Cluster>();
+ Map<Cluster, List<Track>> clustersMatchedToTracks = new HashMap<Cluster, List<Track>>();
+ for (Track tr : trackList) {
+ Cluster matchedCluster = dualMatch.matchTrackToCluster(tr, allMatchableClusters);
+ if (matchedCluster != null) {
+ // Found a match
+ // Optionally, handle these cases:
+ // * Match is to a teeny cluster piece (leftoverHitClusters) but there is structure nearby inside same DTree
+ // * Match is to a photon (try to split up)
+ // * Match is to a cluster with E>>p (try to split up)
+ // ... but those don't really apply here (they aren't MIPs)
+ tracksMatchedToClusters.put(tr, matchedCluster);
+ List<Track> clusTrList = clustersMatchedToTracks.get(matchedCluster);
+ if (clusTrList == null) {
+ clusTrList = new Vector<Track>();
+ clustersMatchedToTracks.put(matchedCluster, clusTrList);
+ }
+ clusTrList.add(tr);
+ }
+ }
+
+ // In this case, we don't forbid ambiguous matches where more than one track points to a single cluster.
+ // But we do need to identify them. For now, describe them as a MultipleTrackTrack. We may want to
+ // revisit this later.
+ Map<Track,Cluster> outputMap = new HashMap<Track,Cluster>();
+ Set<Track> matchedTracks = new HashSet<Track>();
+ for (Cluster clus : clustersMatchedToTracks.keySet()) {
+ if (clus == null) { throw new AssertionError("Null cluster!"); }
+ List<Track> tracksOfMatchedClus = clustersMatchedToTracks.get(clus);
+ if (tracksOfMatchedClus == null) { throw new AssertionError("Book-keeping error!"); }
+ if (tracksOfMatchedClus.size()==0) {
+ throw new AssertionError("Book-keeping error!");
+ } else if (tracksOfMatchedClus.size()==1) {
+ // Unique match -- OK
+ Track tr = tracksOfMatchedClus.get(0);
+ outputMap.put(tr, clus);
+ } else {
+ // Ambiguous match -- also OK
+ Track mergedTrack = new MultipleTrackTrack(tracksOfMatchedClus);
+ outputMap.put(mergedTrack, clus);
+ }
+ matchedTracks.addAll(tracksOfMatchedClus);
+ }
+
+ // Identify unmatched tracks
+ List<Track> unmatchedTracks = new Vector<Track>();
+ unmatchedTracks.addAll(trackList);
+ unmatchedTracks.removeAll(matchedTracks);
+
+ // Separate out lists of matched & unmatched clusters
+ for (String str : m_mapInputNameToMatchedOutputName.keySet()) {
+ List<Cluster> inputList = inputLists.get(str);
+ List<Cluster> outputListMatched = new Vector<Cluster>();
+ List<Cluster> outputListUnmatched = new Vector<Cluster>();
+ String matchedOutputName = m_mapInputNameToMatchedOutputName.get(str);
+ String unmatchedOutputName = m_mapInputNameToUnmatchedOutputName.get(str);
+ for (Cluster clus : inputList) {
+ if (outputMap.values().contains(clus)) {
+ outputListMatched.add(clus);
+ } else {
+ outputListUnmatched.add(clus);
+ }
+ }
+ event.put(matchedOutputName, outputListMatched);
+ event.put(unmatchedOutputName, outputListUnmatched);
+ }
+
+ // All done
+ event.put(m_outputUnmatchedTrackListName, unmatchedTracks);
+ return outputMap;
+ }
+}
lcsim/src/org/lcsim/recon/pfa/identifier
diff -N TrackToClusterMapMaker.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ TrackToClusterMapMaker.java 22 Oct 2008 17:40:34 -0000 1.1
@@ -0,0 +1,53 @@
+package org.lcsim.recon.pfa.identifier;
+
+import java.util.*;
+import org.lcsim.util.*;
+import org.lcsim.event.*;
+import org.lcsim.event.util.*;
+
+/**
+ * Abstract class with several implementations, used for
+ * matching tracks to clusters. The rules are:
+ * 1) The input tracks are supplied as a named List from the event.
+ * 2) Matched tracks are written out to the event as a Map<Track,Cluster>
+ * 3) Unmatched tracks are written out to the event as a List<Track>
+ * 4) The output tracks MAY be altered copies of the input tracks.
+ * For example, if two tracks enter the calorimeter in the same
+ * cell, they may get bundled into a single track. So the user
+ * should not re-use the input track list.
+ * 5) There should be no overlap between the matched tracks and the
+ * unmatched tracks.
+ * 6) Implementing classes MAY write out additional output.
+ *
+ * @version $Id: TrackToClusterMapMaker.java,v 1.1 2008/10/22 17:40:34 mcharles Exp $
+ * @author [log in to unmask]
+ */
+
+public abstract class TrackToClusterMapMaker extends Driver {
+
+ abstract protected Map<Track,Cluster> makeMap(EventHeader event);
+
+ String m_inputTrackListName;
+ String m_outputMapName;
+ String m_outputUnmatchedTrackListName;
+
+ /**
+ * General-purpose constructor. Implementing classes may make their
+ * own constructor with additional arguments.
+ *
+ * @param inputTrackList The name of the input List of Tracks to read in from the event and match to clusters.
+ * @param outputMap The name to write out the output Map<Track,Cluster> of matched tracks as.
+ * @param outputUnmatchedTrackList The name to write unmatched/unused tracks out as.
+ */
+ public TrackToClusterMapMaker(String inputTrackList, String outputMap, String outputUnmatchedTrackList) {
+ super();
+ m_inputTrackListName = inputTrackList;
+ m_outputMapName = outputMap;
+ m_outputUnmatchedTrackListName = outputUnmatchedTrackList;
+ }
+
+ public void process(EventHeader event) {
+ Map<Track,Cluster> output = makeMap(event);
+ event.put(m_outputMapName, output);
+ }
+}
lcsim/src/org/lcsim/recon/pfa/identifier
diff -N TrackToElectronMapMaker.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ TrackToElectronMapMaker.java 22 Oct 2008 17:40:34 -0000 1.1
@@ -0,0 +1,194 @@
+package org.lcsim.recon.pfa.identifier;
+
+import java.util.*;
+import hep.physics.vec.*;
+import org.lcsim.util.*;
+import org.lcsim.event.*;
+import org.lcsim.event.util.*;
+import org.lcsim.recon.pfa.identifier.*;
+import org.lcsim.recon.cluster.util.*;
+import org.lcsim.util.swim.Line;
+
+/**
+ * Try to make electrons.
+ *
+ * @version $Id: TrackToElectronMapMaker.java,v 1.1 2008/10/22 17:40:34 mcharles Exp $
+ * @author [log in to unmask]
+ */
+
+public class TrackToElectronMapMaker extends TrackToClusterMapMaker {
+
+ protected String m_outputElectronClusterListName;
+ protected String m_inputPhotonListName;
+ protected ClusterEnergyCalculator m_photonCalib;
+ protected HelixExtrapolator m_findCluster;
+
+ public TrackToElectronMapMaker(HelixExtrapolator findCluster, String inputPhotonList, String inputTrackList, String outputTrackClusterMap, String outputUnmatchedTrackList, String outputElectronClusterList) {
+ super(inputTrackList, outputTrackClusterMap, outputUnmatchedTrackList);
+ m_outputElectronClusterListName = outputElectronClusterList;
+ m_inputPhotonListName = inputPhotonList;
+ m_findCluster = findCluster;
+ m_photonCalib = new QNeutralHadronClusterEnergyCalculator();
+ }
+
+
+
+ protected Map<Track,Cluster> makeMap(EventHeader event) {
+ // Read in inputs
+ List<Track> trackList = event.get(Track.class, m_inputTrackListName);
+ List<Cluster> photons = event.get(Cluster.class, m_inputPhotonListName);
+
+ // The output
+ Map<Track,Cluster> outputMap = new HashMap<Track,Cluster>();
+
+ // Extrapolation utility
+ LocalHelixExtrapolationTrackClusterMatcher genMatch = new LocalHelixExtrapolationTrackClusterMatcher(m_findCluster);
+
+ // Loop over tracks, looking for a good match to a photon
+ Map<Track,Cluster> electronCandidateMap = new HashMap<Track,Cluster>();
+ Set<Cluster> electronCandidateClusters = new HashSet<Cluster>();
+ Set<Cluster> vetoedElectronCandidateClusters = new HashSet<Cluster>();
+ List<Cluster> electronClusters = new Vector<Cluster>();
+ List<Track> electronTracks = new Vector<Track>();
+ for (Track tr : trackList) {
+ Cluster matchedCluster = genMatch.matchTrackToCluster(tr, photons);
+ if (matchedCluster != null) {
+ if (photons.contains(matchedCluster)) {
+ // Electron candidate
+ if (electronCandidateClusters.contains(matchedCluster)) {
+ // Multiple track matches => veto
+ vetoedElectronCandidateClusters.add(matchedCluster);
+ }
+ electronCandidateClusters.add(matchedCluster);
+ // Now, are we confident that it's an electron?
+ double electronResid = electronEnergyNormalizedResidual(tr, matchedCluster);
+ int hitsInCluster = countHitsInClusterInFirstLayers(tr, matchedCluster, 5);
+ int hitsInCore = countHitsInCoreInFirstLayers(tr, matchedCluster, 5);
+ double originIP = impactParameterFromPhotonCoreToOrigin(matchedCluster);
+ double trackIP = distanceFromTrackToPhotonCore(tr, matchedCluster);
+ if (electronResid > -2.0 && electronResid < 2.0 && trackIP < 7.0 && hitsInCore > 1) {
+ // Accept as electron
+ electronCandidateMap.put(tr, matchedCluster);
+ }
+ }
+ }
+ }
+
+ // Now, did we accept any of those?
+ for (Track tr : electronCandidateMap.keySet()) {
+ Cluster clus = electronCandidateMap.get(tr);
+ if (!electronCandidateClusters.contains(clus)) { throw new AssertionError("Book-keeping failure"); }
+ if (!vetoedElectronCandidateClusters.contains(clus)) {
+ // We accepted it and didn't veto it => electron
+ if (electronClusters.contains(clus)) { throw new AssertionError("Book-keeping failure"); }
+ electronClusters.add(clus);
+ electronTracks.add(tr);
+ }
+ }
+
+ // Unmatched tracks
+ List<Track> unmatchedTracks = new Vector<Track>();
+ unmatchedTracks.addAll(trackList);
+ unmatchedTracks.removeAll(electronTracks);
+
+ // Outputs
+ event.put(m_outputUnmatchedTrackListName, unmatchedTracks);
+ event.put(m_outputElectronClusterListName, electronClusters);
+ return outputMap;
+ }
+
+ // Utility routines
+
+ private double electronEnergyNormalizedResidual(Track tr, Cluster clus) {
+ double energyAssumingElectron = m_photonCalib.getEnergy(clus);
+ double trackMomentum = (new BasicHep3Vector(tr.getMomentum())).magnitude();
+ double residual = trackMomentum - energyAssumingElectron;
+ double estimatedError = 0.2 * Math.sqrt(trackMomentum);
+ if (trackMomentum < 1.0) {
+ // Don't shrink the error too much.
+ estimatedError = 0.2;
+ }
+ return (residual/estimatedError);
+ }
+
+ private int countHitsInClusterInFirstLayers(Track tr, Cluster clus, int nLayers) {
+ Set<Long> allClusterHits = new HashSet<Long>();
+ for (CalorimeterHit hit : clus.getCalorimeterHits()) {
+ allClusterHits.add(hit.getCellID());
+ }
+ int countMatches = 0;
+ HelixExtrapolationResult result = m_findCluster.performExtrapolation(tr);
+ if (result != null) {
+ for (int iLayer=0; iLayer<nLayers; iLayer++) {
+ Long cellID = result.extendToECALLayerAndFindCell(iLayer);
+ if (cellID != null && allClusterHits.contains(cellID)) {
+ countMatches++;
+ }
+ }
+ }
+ return countMatches;
+ }
+
+ private int countHitsInCoreInFirstLayers(Track tr, Cluster clus, int nLayers) {
+ Set<Long> coreClusterHits = new HashSet<Long>();
+ for (CalorimeterHit hit : clus.getClusters().get(0).getCalorimeterHits()) {
+ coreClusterHits.add(hit.getCellID());
+ }
+ int countMatches = 0;
+ HelixExtrapolationResult result = m_findCluster.performExtrapolation(tr);
+ if (result != null) {
+ for (int iLayer=0; iLayer<nLayers; iLayer++) {
+ Long cellID = result.extendToECALLayerAndFindCell(iLayer);
+ if (cellID != null && coreClusterHits.contains(cellID)) {
+ countMatches++;
+ }
+ }
+ }
+ return countMatches;
+ }
+
+ private double impactParameterFromPhotonCoreToOrigin(Cluster clus) {
+ Cluster coreSubCluster = clus.getClusters().get(0);
+ BasicCluster copyOfCoreSubCluster = new BasicCluster();
+ copyOfCoreSubCluster.addCluster(coreSubCluster);
+ TensorClusterPropertyCalculator calc = new TensorClusterPropertyCalculator();
+ copyOfCoreSubCluster.setPropertyCalculator(calc);
+ copyOfCoreSubCluster.calculateProperties();
+ double[][]axes = calc.getPrincipleAxis();
+ Hep3Vector coreDirection = new BasicHep3Vector(axes[0][0], axes[0][1], axes[0][2]);
+ Hep3Vector corePosition = new BasicHep3Vector(calc.getPosition());
+ Line line = new Line(corePosition, coreDirection);
+ Hep3Vector origin = new BasicHep3Vector(0,0,0);
+ double sOrigin = line.getDistanceToPoint(origin);
+ Hep3Vector pocaToOrigin = line.getPointAtDistance(sOrigin);
+ double docaToOrigin = VecOp.sub(pocaToOrigin, origin).magnitude();
+ return docaToOrigin;
+ }
+
+ private double distanceFromTrackToPhotonCore(Track tr, Cluster clus) {
+ HelixExtrapolationResult result = m_findCluster.performExtrapolation(tr);
+ Hep3Vector interceptPoint = null;
+ if (result != null) {
+ interceptPoint = result.getInterceptPoint();
+ }
+ if (interceptPoint != null) {
+ Cluster coreSubCluster = clus.getClusters().get(0);
+ BasicCluster copyOfCoreSubCluster = new BasicCluster();
+ copyOfCoreSubCluster.addCluster(coreSubCluster);
+ TensorClusterPropertyCalculator calc = new TensorClusterPropertyCalculator();
+ copyOfCoreSubCluster.setPropertyCalculator(calc);
+ copyOfCoreSubCluster.calculateProperties();
+ double[][]axes = calc.getPrincipleAxis();
+ Hep3Vector coreDirection = new BasicHep3Vector(axes[0][0], axes[0][1], axes[0][2]);
+ Hep3Vector corePosition = new BasicHep3Vector(calc.getPosition());
+ Line line = new Line(corePosition, coreDirection);
+ double s = line.getDistanceToPoint(interceptPoint);
+ Hep3Vector poca = line.getPointAtDistance(s);
+ double doca = VecOp.sub(poca, interceptPoint).magnitude();
+ return doca;
+ } else {
+ return Double.NaN;
+ }
+ }
+
+}
lcsim/src/org/lcsim/recon/pfa/identifier
diff -N TrackToGenericClusterMapMaker.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ TrackToGenericClusterMapMaker.java 22 Oct 2008 17:40:34 -0000 1.1
@@ -0,0 +1,112 @@
+package org.lcsim.recon.pfa.identifier;
+
+import java.util.*;
+import org.lcsim.util.*;
+import org.lcsim.event.*;
+import org.lcsim.event.util.*;
+import org.lcsim.recon.pfa.identifier.*;
+
+public class TrackToGenericClusterMapMaker extends TrackToClusterMapMaker {
+
+ protected HelixExtrapolator m_findCluster;
+ public TrackToGenericClusterMapMaker(HelixExtrapolator findCluster, String inputTrackList, String outputMap, String outputUnmatchedTrackList) {
+ super(inputTrackList, outputMap, outputUnmatchedTrackList);
+ m_findCluster = findCluster;
+ }
+
+ protected Map<String,String> m_mapInputNameToMatchedOutputName = new HashMap<String,String>();
+ protected Map<String,String> m_mapInputNameToUnmatchedOutputName = new HashMap<String,String>();
+ public void addInputList(String inputName, String matchedOutputName, String unmatchedOutputName) {
+ m_mapInputNameToMatchedOutputName.put(inputName, matchedOutputName);
+ m_mapInputNameToUnmatchedOutputName.put(inputName, unmatchedOutputName);
+ }
+
+ protected Map<Track,Cluster> makeMap(EventHeader event) {
+ // Read in inputs
+ List<Track> trackList = event.get(Track.class, m_inputTrackListName);
+ Map<String, List<Cluster>> inputLists = new HashMap<String, List<Cluster>>();
+ for (String str : m_mapInputNameToMatchedOutputName.keySet()) {
+ List<Cluster> currentList = event.get(Cluster.class, str);
+ inputLists.put(str, currentList);
+ }
+ if (inputLists.size() != m_mapInputNameToMatchedOutputName.size()) { throw new AssertionError("Book-keeping error"); }
+ if (inputLists.size() != m_mapInputNameToUnmatchedOutputName.size()) { throw new AssertionError("Book-keeping error"); }
+
+ // Set up matching
+ LocalHelixExtrapolationTrackMIPClusterMatcher mipMatch = new LocalHelixExtrapolationTrackMIPClusterMatcher(m_findCluster);
+ LocalHelixExtrapolationTrackClusterMatcher genMatch = new LocalHelixExtrapolationTrackClusterMatcher(m_findCluster);
+ DualActionTrackClusterMatcher dualMatch = new DualActionTrackClusterMatcher(mipMatch, genMatch);
+ mipMatch.process(event);
+ genMatch.process(event);
+ List<Cluster> allMatchableClusters = new Vector<Cluster>();
+ for (List<Cluster> inputList : inputLists.values()) {
+ allMatchableClusters.addAll(inputList);
+ }
+
+ // Do matching
+ Map<Track,Cluster> tracksMatchedToClusters = new HashMap<Track,Cluster>();
+ Map<Cluster, List<Track>> clustersMatchedToTracks = new HashMap<Cluster, List<Track>>();
+ for (Track tr : trackList) {
+ Cluster matchedCluster = dualMatch.matchTrackToCluster(tr, allMatchableClusters);
+ if (matchedCluster != null) {
+ // Found a match
+ // Optionally, handle these cases:
+ // * Match is to a teeny cluster piece (leftoverHitClusters) but there is structure nearby inside same DTree
+ // * Match is to a photon (try to split up)
+ // * Match is to a cluster with E>>p (try to split up)
+ // ... but those don't really apply here (they aren't MIPs)
+ tracksMatchedToClusters.put(tr, matchedCluster);
+ List<Track> clusTrList = clustersMatchedToTracks.get(matchedCluster);
+ if (clusTrList == null) {
+ clusTrList = new Vector<Track>();
+ clustersMatchedToTracks.put(matchedCluster, clusTrList);
+ }
+ clusTrList.add(tr);
+ }
+ }
+
+ // Flag unique matches to be written out:
+ Map<Track,Cluster> outputMap = new HashMap<Track,Cluster>();
+ for (Track tr : tracksMatchedToClusters.keySet()) {
+ Cluster matchedClus = tracksMatchedToClusters.get(tr);
+ List<Track> tracksOfMatchedClus = clustersMatchedToTracks.get(matchedClus);
+ if (tracksOfMatchedClus == null) { throw new AssertionError("Book-keeping error!"); }
+ if (tracksOfMatchedClus.size()==0) {
+ throw new AssertionError("Book-keeping error!");
+ } else if (tracksOfMatchedClus.size()==1) {
+ // Unique match -- OK
+ outputMap.put(tr, matchedClus);
+ } else {
+ // Ambiguous match -- ignore for now
+ }
+ }
+
+ // Identify unmatched tracks
+ List<Track> unmatchedTracks = new Vector<Track>();
+ unmatchedTracks.addAll(trackList);
+ unmatchedTracks.removeAll(outputMap.keySet());
+
+ // Separate out lists of matched & unmatched clusters
+ for (String str : m_mapInputNameToMatchedOutputName.keySet()) {
+ List<Cluster> inputList = inputLists.get(str);
+ List<Cluster> outputListMatched = new Vector<Cluster>();
+ List<Cluster> outputListUnmatched = new Vector<Cluster>();
+ String matchedOutputName = m_mapInputNameToMatchedOutputName.get(str);
+ String unmatchedOutputName = m_mapInputNameToUnmatchedOutputName.get(str);
+ for (Cluster clus : inputList) {
+ if (outputMap.values().contains(clus)) {
+ outputListMatched.add(clus);
+ } else {
+ outputListUnmatched.add(clus);
+ }
+ }
+ event.put(matchedOutputName, outputListMatched);
+ event.put(unmatchedOutputName, outputListUnmatched);
+ }
+
+ // All done
+ event.put(m_outputUnmatchedTrackListName, unmatchedTracks);
+ return outputMap;
+ }
+}
+
lcsim/src/org/lcsim/recon/pfa/identifier
diff -N TrackToMipClusterMapMaker.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ TrackToMipClusterMapMaker.java 22 Oct 2008 17:40:34 -0000 1.1
@@ -0,0 +1,102 @@
+package org.lcsim.recon.pfa.identifier;
+
+import java.util.*;
+import org.lcsim.util.*;
+import org.lcsim.event.*;
+import org.lcsim.event.util.*;
+import org.lcsim.recon.pfa.identifier.*;
+
+public class TrackToMipClusterMapMaker extends TrackToClusterMapMaker {
+ protected HelixExtrapolator m_findCluster;
+ public TrackToMipClusterMapMaker(HelixExtrapolator findCluster, String inputTrackList, String outputMap, String outputUnmatchedTrackList) {
+ super(inputTrackList, outputMap, outputUnmatchedTrackList);
+ m_findCluster = findCluster;
+ }
+
+ protected Map<String,String> m_mapInputNameToMatchedOutputName = new HashMap<String,String>();
+ protected Map<String,String> m_mapInputNameToUnmatchedOutputName = new HashMap<String,String>();
+ public void addInputList(String inputName, String matchedOutputName, String unmatchedOutputName) {
+ m_mapInputNameToMatchedOutputName.put(inputName, matchedOutputName);
+ m_mapInputNameToUnmatchedOutputName.put(inputName, unmatchedOutputName);
+ }
+
+ protected Map<Track,Cluster> makeMap(EventHeader event) {
+ // Read in inputs
+ List<Track> trackList = event.get(Track.class, m_inputTrackListName);
+ Map<String, List<Cluster>> inputLists = new HashMap<String, List<Cluster>>();
+ for (String str : m_mapInputNameToMatchedOutputName.keySet()) {
+ List<Cluster> currentList = event.get(Cluster.class, str);
+ inputLists.put(str, currentList);
+ }
+ if (inputLists.size() != m_mapInputNameToMatchedOutputName.size()) { throw new AssertionError("Book-keeping error"); }
+ if (inputLists.size() != m_mapInputNameToUnmatchedOutputName.size()) { throw new AssertionError("Book-keeping error"); }
+
+ // Set up matching
+ LocalHelixExtrapolationTrackMIPClusterMatcher mipMatch = new LocalHelixExtrapolationTrackMIPClusterMatcher(m_findCluster);
+ mipMatch.process(event);
+ List<Cluster> allMatchableClusters = new Vector<Cluster>();
+ for (List<Cluster> inputList : inputLists.values()) {
+ allMatchableClusters.addAll(inputList);
+ }
+
+ // Do matching
+ Map<Track,Cluster> tracksMatchedToClusters = new HashMap<Track,Cluster>();
+ Map<Cluster, List<Track>> clustersMatchedToTracks = new HashMap<Cluster, List<Track>>();
+ for (Track tr : trackList) {
+ Cluster matchedCluster = mipMatch.matchTrackToCluster(tr, allMatchableClusters);
+ if (matchedCluster != null) {
+ // Found a match
+ tracksMatchedToClusters.put(tr, matchedCluster);
+ List<Track> clusTrList = clustersMatchedToTracks.get(matchedCluster);
+ if (clusTrList == null) {
+ clusTrList = new Vector<Track>();
+ clustersMatchedToTracks.put(matchedCluster, clusTrList);
+ }
+ clusTrList.add(tr);
+ }
+ }
+
+ // Flag unique matches to be written out:
+ Map<Track,Cluster> outputMap = new HashMap<Track,Cluster>();
+ for (Track tr : tracksMatchedToClusters.keySet()) {
+ Cluster matchedClus = tracksMatchedToClusters.get(tr);
+ List<Track> tracksOfMatchedClus = clustersMatchedToTracks.get(matchedClus);
+ if (tracksOfMatchedClus == null) { throw new AssertionError("Book-keeping error!"); }
+ if (tracksOfMatchedClus.size()==0) {
+ throw new AssertionError("Book-keeping error!");
+ } else if (tracksOfMatchedClus.size()==1) {
+ // Unique match -- OK
+ outputMap.put(tr, matchedClus);
+ } else {
+ // Ambiguous match -- ignore for now
+ }
+ }
+
+ // Identify unmatched tracks
+ List<Track> unmatchedTracks = new Vector<Track>();
+ unmatchedTracks.addAll(trackList);
+ unmatchedTracks.removeAll(outputMap.keySet());
+
+ // Separate out lists of matched & unmatched clusters
+ for (String str : m_mapInputNameToMatchedOutputName.keySet()) {
+ List<Cluster> inputList = inputLists.get(str);
+ List<Cluster> outputListMatched = new Vector<Cluster>();
+ List<Cluster> outputListUnmatched = new Vector<Cluster>();
+ String matchedOutputName = m_mapInputNameToMatchedOutputName.get(str);
+ String unmatchedOutputName = m_mapInputNameToUnmatchedOutputName.get(str);
+ for (Cluster clus : inputList) {
+ if (outputMap.values().contains(clus)) {
+ outputListMatched.add(clus);
+ } else {
+ outputListUnmatched.add(clus);
+ }
+ }
+ event.put(matchedOutputName, outputListMatched);
+ event.put(unmatchedOutputName, outputListUnmatched);
+ }
+
+ // All done
+ event.put(m_outputUnmatchedTrackListName, unmatchedTracks);
+ return outputMap;
+ }
+}
lcsim/src/org/lcsim/recon/pfa/identifier
diff -N TrackToPreShowerMipMapMaker.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ TrackToPreShowerMipMapMaker.java 22 Oct 2008 17:40:34 -0000 1.1
@@ -0,0 +1,158 @@
+package org.lcsim.recon.pfa.identifier;
+
+import java.util.*;
+import org.lcsim.util.*;
+import org.lcsim.event.*;
+import org.lcsim.event.util.*;
+import org.lcsim.recon.cluster.util.BasicCluster;
+
+public class TrackToPreShowerMipMapMaker extends TrackToClusterMapMaker {
+
+ String m_inputMapTrkToMIP;
+ String m_outputMips;
+ String m_outputSmallClusters;
+ String m_outputBlocks;
+ public TrackToPreShowerMipMapMaker(String inputMapTrkToMIP, String inputTrackList, String outputMap, String outputUnmatchedTrackList, String outputMips, String outputSmallClusters, String outputBlocks) {
+ super(inputTrackList, outputMap, outputUnmatchedTrackList);
+ m_inputMapTrkToMIP = inputMapTrkToMIP;
+ m_outputMips = outputMips;
+ m_outputSmallClusters = outputSmallClusters;
+ m_outputBlocks = outputBlocks;
+ }
+
+ protected Map<Track,Cluster> makeMap(EventHeader event) {
+ // The output
+ Map<Track,Cluster> outputMap = new HashMap<Track,Cluster>();
+ List<Cluster> outputClustersMips = new Vector<Cluster>();
+ List<Cluster> outputClustersBlocks = new Vector<Cluster>();
+ List<Cluster> outputClustersSmall = new Vector<Cluster>();
+
+ // Read in MIP connections
+ List<Track> inputTrackList = event.get(Track.class, m_inputTrackListName);
+ Map<Track,BasicCluster> MapTrkToMIP = (Map<Track,BasicCluster>)(event.get(m_inputMapTrkToMIP));
+
+ // Now, each track is connected to a MIP. But some of these MIP clusters
+ // may overlap. We need to identify the cases when that happens and then
+ // * produce a merged cluster
+ // * have each of the tracks pointing to the same merged cluster
+ // First, check for overlaps...
+ Map<Cluster,Track> mapMipToTrack = new HashMap<Cluster,Track>();
+ Map<Cluster,Cluster> mapMipToMergedCluster = new HashMap<Cluster,Cluster>();
+ Map<Cluster,List<Track>> mapMergedClusterToTracks = new HashMap<Cluster,List<Track>>();
+
+ // Find hits for each MIP & which clusters they're inside
+ Map<CalorimeterHit,Set<Cluster>> hitMipMap = new HashMap<CalorimeterHit,Set<Cluster>>();
+ for (Track tr : MapTrkToMIP.keySet()) {
+ if (!inputTrackList.contains(tr)) { throw new AssertionError("Book-keeping error"); }
+ BasicCluster mip = MapTrkToMIP.get(tr);
+ mapMipToTrack.put(mip,tr);
+ for (CalorimeterHit hit : mip.getCalorimeterHits()) {
+ Set<Cluster> mipsOfHit = hitMipMap.get(hit);
+ if (mipsOfHit == null) {
+ mipsOfHit= new HashSet<Cluster>();
+ hitMipMap.put(hit, mipsOfHit);
+ }
+ mipsOfHit.add(mip);
+ }
+ }
+
+ // Look for groups of mips such that
+ // * Every MIP in a group is connected (directly or indirectly)
+ // to every other MIP in the group.
+ // * Every MIP appears in exactly one group.
+ List<Set<Cluster>> mipOverlapSets = new Vector<Set<Cluster>>();
+ for (CalorimeterHit hit : hitMipMap.keySet()) {
+ Set<Cluster> touchedClusters = hitMipMap.get(hit);
+ Set<Set<Cluster>> oldLinkedClusterSets = new HashSet<Set<Cluster>>();
+ for (Cluster clus : touchedClusters) {
+ for (Set<Cluster> currentSet : mipOverlapSets) {
+ if (currentSet.contains(clus)) {
+ oldLinkedClusterSets.add(currentSet);
+ }
+ }
+ }
+ Set<Cluster> newLinkedClusterSet = new HashSet<Cluster>();
+ newLinkedClusterSet.addAll(touchedClusters);
+ for (Set<Cluster> oldSet : oldLinkedClusterSets) {
+ newLinkedClusterSet.addAll(oldSet);
+ mipOverlapSets.remove(oldSet);
+ }
+ mipOverlapSets.add(newLinkedClusterSet);
+ }
+
+ // Verify that each cluster appears in exactly one set
+ List<Cluster> countedClusterList = new Vector<Cluster>();
+ Set<Cluster> countedClusterSet = new HashSet<Cluster>();
+ for (Set<Cluster> currentSet : mipOverlapSets) {
+ countedClusterList.addAll(currentSet);
+ countedClusterSet.addAll(currentSet);
+ }
+ if (countedClusterList.size() != MapTrkToMIP.size()) { throw new AssertionError("Book-keeping error"); }
+ if (countedClusterSet.size() != MapTrkToMIP.size()) { throw new AssertionError("Book-keeping error"); }
+
+ // Do the merge of overlapping MIPs
+ for (Set<Cluster> currentSet : mipOverlapSets) {
+ if (currentSet.size()==0) {
+ throw new AssertionError("Empty set!");
+ } else if (currentSet.size()==1) {
+ Cluster mip = currentSet.iterator().next();
+ mapMipToMergedCluster.put(mip,mip);
+ Track tr = mapMipToTrack.get(mip);
+ List<Track> mergedTracks = new Vector<Track>();
+ mergedTracks.add(tr);
+ mapMergedClusterToTracks.put(mip, mergedTracks);
+ } else {
+ BasicCluster mergedMip = new BasicCluster();
+ List<Track> mergedTracks = new Vector<Track>();
+ Set<CalorimeterHit> mergedHits = new HashSet<CalorimeterHit>();
+ for (Cluster mip : currentSet) {
+ mergedHits.addAll(mip.getCalorimeterHits());
+ Track tr = mapMipToTrack.get(mip);
+ mergedTracks.add(tr);
+ }
+ for (CalorimeterHit hit : mergedHits) {
+ mergedMip.addHit(hit);
+ }
+ for (Cluster clus : currentSet) {
+ mapMipToMergedCluster.put(clus, mergedMip);
+ mapMergedClusterToTracks.put(mergedMip, mergedTracks);
+ }
+ }
+ }
+
+ // Assign MIPs to tracks, taking overlaps into account
+ for (Cluster mergedMip : mapMergedClusterToTracks.keySet()) {
+ List<Track> tracks = mapMergedClusterToTracks.get(mergedMip);
+ if (tracks == null) { throw new AssertionError("Null tracks!"); }
+ if (tracks.size()==0) {
+ throw new AssertionError("Empty track list!");
+ } else if (tracks.size()==1) {
+ // Unique
+ Track tr = tracks.get(0);
+ if (mergedMip.getCalorimeterHits().size() > 5) {
+ // Found a good MIP
+ outputMap.put(tr, mergedMip);
+ outputClustersMips.add(mergedMip);
+ } else {
+ // Didn't find a good mip
+ outputClustersSmall.add(mergedMip);
+ }
+ } else {
+ // Overlap -- can't treat it as a MIP.
+ outputClustersBlocks.add(mergedMip);
+ }
+ }
+
+ // Identify unmatched tracks
+ List<Track> unmatchedTracks = new Vector<Track>();
+ unmatchedTracks.addAll(inputTrackList);
+ unmatchedTracks.removeAll(outputMap.keySet());
+
+ // All done
+ event.put(m_outputMips, outputClustersMips);
+ event.put(m_outputBlocks, outputClustersBlocks);
+ event.put(m_outputSmallClusters, outputClustersSmall);
+ event.put(m_outputUnmatchedTrackListName, unmatchedTracks);
+ return outputMap;
+ }
+}
CVSspam 0.2.8