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  January 2015

HPS-SVN January 2015

Subject:

r1912 - in /java/trunk/ecal-recon/src: main/java/org/hps/recon/ecal/ main/java/org/hps/recon/ecal/cluster/ test/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:

Sat, 10 Jan 2015 00:24:45 -0000

Content-Type:

text/plain

Parts/Attachments:

Parts/Attachments

text/plain (778 lines)

Author: [log in to unmask]
Date: Fri Jan  9 16:24:39 2015
New Revision: 1912

Log:
Add several more clustering algorithm implementations to the ecal.cluster package.

Added:
    java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/CTPClusterer.java
    java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/GTPClusterDriver.java
    java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/GTPClusterer.java
Modified:
    java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/CTPEcalClusterer.java
    java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/GTPEcalClusterer.java
    java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/ClustererFactory.java
    java/trunk/ecal-recon/src/test/java/org/hps/recon/ecal/cluster/ClustererTest.java

Modified: java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/CTPEcalClusterer.java
 =============================================================================
--- java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/CTPEcalClusterer.java	(original)
+++ java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/CTPEcalClusterer.java	Fri Jan  9 16:24:39 2015
@@ -28,8 +28,10 @@
  * @author Jeremy McCormick <[log in to unmask]>
  * @author Tim Nelson <[log in to unmask]>
  * @author Sho Uemura <[log in to unmask]>
- * @version $Id: CTPEcalClusterer.java,v 1.1 2013/02/25 22:39:24 meeg Exp $
+ * 
+ * @deprecated Use the {@link org.hps.recon.ecal.cluster.CTPClusterer} with the {@link org.hps.recon.ecal.cluster.ClusterDriver}.
  */
+@Deprecated
 public class CTPEcalClusterer extends Driver {
 	
 	Detector detector = null;

Modified: java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/GTPEcalClusterer.java
 =============================================================================
--- java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/GTPEcalClusterer.java	(original)
+++ java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/GTPEcalClusterer.java	Fri Jan  9 16:24:39 2015
@@ -30,7 +30,10 @@
  * either at the same location as the seed hit or is a neighbor to the seed hit.
  * @author Kyle McCarty
  * @author Sho Uemura
+ * 
+ * @deprecated Use the {@link org.hps.recon.ecal.cluster.GTPClusterDriver} instead.
  */
+@Deprecated
 public class GTPEcalClusterer extends Driver {
 	Detector detector = null;
 	

Added: java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/CTPClusterer.java
 =============================================================================
--- java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/CTPClusterer.java	(added)
+++ java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/CTPClusterer.java	Fri Jan  9 16:24:39 2015
@@ -0,0 +1,332 @@
+package org.hps.recon.ecal.cluster;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.PriorityQueue;
+import java.util.Set;
+
+import org.hps.recon.ecal.CalorimeterHitUtilities;
+import org.lcsim.conditions.ConditionsEvent;
+import org.lcsim.event.CalorimeterHit;
+import org.lcsim.event.Cluster;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.base.BaseCalorimeterHit;
+import org.lcsim.event.base.BaseCluster;
+import org.lcsim.geometry.IDDecoder;
+
+/**
+ * Creates clusters from CalorimeterHits in the HPSEcal detector.
+ *
+ * The clustering algorithm is from JLab Hall B 6 GeV DVCS Trigger Design doc.
+ *
+ * @author Kyle McCarty
+ * @author Sho Uemura <[log in to unmask]>
+ * @author Jeremy McCormick <[log in to unmask]>
+ */
+public class CTPClusterer extends AbstractClusterer {
+
+    IDDecoder dec;
+    
+    Set<Long> clusterCenters = null;
+    Map<Long, Double> hitSums = null;
+    Map<Long, CalorimeterHit> hitMap = null;
+
+    // The time period in which clusters may be formed. A negative value means that all hits
+    // will always be used in cluster finding, regardless of the time difference between them.
+    double clusterWindow = -1;
+    
+    // The minimum energy needed for a hit to be considered.
+    double addEMin = 0;
+    
+    CTPClusterer() {
+        super(new String[] { "addEMin", "clusterWindow"}, new double[] { 0., -1. });
+    }
+    
+    public void initialize() {
+        addEMin = getCuts().getValue("addEMin");
+        clusterWindow = getCuts().getValue("clusterWindow");
+    }
+         
+    @Override
+    public void conditionsChanged(ConditionsEvent event) {
+        super.conditionsChanged(event);
+        
+        // Get the decoder for the ECal IDs.
+        dec = ecal.getIDDecoder();    
+                
+        // Make set of valid cluster centers.
+        // Exclude edge crystals as good cluster centers.
+        clusterCenters = new HashSet<Long>();
+        for (Long cellID : neighborMap.keySet()) {
+            boolean isValidCenter = true;
+            Set<Long> neighbors = neighborMap.get(cellID);
+            for (Long neighborID : neighbors) {
+                Set<Long> neighborneighbors = new HashSet<Long>();
+                neighborneighbors.addAll(neighborMap.get(neighborID));
+                neighborneighbors.add(neighborID);
+
+                if (neighborneighbors.containsAll(neighbors)) {
+                    isValidCenter = false;
+                    break;
+                }
+            }
+            if (isValidCenter) {
+                clusterCenters.add(cellID);
+            }
+        }
+    }
+
+    @Override
+    public List<Cluster> createClusters(EventHeader event, List<CalorimeterHit> hits) {
+
+        // Define a list of clusters to be filled.
+        List<Cluster> clusters;
+
+        // If there is a cluster window, run the cluster window code. A cluster window is a time
+        // period in nanoseconds during which hits can be applied to the same cluster.
+        if (clusterWindow >= 0) {
+            // Create priority queues. These are sorted by the time variable associated with each hit.
+            PriorityQueue<CalorimeterHit> futureHits = new PriorityQueue<CalorimeterHit>(10, new TimeComparator());
+            PriorityQueue<CalorimeterHit> pastHits = new PriorityQueue<CalorimeterHit>(10, new TimeComparator());
+
+            // Initialize the cluster list variable.
+            clusters = new ArrayList<Cluster>();
+
+            // Populate the list of unprocessed hits with the calorimeter hits. These will then be sorted
+            // by time, from first to last, automatically by the priority queue.
+            for (CalorimeterHit hit : hits) {
+                if (hit.getRawEnergy() > addEMin) {
+                    futureHits.add(hit);
+                }
+            }
+
+            // We process the unprocessed hits...
+            while (!futureHits.isEmpty()) {
+                // Move the first occurring hit from the unprocessed list to the processed list.
+                CalorimeterHit nextHit = futureHits.poll();
+                pastHits.add(nextHit);
+
+                // Add any hits that occurred at the same time as the hit we just added to the processed list.
+                while (!futureHits.isEmpty() && futureHits.peek().getTime() == nextHit.getTime()) {
+                    pastHits.add(futureHits.poll());
+                }
+
+                // Remove hits that happened earlier than the cluster window period.
+                while (pastHits.peek().getTime() < nextHit.getTime() - clusterWindow) {
+                    pastHits.poll();
+                }
+
+                // Calculate the cluster energy for each crystal. This should be the
+                // total energy for the 3x3 crystal collection sorrounding the center
+                // crystal.
+                sumHits(pastHits);
+
+                // Choose which crystal is the appropriate cluster crystal.
+                clusters.addAll(createClusters());
+            }
+            // If there is no cluster window, then all the hits in the event are visible simultaneously.
+        } else {
+            // Calculate the cluster energy of each crystal.
+            sumHits(hits);
+            // Generate the clusters.
+            clusters = createClusters();
+        }
+        
+        return clusters;
+    }
+
+    private void sumHits(Collection<CalorimeterHit> hits) {
+        // Store the latest hit on each crystal in a map for later reference in
+        // the clustering algorithm.
+        hitMap = new HashMap<Long, CalorimeterHit>();
+        // Store the cluster energy for each crystal. Cluster energy represents
+        // the total energy of the 3x3 crystal set.
+        hitSums = new HashMap<Long, Double>();
+
+        // Loop over the active calorimeter hits to compute the cluster energies.
+        for (CalorimeterHit hit : hits) {
+            // Make a hit map for quick lookup by ID.
+            hitMap.put(hit.getCellID(), hit);
+
+            // Get the cell ID for the current crystal's neighbors.
+            Set<Long> neighbors = neighborMap.get(hit.getCellID());
+
+            // If there are no neighbors, something is rather wrong.
+            if (neighbors == null) {
+                throw new RuntimeException("Oops!  Set of neighbors is null!");
+            }
+
+            // Store the energy of the current calorimeter hit.
+            Double hitSum;
+
+            // We are only interested in this crystal's cluster energy if it is
+            // a valid cluster crystal. Edge crystals are not allowed to be clusters,
+            // so these are ignored.
+            if (clusterCenters.contains(hit.getCellID())) {
+                // Check if an energy has been assigned to the crystal.
+                hitSum = hitSums.get(hit.getCellID());
+
+                // If not, then the crystal's cluster energy is equal to this hit's energy.
+                if (hitSum == null) {
+                    hitSums.put(hit.getCellID(), hit.getRawEnergy());
+                }
+                // Otherwise, add the energy of this hit to the total crystal cluster energy.
+                else {
+                    hitSums.put(hit.getCellID(), hitSum + hit.getRawEnergy());
+                }
+            }
+
+            // Loop over neighbors to add the current hit's energy to the neighbor's
+            // cluster energy.
+            for (Long neighborId : neighbors) {
+                // If the crystal is not an edge crystal, ignore its hit energy.
+                if (!clusterCenters.contains(neighborId)) {
+                    continue;
+                }
+
+                // Get the cluster energy of the neighboring crystals.
+                hitSum = hitSums.get(neighborId);
+
+                // If the neighbor crystal has no cluster energy, then set the
+                // cluster energy to the current hit's energy.
+                if (hitSum == null) {
+                    hitSums.put(neighborId, hit.getRawEnergy());
+                }
+                // Otherwise, add the hit's energy to the neighbor's cluster energy.
+                else {
+                    hitSums.put(neighborId, hitSum + hit.getRawEnergy());
+                }
+            }
+        }
+    }
+
+    private List<Cluster> createClusters() {
+        // Create a list of clusters to be added to the event,
+        List<Cluster> clusters = new ArrayList<Cluster>();
+
+        // We examine each crystal with a non-zero cluster energy.
+        for(Long possibleCluster : hitSums.keySet()) {
+            // Get the luster energy for the crystal this hit is assocaite with.
+            Double thisSum = hitSums.get(possibleCluster);
+
+            // Get neighboring crystals' IDs.
+            Set<Long> neighbors = neighborMap.get(possibleCluster);
+
+            // If there are no neighbors, throw an error.
+            if (neighbors == null) {
+                throw new RuntimeException("Oops!  Set of neighbors is null!");
+            }
+
+            // Get the x/y position of the hit's associated crystal.
+            dec.setID(possibleCluster);
+            int x1 = dec.getValue("ix");
+            int y1 = dec.getValue("iy");
+
+            // Store whether it is a valid cluster or not.
+            boolean isCluster = true;
+
+            // Check to see if any of the crystal's neighbors preclude the current crystal
+            // from being a proper cluster. The cluster crystal should have the highest
+            // energy among its neighbors
+            for (Long neighborId : neighbors) {
+                // Get the x/y position of the neighbor's associated crystal.
+                dec.setID(neighborId);
+                int x2 = dec.getValue("ix");
+                int y2 = dec.getValue("iy");
+
+                // If the neighbor's energy value does not exist, we don't need to perform
+                // any additional checks for this neighbor. A crystal with no energy can
+                // not be the center of a cluster.
+                Double neighborSum = hitSums.get(neighborId);
+                if (neighborSum == null) {
+                    continue;
+                }
+
+                // If the neighbor's energy value is greater than this crystal's value,
+                // then this crystal is not the cluster and we may terminate the check.
+                if (neighborSum > thisSum) {
+                    isCluster = false;
+                    break;
+                }
+                // If the crystals each have the same energy, we choose the crystal that
+                // is closest to the electron side of the detector. If both crystals are
+                // equally close, we choose the crystal closest to the beam gap. If the
+                // neighbor fits these parameters better, this is not a crystal and we
+                // may skip any further checks.
+                else if (neighborSum.equals(thisSum) && (x1 > x2 || (x1 == x2 && Math.abs(y1) < Math.abs(y2)))) {
+                    isCluster = false;
+                    break;
+                }
+            }
+
+            // If the crystal was not invalidated by the any of the neighboring crystals,
+            // then it is a cluster crystal and should be processed.
+            if (isCluster) {
+                // Make a list to store the hits that are part of this cluster.
+                List<CalorimeterHit> hits = new ArrayList<CalorimeterHit>();
+
+                // Store the time at which the cluster occurred.
+                double clusterTime = Double.NEGATIVE_INFINITY;
+
+                // Get the last hit on this crystal.
+                CalorimeterHit hit = hitMap.get(possibleCluster);
+
+                // If the hit exists, add it to the list of associated hits.
+                if (hit != null) {
+                    hits.add(hit);
+
+                    // If the latest hit's time is later than the current cluster time,
+                    // set the cluster time to the latest hit's time.
+                    if (hit.getTime() > clusterTime) {
+                        clusterTime = hit.getTime();
+                    }
+                }
+
+                // Add all of the neighboring crystals to the cluster, if they have a
+                // hit associated with them. Crystals with no hits are not actually part
+                // of a cluster.
+                for (Long neighborId : neighbors) {
+                    hit = hitMap.get(neighborId);
+                    if (hit != null) {
+                        hits.add(hit);
+                        if (hit.getTime() > clusterTime) {
+                            clusterTime = hit.getTime();
+                        }
+                    }
+                }
+
+                // Generate a new cluster seed hit from the above results.
+                CalorimeterHit seedHit = (BaseCalorimeterHit)CalorimeterHitUtilities.create(0.0, clusterTime, possibleCluster, hits.get(0).getMetaData());
+
+                // Generate a new cluster from the seed hit.
+                BaseCluster cluster = new BaseCluster();
+                cluster.addHit(seedHit);
+                // Populate the cluster with each of the chosen neighbors.
+                for (CalorimeterHit clusterHit : hits) {
+                    cluster.addHit(clusterHit);
+                }
+                // Add the cluster to the cluster list.
+                clusters.add(cluster);
+            }
+        }
+
+        // Return the list of clusters.
+        return clusters;
+    }
+
+    static class TimeComparator implements Comparator<CalorimeterHit> {
+        // Compare by time with the earlier coming before the later.
+        public int compare(CalorimeterHit o1, CalorimeterHit o2) {
+            if (o1.getTime() == o2.getTime()) {
+                return 0;
+            } else {
+                return (o1.getTime() > o2.getTime()) ? 1 : -1;
+            }
+        }
+    }
+}

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	Fri Jan  9 16:24:39 2015
@@ -13,13 +13,15 @@
  * this class implements the {@link Clusterer} interface and will throw an error if it does not.
  * 
  * @see Clusterer
+ * @see CTPClusterer
  * @see DualThresholdCosmicClusterer
+ * @see GTPClusterer
  * @see GTPOnlineClusterer
  * @see LegacyClusterer 
  * @see NearestNeighborClusterer
  * @see ReconClusterer
  * @see SimpleReconClusterer
- * @see SimpleCosmicClusterer
+ * @see SimpleCosmicClusterer 
  * 
  * @author Jeremy McCormick <[log in to unmask]>
  */
@@ -54,6 +56,10 @@
             clusterer = new SimpleCosmicClusterer();
         } else if (GTPOnlineClusterer.class.getSimpleName().equals(name)) {
             clusterer = new GTPOnlineClusterer();
+        } else if (GTPClusterer.class.getSimpleName().equals(name)) {
+            clusterer = new GTPClusterer();
+        } else if (CTPClusterer.class.getSimpleName().equals(name)) {
+            clusterer = new CTPClusterer();
         } else {
             // Try to instantiate a Clusterer object from the name argument, assuming it is a canonical class name.
             try {

Added: java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/GTPClusterDriver.java
 =============================================================================
--- java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/GTPClusterDriver.java	(added)
+++ java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/GTPClusterDriver.java	Fri Jan  9 16:24:39 2015
@@ -0,0 +1,31 @@
+package org.hps.recon.ecal.cluster;
+
+/**
+ * This is a Driver to wrap the GTPClusterer algorithm,
+ * allowing the <code>limitClusterRange</code> to be
+ * set publicly.
+ * 
+ * @see GTPClusterer
+ * 
+ * @author Jeremy McCormick <[log in to unmask]>
+ */
+public class GTPClusterDriver extends ClusterDriver {
+    
+    public GTPClusterDriver() {
+        clusterer = ClustererFactory.create("GTPClusterer");
+    }
+    
+    /**
+     * Sets whether hits should be added to a cluster from the entire
+     * cluster window or just the "future" hits, plus one clock-cycle
+     * of "past" hits as a safety buffer to account for time uncertainty.
+     * 
+     * @param limitClusterRange - <code>true</code> indicates that
+     * the asymmetric clustering window should be used and <code>
+     * false</code> that the symmetric window should be used.
+     */
+    void setLimitClusterRange(boolean limitClusterRange) {
+        GTPClusterer gtpClusterer = getClusterer();
+        gtpClusterer.setLimitClusterRange(limitClusterRange);
+    }        
+}

Added: java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/GTPClusterer.java
 =============================================================================
--- java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/GTPClusterer.java	(added)
+++ java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/GTPClusterer.java	Fri Jan  9 16:24:39 2015
@@ -0,0 +1,271 @@
+package org.hps.recon.ecal.cluster;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.lcsim.event.CalorimeterHit;
+import org.lcsim.event.Cluster;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.base.BaseCluster;
+
+/**
+ * Class <code>GTPCalorimeterClusterer</code> processes events and converts hits
+ * into clusters, where appropriate. It uses the modified 2014 clustering algorithm.<br/>
+ * <br/>
+ * For a hit to be a cluster center, it is required to have an energy above some
+ * tunable minimum threshold. Additionally, the hit must be a local maximum with
+ * respect to its neighbors and itself over a tunable (default 2) clock cycles.
+ * Hits that pass these checks are then required to additional have a total
+ * cluster energy that exceeds another tunable minimum threshold.<br/>
+ * <br/>
+ * A hit is added to a cluster as a component if it has a non-zero energy and
+ * within the aforementioned tunable time buffer used for clustering and is
+ * either at the same location as the seed hit or is a neighbor to the seed hit.
+ * @author Kyle McCarty
+ * @author Sho Uemura
+ */
+public class GTPClusterer extends AbstractClusterer {
+        
+    /**
+     * <b>seedEnergyThreshold</b><br/><br/>
+     * <code>private double <b>seedEnergyThreshold</b></code><br/><br/>
+     * The minimum energy required for a hit to be considered as a cluster
+     * center. Hits with energy less than this value will be ignored.
+     */
+    private double seedEnergyThreshold;
+    
+    /**
+     * <b>clusterWindow</b><br/><br/>
+     * <code>private int <b>clusterWindow</b></code><br/><br/>
+     * Indicates the number of FADC clock cycles (each cycle is 4 ns) before and
+     * after a given cycle that should be considered when checking if a cluster
+     * is a local maximum in space-time.
+     */
+    private int clusterWindow;
+    
+    /**
+     * <b>hitBuffer</b><br/><br/>
+     * <code>private LinkedList<List<CalorimeterHit>> <b>hitBuffer</b></code><br/><br/>
+     * Stores a set of all the hits occurring in each clock cycle for the number
+     * of clock cycles that should be considered for clustering.
+     */
+    private LinkedList<Map<Long, CalorimeterHit>> hitBuffer;
+
+    /**
+     * <b>limitClusterRange</b><br/><br/>
+     * <code>private boolean <b>limitClusterRange</b></code><br/><br/>
+     * Whether an asymmetric or symmetric window should be used for
+     * adding hits to a cluster.
+     */
+    private boolean limitClusterRange = false;
+    
+    GTPClusterer() {
+        super(new String[] { "seedEnergyThreshold", "clusterWindow" }, new double[] { 0.05, 2.});
+    }    
+    
+    public void initialize() {
+        
+        // Set cuts.
+        setSeedEnergyThreshold(getCuts().getValue("seedEnergyThreshold"));
+        setClusterWindow((int) getCuts().getValue("clusterWindow"));
+        
+        // Initiate the hit buffer.
+        hitBuffer = new LinkedList<Map<Long, CalorimeterHit>>();
+        
+        // Populate the event buffer with (2 * clusterWindow + 1)
+        // empty events. These empty events represent the fact that
+        // the first few events will not have any events in the past
+        // portion of the buffer.
+        int bufferSize = (2 * clusterWindow) + 1;
+        for (int i = 0; i < bufferSize; i++) {
+            hitBuffer.add(new HashMap<Long, CalorimeterHit>(0));
+        }
+    }
+        
+    /**
+     * Generates a list of clusters from the current hit buffer. The "present"
+     * event is taken to be the list of hits occurring at index
+     * <code>clusterWindow</code>, which is the middle of the buffer.
+     *
+     * @return Returns a <code>List</code> of <code>HPSEcalCluster
+     * </code> objects generated from the current event.
+     */
+    private List<Cluster> getClusters() {
+        // Generate a list for storing clusters.
+        List<Cluster> clusters = new ArrayList<Cluster>();
+        
+        // Get the list of hits at the current time in the event buffer.
+        Map<Long, CalorimeterHit> currentHits = hitBuffer.get(clusterWindow);
+        
+        // For a hit to be a cluster center, it must be a local maximum
+        // both with respect to its neighbors and itself both in the
+        // present time and at all times within the event buffer.
+        seedLoop:
+        for (Long currentID : currentHits.keySet()) {
+            // Get the actual hit object.
+            CalorimeterHit currentHit = currentHits.get(currentID);
+            
+            // Store the energy of the current hit.
+            double currentEnergy = currentHit.getRawEnergy();
+            
+            // If the hit energy is lower than the minimum threshold,
+            // then we immediately reject this hit as a possible cluster.
+            if (currentEnergy < seedEnergyThreshold) {
+                continue seedLoop;
+            }
+            
+            // Store the crystals that are part of this potential cluster, 
+            // starting with the cluster seed candidate.
+            BaseCluster cluster = new BaseCluster();            
+            cluster.addHit(currentHit);
+            
+            // Get the set of neighbors for this hit.
+            Set<Long> neighbors = neighborMap.get(currentHit.getCellID());
+            
+            // Sort through each event stored in the buffer.
+            int bufferIndex = 0;
+            for (Map<Long, CalorimeterHit> bufferHits : hitBuffer) {
+                // Get the hit energy at the current hit's position in
+                // the buffer, if it exists. Ignore the current seed candidate.
+                CalorimeterHit bufferHit = bufferHits.get(currentID);
+                if (bufferHit != null && bufferHit != currentHit) {
+                    double bufferHitEnergy = bufferHit.getRawEnergy();
+                    
+                    // Check to see if the hit at this point in the buffer
+                    // is larger than then original hit. If it is, we may
+                    // stop the comparison because this is not a cluster.
+                    if (bufferHitEnergy > currentEnergy) {
+                        continue seedLoop;
+                    }
+                    
+                    // If the buffer hit is smaller, then add its energy
+                    // to the cluster total energy.
+                    else {
+                        if(limitClusterRange && bufferIndex <= clusterWindow + 1) { cluster.addHit(bufferHit); }
+                        else if(!limitClusterRange) { cluster.addHit(bufferHit); }
+                    }
+                }
+                
+                // We must also make sure that the original hit is
+                // larger than all of the neighboring hits at this
+                // point in the buffer as well.
+                for (Long neighborID : neighbors) {
+                    // Get the neighbor hit energy if it exists.
+                    CalorimeterHit neighborHit = bufferHits.get(neighborID);
+                    if (neighborHit != null) {
+                        double neighborHitEnergy = neighborHit.getRawEnergy();
+                        
+                        // Check to see if the neighbor hit at this point
+                        // in the buffer is larger than then original hit.
+                        // If it is, we may stop the comparison because this
+                        // is not a cluster.
+                        if (neighborHitEnergy > currentEnergy) {
+                            continue seedLoop;
+                        }
+                        
+                        // If the buffer neighbor hit is smaller, then
+                        // add its energy to the cluster total energy.
+                        else {
+                            if(limitClusterRange && bufferIndex <= clusterWindow + 1) { cluster.addHit(neighborHit); }
+                            else if(!limitClusterRange) { cluster.addHit(neighborHit); }
+                        }
+                    }
+                }
+                
+                // Increment the buffer index.
+                bufferIndex++;
+            }
+            
+            // Add the cluster to the list of clusters.
+            clusters.add(cluster);
+        }
+        
+        // Return the generated list of clusters.
+        return clusters;
+    }
+    
+    /**
+     * Places hits from the current event into the event hit buffer and
+     * processes the buffer to extract clusters. Clusters are then stored in the
+     * event object.
+     *
+     * @param event - The event to process.
+     */
+    public List<Cluster> createClusters(EventHeader event, List<CalorimeterHit> hits) {
+            
+        // Store each hit in a set by its cell ID so that it may be
+        // easily acquired later.
+        HashMap<Long, CalorimeterHit> hitMap = new HashMap<Long, CalorimeterHit>();
+        for (CalorimeterHit hit : hits) {
+            hitMap.put(hit.getCellID(), hit);
+        }
+
+        // Remove the last event from the hit buffer and add the new one.
+        hitBuffer.removeLast();
+        hitBuffer.addFirst(hitMap);
+
+        // Run the clustering algorithm on the buffer.
+        List<Cluster> clusterList = getClusters();
+
+        return clusterList;
+    }
+               
+    /**
+     * Sets the number of clock cycles before and after a given cycle that will
+     * be used when checking whether a given hit is a local maximum in both time
+     * and space. Note that a value of
+     * <code>N
+     * </code> indicates that
+     * <code>N</code> clock cycles before and
+     * <code>N</code> clock cycles after will be considered. Thusly, a total of
+     * <code>2N + 1</code> clock cycles will be used total.
+     *
+     * @param clusterWindow - The number of additional clock cycles to include
+     * in the clustering checks. A negative value will be treated as zero.
+     */
+    void setClusterWindow(int clusterWindow) {
+        // The cluster window of must always be at least zero.
+        if (clusterWindow < 0) {
+            this.clusterWindow = 0;
+        }
+        
+        // If the cluster window is non-zero, then store it.
+        else {
+            this.clusterWindow = clusterWindow;
+        }
+    }
+    
+    /**
+     * Sets whether hits should be added to a cluster from the entire
+     * cluster window or just the "future" hits, plus one clock-cycle
+     * of "past" hits as a safety buffer to account for time uncertainty.
+     * 
+     * @param limitClusterRange - <code>true</code> indicates that
+     * the asymmetric clustering window should be used and <code>
+     * false</code> that the symmetric window should be used.
+     */
+    void setLimitClusterRange(boolean limitClusterRange) {
+        this.limitClusterRange = limitClusterRange;
+    }
+    
+    /**
+     * Sets the minimum energy threshold below which hits will not be considered
+     * as cluster centers.
+     *
+     * @param seedEnergyThreshold - The minimum energy for a cluster center.
+     */
+    void setSeedEnergyThreshold(double seedEnergyThreshold) {
+        // A negative energy threshold is non-physical. All thresholds
+        // be at least zero.
+        if (seedEnergyThreshold < 0.0) {
+            this.seedEnergyThreshold = 0.0;
+        } // If the energy threshold is valid, then use it.
+        else {
+            this.seedEnergyThreshold = seedEnergyThreshold;
+        }
+    }     
+}

Modified: java/trunk/ecal-recon/src/test/java/org/hps/recon/ecal/cluster/ClustererTest.java
 =============================================================================
--- java/trunk/ecal-recon/src/test/java/org/hps/recon/ecal/cluster/ClustererTest.java	(original)
+++ java/trunk/ecal-recon/src/test/java/org/hps/recon/ecal/cluster/ClustererTest.java	Fri Jan  9 16:24:39 2015
@@ -35,7 +35,7 @@
  */
 public class ClustererTest extends TestCase {
     
-    static int nEvents = 1000;
+    static int nEvents = 100;
     static final String fileLocation = "http://www.lcsim.org/test/hps-java/MockDataReconTest.slcio";
     File inputFile;
     File testOutputDir;
@@ -48,11 +48,11 @@
             throw new RuntimeException(e);
         }
         
-        // Create test output dir.
+        // Create test output directory.
         testOutputDir = new TestOutputFile(getClass().getSimpleName());
         testOutputDir.mkdir();        
         
-        // Initialize conditions system.
+        // Initialize the conditions system.
         new DatabaseConditionsManager();
         DatabaseConditionsManager.getInstance().setLogLevel(Level.WARNING);
     }
@@ -79,6 +79,14 @@
     
     public void testGTPOnlineClusterer() {
         runClustererTest("GTPOnlineClusterer", null, true, true);
+    }
+    
+    public void testCTPClusterer() {
+        runClustererTest("CTPClusterer", null, true, false);
+    }
+    
+    public void testGTPClusterer() {
+        runClustererTest("GTPClusterer", null, true, false);
     }
     
     /**

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