lcsim/src/org/lcsim/recon/pfa/identifier
diff -N SmallPhotonMaker.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ SmallPhotonMaker.java 21 Mar 2007 00:51:24 -0000 1.1
@@ -0,0 +1,133 @@
+package org.lcsim.recon.pfa.identifier;
+
+import java.util.*;
+import hep.physics.vec.Hep3Vector;
+import hep.physics.vec.BasicHep3Vector;
+import org.lcsim.recon.cluster.structural.FragmentIdentifier;
+import org.lcsim.event.EventHeader;
+import org.lcsim.util.Driver;
+import org.lcsim.event.Cluster;
+import org.lcsim.event.CalorimeterHit;
+import org.lcsim.geometry.Detector;
+import org.lcsim.event.ReconstructedParticle;
+import org.lcsim.event.MCParticle;
+import org.lcsim.event.SimCalorimeterHit;
+
+/**
+ * Given a list of clusters, make ones that are consistent with
+ * fragments AND pass photon selection into small photon clusters.
+ *
+ * Photon selection: Innermost hit is in layer 0-3 of ECAL
+ *
+ * FIXME: I think this could be implemented as a combination of a
+ * filter and SimpleNeutralParticleMaker without the need for a
+ * new class.
+ */
+
+public class SmallPhotonMaker extends SimpleNeutralParticleMaker
+{
+ protected FragmentIdentifier m_fragID = null;
+ public SmallPhotonMaker(FragmentIdentifier fragID) {
+ super(22); // make photons
+ m_fragID = fragID;
+ }
+
+ public void process(EventHeader event)
+ {
+ m_event = event;
+
+ // Input, output:
+ List<Cluster> inputClusterList = event.get(Cluster.class, m_inputClusterListName);
+ List<Cluster> outputClusterList = new Vector<Cluster>();
+ outputClusterList.addAll(inputClusterList); // initially full
+ List<ReconstructedParticle> outputParticleList = new Vector<ReconstructedParticle>();
+
+ for (Cluster clus : inputClusterList) {
+ if (m_fragID.isFragment(clus, event)) {
+ // Small cluster/fragment -- is it photon-like?
+ CalorimeterHit firstHitInECAL = findInnermostHitInECAL(clus);
+ boolean isPhoton = (firstHitInECAL!=null && getLayer(firstHitInECAL)<4);
+ if (isPhoton) {
+ LocalReconstructedParticle part = new LocalReconstructedParticle();
+ part.addCluster(clus);
+ double clusterEnergy = estimateClusterEnergy(clus); // clumsy, not a real calibration...
+ double particleEnergy = Math.sqrt(clusterEnergy*clusterEnergy + m_mass*m_mass);
+ part.setEnergy(particleEnergy);
+ // Set the other particle properties that are needed to render
+ // properly in the event display.
+ part.setMomentum(computeMomentum(particleEnergy, clus));
+ part.setReferencePoint(new BasicHep3Vector(0,0,0));
+ part.setCharge(0);
+ // Add to the output list
+ outputParticleList.add(part);
+ outputClusterList.remove(clus);
+ }
+ if (m_debug) {
+ String printme = new String();
+ printme += "DEBUG: This fragment with ";
+ printme += clus.getCalorimeterHits().size();
+ printme += " hits has first ECAL layer ";
+ if (firstHitInECAL==null) {
+ printme += "[null]";
+ } else {
+ printme += getLayer(firstHitInECAL);
+ }
+ printme += " => isPhoton="+isPhoton;
+ printme += ". True contributions: ";
+ Map<MCParticle, List<CalorimeterHit>> tmpMap = new HashMap<MCParticle, List<CalorimeterHit>>();
+ for (CalorimeterHit hit : clus.getCalorimeterHits()) {
+ SimCalorimeterHit simhit = (SimCalorimeterHit) (hit);
+ for (int i=0; i<simhit.getMCParticleCount(); i++) {
+ MCParticle hitPart = simhit.getMCParticle(i);
+ if ( ! (tmpMap.keySet().contains(hitPart)) ) {
+ tmpMap.put(hitPart, new Vector<CalorimeterHit>());
+ }
+ tmpMap.get(hitPart).add(hit);
+ }
+ }
+ for (MCParticle hitPart : tmpMap.keySet()) {
+ printme += " ";
+ printme += hitPart.getType().getName();
+ printme += " (E=";
+ printme += hitPart.getEnergy();
+ printme += ", hits=";
+ printme += tmpMap.get(hitPart).size();
+ printme += ")";
+ }
+ System.out.println(printme);
+ }
+ }
+ }
+
+ event.put(m_outputParticleListName, outputParticleList);
+ event.put(m_outputClusterListName, outputClusterList);
+ }
+
+ protected String m_outputClusterListName;
+ public void setOutputClusterList(String name) { m_outputClusterListName = name; }
+
+
+ protected CalorimeterHit findInnermostHitInECAL(Cluster clus) {
+ CalorimeterHit innermostHit = null;
+ for (CalorimeterHit hit : clus.getCalorimeterHits()) {
+ int layer = getLayer(hit);
+ org.lcsim.geometry.Subdetector subdet = hit.getSubdetector();
+ if ( ! subdet.isCalorimeter() ) { throw new AssertionError("Cluster hit outside calorimeter"); }
+ String name = subdet.getName();
+ if (name.compareTo("EMBarrel") == 0 || name.compareTo("EMEndcap") == 0) {
+ // EM -- OK
+ if (innermostHit==null || getLayer(innermostHit)>layer) {
+ innermostHit = hit;
+ }
+ }
+ }
+ return innermostHit;
+ }
+
+ protected int getLayer(CalorimeterHit hit) {
+ org.lcsim.geometry.IDDecoder id = hit.getIDDecoder();
+ id.setID(hit.getCellID());
+ int layer = id.getLayer();
+ return layer;
+ }
+}