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:

r1878 - in /java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster: ClustererFactory.java GTPOnlineClusterer.java

From:

[log in to unmask]

Reply-To:

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

Date:

Tue, 6 Jan 2015 03:17:14 -0000

Content-Type:

text/plain

Parts/Attachments:

Parts/Attachments

text/plain (402 lines)

Author: [log in to unmask]
Date: Mon Jan  5 19:17:08 2015
New Revision: 1878

Log:
Port GTPOnlineClusterer Driver to new clustering package.

Added:
    java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/GTPOnlineClusterer.java
Modified:
    java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/ClustererFactory.java

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	Mon Jan  5 19:17:08 2015
@@ -13,10 +13,11 @@
  * this class implements the {@link Clusterer} interface and will throw an error if it does not.
  * 
  * @see Clusterer
- * @see ReconClusterer
  * @see DualThresholdCosmicClusterer
+ * @see GTPOnlineClusterer
  * @see LegacyClusterer 
  * @see NearestNeighborClusterer
+ * @see ReconClusterer
  * @see SimpleReconClusterer
  * @see SimpleCosmicClusterer
  * 
@@ -51,6 +52,8 @@
             clusterer = new DualThresholdCosmicClusterer();
         } else if (SimpleCosmicClusterer.class.getSimpleName().equals(name)) {
             clusterer = new SimpleCosmicClusterer();
+        } else if (GTPOnlineClusterer.class.getSimpleName().equals(name)) {
+            clusterer = new GTPOnlineClusterer();
         } 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/GTPOnlineClusterer.java
 =============================================================================
--- java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/GTPOnlineClusterer.java	(added)
+++ java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/GTPOnlineClusterer.java	Mon Jan  5 19:17:08 2015
@@ -0,0 +1,357 @@
+package org.hps.recon.ecal.cluster;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+import org.hps.recon.ecal.HPSEcalCluster;
+import org.lcsim.event.CalorimeterHit;
+import org.lcsim.event.Cluster;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.base.BaseCluster;
+
+/**
+ * Class <code>GTPOnlineClusterer</code> is an implementation of the
+ * GTP clustering algorithm for EVIO readout data for use in either
+ * online reconstruction/diagnostics or for general analysis of EVIO
+ * readout data.<br/>
+ * <br/>
+ * The GTP algorithm searches the set of hits in a readout event and
+ * compares them to select those that are a maximum in their 3x3 window
+ * and across a period of time that can be set. Hits that are maxima
+ * are declared "cluster seeds" and a cluster is created from them.
+ * All hits within the clustering window of the seed time are then
+ * added to the cluster and it is written to the event stream.<br/>
+ * <br/>
+ * The GTP algorithm uses three time windows. THe verification window
+ * is the time around the seed hit in which it is required to have more
+ * energy than any other hits in the 3x3 spatial window surrounding it.
+ * This is always symmetric. The other two windows combined define the
+ * clustering window. The clustering window is composed of a window
+ * before and a window after the seed time. These may be defined using
+ * different values. The window after should be as long or longer than
+ * the window before to make physical sense. The verification window is
+ * then defined as the larger of the two constituents of the clustering
+ * window. This is required for clustering to be consistent.
+ * 
+ * @author Kyle McCarty <[log in to unmask]>
+ */
+// TODO: Handle time window arguments.
+public class GTPOnlineClusterer extends AbstractClusterer {
+
+    // The size of the temporal window in nanoseconds. By default,
+    // this is 1 clock-cycle before and 3 clock-cycles after.
+    private double timeBefore = 4;
+    private double timeAfter = 12;
+    private double timeWindow = 12;
+
+    // Cluster formation energy thresholds. Currently, the hardware
+    // only supports a lower bound seed energy. Units are in GeV.
+    private double seedThreshold = 0.050;
+
+    // Internal variables.
+    private boolean verbose = false;
+    
+    public GTPOnlineClusterer() {
+        super(new String[] { "seedThreshold" }, 
+                new double[] { 0.050 });
+    }
+
+    public void initialize() {
+        seedThreshold = getCuts().getValue("seedThreshold");
+    }
+
+    /**
+     * Reads in hits and processes them into clusters as per the GTP
+     * clustering algorithm implemented in the hardware.
+     * @param event - The object containing event data.
+     */
+    @Override
+    public List<Cluster> createClusters(EventHeader event, List<CalorimeterHit> hitList) {
+
+        // Track the valid clusters.
+        List<Cluster> clusterList = new ArrayList<Cluster>();
+
+        // VERBOSE :: Indicate whether the event has hits.
+        //if(verbose) { System.out.printf("Event %7d :: Has hits [%5b]%n", event.getEventNumber(), hasHits); }
+
+        // Sort the hits by time in reverse order.
+        Collections.sort(hitList, new Comparator<CalorimeterHit>() {
+            @Override
+            public int compare(CalorimeterHit firstHit, CalorimeterHit secondHit) {
+                return Double.compare(secondHit.getTime(), firstHit.getTime());
+            }
+        }); 
+
+        // VERBOSE :: Print the hit information.
+        if(verbose) { 
+            for(CalorimeterHit hit : hitList) {
+                int ix = hit.getIdentifierFieldValue("ix");
+                int iy = hit.getIdentifierFieldValue("iy");
+                double energy = hit.getCorrectedEnergy();
+                double time = hit.getTime();
+
+                System.out.printf("\tHit --> %.3f GeV at (%3d, %3d) and at t = %.2f%n", energy, ix, iy, time);
+            }
+        }
+
+        // A seed hit is a hit that is the largest both within its
+        // spatial range (+/- 1 in the ix and iy direction) and
+        // within a certain temporal window. If a hit is a seed, all
+        // hits within the 3x3 spatial range around it that are also
+        // within the temporal window are considered part of the
+        // cluster.
+
+        // Iterate over each hit and see if it qualifies as a seed hit.
+        seedLoop:
+            for(CalorimeterHit seed : hitList) {
+                // Check whether the potential seed passes the seed
+                // energy cut.
+                if(seed.getCorrectedEnergy() < seedThreshold) {
+                    continue seedLoop;
+                }
+
+                // Create a cluster for the potential seed.
+                BaseCluster protoCluster = new HPSEcalCluster(); // FIXME: Should be changed to BaseCluster but needs prop calculations for now.
+                protoCluster.addHit(seed);
+
+                // Iterate over the other hits and if the are within
+                // the clustering spatiotemporal window, compare their
+                // energies.
+                for(CalorimeterHit hit : hitList) {
+                    // Do not perform the comparison if the hit is the
+                    // current potential seed.
+                    if (hit != seed) {
+                        // Check if the hit is within the spatiotemporal
+                        // clustering window.
+                        if (withinTimeVerificationWindow(seed, hit) && withinSpatialWindow(seed, hit)) {
+                            // Check if the hit invalidates the potential
+                            // seed.
+                            if (isValidSeed(seed, hit)) {
+                                // Make sure that the hit is also within
+                                // the hit add window; this may not be
+                                // the same as the verification window
+                                // if the asymmetric window is active.
+                                if(withinTimeClusteringWindow(seed, hit)) {
+                                    protoCluster.addHit(hit);
+                                }
+                            }
+
+                            // If it is not, then skip the rest of the
+                            // loop; the potential seed is not really
+                            // a seed.
+                            else { continue seedLoop; }
+                        }
+                    }
+                }
+
+                // If this point is reached, then the seed was not
+                // invalidated by any of the other hits and is really
+                // a cluster center. Add the cluster to the list.
+                clusterList.add(protoCluster);
+            }
+
+        // VERBOSE :: Print out all the clusters in the event.
+        if(verbose) { 
+            for(Cluster cluster : clusterList) {
+                CalorimeterHit seedHit = cluster.getCalorimeterHits().get(0);
+                int ix = seedHit.getIdentifierFieldValue("ix");
+                int iy = seedHit.getIdentifierFieldValue("iy");
+                double energy = cluster.getEnergy();
+                double time = seedHit.getTime();
+
+                System.out.printf("\tCluster --> %.3f GeV at (%3d, %3d) and at t = %.2f%n", energy, ix, iy, time);
+
+                for(CalorimeterHit hit : cluster.getCalorimeterHits()) {
+                    int hix = hit.getIdentifierFieldValue("ix");
+                    int hiy = hit.getIdentifierFieldValue("iy");
+                    double henergy = hit.getCorrectedEnergy();
+                    double htime = hit.getTime();
+                    System.out.printf("\t\tCompHit --> %.3f GeV at (%3d, %3d) and at t = %.2f%n", henergy, hix, hiy, htime);
+                }
+            }
+        }
+
+
+        // VERBOSE :: Print a new line.
+        if(verbose) { System.out.println(); }
+
+        return clusterList;
+    }
+
+    /**
+     * Checks whether the hit <code>hit</code> keeps the hit <code>seed
+     * </code> from meeting the criteria for being a seed hit. Note that
+     * this does not check to see if the two hits are within the valid
+     * spatiotemporal window of one another.
+     * @param seed - The potential seed hit.
+     * @param hit - The hit to compare with the seed.
+     * @return Returns <code>true</code> if either the two hits are the
+     * same hit or if the hit does not invalidate the potential seed.
+     * Returns <code>false</code> otherwise.
+     */
+    private boolean isValidSeed(CalorimeterHit seed, CalorimeterHit hit) {
+        // Get the hit and seed energies.
+        double henergy = hit.getCorrectedEnergy();
+        double senergy = seed.getCorrectedEnergy();
+
+        // If the hit energy is less than the seed, the seed is valid.
+        if(henergy < senergy) {
+            return true;
+        }
+
+        // If the hit energy is the same as the seed energy, spatial
+        // comparisons are used to ensure the uniqueness of the seed.
+        if(henergy == senergy) {
+            // Get the x-indices of the hits.
+            int six = seed.getIdentifierFieldValue("ix");
+            int hix = hit.getIdentifierFieldValue("ix");
+
+            // The hit closest to the electron-side of the detector
+            // is considered the seed.
+            if(six < hix) { return true; }
+            else if(six > hix) { return false; }
+
+            // If both hits are at the same x-index, compare how close
+            // they are to the beam gap.
+            else {
+                // Get the y-indices. The absolute values are used
+                // because closeness to iy = 0 represents closeness
+                // to the beam gap.
+                int siy = Math.abs(seed.getIdentifierFieldValue("iy"));
+                int hiy = Math.abs(seed.getIdentifierFieldValue("iy"));
+
+                // If the seed is closer, it is valid.
+                if(siy < hiy) { return true; }
+                else if(siy > hiy) { return false; }
+
+                // If the y-index is the same, these are the same hit.
+                // This case shouldn't really ever happen, but for the
+                // compiler's sake, it returns true. A hit can not render
+                // itself invalid for the purpose of being a seed.
+                else { return true; }
+            }
+        }
+
+        // Otherwise, the seed is invalid.
+        else { return false; }
+    }
+
+    /**
+     * Checks whether the hit <code>hit</code> falls within the spatial
+     * window of the hit <code>Seed</code>. This is defined as within
+     * 1 index of the seed's x-index and similarly for the seed's
+     * y-index. 
+     * @param seed - The seed hit.
+     * @param hit - The comparison hit.
+     * @return Returns <code>true</code> if either both hits are the
+     * the same hit or if the comparison hit is within 1 index of the
+     * seed's x-index and within 1 index of the seed's y-index. Returns
+     * <code>false</code> otherwise.
+     */
+    private boolean withinSpatialWindow(CalorimeterHit seed, CalorimeterHit hit) {
+        // Get the x-indices of each hit.
+        int six = seed.getIdentifierFieldValue("ix");
+        int hix = hit.getIdentifierFieldValue("ix");
+
+        // Check that the x indices are either the same or within a
+        // range of one of one another.
+        if((six == hix) || (six + 1 == hix) || (six - 1 == hix)) {
+            // Get the y-indices of each hit.
+            int siy = seed.getIdentifierFieldValue("iy");
+            int hiy = hit.getIdentifierFieldValue("iy");
+
+            // Ensure that the y-indices are either the same or are
+            // within one of one another.
+            return (siy == hiy) || (siy + 1 == hiy) || (siy - 1 == hiy);
+        }
+
+        // If the x-index comparison fails, return false.
+        return false;
+    }
+
+    /**
+     * Checks whether the hit <code>hit</code> is within the temporal
+     * window of the hit <code>seed</code> for the purpose of seed
+     * verification.
+     * @param seed - The seed hit.
+     * @param hit - The comparison hit.
+     * @return Returns <code>true</code> if the comparison hit is within
+     * the temporal window of the seed hit and <code>false</code>
+     * otherwise.
+     */
+    private boolean withinTimeVerificationWindow(CalorimeterHit seed, CalorimeterHit hit) {
+        // If the hit is within the hit time window, it is valid.
+        if(Math.abs(seed.getTime() - hit.getTime()) <= timeWindow) {
+            return true;
+        }
+
+        // Otherwise, they are not.
+        else { return false; }
+    }
+
+    /**
+     * Checks whether the hit <code>hit</code> is within the temporal
+     * window of the hit <code>seed</code> for the purpose of adding
+     * a hit to a cluster.
+     * @param seed - The seed hit.
+     * @param hit - The comparison hit.
+     * @return Returns <code>true</code> if the comparison hit is within
+     * the temporal window of the seed hit and <code>false</code>
+     * otherwise.
+     */
+    private boolean withinTimeClusteringWindow(CalorimeterHit seed, CalorimeterHit hit) {
+        // Get the hit time and seed time.
+        double hitTime = hit.getTime();
+        double seedTime = seed.getTime();
+
+        // If the hit is before the seed, use the before window.
+        if(hitTime < seedTime) {
+            return (seedTime - hitTime) <= timeBefore;
+        }
+
+        // If the hit occurs after the seed, use the after window.
+        else if(hitTime > seedTime) {
+            return (hitTime - seedTime) <= timeAfter;
+        }
+
+        // If the times are the same, the are within the window.
+        if(hitTime == seedTime) { return true; }
+
+        // Otherwise, one or both times is undefined and should not be
+        // treated as within time.
+        else { return false; }
+    }
+ 
+    /**
+     * Sets the minimum energy a hit must have before it will be
+     * considered for cluster formation.
+     * @param seedThreshold - The seed threshold in GeV.
+     */
+    public void setSeedLowThreshold(double seedThreshold) {
+        this.seedThreshold = seedThreshold;
+    }
+
+    /**
+     * Sets the number of clock-cycles to include in the clustering
+     * window before the seed hit. One clock-cycle is four nanoseconds.
+     * @param cyclesBefore - The length of the clustering window before
+     * the seed hit in clock cycles.
+     */
+    public void setWindowBefore(int cyclesBefore) {
+        timeBefore = cyclesBefore * 4;
+        timeWindow = Math.max(timeBefore, timeAfter);
+    }
+
+    /**
+     * Sets the number of clock-cycles to include in the clustering
+     * window after the seed hit. One clock-cycle is four nanoseconds.
+     * @param cyclesAfter - The length of the clustering window after
+     * the seed hit in clock cycles.
+     */
+    public void setWindowAfter(int cyclesAfter) {
+        timeAfter = cyclesAfter * 4;
+        timeWindow = Math.max(timeBefore, timeAfter);
+    }
+}

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