LISTSERV mailing list manager LISTSERV 16.5

Help for HPS-SVN Archives


HPS-SVN Archives

HPS-SVN Archives


HPS-SVN@LISTSERV.SLAC.STANFORD.EDU


View:

Message:

[

First

|

Previous

|

Next

|

Last

]

By Topic:

[

First

|

Previous

|

Next

|

Last

]

By Author:

[

First

|

Previous

|

Next

|

Last

]

Font:

Proportional Font

LISTSERV Archives

LISTSERV Archives

HPS-SVN Home

HPS-SVN Home

HPS-SVN  December 2014

HPS-SVN December 2014

Subject:

r1761 - /java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/

From:

[log in to unmask]

Reply-To:

Notification of commits to the hps svn repository <[log in to unmask]>

Date:

Tue, 16 Dec 2014 23:15:45 -0000

Content-Type:

text/plain

Parts/Attachments:

Parts/Attachments

text/plain (817 lines)

Author: [log in to unmask]
Date: Tue Dec 16 15:15:39 2014
New Revision: 1761

Log:
Snapshot of work on new clustering package including better doc and API additions.  Several simple Clusterer algorithms are implemented now and seem to basically work.

Added:
    java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/SimpleClasInnerCalClusterer.java
      - copied, changed from r1759, java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/SimpleInnerCalClusterer.java
Removed:
    java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/SimpleInnerCalClusterer.java
Modified:
    java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/AbstractClusterer.java
    java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/ClusterDriver.java
    java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/ClusterUtilities.java
    java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/Clusterer.java
    java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/ClustererFactory.java
    java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/LegacyClusterer.java

Modified: java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/AbstractClusterer.java
 =============================================================================
--- java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/AbstractClusterer.java	(original)
+++ java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/AbstractClusterer.java	Tue Dec 16 15:15:39 2014
@@ -2,20 +2,131 @@
 
 import java.util.List;
 
+import org.hps.conditions.database.DatabaseConditionsManager;
+import org.lcsim.conditions.ConditionsEvent;
 import org.lcsim.event.CalorimeterHit;
 import org.lcsim.event.Cluster;
+import org.lcsim.event.EventHeader;
 import org.lcsim.geometry.subdetector.HPSEcal3;
 import org.lcsim.geometry.subdetector.HPSEcal3.NeighborMap;
 
+/**
+ * This is an abstract class that {@link Clusterer} classes should implement
+ * to perform a clustering algorithm on a <code>CalorimeterHit</code> collection.
+ * The sub-class should implement {@link #createClusters(List)} which is 
+ * the method that should perform the clustering.
+ * 
+ * @author Jeremy McCormick <[log in to unmask]>
+ */
 public abstract class AbstractClusterer implements Clusterer {
     
-    HPSEcal3 ecal;
-    NeighborMap neighborMap;
+    protected HPSEcal3 ecal;
+    protected NeighborMap neighborMap;
+    protected double[] cuts;
+    protected double[] defaultCuts;
+    protected String[] cutNames;
     
-    public void setEcalSubdetector(HPSEcal3 ecal) {
-        this.ecal = ecal;
+    /**
+     * This is the primary method for sub-classes to implement their clustering algorithm.
+     * @param hits
+     * @return
+     */
+    public abstract List<Cluster> createClusters(EventHeader event, List<CalorimeterHit> hits);
+    
+    /**
+     * Detector setup performed here to get reference to ECAL subdetector and neighbor mapping.
+     */
+    @Override
+    public void conditionsChanged(ConditionsEvent event) {
+        // Default setup of ECAL subdetector.
+        this.ecal = (HPSEcal3) DatabaseConditionsManager.getInstance().getDetectorObject().getSubdetector("Ecal");
         this.neighborMap = ecal.getNeighborMap();
     }
     
-    public abstract List<Cluster> createClusters(List<CalorimeterHit> hits);    
+    /**
+     * By default nothing is done in this method, but start of job initialization can happen here like reading
+     * cut settings into instance variables for convenience.  This is called in the <code>startOfData</code>
+     * method of {@link ClusterDriver}.
+     */
+    public void initialize() {
+    }    
+        
+    /**
+     * Default constructor which takes names of cuts and their default values.
+     * Even if there are no cuts, these should be arrays of length 0 instead of null.
+     * @param cutNames The names of the cuts for this clustering algorithm.
+     * @param defaultCuts The default cut values for the algorithm matching the cutNames ordering.
+     * @throw IllegalArgumentException if the arguments are null or the arrays are different lengths.
+     */
+    protected AbstractClusterer(String cutNames[], double[] defaultCuts) {
+        if (cutNames == null) {
+            throw new IllegalArgumentException("The cutNames is set to null.");
+        }
+        if (defaultCuts == null) {
+            throw new IllegalArgumentException("The defaultCuts is set to null.");
+        }
+        if (cutNames.length != defaultCuts.length) {
+            throw new IllegalArgumentException("The cutNames and defaultCuts are not the same length.");
+        }
+        this.cutNames = cutNames;
+        this.defaultCuts = defaultCuts;
+        this.cuts = defaultCuts;
+    }
+            
+    public void setCuts(double[] cuts) {
+        if (cuts.length != this.cutNames.length) {
+            throw new IllegalArgumentException("The cuts array has the wrong length: " + cuts.length);
+        }
+        this.cuts = cuts;
+    }
+    
+    public double[] getCuts() {
+        return cuts;
+    }
+    
+    public double getCut(String name) {
+         int index = indexFromName(name);
+         if (index == -1) {
+             throw new IllegalArgumentException("There is no cut called " + name + " defined by this clusterer.");
+         }
+         return getCut(index);
+    }
+    
+    public double getCut(int index) {
+        if (index > cuts.length || index < 0) {
+            throw new IndexOutOfBoundsException("The index " + index + " is out of bounds for cuts array.");
+        }
+        return cuts[index];
+    }
+         
+    public String[] getCutNames() {
+        return cutNames;
+    }    
+    
+    @Override
+    public void setCut(int index, double value) {
+        cuts[index] = value;
+    }
+
+    public boolean isDefaultCuts() {
+        return cuts == defaultCuts;
+    }
+    
+    public double[] getDefaultCuts() {
+        return defaultCuts;
+    }
+    
+    public void setCut(String name, double value) {
+        int index = indexFromName(name);
+        cuts[index] = value;
+    }
+        
+    protected int indexFromName(String name) {
+        for (int index = 0; index < cuts.length; index++) {
+            if (getCutNames()[index] == name) {
+                return index;
+            }                 
+        }
+        return -1;
+    }       
 }

Modified: java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/ClusterDriver.java
 =============================================================================
--- java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/ClusterDriver.java	(original)
+++ java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/ClusterDriver.java	Tue Dec 16 15:15:39 2014
@@ -1,6 +1,7 @@
 package org.hps.recon.ecal.cluster;
 
 import java.util.List;
+import java.util.logging.Logger;
 
 import org.lcsim.event.CalorimeterHit;
 import org.lcsim.event.Cluster;
@@ -10,10 +11,18 @@
 import org.lcsim.geometry.subdetector.HPSEcal3;
 import org.lcsim.lcio.LCIOConstants;
 import org.lcsim.util.Driver;
+import org.lcsim.util.log.LogUtil;
+import org.lcsim.util.log.BasicFormatter;
 
 /**
- * This is a basic Driver that creates Cluster collections through the
- * Clusterer interface.
+ * <p>
+ * This is a basic Driver that creates ECAL <code>Cluster</code> collections 
+ * through the {@link Clusterer} interface.
+ * <p>
+ * A specific clustering engine can be created with the {@link #setClusterer(String)} method
+ * which will use a factory to create it by name.  The cuts of the {@link Clusterer}
+ * can be set generically with the {@link #setCuts(double[])} method.  
+ * 
  * @author Jeremy McCormick <[log in to unmask]>
  */
 public class ClusterDriver extends Driver {
@@ -28,28 +37,35 @@
     protected boolean skipNoClusterEvents = false;
     protected boolean writeClusterCollection = true;
     protected boolean storeHits = true;
+    protected double[] cuts;
+    protected Logger logger = LogUtil.create(ClusterDriver.class, new BasicFormatter(ClusterDriver.class.getSimpleName()));
     
     protected ClusterDriver() {
+        logger.config("initializing");
     }
     
     public void setEcalName(String ecalName) {
         this.ecalName = ecalName;
     }
     
-    public void setOutputClusterCollectionName(String outputClusterCollectionName) {
+    public void setOutputClusterCollectionName(String outputClusterCollectionName) {        
         this.outputClusterCollectionName = outputClusterCollectionName;
+        this.getLogger().config("outputClusterCollectionName = " + this.outputClusterCollectionName);
     }
     
     public void setInputHitCollectionName(String inputHitCollectionName) {
         this.inputHitCollectionName = inputHitCollectionName;
+        this.getLogger().config("inputClusterCollectionName = " + this.inputHitCollectionName);
     }
     
     public void setSkipNoClusterEvents(boolean skipNoClusterEvents) {
-        this.skipNoClusterEvents = skipNoClusterEvents;
+        this.skipNoClusterEvents = skipNoClusterEvents;       
+        this.getLogger().config("skipNoClusterEvents = " + this.skipNoClusterEvents);
     }
     
     public void setWriteClusterCollection(boolean writeClusterCollection) {
         this.writeClusterCollection = writeClusterCollection;
+        this.getLogger().config("writeClusterCollection = " + this.writeClusterCollection);
     }
     
     public void setRaiseErrorNoHitCollection(boolean raiseErrorNoHitCollection) {
@@ -72,7 +88,12 @@
         this.createEmptyClusterCollection = createEmptyClusterCollection;
     }
     
+    public void setCuts(double[] cuts) {
+        this.cuts = cuts;
+    }
+    
     public void detectorChanged(Detector detector) {
+        logger.fine("detectorChanged");
         Subdetector subdetector = detector.getSubdetector(ecalName);
         if (subdetector == null) {
             throw new RuntimeException("There is no subdetector called " + ecalName + " in the detector.");
@@ -84,45 +105,62 @@
     }
     
     public void startOfData() {
+        logger.fine("startOfData");
         if (this.clusterer == null) {
             throw new RuntimeException("The clusterer was never initialized.");
         }
-        if (this.clusterer instanceof AbstractClusterer) {
-            ((AbstractClusterer)clusterer).setEcalSubdetector(ecal);
-        }
+        if (this.cuts != null) {
+            logger.config("setting cuts on clusterer");
+            this.clusterer.setCuts(cuts);
+            for (int cutIndex = 0; cutIndex < clusterer.getCuts().length; cutIndex++) {
+                logger.config("  " + this.clusterer.getCutNames()[cutIndex] + " = " + this.clusterer.getCut(cutIndex));
+            }            
+        } 
+        logger.config("initializing clusterer");
+        this.clusterer.initialize();
     }
     
     /**
      * This method implements the default clustering procedure based on input parameters.
      */
     public void process(EventHeader event) {
+        this.getLogger().fine("processing event #" + event.getEventNumber());
         if (event.hasCollection(CalorimeterHit.class, inputHitCollectionName)) {       
             List<CalorimeterHit> hits = event.get(CalorimeterHit.class, inputHitCollectionName);
-            List<Cluster> clusters = clusterer.createClusters(hits);
+            this.getLogger().fine("Input hit collection " + inputHitCollectionName + " has " + hits.size() + " hits.");
+            List<Cluster> clusters = clusterer.createClusters(event, hits);
             if (clusters == null) {
-                throw new RuntimeException("The clusterer returned a null pointer.");
+                throw new RuntimeException("The clusterer returned null from its createClusters method.");
             }
             if (clusters.isEmpty() && this.skipNoClusterEvents) {
+                logger.finer("Skipping event with no clusters.");
                 throw new NextEventException();
             }
             if (event.hasCollection(Cluster.class, this.outputClusterCollectionName)) {
-                throw new RuntimeException("There is already a cluster collection called " + this.outputClusterCollectionName);
+                this.getLogger().severe("There is already a cluster collection called " + this.outputClusterCollectionName);
+                throw new RuntimeException("Cluster collection already exists in event.");
             }
             int flags = 0;
             if (this.storeHits) {
                 flags = 1 << LCIOConstants.CLBIT_HITS;
             }
             if (!clusters.isEmpty() || this.createEmptyClusterCollection) {
+                logger.finer("writing " + clusters.size() + " clusters to collection " + outputClusterCollectionName);
                 event.put(outputClusterCollectionName, clusters, Cluster.class, flags);
                 if (!this.writeClusterCollection) {
+                    logger.finer("Collection is set to transient and will not be persisted.");
                     event.getMetaData(clusters).setTransient(true);
                 }
             }
         } else {
-            this.getLogger().warning("The input hit collection " + this.inputHitCollectionName + " is missing from the event.");
+            this.getLogger().severe("The input hit collection " + this.inputHitCollectionName + " is missing from the event.");
             if (this.raiseErrorNoHitCollection) {
-                throw new RuntimeException("The expected hit collection " + this.inputHitCollectionName + " is missing from the event.");
+                throw new RuntimeException("The expected input hit collection is missing from the event.");
             }
         }
     }
+    
+    public Logger getLogger() {
+       return logger;
+    }
 }

Modified: java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/ClusterUtilities.java
 =============================================================================
--- java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/ClusterUtilities.java	(original)
+++ java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/ClusterUtilities.java	Tue Dec 16 15:15:39 2014
@@ -1,5 +1,6 @@
 package org.hps.recon.ecal.cluster;
 
+import java.util.Comparator;
 import java.util.HashSet;
 import java.util.LinkedHashMap;
 import java.util.List;
@@ -7,13 +8,21 @@
 import java.util.Set;
 
 import org.lcsim.event.CalorimeterHit;
+import org.lcsim.event.Cluster;
+import org.lcsim.event.base.BaseCluster;
 import org.lcsim.geometry.subdetector.HPSEcal3;
 
+/**
+ * This is a set of simple clustering utility methods.
+ */
 public final class ClusterUtilities {
     
     private ClusterUtilities() {        
     }
 
+    /**
+     * Create a map of IDs to their hits.
+     */
     public static Map<Long, CalorimeterHit> createHitMap(List<CalorimeterHit> hits) {
         Map<Long, CalorimeterHit> hitMap = new LinkedHashMap<Long, CalorimeterHit>();
         for (CalorimeterHit hit : hits) {
@@ -23,7 +32,7 @@
     }
     
     /**
-     * Given a hit, find its list of neighboring crystals that have hits and return their IDs.
+     * Given a hit, find the list of neighboring crystal IDs that also have hits.
      * @param hit The input hit.
      * @param hitMap The hit map with all the collection's hits.
      * @return The set of neighboring hit IDs.
@@ -38,4 +47,30 @@
         }
         return neighborHitIDs;
     }
+    
+    /**
+     * Create a basic cluster from a list of hits.
+     * @param clusterHits The list of hits.
+     * @return The basic cluster.
+     */
+    protected static Cluster createBasicCluster(List<CalorimeterHit> clusterHits) {
+        BaseCluster cluster = new BaseCluster();
+        double totalEnergy = 0;
+        for (CalorimeterHit clusterHit : clusterHits) {
+            cluster.addHit(clusterHit);
+            totalEnergy += clusterHit.getCorrectedEnergy();
+        }
+        cluster.setEnergy(totalEnergy);        
+        return cluster;
+    }
+    
+    /**
+     * Compare CalorimeterHit objects by their energy.
+     */
+    public static class HitEnergyComparator implements Comparator<CalorimeterHit> {
+        @Override
+        public int compare(CalorimeterHit o1, CalorimeterHit o2) {
+            return Double.compare(o1.getCorrectedEnergy(), o2.getCorrectedEnergy());
+        }
+    }    
 }

Modified: java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/Clusterer.java
 =============================================================================
--- java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/Clusterer.java	(original)
+++ java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/Clusterer.java	Tue Dec 16 15:15:39 2014
@@ -2,11 +2,85 @@
 
 import java.util.List;
 
+import org.lcsim.conditions.ConditionsListener;
 import org.lcsim.event.CalorimeterHit;
 import org.lcsim.event.Cluster;
-import org.lcsim.geometry.subdetector.HPSEcal3;
+import org.lcsim.event.EventHeader;
 
-public interface Clusterer {
+/**
+ * This is an interface for creating clusters and providing cut values
+ * to the clustering algorithms in a generic fashion.
+ */
+public interface Clusterer extends ConditionsListener {
 
-    List<Cluster> createClusters(List<CalorimeterHit> hits);
+    /**
+     * Create a list of output clusters from input hits.
+     * @param event The current LCSim event.
+     * @param hits The list of hits.
+     * @return The output clusters.
+     */
+    List<Cluster> createClusters(EventHeader event, List<CalorimeterHit> hits);
+    
+    /**
+     * Perform start of job intialization on this object.
+     */
+    void initialize();
+    
+    /**
+     * Get the list of numerical cuts.
+     * @return The list of numerical cuts.
+     */
+    double[] getCuts();
+    
+    /**
+     * Get the default cut values.
+     * @return The default cut values.
+     */
+    double[] getDefaultCuts();
+    
+    /**
+     * True if algorithm is using its default cuts.
+     * @return True if using the default cuts.
+     */
+    boolean isDefaultCuts();
+    
+    /**
+     * Set numerical cuts array.
+     * @param cuts The numerical cuts.
+     */
+    void setCuts(double[] cuts);
+                 
+    /**
+     * Get a cut value by its index.
+     * @param index The index of the cut.
+     * @return The cut value at index.
+     */
+    double getCut(int index);
+    
+    /**
+     * Get a cut value by name.
+     * @param name The name of the cut.
+     * @return The named cut.
+     */
+    double getCut(String name);
+    
+    /**
+     * Set a cut value by name.
+     * @param name The name of the cut.
+     * @param value The value of the cut.
+     */
+    void setCut(String name, double value);
+    
+    /**
+     * Set a cut value by index.
+     * @param index The index of the cut.
+     * @param value The value of the cut.
+     */
+    void setCut(int index, double value);
+    
+    /**
+     * Get the names of the cuts.
+     * @return The names of the cuts.
+     */
+    String[] getCutNames();       
 }

Modified: java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/ClustererFactory.java
 =============================================================================
--- java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/ClustererFactory.java	(original)
+++ java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/ClustererFactory.java	Tue Dec 16 15:15:39 2014
@@ -1,18 +1,49 @@
 package org.hps.recon.ecal.cluster;
 
+import org.lcsim.conditions.ConditionsListener;
+import org.lcsim.conditions.ConditionsManager;
+
+/**
+ * This is a convenience class for creating different kinds of clustering algorithms.
+ * @author Jeremy McCormick <[log in to unmask]>
+ */
 public final class ClustererFactory {
     
     private ClustererFactory() {        
     }
     
+    /**
+     * Create a clustering algorithm with a set of cuts.
+     * @param name The name of the clustering algorithm.
+     * @param cuts The set of cuts (can be null).
+     * @return The clustering algorithm.
+     * @throw IllegalArgumentException if there is no Clusterer found with name.
+     */
+    public static Clusterer create(String name, double[] cuts) {
+        Clusterer clusterer;
+        System.out.println("simple name:" + LegacyClusterer.class.getSimpleName());
+        if (LegacyClusterer.class.getSimpleName().equals(name)) {            
+            clusterer = new LegacyClusterer();
+        } else if (SimpleClasInnerCalClusterer.class.getSimpleName().equals(name)) {
+            clusterer = new SimpleClasInnerCalClusterer();
+        } else {
+            throw new IllegalArgumentException("Unknown clusterer type: " + name);
+        }
+        if (clusterer instanceof ConditionsListener) {
+            ConditionsManager.defaultInstance().addConditionsListener((ConditionsListener) clusterer);
+        }
+        if (cuts != null) {
+            clusterer.setCuts(cuts);
+        }
+        return clusterer;
+    }
+    
+    /**
+     * Create a clustering algorithm with default cut values.
+     * @param name The name of the clustering algorithm.
+     * @return The clustering algorithm.
+     */
     public static Clusterer create(String name) {
-        if (LegacyClusterer.class.getSimpleName().equals(name)) {
-            return new LegacyClusterer();
-        } if (SimpleInnerCalClusterer.class.getSimpleName().equals(name)) {
-            return new SimpleInnerCalClusterer();
-        } else {
-            throw new IllegalArgumentException("Unknown clusterer: " + name);
-        }
+        return create(name, null);
     }
-
 }

Modified: java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/LegacyClusterer.java
 =============================================================================
--- java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/LegacyClusterer.java	(original)
+++ java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/LegacyClusterer.java	Tue Dec 16 15:15:39 2014
@@ -9,36 +9,35 @@
 import org.hps.recon.ecal.HPSEcalCluster;
 import org.lcsim.event.CalorimeterHit;
 import org.lcsim.event.Cluster;
+import org.lcsim.event.EventHeader;
 
 /**
- * This Driver creates clusters from the CalorimeterHits of an
- * {@link org.lcsim.geometry.subdetectur.HPSEcal3} detector.
- *
- * The clustering algorithm is from pages 83 and 84 of the HPS Proposal.
+ * <p>
+ * This Driver creates clusters from a CalorimeterHit input collection.
+ * <p>
+ * The clustering algorithm is implemented according to the description in pages 83 and 84 of the 
+ * <a href="https://confluence.slac.stanford.edu/download/attachments/86676777/HPSProposal-FINAL_Rev2.pdf">HPS Proposal document</a>.
+ * <p>
+ * This is a simple algorithm that is obsolete!  The current IC or hardware algorithm clustering algorithms should generally be used instead.
  *
  * @author Jeremy McCormick <[log in to unmask]>
  * @author Tim Nelson <[log in to unmask]>
  */
 public class LegacyClusterer extends AbstractClusterer {
-        
-    // Minimum E for cluster seed.
-    double minimumClusterSeedEnergy = 0.05 * ECalUtils.GeV;
-
-    // Minimum E to add hit to cluster.
-    double minimumHitEnergy = 0.03 * ECalUtils.GeV;
-     
-    void setMinimumClusterSeedEnergy(double minimumClusterSeedEnergy) {
-        this.minimumClusterSeedEnergy = minimumClusterSeedEnergy;
-    }
-
-    void setMinimumHitEnergy(double minimumHitEnergy) {
-        this.minimumHitEnergy = minimumHitEnergy;
-        if (minimumClusterSeedEnergy < minimumHitEnergy) {
-            minimumClusterSeedEnergy = minimumHitEnergy;
-        }
+    
+    double minClusterSeedEnergy;
+    double minHitEnergy;
+    
+    LegacyClusterer() {
+        super(new String[] { "minClusterSeedEnergy", "minHitEnergy" }, new double[] { 0.05 * ECalUtils.GeV, 0.03 * ECalUtils.GeV });
     }
     
-    public List<Cluster> createClusters(List<CalorimeterHit> hits) {
+    public void initialize() {
+        minClusterSeedEnergy = this.getCut("minClusterSeedEnergy");
+        minHitEnergy = this.getCut("minHitEnergy");
+    }
+                 
+    public List<Cluster> createClusters(EventHeader event, List<CalorimeterHit> hits) {
 
         Map<Long, CalorimeterHit> hitMap = ClusterUtilities.createHitMap(hits);
         
@@ -48,7 +47,7 @@
         // Loop over ECal hits to find cluster seeds.
         for (CalorimeterHit hit : hitMap.values()) {
             // Cut on min seed E.
-            if (hit.getRawEnergy() < minimumClusterSeedEnergy) {
+            if (hit.getRawEnergy() < minClusterSeedEnergy) {
                 continue;
             }
 
@@ -74,7 +73,7 @@
                     }
 
                     // Add to cluster if above min E.
-                    if (neighborHit.getRawEnergy() >= minimumHitEnergy) {
+                    if (neighborHit.getRawEnergy() >= minHitEnergy) {
                         neighborHits.add(neighborHit);
                     }
                 }

Copied: java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/SimpleClasInnerCalClusterer.java (from r1759, java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/SimpleInnerCalClusterer.java)
 =============================================================================
--- java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/SimpleInnerCalClusterer.java	(original)
+++ java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/SimpleClasInnerCalClusterer.java	Tue Dec 16 15:15:39 2014
@@ -2,7 +2,6 @@
 
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.Comparator;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -10,98 +9,83 @@
 import org.hps.recon.ecal.HPSEcalCluster;
 import org.lcsim.event.CalorimeterHit;
 import org.lcsim.event.Cluster;
+import org.lcsim.event.EventHeader;
 
 /**
- * This Driver creates clusters from the CalorimeterHits of an
- * {@link org.lcsim.geometry.subdetector.HPSEcal3} detector.
- *
- * Uses basic IC clustering algorithm as given in CLAS note 2004-040: no common
- * hits (hits are assigned to cluster with largest seed hit energy).
- *
- * Hit time information is not used, and multiple hits in the same crystal are
- * not handled correctly (a warning is printed); optional time cut is applied at
- * the beginning to discard hits too far from t0.
+ * <p>
+ * This clustering algorithm creates clusters from an input CalorimeterHit collection.
+ * <p>
+ * It uses the basic Inner Calorimeter (IC) clustering algorithm as described in 
+ * <a href="https://misportal.jlab.org/ul/Physics/Hall-B/clas/viewFile.cfm/2005-001.pdf?documentId=6">CLAS Note 2004-040</a>.
+ * <p> 
+ * Hits are assigned to a cluster with the largest seed hit energy.  Time information is not used, and multiple hits in the same 
+ * crystal are not handled correctly so an exception is throw if this occurs.  An optional cut can be applied to discard hits
+ * with a time that is too far from t0.
  *
  * @author Holly Szumila-Vance <[log in to unmask]>
  * @author Sho Uemura <[log in to unmask]>
- *
+ * @author Jeremy McCormick <[log in to unmask]>
  */
-public class SimpleInnerCalClusterer extends AbstractClusterer {
-
-    //Minimum energy that counts as hit
-    double Emin = 0.001;
-    boolean timeCut = false;
-    double minTime = 0.0;
-    double timeWindow = 20.0;
+public class SimpleClasInnerCalClusterer extends AbstractClusterer {
+    
+    double minEnergy;
+    double minTime;
+    double timeWindow;
+    boolean timeCut;
 
     /**
-     * Minimum energy for a hit to be used in a cluster. Default of 0.001 GeV..
-     * @param Emin
+     * Initialize the algorithm with default cuts.
      */
-    public void setEmin(double Emin) {
-        this.Emin = Emin;
+    public SimpleClasInnerCalClusterer() {
+        super(new String[] { "minEnergy", "minTime", "timeWindow", "timeCut" }, new double[] { 0., 0.001, 0.0, 20.0 });
     }
 
-    /**
-     * Apply time cuts to hits. Defaults to false.
-     * @param timeCut
-     */
-    public void setTimeCut(boolean timeCut) {
-        this.timeCut = timeCut;
+    public void initialize() {
+        // Setup class variables from cuts.
+        timeCut = (this.getCut("timeCut") == 1.0);
+        minEnergy = this.getCut("minEnergy");
+        minTime = this.getCut("minTime");
+        timeWindow = this.getCut("timeWindow");
     }
 
-    /**
-     * Minimum hit time, if timeCut is true. Default of 0 ns.
-     * @param minTime
-     */
-    public void setMinTime(double minTime) {
-        this.minTime = minTime;
-    }
-
-    /**
-     * Width of time window, if timeCut is true. Default of 20 ns.
-     * @param timeWindow
-     */
-    public void setTimeWindow(double timeWindow) {
-        this.timeWindow = timeWindow;
-    }
-
-    public List<Cluster> createClusters(List<CalorimeterHit> allHits) {
+    public List<Cluster> createClusters(EventHeader event, List<CalorimeterHit> hitCollection) {
 
         // New Cluster list to be added to event.
         List<Cluster> clusters = new ArrayList<Cluster>();
 
-        //Create a Calorimeter hit list in each event, then sort with highest energy first
-        ArrayList<CalorimeterHit> sortedHitList = new ArrayList<CalorimeterHit>(allHits.size());
-        for (CalorimeterHit h : allHits) {
-            //reject hits below the energy cut
-            if (h.getCorrectedEnergy() < Emin) {
+        // Create a Calorimeter hit list in each event, then sort with highest energy first
+        ArrayList<CalorimeterHit> sortedHitList = new ArrayList<CalorimeterHit>(hitCollection.size());
+        for (CalorimeterHit h : hitCollection) {
+            // reject hits below the energy cut
+            if (h.getCorrectedEnergy() < this.minEnergy) {
                 continue;
             }
-            //if time cut is being used, reject hits outside the time window
+            // if time cut is being used, reject hits outside the time window
             if (timeCut && (h.getTime() < minTime || h.getTime() > minTime + timeWindow)) {
                 continue;
             }
             sortedHitList.add(h);
         }
-        
-        //sort the list, highest energy first
-        Collections.sort(sortedHitList, Collections.reverseOrder(new EnergyComparator()));
 
-        //map from seed hit to cluster
+        // sort the list, highest energy first
+        Collections.sort(sortedHitList, Collections.reverseOrder(new CalorimeterHit.CalorimeterHitEnergyComparator()));
+
+        // map from seed hit to cluster
         Map<CalorimeterHit, HPSEcalCluster> seedToCluster = new HashMap<CalorimeterHit, HPSEcalCluster>();
 
-        //Quick Map to access hits from cell IDs
+        // Quick Map to access hits from cell IDs
         Map<Long, CalorimeterHit> idToHit = new HashMap<Long, CalorimeterHit>();
 
-        //map from each hit to its cluster seed
+        // map from each hit to its cluster seed
         Map<CalorimeterHit, CalorimeterHit> hitToSeed = new HashMap<CalorimeterHit, CalorimeterHit>();
 
-        //Fill Map with cell ID and hit
+        // Fill Map with cell ID and hit
         for (CalorimeterHit hit : sortedHitList) {
-            //if (idToHit.containsKey(hit.getCellID())) {
-            //    System.out.println(this.getName() + ": multiple CalorimeterHits in same crystal");
-            //}
+            if (idToHit.containsKey(hit.getCellID())) {
+                //System.out.println(this.getName() + ": multiple CalorimeterHits in same crystal");
+                // Make this an error for now.
+                throw new RuntimeException("Multiple CalorimeterHits found in same crystal.");
+            }
             idToHit.put(hit.getCellID(), hit);
         }
 
@@ -121,7 +105,7 @@
                     }
                 }
             }
-            if (biggestSeed == null) { //if no neighbors had more energy than this hit, this hit is a seed
+            if (biggestSeed == null) { // if no neighbors had more energy than this hit, this hit is a seed
                 hitToSeed.put(hit, hit);
                 HPSEcalCluster cluster = new HPSEcalCluster(hit.getCellID());
                 clusters.add(cluster);
@@ -131,7 +115,7 @@
             }
         }
 
-        //add all hits to clusters
+        // add all hits to clusters
         for (CalorimeterHit hit : sortedHitList) {
             CalorimeterHit seed = hitToSeed.get(hit);
             HPSEcalCluster cluster = seedToCluster.get(seed);
@@ -140,12 +124,4 @@
 
         return clusters;
     }
-
-    private class EnergyComparator implements Comparator<CalorimeterHit> {
-
-        @Override
-        public int compare(CalorimeterHit o1, CalorimeterHit o2) {
-            return Double.compare(o1.getCorrectedEnergy(), o2.getCorrectedEnergy());
-        }
-    }
 }

Top of Message | Previous Page | Permalink

Advanced Options


Options

Log In

Log In

Get Password

Get Password


Search Archives

Search Archives


Subscribe or Unsubscribe

Subscribe or Unsubscribe


Archives

November 2017
August 2017
July 2017
January 2017
December 2016
November 2016
October 2016
September 2016
August 2016
July 2016
June 2016
May 2016
April 2016
March 2016
February 2016
January 2016
December 2015
November 2015
October 2015
September 2015
August 2015
July 2015
June 2015
May 2015
April 2015
March 2015
February 2015
January 2015
December 2014
November 2014
October 2014
September 2014
August 2014
July 2014
June 2014
May 2014
April 2014
March 2014
February 2014
January 2014
December 2013
November 2013

ATOM RSS1 RSS2



LISTSERV.SLAC.STANFORD.EDU

Secured by F-Secure Anti-Virus CataList Email List Search Powered by the LISTSERV Email List Manager

Privacy Notice, Security Notice and Terms of Use