8 added files
lcsim/src/org/lcsim/contrib/uiowa/util
diff -N Associator.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ Associator.java 29 Sep 2005 21:05:36 -0000 1.1
@@ -0,0 +1,50 @@
+package util;
+
+import java.util.List;
+import org.lcsim.event.ReconstructedParticle;
+import org.lcsim.event.MCParticle;
+import org.lcsim.event.Cluster;
+import org.lcsim.event.CalorimeterHit;
+import org.lcsim.event.SimCalorimeterHit;
+import org.lcsim.event.Track;
+import org.lcsim.event.EventHeader;
+
+/**
+ * Truth association.
+ * This interface allows you to map between reco and sim
+ * objects. In general, this is not a 1:1 mapping -- for
+ * example, a reconstructed cluster can have contributions
+ * from several MC particles, and a single MC particle can
+ * contribute to several different clusters. To allow for
+ * this, the methods return an ordered list of matches
+ * (so that the first item in the list is the best match,
+ * and the last is the worst match). The metric used to
+ * determine which is "best" is implementation-defined,
+ * but should have a strict total ordering.
+ *
+ * One common use case is to need the best available
+ * 1:1 mapping. This is provided by the bestAssoc methods.
+ * Since this can fail, these methods are allowed to throw
+ * an AssociationFailedException. How the match is made
+ * and what constitutes failure are implementation-defined,
+ * but a minimum sanity requirement is that, when successful,
+ * bestAssoc(x) == assoc(x).first
+ *
+ * If these routines are somehow called when analysing
+ * experimental data, they should throw an AssertionError.
+ */
+
+public interface Associator
+{
+ public List<MCParticle> associateHitToMCParticles(SimCalorimeterHit hit);
+ public List<SimCalorimeterHit> associateMCParticleToHits(MCParticle part);
+
+ public List<MCParticle> associateClusterToMCParticles(Cluster clus);
+ public List<Cluster> associateMCParticleToClusters(MCParticle part);
+
+ public List<MCParticle> associateTrackToMCParticles(Track track);
+ public List<Track> associateMCParticleToTracks(MCParticle part);
+
+ public List<MCParticle> associateParticleToMCParticles(ReconstructedParticle part);
+ public List<ReconstructedParticle> associateMCParticleToParticles(MCParticle part);
+}
lcsim/src/org/lcsim/contrib/uiowa/util
diff -N BasicObjectToClusterWrapper.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ BasicObjectToClusterWrapper.java 29 Sep 2005 21:05:36 -0000 1.1
@@ -0,0 +1,81 @@
+package util; // package org.lcsim.recon.cluster.util;
+
+import java.util.List;
+import java.util.ArrayList;
+
+import org.lcsim.recon.cluster.util.BasicCluster;
+import org.lcsim.event.CalorimeterHit;
+import org.lcsim.event.Cluster;
+
+/**
+ * Interface describing a class that takes an object and turns it
+ * into a cluster (or takes a list of objects and turns it
+ * into a list of clusters). If it can't handle an object, it throws
+ * an UnwrappableObjectException. In this implementation, the
+ * input objects must be instances of Cluster or CalorimeterHit.
+ */
+
+public class BasicObjectToClusterWrapper implements ObjectToClusterWrapper
+{
+ /**
+ * Simple constructor
+ */
+ public BasicObjectToClusterWrapper() {}
+
+ /**
+ * Wrap one object (Cluster or CalorimeterHit) into a Cluster
+ */
+ public Cluster wrapObject(Object obj) throws UnwrappableObjectException
+ {
+ if (obj instanceof Cluster) {
+ // Already a cluster
+ Cluster clus = (Cluster) obj;
+ return clus;
+ } else if (obj instanceof CalorimeterHit) {
+ CalorimeterHit hit = (CalorimeterHit) obj;
+ return wrapCalorimeterHit(hit);
+ } else {
+ throw new UnwrappableObjectException("Don't knowhow to wrap class "+obj.getClass().getName());
+ }
+ }
+
+ /**
+ * Wrap a list of objects (Cluster or CalorimeterHit) into a newly
+ * created list of Clusters.
+ */
+ public List<Cluster> wrapListOfObjects(List inputList) throws UnwrappableObjectException {
+ List<Cluster> emptyList = new ArrayList<Cluster>();
+ try {
+ return wrapListOfObjects(inputList, emptyList);
+ } catch (UnwrappableObjectException x) {
+ throw x;
+ }
+ }
+
+ /**
+ * Wrap a list of objects into a list of clusters, allowing user to
+ * specify the empty list (outputList) which will hold the clusters.
+ */
+ public List<Cluster> wrapListOfObjects(List inputList, List<Cluster> outputList) throws UnwrappableObjectException {
+ outputList.clear();
+ if (!outputList.isEmpty()) { throw new AssertionError("Non-empty output list at start of method."); }
+ for (Object obj : inputList) {
+ try {
+ Cluster clus = wrapObject(obj);
+ outputList.add(clus);
+ } catch (UnwrappableObjectException x) {
+ throw x;
+ }
+ }
+ return outputList;
+ }
+
+ /**
+ * Internal utility routine to wrap a CalorimeterHit into a Cluster
+ */
+ protected Cluster wrapCalorimeterHit(CalorimeterHit hit) {
+ BasicCluster clus = new BasicCluster();
+ clus.addHit(hit);
+ return clus;
+ }
+}
lcsim/src/org/lcsim/contrib/uiowa/util
diff -N EnergyAssociator.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ EnergyAssociator.java 29 Sep 2005 21:05:36 -0000 1.1
@@ -0,0 +1,249 @@
+package util;
+
+import java.util.List;
+import java.util.Vector;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Comparator;
+import java.util.Collections;
+
+import org.lcsim.event.ReconstructedParticle;
+import org.lcsim.event.MCParticle;
+import org.lcsim.event.Cluster;
+import org.lcsim.event.TrackerHit;
+import org.lcsim.event.CalorimeterHit;
+import org.lcsim.event.SimCalorimeterHit;
+import org.lcsim.event.Track;
+import org.lcsim.event.EventHeader;
+
+/**
+ * A truth associator that works by comparing energy
+ * deposits. The match with the greatest amount or
+ * proportion of matched energy (after correcting
+ * by the sampling fraction) is the best.
+ */
+
+class EnergyAssociator implements Associator
+{
+ protected List<SimCalorimeterHit> m_hits;
+ protected List<MCParticle> m_mcParticles;
+ protected List<Track> m_tracks;
+ protected List<Cluster> m_clusters;
+ protected List<ReconstructedParticle> m_reconParticles;
+ protected EventHeader m_event;
+
+ public EnergyAssociator(EventHeader event)
+ {
+ // Initially, use defaults that people will expect:
+ // Calorimeter hits:
+ List<SimCalorimeterHit> newList = new Vector<SimCalorimeterHit>();
+ newList.addAll(event.getSimCalorimeterHits("EcalBarrHits"));
+ newList.addAll(event.getSimCalorimeterHits("HcalBarrHits"));
+ newList.addAll(event.getSimCalorimeterHits("EcalEndcapHits"));
+ newList.addAll(event.getSimCalorimeterHits("HcalEndcapHits"));
+ setCalorimeterHits(newList);
+ // MC Particles
+ setMCParticles(event.getMCParticles());
+ // Tracks
+ setTracks(event.getTracks());
+ // Reconstructed particles
+ setReconstructedParticles(event.get(ReconstructedParticle.class, event.MCFASTRECONSTRUCTEDPARTICLES));
+
+ m_event = event;
+ }
+
+ public void setCalorimeterHits(List<SimCalorimeterHit> hits) { m_hits = hits; }
+ public void setMCParticles(List<MCParticle> particles) { m_mcParticles = particles; }
+ public void setTracks(List<Track> tracks) { m_tracks = tracks; }
+ public void setClusters(List<Cluster> clusters) { m_clusters = clusters; }
+ public void setReconstructedParticles(List<ReconstructedParticle> particles) { m_reconParticles = particles; }
+ public List<SimCalorimeterHit> getCalorimeterHits() { return m_hits; }
+ public List<MCParticle> getMCParticles() { return m_mcParticles; }
+ public List<Track> getTracks() { return m_tracks; }
+ public List<Cluster> getClusters() { return m_clusters; }
+ public List<ReconstructedParticle> getReconstructedParticles() { return m_reconParticles; }
+
+ /**
+ * Given a SimCalorimeterHit, returns a list of all MCParticles that
+ * contributed, sorted by amount of energy contributed.
+ */
+ public List<MCParticle> associateHitToMCParticles(SimCalorimeterHit hit)
+ {
+ SortMCList comp = new SortMCList(hit);
+ List<MCParticle> output = comp.contributingMCParticles();
+ Collections.sort(output, comp);
+ return output;
+ }
+ /**
+ * Given an MCParticle, returns a list of all SimCalorimeterHits to
+ * which it contributes, sorted by purity.
+ */
+ public List<SimCalorimeterHit> associateMCParticleToHits(MCParticle part)
+ {
+ if (m_mapMCParticlesToHits == null) { makeMapMCParticlesToHits(); }
+ // Clone it, to make sure our internals don't get messed up by an enthusiastic user
+ ArrayList<SimCalorimeterHit> internalHits = m_mapMCParticlesToHits.get(part);
+ ArrayList<SimCalorimeterHit> hits = new ArrayList<SimCalorimeterHit>(internalHits);
+ SortHitList comp = new SortHitList(part);
+ Collections.sort(hits, comp);
+ return hits;
+ }
+
+ /**
+ * Given a Cluster, returns a list of all MCParticles that
+ * contributed, sorted by amount of energy contributed.
+ */
+ public List<MCParticle> associateClusterToMCParticles(Cluster clus)
+ {
+ // Use hits. They have to be cast to SimCalorimeterHit objects first...
+ List<CalorimeterHit> hits = clus.getCalorimeterHits();
+ List<SimCalorimeterHit> simHits = new Vector<SimCalorimeterHit>();
+ for (CalorimeterHit hit : hits) {
+ SimCalorimeterHit simHit = (SimCalorimeterHit) hit;
+ simHits.add(simHit);
+ }
+ // Now do the sort/extraction
+ SortMCList comp = new SortMCList(simHits);
+ List<MCParticle> output = comp.contributingMCParticles();
+ Collections.sort(output, comp);
+ return output;
+ }
+
+ /**
+ * Given an MCParticle, returns a list of all Clusters to which it
+ * contributes, sorted by amount of energy contributed.
+ */
+ public List<Cluster> associateMCParticleToClusters(MCParticle part)
+ {
+ throw new AssertionError("Not yet implemented");
+ }
+
+ public List<MCParticle> associateTrackToMCParticles(Track track)
+ {
+ List<TrackerHit> hits = track.getTrackerHits();
+ throw new AssertionError("Not yet implemented");
+ }
+ public List<Track> associateMCParticleToTracks(MCParticle part)
+ {
+ throw new AssertionError("Not yet implemented");
+ }
+
+ public List<MCParticle> associateParticleToMCParticles(ReconstructedParticle part)
+ {
+ throw new AssertionError("Not yet implemented");
+ }
+ public List<ReconstructedParticle> associateMCParticleToParticles(MCParticle part)
+ {
+ throw new AssertionError("Not yet implemented");
+ }
+
+ class SortHitList implements Comparator<SimCalorimeterHit>
+ {
+ MCParticle m_part;
+ public SortHitList(MCParticle part) {
+ m_part = part;
+ }
+ public int compare(SimCalorimeterHit hit1, SimCalorimeterHit hit2) {
+ // Compute purity in each
+ double purity1 = getPurity(hit1);
+ double purity2 = getPurity(hit2);
+ if (purity1 > purity2) {
+ return +1;
+ } else if (purity1 < purity2) {
+ return -1;
+ } else if (purity1 == purity2) {
+ return 0;
+ } else {
+ // NaN or similar
+ throw new AssertionError("Hits "+hit1+","+hit2+": an purity is undefined. Purities: "+purity1+","+purity2);
+ }
+ }
+ protected double getPurity(SimCalorimeterHit hit) {
+ double partEnergy = 0.0;
+ double totalEnergy = 0.0;
+ int nContributingParticles = hit.getMCParticleCount();
+ for (int i=0; i<nContributingParticles; i++) {
+ MCParticle part = hit.getMCParticle(i);
+ double energy = hit.getContributedEnergy(i);
+ totalEnergy += energy;
+ if (part == m_part) {
+ partEnergy += energy;
+ }
+ }
+ return partEnergy / totalEnergy;
+ }
+ }
+
+ class SortMCList implements Comparator<MCParticle>
+ {
+ protected Map<MCParticle, Double> m_mapParticleToEnergy = null;
+
+ public SortMCList(SimCalorimeterHit hit) {
+ m_mapParticleToEnergy = new HashMap<MCParticle, Double> ();
+ int nContributingParticles = hit.getMCParticleCount();
+ for (int i=0; i<nContributingParticles; i++) {
+ MCParticle part = hit.getMCParticle(i);
+ double energy = hit.getContributedEnergy(i);
+ m_mapParticleToEnergy.put(part, new Double(energy));
+ }
+ }
+
+ public SortMCList(List<SimCalorimeterHit> hits) {
+ m_mapParticleToEnergy = new HashMap<MCParticle, Double> ();
+ for (SimCalorimeterHit hit : hits) {
+ int nContributingParticles = hit.getMCParticleCount();
+ for (int i=0; i<nContributingParticles; i++) {
+ MCParticle part = hit.getMCParticle(i);
+ double totalEnergy = hit.getContributedEnergy(i);
+ Double previousTotalEnergy = m_mapParticleToEnergy.get(part);
+ if (previousTotalEnergy != null) {
+ totalEnergy += previousTotalEnergy.doubleValue();
+ }
+ m_mapParticleToEnergy.put(part, new Double(totalEnergy));
+ }
+ }
+ }
+
+ public List<MCParticle> contributingMCParticles() {
+ ArrayList<MCParticle> output = new ArrayList<MCParticle>();
+ output.addAll(m_mapParticleToEnergy.keySet());
+ return output;
+ }
+
+ public int compare(MCParticle o1, MCParticle o2) {
+ double energy1 = (m_mapParticleToEnergy.get(o1)).doubleValue();
+ double energy2 = (m_mapParticleToEnergy.get(o2)).doubleValue();
+ if (energy1 > energy2) {
+ return +1;
+ } else if (energy1 < energy2) {
+ return -1;
+ } else if (energy1 == energy2) {
+ return 0;
+ } else {
+ // NaN or similar
+ throw new AssertionError("Particles "+o1+","+o2+": an energy is undefined. Energies: "+energy1+","+energy2);
+ }
+ }
+ }
+
+ protected Map<MCParticle, ArrayList<SimCalorimeterHit> > m_mapMCParticlesToHits;
+
+ protected void makeMapMCParticlesToHits()
+ {
+ // Make a map: MCParticle --> list of hits
+ m_mapMCParticlesToHits = new HashMap<MCParticle, ArrayList<SimCalorimeterHit> >();
+ for (SimCalorimeterHit hit : getCalorimeterHits()) {
+ int nContributingParticles = hit.getMCParticleCount();
+ for (int i=0; i<nContributingParticles; i++) {
+ MCParticle contributingPart = hit.getMCParticle(i);
+ ArrayList<SimCalorimeterHit> assocHits = m_mapMCParticlesToHits.get(contributingPart);
+ if (assocHits == null) {
+ assocHits = new ArrayList<SimCalorimeterHit>();
+ m_mapMCParticlesToHits.put(contributingPart, assocHits);
+ }
+ assocHits.add(hit);
+ }
+ }
+ }
+}
lcsim/src/org/lcsim/contrib/uiowa/util
diff -N ObjectToClusterWrapper.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ObjectToClusterWrapper.java 29 Sep 2005 21:05:36 -0000 1.1
@@ -0,0 +1,32 @@
+package util; // package org.lcsim.recon.cluster.util;
+
+import java.util.List;
+import org.lcsim.event.Cluster;
+
+/**
+ * Interface describing a wrapper that takes an arbitrary object and
+ * turns it into a cluster (or takes a list of objects and turns it
+ * into a list of clusters). If it can't handle an object, it throws
+ * an UnwrappableObjectException.
+ */
+
+public interface ObjectToClusterWrapper
+{
+ /**
+ * Wrap one object into a cluster
+ */
+ public Cluster wrapObject(Object obj) throws UnwrappableObjectException;
+
+ /**
+ * Wrap a list of objects into a list of clusters.
+ */
+ public List<Cluster> wrapListOfObjects(List inputList) throws UnwrappableObjectException;
+
+ /**
+ * Wrap a list of objects into a list of clusters, allowing user to
+ * specify the empty list (outputList) which will hold the clusters.
+ */
+ public List<Cluster> wrapListOfObjects(List inputList, List<Cluster> outputList) throws UnwrappableObjectException;
+
+}
+
lcsim/src/org/lcsim/contrib/uiowa/util
diff -N UnwrappableObjectException.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ UnwrappableObjectException.java 29 Sep 2005 21:05:36 -0000 1.1
@@ -0,0 +1,8 @@
+package util; // package org.lcsim.recon.cluster.util;
+
+import java.lang.String;
+
+public class UnwrappableObjectException extends java.lang.Exception {
+ public UnwrappableObjectException(String m) { super(m); }
+}
+
lcsim/src/org/lcsim/contrib/uiowa/util/decision
diff -N DecisionMakerPair.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ DecisionMakerPair.java 29 Sep 2005 21:05:37 -0000 1.1
@@ -0,0 +1,10 @@
+package util.decision; //package org.lcsim.util.decision;
+
+import java.io.*;
+import java.util.*;
+
+public interface DecisionMakerPair<E,T> {
+
+ public boolean valid(E objectToTest1, T objectToTest2);
+
+}
lcsim/src/org/lcsim/contrib/uiowa/util/decision
diff -N DecisionMakerSingle.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ DecisionMakerSingle.java 29 Sep 2005 21:05:37 -0000 1.1
@@ -0,0 +1,11 @@
+package util.decision; //package org.lcsim.util.decision;
+
+/**
+ * This interface describes a decision-maker which takes a single
+ * object as input. It is templated...
+ */
+public interface DecisionMakerSingle<E> {
+
+ public boolean valid(E objectToTest);
+
+}
lcsim/src/org/lcsim/contrib/uiowa/util/decision
diff -N ListFilter.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ListFilter.java 29 Sep 2005 21:05:37 -0000 1.1
@@ -0,0 +1,26 @@
+package util.decision; //package org.lcsim.util.decision;
+
+import java.util.*;
+
+public class ListFilter<E>
+{
+ public ListFilter (DecisionMakerSingle<E> dec) {
+ m_dec = dec;
+ }
+
+ public List<E> filterList(List<E> inputList, List<E> outputList) {
+ for (E item : inputList) {
+ if (m_dec.valid(item)) {
+ outputList.add(item);
+ }
+ }
+ return outputList;
+ }
+
+ public List<E> filterList(List<E> inputList) {
+ List<E> emptyList = new ArrayList<E>();
+ return filterList(inputList, emptyList);
+ }
+
+ protected DecisionMakerSingle<E> m_dec = null;
+}
CVSspam 0.2.8