19 added files
java/sandbox/ecal-recon
--- java/sandbox/ecal-recon/pom.xml (rev 0)
+++ java/sandbox/ecal-recon/pom.xml 2014-03-25 23:35:20 UTC (rev 346)
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>hps-ecal-recon</artifactId>
+ <name>hps-ecal-recon</name>
+ <description>HPS ECAL reconstruction module</description>
+
+ <parent>
+ <groupId>org.hps</groupId>
+ <artifactId>hps-parent</artifactId>
+ <relativePath>../parent/pom.xml</relativePath>
+ <version>3.0.2-SNAPSHOT</version>
+ </parent>
+
+ <scm>
+ <url>http://java.freehep.org/svn/repos/hps/list/java/trunk/ecal-recon/</url>
+ <connection>scm:svn:svn://svn.freehep.org/hps/java/trunk/ecal-recon/</connection>
+ <developerConnection>scm:svn:svn://svn.freehep.org/hps/java/trunk/ecal-recon/</developerConnection>
+ </scm>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.lcsim</groupId>
+ <artifactId>lcsim-distribution</artifactId>
+ <version>${lcsimVersion}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.hps</groupId>
+ <artifactId>hps-conditions</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.hps</groupId>
+ <artifactId>hps-util</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-math3</artifactId>
+ <version>3.2</version>
+ </dependency>
+ </dependencies>
+
+</project>
java/sandbox/ecal-recon/src/main/java/org/hps/recon/ecal
--- java/sandbox/ecal-recon/src/main/java/org/hps/recon/ecal/CTPEcalClusterer.java (rev 0)
+++ java/sandbox/ecal-recon/src/main/java/org/hps/recon/ecal/CTPEcalClusterer.java 2014-03-25 23:35:20 UTC (rev 346)
@@ -0,0 +1,377 @@
+package org.hps.recon.ecal;
+
+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.lcsim.event.CalorimeterHit;
+import org.lcsim.event.EventHeader;
+import org.lcsim.geometry.Detector;
+import org.lcsim.geometry.IDDecoder;
+import org.lcsim.geometry.subdetector.HPSEcal3.NeighborMap;
+import org.lcsim.geometry.subdetector.HPSEcal3;
+import org.lcsim.util.Driver;
+import org.lcsim.lcio.LCIOConstants;
+
+/**
+ * Creates clusters from CalorimeterHits in the HPSEcal detector.
+ *
+ * The clustering algorithm is from JLab Hall B 6 GeV DVCS Trigger Design doc.
+ *
+ * @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 $
+ */
+public class CTPEcalClusterer extends Driver {
+ // The calorimeter object.
+ HPSEcal3 ecal;
+ IDDecoder dec;
+ // The identification name for getting the calorimeter object.
+ String ecalName;
+ // The collection name for the calorimeter hits.
+ String ecalCollectionName;
+ // The collection name in which to store clusters.
+ String clusterCollectionName = "EcalClusters";
+ Set<Long> clusterCenters = null;
+ Map<Long, Double> hitSums = null;
+ Map<Long, CalorimeterHit> hitMap = null;
+ // Map of crystals to their neighbors.
+ NeighborMap neighborMap = 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;
+
+ public CTPEcalClusterer() {
+ }
+
+ public void setAddEMin(double addEMin) {
+ this.addEMin = addEMin;
+ }
+
+ public void setClusterWindow(double clusterWindow) {
+ this.clusterWindow = clusterWindow;
+ }
+
+ public void setClusterCollectionName(String clusterCollectionName) {
+ this.clusterCollectionName = clusterCollectionName;
+ }
+
+ public void setEcalCollectionName(String ecalCollectionName) {
+ this.ecalCollectionName = ecalCollectionName;
+ }
+
+ public void setEcalName(String ecalName) {
+ this.ecalName = ecalName;
+ }
+
+ public void startOfData() {
+ // Make sure that there is a cluster collection name into which clusters may be placed.
+ if (ecalCollectionName == null) {
+ throw new RuntimeException("The parameter ecalCollectionName was not set!");
+ }
+
+ // Make sure that there is a calorimeter detector.
+ if (ecalName == null) {
+ throw new RuntimeException("The parameter ecalName was not set!");
+ }
+ }
+
+ @Override
+ public void detectorChanged(Detector detector) {
+ // Get the Subdetector.
+ ecal = (HPSEcal3) detector.getSubdetector(ecalName);
+
+ // Get the decoder for the ECal IDs.
+ dec = ecal.getIDDecoder();
+
+ // Cache reference to the neighbor map.
+ neighborMap = ecal.getNeighborMap();
+
+ clusterCenters = new HashSet<Long>();
+ // Make set of valid cluster centers.
+ // Exclude edge crystals as good cluster centers.
+ 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);
+ }
+ }
+ }
+
+ public void process(EventHeader event) {
+ // Make sure that this event has calorimeter hits.
+ if (event.hasCollection(CalorimeterHit.class, ecalCollectionName)) {
+ // Get the list of calorimeter hits from the event.
+ List<CalorimeterHit> hits = event.get(CalorimeterHit.class, ecalCollectionName);
+
+ // Define a list of clusters to be filled.
+ List<HPSEcalCluster> clusters;
+
+ // If there is a cluster window, run the clsuter 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<HPSEcalCluster>();
+
+ // 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();
+ }
+
+ // Put the cluster collection into the event.
+ int flag = 1 << LCIOConstants.CLBIT_HITS;
+ event.put(clusterCollectionName, clusters, HPSEcalCluster.class, flag);
+ }
+ }
+
+ public 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());
+ }
+ }
+ }
+ }
+
+ public List<HPSEcalCluster> createClusters() {
+ // Create a list of clusters to be added to the event,
+ List<HPSEcalCluster> clusters = new ArrayList<HPSEcalCluster>();
+
+ // 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 = new HPSCalorimeterHit(0.0, clusterTime, possibleCluster, hits.get(0).getType());
+ seedHit.setMetaData(hits.get(0).getMetaData());
+
+ // Generate a new cluster from the seed hit.
+ HPSEcalCluster cluster = new HPSEcalCluster(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;
+ }
+ }
+ }
+}
java/sandbox/ecal-recon/src/main/java/org/hps/recon/ecal
--- java/sandbox/ecal-recon/src/main/java/org/hps/recon/ecal/ECalUtils.java (rev 0)
+++ java/sandbox/ecal-recon/src/main/java/org/hps/recon/ecal/ECalUtils.java 2014-03-25 23:35:20 UTC (rev 346)
@@ -0,0 +1,77 @@
+package org.hps.recon.ecal;
+
+import org.lcsim.event.CalorimeterHit;
+
+/**
+ *
+ * @author Sho Uemura <[log in to unmask]>
+ * @version $Id: ECalUtils.java,v 1.1 2013/02/25 22:39:24 meeg Exp $
+ */
+public class ECalUtils {
+
+ public static final double GeV = 1.0;
+ public static final double MeV = 0.001;
+ //parameters for 2014 APDs and preamp
+ public static final double riseTime = 10.0; //10 pulse rise time in ns
+ public static final double fallTime = 17.0; //17 pulse fall time in ns
+ public static final double lightYield = 120. / MeV; // number of photons per GeV
+ public static final double quantumEff = 0.7; // quantum efficiency of the APD
+ public static final double surfRatio = (10. * 10.) / (16 * 16); // surface ratio between APD and crystals
+ public static final double gainAPD = 150.; // Gain of the APD
+ public static final double elemCharge = 1.60217657e-19;
+ public static final double gainPreAmpl = 525e12; // Gain of the preamplifier in pC/pC, true value is higher but does not take into account losses
+ public static final int nBit = 12; //number of bits used by the fADC to code a value
+ public static final double maxVolt = 2.0; //maximum volt intput of the fADC
+ public static final double Req = 1.0 / 27.5; // equivalent resistance of the amplification chain
+ public static final double adcResolution = 2.0 / (Math.pow(2, nBit) - 1); //volts per ADC count
+ public static final double readoutGain = Req * lightYield * quantumEff * surfRatio * gainAPD * gainPreAmpl * elemCharge;// = 15.0545 volt-seconds/GeV
+ public static final double gainFactor = adcResolution / readoutGain;
+ public static final double ecalReadoutPeriod = 4.0; // readout period in ns, it is hardcoded in the public declaration of EcalReadoutDriver.
+
+ /**
+ * Returns the quadrant which contains the ECal cluster
+ *
+ * @param ecalCluster : ECal cluster
+ * @return Quadrant number
+ */
+ public static int getQuadrant(HPSEcalCluster ecalCluster) {
+ return getQuadrant(ecalCluster.getSeedHit());
+ }
+
+ public static int getQuadrant(CalorimeterHit hit) {
+ int ix = hit.getIdentifierFieldValue("ix");
+ int iy = hit.getIdentifierFieldValue("iy");
+ return getQuadrant(ix, iy);
+ }
+
+ public static int getQuadrant(int x, int y) {
+ if (x > 0) {
+ if (y > 0) {
+ return 1;
+ } else {
+ return 4;
+ }
+ } else {
+ if (y > 0) {
+ return 2;
+ } else {
+ return 3;
+ }
+ }
+ }
+
+ public static int getHVGroup(int x, int y) {
+ int absy = Math.abs(y);
+ if (x > 0 || x <= -8) {
+ return (23 - Math.abs(x)) / 2 + 1;
+ } else {
+ if (x == -7 && absy == 5) {
+ return 8;
+ } else if (x >= -4) {
+ return 12 - Math.max(x + 4, absy - 2);
+ } else {
+ return 12 - Math.max(-5 - x, absy - 2);
+ }
+ }
+ }
+}
java/sandbox/ecal-recon/src/main/java/org/hps/recon/ecal
--- java/sandbox/ecal-recon/src/main/java/org/hps/recon/ecal/EcalClusterIC.java (rev 0)
+++ java/sandbox/ecal-recon/src/main/java/org/hps/recon/ecal/EcalClusterIC.java 2014-03-25 23:35:20 UTC (rev 346)
@@ -0,0 +1,372 @@
+package org.hps.recon.ecal;
+
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.lcsim.event.CalorimeterHit;
+import org.lcsim.event.EventHeader;
+import org.lcsim.geometry.Detector;
+import org.lcsim.geometry.subdetector.HPSEcal3;
+import org.lcsim.geometry.subdetector.HPSEcal3.NeighborMap;
+import org.lcsim.lcio.LCIOConstants;
+import org.lcsim.util.Driver;
+
+/**
+ * This Driver creates clusters from the CalorimeterHits of an
+ * {@link org.lcsim.geometry.subdetectur.HPSEcal3} detector.
+ *
+ *
+ * @author Holly Szumila-Vance <[log in to unmask]>
+ *
+ */
+public class EcalClusterIC extends Driver {
+ FileWriter writeHits;
+ HPSEcal3 ecal;
+ String ecalCollectionName;
+ String ecalName = "Ecal";
+ String clusterCollectionName = "EcalClusters";
+ // Map of crystals to their neighbors.
+ NeighborMap neighborMap = null;
+ //Minimum energy that counts as hit
+ double Emin = 0.001;
+
+
+ public EcalClusterIC() {
+ }
+
+ public void setClusterCollectionName(String clusterCollectionName) {
+ this.clusterCollectionName = clusterCollectionName;
+ }
+
+ public void setEcalCollectionName(String ecalCollectionName) {
+ this.ecalCollectionName = ecalCollectionName;
+ }
+
+ public void setEcalName(String ecalName) {
+ this.ecalName = ecalName;
+ }
+
+ public void startOfData() {
+ if (ecalCollectionName == null) {
+ throw new RuntimeException("The parameter ecalCollectionName was not set!");
+ }
+
+ if (ecalName == null) {
+ throw new RuntimeException("The parameter ecalName was not set!");
+ }
+
+ try{
+ writeHits = new FileWriter("cluster-hit-IC.txt");
+ writeHits.write("");
+ }
+ catch(IOException e) {};
+ }
+
+ public void detectorChanged(Detector detector) {
+ // Get the Subdetector.
+ ecal = (HPSEcal3) detector.getSubdetector(ecalName);
+
+ // Cache ref to neighbor map.
+ neighborMap = ecal.getNeighborMap();
+ }
+
+ public void process(EventHeader event) {
+
+
+
+ if (event.hasCollection(CalorimeterHit.class, ecalCollectionName)) {
+ // Get the list of raw ECal hits.
+ List<CalorimeterHit> hits = event.get(CalorimeterHit.class, ecalCollectionName);
+
+ // Make a hit map for quick lookup by ID.
+ Map<Long, CalorimeterHit> hitMap = new HashMap<Long, CalorimeterHit>();
+
+ for (CalorimeterHit hit : hits) {
+ hitMap.put(hit.getCellID(), hit);
+ }
+
+ //System.out.println("Number of ECal hits: "+hitMap.size());
+
+ // Put Cluster collection into event.
+ int flag = 1 << LCIOConstants.CLBIT_HITS;
+ try {
+
+ event.put(clusterCollectionName, createClusters(hitMap), HPSEcalCluster.class, flag);
+ }
+ catch(IOException e) { }
+ }
+ }
+
+ public List<HPSEcalCluster> createClusters(Map<Long, CalorimeterHit> map) throws IOException {
+
+ // New Cluster list to be added to event.
+ List<HPSEcalCluster> clusters = new ArrayList<HPSEcalCluster>();
+
+ //Create a Calorimeter hit list in each event, then sort with highest energy first
+ ArrayList<CalorimeterHit> chitList = new ArrayList<CalorimeterHit>(map.size());
+ for(CalorimeterHit h : map.values()) {
+ if(h.getCorrectedEnergy()>Emin){
+ chitList.add(h);}
+
+ Collections.sort(chitList, new EnergyComparator());}
+
+ //New Seed list containing each local maximum energy hit
+ List<CalorimeterHit> seedHits = new ArrayList<CalorimeterHit>();
+
+ //Create map to contain common hits for evaluation later, key is crystal and values are seed
+ Map<CalorimeterHit, List<CalorimeterHit>> commonHits = new HashMap<CalorimeterHit, List<CalorimeterHit>>();
+
+ //Created map to contain seeds with listed hits, key is crystal, and value is seed
+ Map<CalorimeterHit, CalorimeterHit> clusterHits = new HashMap<CalorimeterHit, CalorimeterHit>();
+
+ //Create map to contain the total energy of each cluster
+ Map<CalorimeterHit, Double> seedEnergy = new HashMap<CalorimeterHit,Double>();
+
+ //Quick Map to access hits from cell IDs
+ Map<Long, CalorimeterHit> hitID = new HashMap<Long, CalorimeterHit>();
+
+ //List to contain all hits already put into clusters
+ List<CalorimeterHit> clusterHitList = new ArrayList<CalorimeterHit>();
+
+ //Fill Map with cell ID and hit
+ for (CalorimeterHit hit : chitList){
+ hitID.put(hit.getCellID(), hit);
+ }
+
+ for (CalorimeterHit hit : chitList) {
+ Set<Long> neighbors = neighborMap.get(hit.getCellID()); //get all neighbors of hit
+ List<CalorimeterHit> neighborHits = new ArrayList<CalorimeterHit>();
+ for(Long neighbor : neighbors){
+ if(hitID.containsKey(neighbor)){//map contains (neighbor's cell id, neighbor hit)
+ neighborHits.add(hitID.get(neighbor));
+ }
+ }
+
+ Collections.sort(neighborHits, new EnergyComparator());
+
+ boolean highestE = true;
+ for(CalorimeterHit neighborHit : neighborHits){//check for seed hit
+ if(hit.getCorrectedEnergy()>neighborHit.getCorrectedEnergy()){
+ continue;
+ }
+ else {
+ highestE = false;
+ break;
+ }
+ }
+
+ if (highestE == true){//seed hit, local maximum
+ seedHits.add(hit);
+ clusterHits.put(hit, hit);
+ clusterHitList.add(hit);
+ }
+
+ //not seed hit
+ else {
+ //builds immediate clusters around seed hits
+ for(CalorimeterHit neighborHit : neighborHits){
+ //if neighbor to seed, add to seed
+ if (seedHits.contains(neighborHit)&&!clusterHits.containsKey(hit)){
+ CalorimeterHit seed = clusterHits.get(neighborHit);
+ clusterHits.put(hit, seed);
+ clusterHitList.add(hit);
+ }
+ //if neighbor to two seeds, add to common hits
+ else if (seedHits.contains(neighborHit)&&clusterHits.containsKey(hit)){
+ CalorimeterHit prevSeed = clusterHits.get(neighborHit);
+ CalorimeterHit currSeed = clusterHits.get(hit);
+ List<CalorimeterHit> commonHitList = new ArrayList<CalorimeterHit>();
+ commonHitList.add(prevSeed);
+ commonHitList.add(currSeed);
+ commonHits.put(hit, commonHitList);
+ }
+ }
+ }
+ }
+
+ //loop over hit list, find neighbors, compare energies, add to list
+ for(CalorimeterHit nHit : chitList){
+ Set<Long> neighbors2 = neighborMap.get(nHit.getCellID()); //get all neighbors of hit
+ List<CalorimeterHit> neighborHits2 = new ArrayList<CalorimeterHit>();
+ for(Long neighbor : neighbors2){
+ if(hitID.containsKey(neighbor)){//map contains (neighbor's cell id, neighbor hit)
+ if(!clusterHitList.contains(hitID.get(neighbor))){
+ neighborHits2.add(hitID.get(neighbor));
+ }
+ }
+ }
+
+ Collections.sort(neighborHits2, new EnergyComparator());
+ for(CalorimeterHit neighbor : neighborHits2){
+ if(neighbor.getCorrectedEnergy()<nHit.getCorrectedEnergy()){
+ CalorimeterHit seed = clusterHits.get(nHit);
+ clusterHits.put(neighbor, seed);
+ clusterHitList.add(neighbor);
+ }
+ else{continue;}
+ }
+ }
+ //loop over cluster hits, compare energies of neighbors with diff seeds, if min->add to commonHits
+ for (CalorimeterHit mHit : clusterHitList){
+ //exclude seed hits as possible common hits
+ if(clusterHits.get(mHit) != mHit){
+
+ Set<Long> neighbors3 = neighborMap.get(mHit.getCellID()); //get all neighbors of hit
+ List<CalorimeterHit> neighborHits3 = new ArrayList<CalorimeterHit>();
+ for(Long neighbor : neighbors3){
+ if(hitID.containsKey(neighbor)){//map contains (neighbor's cell id, neighbor hit)
+ neighborHits3.add(hitID.get(neighbor));
+
+ }
+ }
+
+ Collections.sort(neighborHits3, new EnergyComparator());
+
+ CalorimeterHit compSeed = clusterHits.get(mHit);
+ for(CalorimeterHit neighbor : neighborHits3){
+ if(clusterHits.get(neighbor)!=compSeed){//borders clusters
+ if(mHit.getCorrectedEnergy() < neighbor.getCorrectedEnergy()){
+ //add to common hits,
+ List<CalorimeterHit> commonHitList = new ArrayList<CalorimeterHit>();
+ commonHitList.add(compSeed);
+ commonHitList.add(clusterHits.get(neighbor));
+ commonHits.put(mHit, commonHitList);
+ }
+ }
+ }
+ }
+ }
+
+ //remove common hits from cluster hits list
+ for(CalorimeterHit commHit : clusterHitList){
+ if(clusterHitList.contains(commHit)&&commonHits.containsKey(commHit)){
+ clusterHits.remove(commHit);
+ }
+ else{
+ continue;
+ }
+ }
+
+
+
+ //Get energy of each cluster, excluding common hits
+ for(CalorimeterHit iSeed : seedHits){
+ seedEnergy.put(iSeed, 0.0);
+ }
+ //Putting total cluster energies excluding common hit energies into map with seed keys
+ for (Map.Entry<CalorimeterHit, CalorimeterHit> entry : clusterHits.entrySet()) {
+ CalorimeterHit eSeed = entry.getValue();
+ double eEnergy = seedEnergy.get(eSeed);
+ eEnergy += entry.getKey().getRawEnergy();
+ seedEnergy.put(eSeed, eEnergy);
+ }
+
+ //Distribute common hit energies with clusters
+ Map<CalorimeterHit, Double> seedEnergyTot = seedEnergy;
+ for (Map.Entry<CalorimeterHit, List<CalorimeterHit>> entry1 : commonHits.entrySet()) {
+ CalorimeterHit commonCell = entry1.getKey();
+ List<CalorimeterHit> commSeedList = entry1.getValue();
+ CalorimeterHit seedA = commSeedList.get(0);
+ CalorimeterHit seedB = commSeedList.get(1);
+ double eFractionA = seedEnergy.get(seedA)/(seedEnergy.get(seedA)+seedEnergy.get(seedB));
+ double eFractionB = seedEnergy.get(seedB)/(seedEnergy.get(seedA)+seedEnergy.get(seedB));
+ double currEnergyA = seedEnergyTot.get(seedA);
+ double currEnergyB = seedEnergyTot.get(seedB);
+ currEnergyA += eFractionA*commonCell.getCorrectedEnergy();
+ currEnergyB += eFractionB*commonCell.getCorrectedEnergy();
+
+ seedEnergyTot.put(seedA, currEnergyA);
+ seedEnergyTot.put(seedB, currEnergyB);
+ }
+
+
+ //Do some system.out for number of crystals in each cluster, energy of each cluster
+ for (Map.Entry<CalorimeterHit, Double> entryEnergy : seedEnergyTot.entrySet()){
+ // System.out.println(entryEnergy.getKey().getCellID()+"\t"+entryEnergy.getKey().getCorrectedEnergy()+
+ // "\t"+entryEnergy.getValue());
+ }
+
+ // System.out.println("Number of clusters: "+seedHits.size());
+
+
+ if (map.size()!=0){
+ writeHits.append("Event"+"\t"+"1"+"\n");
+ for (CalorimeterHit n : chitList){
+ writeHits.append("EcalHit" + "\t" + n.getIdentifierFieldValue("ix") + "\t" + n.getIdentifierFieldValue("iy")
+ + "\t" +n.getCorrectedEnergy() + "\n");
+ }
+
+ for (Map.Entry<CalorimeterHit, CalorimeterHit> entry2 : clusterHits.entrySet()){
+ if (entry2.getKey()==entry2.getValue()){//seed
+ writeHits.append("Cluster" + "\t" + entry2.getKey().getIdentifierFieldValue("ix")+
+ "\t"+entry2.getKey().getIdentifierFieldValue("iy")+"\t"+seedEnergyTot.get(entry2.getKey())+"\n");
+
+ HPSEcalCluster cluster = new HPSEcalCluster(entry2.getKey());
+ cluster.addHit(entry2.getKey());
+
+ for (Map.Entry<CalorimeterHit, CalorimeterHit> entry3 : clusterHits.entrySet()){
+ if (entry3.getValue() == entry2.getValue()){
+ writeHits.append("CompHit" + "\t" + entry3.getKey().getIdentifierFieldValue("ix")+ "\t"
+ +entry3.getKey().getIdentifierFieldValue("iy") + "\n");
+
+ cluster.addHit(entry3.getKey());
+ }
+ }
+ for (Map.Entry<CalorimeterHit, List<CalorimeterHit>> entry4 : commonHits.entrySet()){
+ if (entry4.getValue().contains(entry2.getKey())){
+ writeHits.append("SharHit" + "\t" + entry4.getKey().getIdentifierFieldValue("ix")+ "\t"
+ +entry4.getKey().getIdentifierFieldValue("iy") + "\n");
+
+ cluster.addHit(entry4.getKey());
+
+ }
+ }
+
+ clusters.add(cluster);
+ }
+ }
+ writeHits.append("EndEvent\n");
+
+ }
+
+ //Clear all maps for next event iteration
+ hitID.clear();
+ clusterHits.clear();
+ seedHits.clear();
+ commonHits.clear();
+ chitList.clear();
+ seedEnergy.clear();
+
+ return clusters;
+
+
+
+
+ }
+
+ public void endOfData() {
+ try{
+ writeHits.close();
+ }
+ catch (IOException e){ }
+ }
+
+ private class EnergyComparator implements Comparator<CalorimeterHit>{
+
+ @Override
+ public int compare(CalorimeterHit o1, CalorimeterHit o2) {
+ // TODO Auto-generated method stub
+ double diff = o1.getCorrectedEnergy()-o2.getCorrectedEnergy();
+ if(diff < 0) { return 1; }
+ if(diff > 0) { return -1; }
+ else { return 0; }
+ }
+ }
+}
java/sandbox/ecal-recon/src/main/java/org/hps/recon/ecal
--- java/sandbox/ecal-recon/src/main/java/org/hps/recon/ecal/EcalClusterer.java (rev 0)
+++ java/sandbox/ecal-recon/src/main/java/org/hps/recon/ecal/EcalClusterer.java 2014-03-25 23:35:20 UTC (rev 346)
@@ -0,0 +1,171 @@
+package org.hps.recon.ecal;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.lcsim.event.CalorimeterHit;
+import org.lcsim.event.EventHeader;
+import org.lcsim.geometry.Detector;
+import org.lcsim.geometry.subdetector.HPSEcal3.NeighborMap;
+import org.lcsim.geometry.subdetector.HPSEcal3;
+import org.lcsim.util.Driver;
+import org.lcsim.lcio.LCIOConstants;
+
+/**
+ * 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.
+ *
+ * @author Jeremy McCormick <[log in to unmask]>
+ * @author Tim Nelson <[log in to unmask]>
+ *
+ * @version $Id: EcalClusterer.java,v 1.1 2013/02/25 22:39:24 meeg Exp $
+ */
+public class EcalClusterer extends Driver {
+
+ HPSEcal3 ecal;
+ String ecalCollectionName;
+ String ecalName = "Ecal";
+ String clusterCollectionName = "EcalClusters";
+ // Minimum E for cluster seed.
+ double seedEMin = .05 * ECalUtils.GeV;
+ // Minimum E to add hit to cluster.
+ double addEMin = .03 * ECalUtils.GeV;
+ // Odd or even number of crystals in X.
+ boolean oddX;
+ // Map of crystals to their neighbors.
+ NeighborMap neighborMap = null;
+
+ public EcalClusterer() {
+ }
+
+ public void setClusterCollectionName(String clusterCollectionName) {
+ this.clusterCollectionName = clusterCollectionName;
+ }
+
+ public void setSeedEMin(double seedEMin) {
+ this.seedEMin = seedEMin;
+ }
+
+ public void setAddEMin(double addEMin) {
+ this.addEMin = addEMin;
+ if (seedEMin < addEMin) {
+ seedEMin = addEMin;
+ }
+ }
+
+ public void setEcalCollectionName(String ecalCollectionName) {
+ this.ecalCollectionName = ecalCollectionName;
+ }
+
+ public void setEcalName(String ecalName) {
+ this.ecalName = ecalName;
+ }
+
+ public void startOfData() {
+ if (ecalCollectionName == null) {
+ throw new RuntimeException("The parameter ecalCollectionName was not set!");
+ }
+
+ if (ecalName == null) {
+ throw new RuntimeException("The parameter ecalName was not set!");
+ }
+ }
+
+ public void detectorChanged(Detector detector) {
+ // Get the Subdetector.
+ ecal = (HPSEcal3) detector.getSubdetector(ecalName);
+
+ // Cache ref to neighbor map.
+ neighborMap = ecal.getNeighborMap();
+
+ //System.out.println(ecal.getName());
+ //System.out.println(" nx="+ecal.nx());
+ //System.out.println(" ny="+ecal.ny());
+ //System.out.println(" beamgap="+ecal.beamGap());
+ //System.out.println(" dface="+ecal.distanceToFace());
+
+ //System.out.println(neighborMap.toString());
+ }
+
+ public void process(EventHeader event) {
+ //System.out.println(this.getClass().getCanonicalName() + " - process");
+
+ if (event.hasCollection(CalorimeterHit.class, ecalCollectionName)) {
+ // Get the list of raw ECal hits.
+ List<CalorimeterHit> hits = event.get(CalorimeterHit.class, ecalCollectionName);
+
+ // Make a hit map for quick lookup by ID.
+ Map<Long, CalorimeterHit> hitMap = new HashMap<Long, CalorimeterHit>();
+ for (CalorimeterHit hit : hits) {
+ hitMap.put(hit.getCellID(), hit);
+ }
+
+ // Put Cluster collection into event.
+ int flag = 1 << LCIOConstants.CLBIT_HITS;
+ event.put(clusterCollectionName, createClusters(hitMap), HPSEcalCluster.class, flag);
+ }
+ }
+
+ public List<HPSEcalCluster> createClusters(Map<Long, CalorimeterHit> map) {
+
+ // New Cluster list to be added to event.
+ List<HPSEcalCluster> clusters = new ArrayList<HPSEcalCluster>();
+
+ // Loop over ECal hits to find cluster seeds.
+ for (CalorimeterHit hit : map.values()) {
+ // Cut on min seed E.
+ if (hit.getRawEnergy() < seedEMin) {
+ continue;
+ }
+
+ // Get neighbor crystal IDs.
+ Set<Long> neighbors = neighborMap.get(hit.getCellID());
+
+ if (neighbors == null) {
+ throw new RuntimeException("Oops! Set of neighbors is null!");
+ }
+
+ // List for neighboring hits.
+ List<CalorimeterHit> neighborHits = new ArrayList<CalorimeterHit>();
+
+ // Loop over neighbors to make hit list for cluster.
+ boolean isSeed = true;
+ for (Long neighborId : neighbors) {
+ // Find the neighbor hit in the event if it exists.
+ CalorimeterHit neighborHit = map.get(neighborId);
+
+ // Was this neighbor cell hit?
+ if (neighborHit != null) {
+ // Check if neighbor cell has more energy.
+ if (neighborHit.getRawEnergy() > hit.getRawEnergy()) {
+ // Neighbor has more energy, so cell is not a seed.
+ isSeed = false;
+ break;
+ }
+
+ // Add to cluster if above min E.
+ if (neighborHit.getRawEnergy() >= addEMin) {
+ neighborHits.add(neighborHit);
+ }
+ }
+ }
+
+ // Did we find a seed?
+ if (isSeed) {
+ // Make a cluster from the hit list.
+ HPSEcalCluster cluster = new HPSEcalCluster(hit);
+ cluster.addHit(hit);
+ for (CalorimeterHit clusHit : neighborHits) {
+ cluster.addHit(clusHit);
+ }
+ clusters.add(cluster);
+ }
+ }
+ return clusters;
+ }
+}
\ No newline at end of file
java/sandbox/ecal-recon/src/main/java/org/hps/recon/ecal
--- java/sandbox/ecal-recon/src/main/java/org/hps/recon/ecal/EcalConditions.java (rev 0)
+++ java/sandbox/ecal-recon/src/main/java/org/hps/recon/ecal/EcalConditions.java 2014-03-25 23:35:20 UTC (rev 346)
@@ -0,0 +1,351 @@
+package org.hps.recon.ecal;
+
+import java.io.BufferedReader;
+import org.lcsim.geometry.compact.Subdetector;
+import java.io.IOException;
+import java.io.Reader;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.StringTokenizer;
+import org.lcsim.conditions.ConditionsManager;
+import org.lcsim.detector.identifier.ExpandedIdentifier;
+import org.lcsim.detector.identifier.IExpandedIdentifier;
+import org.lcsim.detector.identifier.IIdentifierHelper;
+import org.lcsim.geometry.Detector;
+import org.lcsim.util.Driver;
+
+/**
+ *
+ * @author meeg
+ * @version $Id: EcalConditions.java,v 1.2 2013/10/24 20:01:54 meeg Exp $
+ */
+public class EcalConditions extends Driver {
+
+ //DAQ channel map
+ private static HashMap<Long, Long> daqToPhysicalMap = new HashMap<Long, Long>();
+ private static HashMap<Long, Long> physicalToDaqMap = new HashMap<Long, Long>();
+ //pedestals
+ private static HashMap<Long, Double> daqToPedestalMap = new HashMap<Long, Double>();
+ private static HashMap<Long, Double> daqToNoiseMap = new HashMap<Long, Double>();
+ //set of bad channels to ignore
+ private static HashSet<Long> badChannelsSet = new HashSet<Long>();
+ private static boolean badChannelsLoaded = false;
+ private static IIdentifierHelper helper = null;
+ //gain
+ private static HashMap<Long, Double> physicalToGainMap = new HashMap<Long, Double>();
+ //subdetector name (for when this is used as a driver)
+ private String subdetectorName = "Ecal";
+ private static Subdetector subdetector;
+ private static boolean debug = false;
+ private static boolean calibrationLoaded = false;
+ private static String gainFilename = "default.gain";
+
+ public EcalConditions() {
+ }
+
+ @Override
+ public void detectorChanged(Detector detector) {
+ detectorChanged(detector, subdetectorName);
+ }
+
+ public static void detectorChanged(Detector detector, String ecalName) {
+ subdetector = detector.getSubdetector(ecalName);
+ if (subdetector == null) {
+ throw new RuntimeException("Subdetector " + ecalName + " not found");
+ }
+ helper = subdetector.getDetectorElement().getIdentifierHelper();
+ }
+
+ public static boolean calibrationLoaded() {
+ return calibrationLoaded;
+ }
+
+ public static void loadDaqMap(Detector detector, String ecalName) {
+ detectorChanged(detector, ecalName);
+ fillDaqCellMap(subdetector);
+ }
+
+ public static void loadCalibration() {
+ fillDaqCellMap(subdetector);
+ loadBadChannels(subdetector);
+ loadGains();
+ loadPedestals();
+ calibrationLoaded = true;
+ }
+
+ public static void setGainFilename(String name) {
+ gainFilename = name;
+ }
+
+ public void setSubdetectorName(String subdetectorName) {
+ this.subdetectorName = subdetectorName;
+ }
+
+ public static IIdentifierHelper getHelper() {
+ return helper;
+ }
+
+ public static Subdetector getSubdetector() {
+ return subdetector;
+ }
+
+ public static boolean badChannelsLoaded() {
+ return badChannelsLoaded;
+ }
+
+ public static void loadPedestals() {
+ ConditionsManager conditions = ConditionsManager.defaultInstance();
+ try {
+ Reader pedestalsReader = conditions.getRawConditions("calibECal/default01.ped").getReader();
+ loadPedestals(pedestalsReader, 1);
+ pedestalsReader = conditions.getRawConditions("calibECal/default02.ped").getReader();
+ loadPedestals(pedestalsReader, 2);
+ } catch (IOException e) {
+ throw new RuntimeException("couldn't get pedestals file", e);
+ }
+ }
+
+ public static void loadPedestals(Reader reader, int crate) {
+
+ System.out.println("reading pedestals for ECal");
+
+ BufferedReader bufferedReader = new BufferedReader(reader);
+ String line;
+ while (true) {
+ try {
+ line = bufferedReader.readLine();
+ } catch (IOException e) {
+ throw new RuntimeException("couldn't parse pedestals file", e);
+ }
+ if (line == null) {
+ break;
+ }
+
+ if (line.indexOf("#") != -1) {
+ line = line.substring(0, line.indexOf("#"));
+ }
+
+ StringTokenizer lineTok = new StringTokenizer(line);
+
+ if (lineTok.countTokens() != 0) {
+ if (lineTok.countTokens() != 4) {
+ throw new RuntimeException("Invalid line in pedestals file: " + line);
+ } else {
+ short slot = Short.valueOf(lineTok.nextToken());
+ short channel = Short.valueOf(lineTok.nextToken());
+ double pedestal = Double.valueOf(lineTok.nextToken());
+ double noise = Double.valueOf(lineTok.nextToken());
+ long daqid = getDaqID(crate, slot, channel);
+ daqToPedestalMap.put(daqid, pedestal);
+ daqToNoiseMap.put(daqid, noise);
+ if (debug) {
+ System.out.printf("Channel %d: pede %.2f noise %.2f (crate %d slot %d channel %d)\n", daqid,pedestal,noise,crate,slot,channel);
+ }
+ }
+ }
+ }
+ }
+
+ private static void loadBadChannels(Subdetector ecal) {
+
+ System.out.println("reading ECal bad channels");
+
+ IExpandedIdentifier expId = new ExpandedIdentifier(helper.getIdentifierDictionary().getNumberOfFields());
+ expId.setValue(helper.getFieldIndex("system"), ecal.getSystemID());
+ ConditionsManager conditions = ConditionsManager.defaultInstance();
+ BufferedReader bufferedReader;
+ try {
+ bufferedReader = new BufferedReader(conditions.getRawConditions("daqmap/ecal.badchannels").getReader());
+ } catch (IOException e) {
+ throw new RuntimeException("couldn't get ECal bad channels from conditions manager", e);
+ }
+ String line;
+ while (true) {
+ try {
+ line = bufferedReader.readLine();
+ } catch (IOException e) {
+ throw new RuntimeException("couldn't parse ECal bad channels", e);
+ }
+ if (line == null) {
+ break;
+ }
+
+ if (line.indexOf("#") != -1) {
+ line = line.substring(0, line.indexOf("#"));
+ }
+
+ StringTokenizer lineTok = new StringTokenizer(line);
+
+ if (lineTok.countTokens() != 0) {
+ if (lineTok.countTokens() != 2) {
+ throw new RuntimeException("Invalid line in ECal bad channels: " + line);
+ } else {
+ int x = Integer.valueOf(lineTok.nextToken());
+ int y = Integer.valueOf(lineTok.nextToken());
+ expId.setValue(helper.getFieldIndex("ix"), x);
+ expId.setValue(helper.getFieldIndex("iy"), y);
+ badChannelsSet.add(helper.pack(expId).getValue());
+ if (debug) {
+ System.out.printf("Channel %d is bad (x=%d y=%d)\n", helper.pack(expId).getValue(),x,y);
+ }
+ }
+ }
+ }
+ badChannelsLoaded = true;
+ }
+
+ public static void loadGains() {
+ if (debug) {
+ System.out.println("Loading gains");
+ }
+ BufferedReader bufferedReader;
+ ConditionsManager conditions = ConditionsManager.defaultInstance();
+ try {
+ bufferedReader = new BufferedReader(conditions.getRawConditions("calibECal/"+EcalConditions.gainFilename).getReader());
+ } catch (IOException e) {
+ throw new RuntimeException("couldn't get gain file("+gainFilename+") ", e);
+ }
+
+ String line;
+ while (true) {
+ try {
+ line = bufferedReader.readLine();
+ } catch (IOException e) {
+ throw new RuntimeException("couldn't parse gain file", e);
+ }
+ if (line == null) {
+ break;
+ }
+
+ if (line.indexOf("#") != -1) {
+ line = line.substring(0, line.indexOf("#"));
+ }
+
+ StringTokenizer lineTok = new StringTokenizer(line);
+
+ if (lineTok.countTokens() != 0) {
+ if (lineTok.countTokens() != 3) {
+ throw new RuntimeException("Invalid line in gain file: " + line);
+ } else {
+ int x = Integer.valueOf(lineTok.nextToken());
+ int y = Integer.valueOf(lineTok.nextToken());
+ double gain = Double.valueOf(lineTok.nextToken());
+ physicalToGainMap.put(makePhysicalID(x, y), gain);
+ if (debug) {
+ System.out.printf("Channel %d: gain %.2f (x=%d y=%d)\n", makePhysicalID(x, y),gain,x,y);
+ }
+ }
+ }
+ }
+ }
+
+ public static boolean isBadChannel(long id) {
+ return badChannelsSet.contains(id);
+ }
+
+ private static void fillDaqCellMap(Subdetector ecal) {
+
+ System.out.println("reading ECal DAQ map");
+
+ IExpandedIdentifier expId = new ExpandedIdentifier(helper.getIdentifierDictionary().getNumberOfFields());
+ expId.setValue(helper.getFieldIndex("system"), ecal.getSystemID());
+
+ ConditionsManager conditions = ConditionsManager.defaultInstance();
+ BufferedReader bufferedReader;
+ try {
+ bufferedReader = new BufferedReader(conditions.getRawConditions("daqmap/ecal.txt").getReader());
+ } catch (IOException e) {
+ throw new RuntimeException("couldn't get DAQ map from conditions manager", e);
+ }
+ String line;
+ while (true) {
+ try {
+ line = bufferedReader.readLine();
+ } catch (IOException e) {
+ throw new RuntimeException("couldn't parse ECal DAQ map", e);
+ }
+ if (line == null) {
+ break;
+ }
+
+ if (line.indexOf("#") != -1) {
+ line = line.substring(0, line.indexOf("#"));
+ }
+
+ StringTokenizer lineTok = new StringTokenizer(line);
+
+ if (lineTok.countTokens() != 0) {
+ if (lineTok.countTokens() != 5) {
+ throw new RuntimeException("Invalid line in ECal DAQ map: " + line);
+ } else {
+ int x = Integer.valueOf(lineTok.nextToken());
+ int y = Integer.valueOf(lineTok.nextToken());
+// if (x>0 && y>0) x = 24-x;
+ expId.setValue(helper.getFieldIndex("ix"), x);
+ expId.setValue(helper.getFieldIndex("iy"), y);
+ int crate = Integer.valueOf(lineTok.nextToken());
+ short slot = Short.valueOf(lineTok.nextToken());
+ short channel = Short.valueOf(lineTok.nextToken());
+ addMapEntry(helper.pack(expId).getValue(), getDaqID(crate, slot, channel));
+ }
+ }
+ }
+ }
+
+ public static long makePhysicalID(int ix, int iy) {
+ IExpandedIdentifier expId = new ExpandedIdentifier(helper.getIdentifierDictionary().getNumberOfFields());
+ expId.setValue(helper.getFieldIndex("system"), subdetector.getSystemID());
+ expId.setValue(helper.getFieldIndex("ix"), ix);
+ expId.setValue(helper.getFieldIndex("iy"), iy);
+ return helper.pack(expId).getValue();
+ }
+
+ private static void addMapEntry(long physicalID, long daqID) {
+ daqToPhysicalMap.put(daqID, physicalID);
+ physicalToDaqMap.put(physicalID, daqID);
+ }
+
+ public static long getDaqID(int crate, short slot, short channel) {
+ return (((long) crate) << 32) | ((long) slot << 16) | (long) channel;
+ }
+
+ public static Long daqToPhysicalID(int crate, short slot, short channel) {
+ return daqToPhysicalMap.get(getDaqID(crate, slot, channel));
+ }
+
+ public static int getCrate(long daqID) {
+ return (int) (daqID >>> 32);
+ }
+
+ public static short getSlot(long daqID) {
+ return (short) ((daqID >>> 16) & 0xFFFF);
+ }
+
+ public static short getChannel(long daqID) {
+ return (short) (daqID & 0xFFFF);
+ }
+
+ public static Long physicalToDaqID(long physicalID) {
+ return physicalToDaqMap.get(physicalID);
+ }
+
+ public static Long daqToPhysicalID(long daqID) {
+ return daqToPhysicalMap.get(daqID);
+ }
+
+ public static Double daqToPedestal(long daqID) {
+ return daqToPedestalMap.get(daqID);
+ }
+
+ public static Double physicalToPedestal(long physicalID) {
+ return daqToPedestalMap.get(physicalToDaqMap.get(physicalID));
+ }
+
+ public static Double physicalToNoise(long physicalID) {
+ return daqToNoiseMap.get(physicalToDaqMap.get(physicalID));
+ }
+
+ public static Double physicalToGain(long physicalID) {
+ return physicalToGainMap.get(physicalID);
+ }
+}
java/sandbox/ecal-recon/src/main/java/org/hps/recon/ecal
--- java/sandbox/ecal-recon/src/main/java/org/hps/recon/ecal/EcalConverterDriver.java (rev 0)
+++ java/sandbox/ecal-recon/src/main/java/org/hps/recon/ecal/EcalConverterDriver.java 2014-03-25 23:35:20 UTC (rev 346)
@@ -0,0 +1,86 @@
+package org.hps.recon.ecal;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.lcsim.event.CalorimeterHit;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.RawCalorimeterHit;
+import org.lcsim.util.Driver;
+import org.lcsim.lcio.LCIOConstants;
+
+/**
+ *
+ * @author Sho Uemura <[log in to unmask]>
+ * @version $Id: EcalConverterDriver.java,v 1.1 2013/02/25 22:39:24 meeg Exp $
+ */
+public class EcalConverterDriver extends Driver {
+
+ String rawCollectionName;
+ String ecalReadoutName = "EcalHits";
+ String ecalCollectionName = "EcalCorrectedHits";
+ int flags;
+ double scale = 1.0;
+// double pedestal = 0.0;
+ double period = 4.0;
+ double dt = 0.0;
+
+ public EcalConverterDriver() {
+ flags = 0;
+ flags += 1 << LCIOConstants.CHBIT_LONG; //store position
+ flags += 1 << LCIOConstants.RCHBIT_ID1; //store cell ID
+ }
+
+// public void setPedestal(double pedestal) {
+// this.pedestal = pedestal;
+// }
+ public void setScale(double scale) {
+ this.scale = scale;
+ }
+
+ public void setEcalCollectionName(String ecalCollectionName) {
+ this.ecalCollectionName = ecalCollectionName;
+ }
+
+ public void setRawCollectionName(String rawCollectionName) {
+ this.rawCollectionName = rawCollectionName;
+ }
+
+ @Override
+ public void startOfData() {
+ if (ecalCollectionName == null) {
+ throw new RuntimeException("The parameter ecalCollectionName was not set!");
+ }
+ }
+
+ @Override
+ public void process(EventHeader event) {
+ if (event.hasCollection(HPSRawCalorimeterHit.class, rawCollectionName)) {
+ // Get the list of ECal hits.
+ List<HPSRawCalorimeterHit> hits = event.get(HPSRawCalorimeterHit.class, rawCollectionName);
+
+ ArrayList<CalorimeterHit> newHits = new ArrayList<CalorimeterHit>();
+
+ for (HPSRawCalorimeterHit hit : hits) {
+ newHits.add(HitDtoA(hit));
+ }
+
+ event.put(ecalCollectionName, newHits, CalorimeterHit.class, flags, ecalReadoutName);
+ }
+ }
+
+// private int AtoD(double amplitude, long cellID) {
+// return (int) Math.round(amplitude / scale);
+// }
+
+ private double DtoA(int amplitude, long cellID) {
+ return scale * amplitude;
+ }
+
+ private CalorimeterHit HitDtoA(RawCalorimeterHit hit) {
+ return new HPSCalorimeterHit(DtoA(hit.getAmplitude(), hit.getCellID()), period * hit.getTimeStamp() + dt, hit.getCellID(), 0);
+ }
+
+// private RawCalorimeterHit HitAtoD(CalorimeterHit hit) {
+// return new HPSFADCCalorimeterHit(hit.getCellID(), AtoD(hit.getRawEnergy(), hit.getCellID()), (int) Math.round(hit.getTime() / period), 0);
+// }
+}
java/sandbox/ecal-recon/src/main/java/org/hps/recon/ecal
--- java/sandbox/ecal-recon/src/main/java/org/hps/recon/ecal/EcalCrystalFilter.java (rev 0)
+++ java/sandbox/ecal-recon/src/main/java/org/hps/recon/ecal/EcalCrystalFilter.java 2014-03-25 23:35:20 UTC (rev 346)
@@ -0,0 +1,1048 @@
+package org.hps.recon.ecal;
+
+import hep.aida.IHistogram1D;
+import hep.aida.IHistogram2D;
+import hep.aida.IPlotter;
+import hep.aida.IPlotterStyle;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
+
+import org.lcsim.detector.identifier.ExpandedIdentifier;
+import org.lcsim.detector.identifier.IExpandedIdentifier;
+import org.lcsim.detector.identifier.IIdentifier;
+import org.lcsim.detector.identifier.IIdentifierHelper;
+import org.lcsim.detector.identifier.Identifier;
+import org.lcsim.event.CalorimeterHit;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.RawTrackerHit;
+import org.lcsim.event.base.BaseRawCalorimeterHit;
+import org.lcsim.geometry.Detector;
+import org.lcsim.hps.util.AIDAFrame;
+import org.lcsim.hps.util.Resettable;
+import org.lcsim.hps.util.Redrawable;
+import org.lcsim.util.Driver;
+import org.lcsim.util.aida.AIDA;
+
+public class EcalCrystalFilter extends Driver implements Resettable, ActionListener, Redrawable {
+
+ private String inputCollection;
+ private String outputPlotFileName;
+ private IPlotter plotter;
+ private IPlotter plotter2;
+ private IPlotter plotter3;
+ private IPlotter plotter4;
+ private IPlotter plotterTop;
+ private IPlotter plotterTop2;
+ private IPlotter plotterTop3;
+ private IPlotter plotterTop4;
+ private IPlotter plotterBot;
+ private IPlotter plotterBot2;
+ private IPlotter plotterBot3;
+ private IPlotter plotterBot4;
+ private AIDA aida = AIDA.defaultInstance();
+ private AIDAFrame plotterFrame;
+ private AIDAFrame plotterFrameTop;
+ private AIDAFrame plotterFrameBot;
+ private IHistogram1D aMeanPlot;
+ private IHistogram1D aSigmaPlot;
+ private IHistogram1D tMeanPlot;
+ private IHistogram1D tSigmaPlot;
+ private IHistogram1D aTMeanPlot;
+ private IHistogram1D aTSigmaPlot;
+ private IHistogram1D tTMeanPlot;
+ private IHistogram1D tTSigmaPlot;
+ private IHistogram1D aBMeanPlot;
+ private IHistogram1D aBSigmaPlot;
+ private IHistogram1D tBMeanPlot;
+ private IHistogram1D tBSigmaPlot;
+ private IHistogram2D aTOutMeanPlot;
+ private IHistogram2D aTOutSigmaPlot;
+ private IHistogram2D tTOutMeanPlot;
+ private IHistogram2D tTOutSigmaPlot;
+ private IHistogram2D aTTOutMeanPlot;
+ private IHistogram2D aTTOutSigmaPlot;
+ private IHistogram2D tTTOutMeanPlot;
+ private IHistogram2D tTTOutSigmaPlot;
+ private IHistogram2D aBTOutMeanPlot;
+ private IHistogram2D aBTOutSigmaPlot;
+ private IHistogram2D tBTOutMeanPlot;
+ private IHistogram2D tBTOutSigmaPlot;
+ private IHistogram1D[][] aPlots = new IHistogram1D[47][11];
+ private IHistogram1D[][] tPlots = new IHistogram1D[47][11];
+ private IHistogram1D[][] aTPlots = new IHistogram1D[47][11];
+ private IHistogram1D[][] tTPlots = new IHistogram1D[47][11];
+ private IHistogram1D[][] aBPlots = new IHistogram1D[47][11];
+ private IHistogram1D[][] tBPlots = new IHistogram1D[47][11];
+ private JLabel xLabel, yLabel;
+ private JComboBox xCombo;
+ private JComboBox yCombo;
+ private JButton blankButton;
+ private JLabel xLabelTop, yLabelTop;
+ private JComboBox xComboTop;
+ private JComboBox yComboTop;
+ private JButton blankButtonTop;
+ private JLabel xLabelBot, yLabelBot;
+ private JComboBox xComboBot;
+ private JComboBox yComboBot;
+ private JButton blankButtonBot;
+ private static final Integer[] xList = new Integer[46];
+ private static final Integer[] yList = new Integer[10];
+ private static final Integer[] xListTop = new Integer[46];
+ private static final Integer[] yListTop = new Integer[10];
+ private static final Integer[] xListBot = new Integer[46];
+ private static final Integer[] yListBot = new Integer[10];
+ int eventRefreshRate = 1;
+ int eventn = 0;
+ boolean hide = false;
+ int calWindow = 0;
+ double maxE = 1000;
+ double tTOutNSigmaThr = 5.0;
+ String hotCrystalFileName = "ecal_hotcrystals.txt";
+ FileWriter fWriter;
+ PrintWriter pWriter;
+ int[] _trigger = new int[2];
+
+ public EcalCrystalFilter() {
+ int count = 0;
+ for (int i = -23; i <= 23; i++) {
+ if (i != 0) {
+ xList[count] = i;
+ xListTop[count] = i;
+ xListBot[count] = i;
+
+ count++;
+ }
+ }
+ count = 0;
+ for (int i = -5; i <= 5; i++) {
+ if (i != 0) {
+ yList[count] = i;
+ yListTop[count] = i;
+ yListBot[count] = i;
+ count++;
+ }
+ }
+ try {
+ fWriter = new FileWriter(hotCrystalFileName);
+ pWriter = new PrintWriter(fWriter);
+ } catch (IOException ex) {
+ Logger.getLogger(EcalCrystalFilter.class.getName()).log(Level.SEVERE, null, ex);
+ }
+
+
+ outputPlotFileName = "";
+
+ }
+
+ public void closeFile() throws IOException {
+ pWriter.close();
+ fWriter.close();
+ }
+
+ public void setMaxE(double maxE) {
+ this.maxE = maxE;
+ }
+
+ public void setCalWindow(int calWindow) {
+ this.calWindow = calWindow;
+ }
+
+ public void setHide(boolean hide) {
+ this.hide = hide;
+ }
+
+ public void setInputCollection(String inputCollection) {
+ this.inputCollection = inputCollection;
+ }
+
+ @Override
+ public void detectorChanged(Detector detector) {
+ if (inputCollection == null) {
+ throw new RuntimeException("The inputCollection parameter was not set.");
+ }
+
+ aida = AIDA.defaultInstance();
+ aida.tree().cd("/");
+
+ aSigmaPlot = aida.histogram1D(detector.getDetectorName() + " : " + inputCollection + " : <Sigma> (Amplitude) Filter", 50, 0, 200);
+ aMeanPlot = aida.histogram1D(detector.getDetectorName() + " : " + inputCollection + " : <Mean> (Amplitude) Filter", 50, 0, 1000);
+ tSigmaPlot = aida.histogram1D(detector.getDetectorName() + " : " + inputCollection + " : <Sigma> (Time) Filter", 50, 0, 50);
+ tMeanPlot = aida.histogram1D(detector.getDetectorName() + " : " + inputCollection + " : <Mean> (Time) Filter", 50, 0, 100);
+
+ aTSigmaPlot = aida.histogram1D(detector.getDetectorName() + " : " + inputCollection + " : <Sigma> (Amplitude) Top Trig Filter", 50, 0, 200);
+ aTMeanPlot = aida.histogram1D(detector.getDetectorName() + " : " + inputCollection + " : <Mean> (Amplitude) Top Trig Filter", 50, 0, 1000);
+ tTSigmaPlot = aida.histogram1D(detector.getDetectorName() + " : " + inputCollection + " : <Sigma> (Time) Top Trig Filter", 50, 0, 50);
+ tTMeanPlot = aida.histogram1D(detector.getDetectorName() + " : " + inputCollection + " : <Mean> (Time) Top Trig Filter", 50, 0, 100);
+
+ aBSigmaPlot = aida.histogram1D(detector.getDetectorName() + " : " + inputCollection + " : <Sigma> (Amplitude) Bottom Trig Filter", 50, 0, 200);
+ aBMeanPlot = aida.histogram1D(detector.getDetectorName() + " : " + inputCollection + " : <Mean> (Amplitude) Bottom Trig Filter", 50, 0, 1000);
+ tBSigmaPlot = aida.histogram1D(detector.getDetectorName() + " : " + inputCollection + " : <Sigma> (Time) Bottom Trig Filter", 50, 0, 50);
+ tBMeanPlot = aida.histogram1D(detector.getDetectorName() + " : " + inputCollection + " : <Mean> (Time) Bottom Trig Filter", 50, 0, 100);
+
+
+ aTOutSigmaPlot = aida.histogram2D(detector.getDetectorName() + " : " + inputCollection + " : Sigma (Amplitude) Time Outliers", 47, -23.5, 23.5, 11, -5.5, 5.5);
+ aTOutMeanPlot = aida.histogram2D(detector.getDetectorName() + " : " + inputCollection + " : Mean (Amplitude) Time Outliers", 47, -23.5, 23.5, 11, -5.5, 5.5);
+ tTOutSigmaPlot = aida.histogram2D(detector.getDetectorName() + " : " + inputCollection + " : Sigma (Time) Time Outliers", 47, -23.5, 23.5, 11, -5.5, 5.5);
+ tTOutMeanPlot = aida.histogram2D(detector.getDetectorName() + " : " + inputCollection + " : Mean (Time) Time Outliers", 47, -23.5, 23.5, 11, -5.5, 5.5);
+
+ aTTOutSigmaPlot = aida.histogram2D(detector.getDetectorName() + " : " + inputCollection + " : Sigma (Amplitude) Time Bot Outliers", 47, -23.5, 23.5, 11, -5.5, 5.5);
+ aTTOutMeanPlot = aida.histogram2D(detector.getDetectorName() + " : " + inputCollection + " : Mean (Amplitude) Time Bot Outliers", 47, -23.5, 23.5, 11, -5.5, 5.5);
+ tTTOutSigmaPlot = aida.histogram2D(detector.getDetectorName() + " : " + inputCollection + " : Sigma (Time) Time Bot Outliers", 47, -23.5, 23.5, 11, -5.5, 5.5);
+ tTTOutMeanPlot = aida.histogram2D(detector.getDetectorName() + " : " + inputCollection + " : Mean (Time) Time Bot Outliers", 47, -23.5, 23.5, 11, -5.5, 5.5);
+
+ aBTOutSigmaPlot = aida.histogram2D(detector.getDetectorName() + " : " + inputCollection + " : Sigma (Amplitude) Time Top Outliers", 47, -23.5, 23.5, 11, -5.5, 5.5);
+ aBTOutMeanPlot = aida.histogram2D(detector.getDetectorName() + " : " + inputCollection + " : Mean (Amplitude) Time Top Outliers", 47, -23.5, 23.5, 11, -5.5, 5.5);
+ tBTOutSigmaPlot = aida.histogram2D(detector.getDetectorName() + " : " + inputCollection + " : Sigma (Time) Time Top Outliers", 47, -23.5, 23.5, 11, -5.5, 5.5);
+ tBTOutMeanPlot = aida.histogram2D(detector.getDetectorName() + " : " + inputCollection + " : Mean (Time) Time Top Outliers", 47, -23.5, 23.5, 11, -5.5, 5.5);
+
+
+ for (int x = -23; x <= 23; x++) { // slot
+ for (int y = -5; y <= 5; y++) { // crate
+ //System.out.println("creating plot: " + "ECAL: Crate " + j + "; Slot " + i + " in region " + region);
+// IHistogram1D hist = aida.histogram1D("ECAL: x=" + i + "; y=" + j, 1000, 0, 16);
+// plots[x + 23][y + 5] = aida.cloud1D("ECAL: x=" + x + "; y=" + y);
+ if (calWindow == 0) {
+ aPlots[x + 23][y + 5] = aida.histogram1D("ECAL Amplitudes: x=" + x + "; y=" + y, 500, -0.1, maxE);
+ aTPlots[x + 23][y + 5] = aida.histogram1D("Top ECAL Amplitudes: x=" + x + "; y=" + y, 500, -0.1, maxE);
+ aBPlots[x + 23][y + 5] = aida.histogram1D("Bottom ECAL Amplitudes: x=" + x + "; y=" + y, 500, -0.1, maxE);
+
+ } else {
+ aPlots[x + 23][y + 5] = aida.histogram1D("ECAL Amplitudes: x=" + x + "; y=" + y, 1024, -0.5, 1023.5);
+ aTPlots[x + 23][y + 5] = aida.histogram1D("Top Trig CAL Amplitudes: x=" + x + "; y=" + y, 1024, -0.5, 1023.5);
+ aBPlots[x + 23][y + 5] = aida.histogram1D("Bottom Trig CAL Amplitudes: x=" + x + "; y=" + y, 1024, -0.5, 1023.5);
+ }
+ tPlots[x + 23][y + 5] = aida.histogram1D("ECAL Times: x=" + x + "; y=" + y, 100, 0, 100);
+ tTPlots[x + 23][y + 5] = aida.histogram1D("Top Trig ECAL Times: x=" + x + "; y=" + y, 100, 0, 100);
+ tBPlots[x + 23][y + 5] = aida.histogram1D("Bottom Trig ECAL Times: x=" + x + "; y=" + y, 100, 0, 100);
+ }
+ }
+
+ plotterFrame = new AIDAFrame();
+ plotterFrame.setTitle("HPS ECal Crystal Filter Plots");
+
+ xCombo = new JComboBox(xList);
+ xCombo.addActionListener(this);
+ xLabel = new JLabel("x");
+ xLabel.setLabelFor(xCombo);
+ plotterFrame.getControlsPanel().add(xLabel);
+ plotterFrame.getControlsPanel().add(xCombo);
+ yCombo = new JComboBox(yList);
+ yCombo.addActionListener(this);
+ yLabel = new JLabel("y");
+ yLabel.setLabelFor(yCombo);
+ plotterFrame.getControlsPanel().add(yLabel);
+ plotterFrame.getControlsPanel().add(yCombo);
+ blankButton = new JButton("Hide histogram");
+ plotterFrame.getControlsPanel().add(blankButton);
+ blankButton.addActionListener(this);
+
+ // Setup the plotter.
+ plotter = aida.analysisFactory().createPlotterFactory().create();
+ plotter.setTitle("HPS ECal Amplitude");
+ plotterFrame.addPlotter(plotter);
+ plotter.createRegions(1, 3);
+
+ plotter.style().statisticsBoxStyle().setVisible(false);
+ plotter.style().dataStyle().errorBarStyle().setVisible(false);
+ plotter.style().zAxisStyle().setParameter("allowZeroSuppression", "true");
+ IPlotterStyle style = plotter.region(0).style();
+ style.setParameter("hist2DStyle", "colorMap");
+ style.dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+ style = plotter.region(1).style();
+ style.setParameter("hist2DStyle", "colorMap");
+ style.dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+ plotter.region(0).plot(aSigmaPlot);
+ plotter.region(1).plot(aMeanPlot);
+ plotter.style().dataStyle().fillStyle().setColor("yellow");
+
+ // Setup the plotter.
+ plotter2 = aida.analysisFactory().createPlotterFactory().create();
+ plotter2.setTitle("HPS ECal Hit Time ");
+ plotterFrame.addPlotter(plotter2);
+ plotter2.createRegions(1, 3);
+
+ plotter2.style().statisticsBoxStyle().setVisible(true);
+ plotter2.style().dataStyle().errorBarStyle().setVisible(false);
+ plotter2.style().zAxisStyle().setParameter("allowZeroSuppression", "true");
+ style = plotter2.region(0).style();
+ style.setParameter("hist2DStyle", "colorMap");
+ style.dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+ style = plotter2.region(1).style();
+ style.setParameter("hist2DStyle", "colorMap");
+ style.dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+ plotter2.region(0).plot(tSigmaPlot);
+ plotter2.region(1).plot(tMeanPlot);
+ plotter2.style().dataStyle().fillStyle().setColor("green");
+
+
+ // Setup the plotter.
+ plotter3 = aida.analysisFactory().createPlotterFactory().create();
+ plotter3.setTitle("HPS ECal for Time Outliers ");
+ plotterFrame.addPlotter(plotter3);
+ plotter3.createRegions(1, 3);
+
+ plotter3.style().statisticsBoxStyle().setVisible(false);
+ plotter3.style().dataStyle().errorBarStyle().setVisible(false);
+ plotter3.style().zAxisStyle().setParameter("allowZeroSuppression", "true");
+ style = plotter3.region(0).style();
+ style.setParameter("hist2DStyle", "colorMap");
+ style.dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+ style = plotter3.region(1).style();
+ style.setParameter("hist2DStyle", "colorMap");
+ style.dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+ plotter3.region(0).plot(tTOutSigmaPlot);
+ plotter3.region(1).plot(tTOutMeanPlot);
+ plotter3.style().dataStyle().fillStyle().setColor("green");
+
+ // Setup the plotter.
+ plotter4 = aida.analysisFactory().createPlotterFactory().create();
+ plotter4.setTitle("HPS ECal Amplitude for Time Outliers ");
+ plotterFrame.addPlotter(plotter4);
+ plotter4.createRegions(1, 3);
+
+ plotter4.style().statisticsBoxStyle().setVisible(false);
+ plotter4.style().dataStyle().errorBarStyle().setVisible(false);
+ plotter4.style().zAxisStyle().setParameter("allowZeroSuppression", "true");
+ style = plotter4.region(0).style();
+ style.setParameter("hist2DStyle", "colorMap");
+ style.dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+ style = plotter4.region(1).style();
+ style.setParameter("hist2DStyle", "colorMap");
+ style.dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+ plotter4.region(0).plot(aTOutSigmaPlot);
+ plotter4.region(1).plot(aTOutMeanPlot);
+ plotter4.style().dataStyle().fillStyle().setColor("green");
+
+ plotter.region(2).plot(aPlots[-5 + 23][2 + 5 - 1]);
+ plotter2.region(2).plot(tPlots[-5 + 23][2 + 5 - 1]);
+ plotter3.region(2).plot(tPlots[-5 + 23][2 + 5 - 1]);
+ plotter4.region(2).plot(aPlots[-5 + 23][2 + 5 - 1]);
+
+
+
+
+
+
+
+
+ plotterFrameTop = new AIDAFrame();
+ plotterFrameTop.setTitle("HPS Top Trig ECal Crystal Filter Plots");
+
+ xComboTop = new JComboBox(xListTop);
+ xComboTop.addActionListener(this);
+ xLabelTop = new JLabel("xT");
+ xLabelTop.setLabelFor(xComboTop);
+ plotterFrameTop.getControlsPanel().add(xLabelTop);
+ plotterFrameTop.getControlsPanel().add(xComboTop);
+ yComboTop = new JComboBox(yListTop);
+ yComboTop.addActionListener(this);
+ yLabelTop = new JLabel("yT");
+ yLabelTop.setLabelFor(yComboTop);
+
+
+ plotterFrameTop.getControlsPanel().add(yLabelTop);
+ plotterFrameTop.getControlsPanel().add(yComboTop);
+ blankButtonTop = new JButton("Hide histogram (Top)");
+ plotterFrameTop.getControlsPanel().add(blankButtonTop);
+ blankButtonTop.addActionListener(this);
+
+
+ // Setup the plotterTop.
+ plotterTop = aida.analysisFactory().createPlotterFactory().create();
+ plotterTop.setTitle("HPS ECal Amplitude");
+ plotterFrameTop.addPlotter(plotterTop);
+ plotterTop.createRegions(1, 3);
+ plotterTop.setStyle(plotter.style());
+ style = plotterTop.region(0).style();
+ style.setParameter("hist2DStyle", "colorMap");
+ style.dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+ style = plotterTop.region(1).style();
+ style.setParameter("hist2DStyle", "colorMap");
+ style.dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+ plotterTop.region(0).plot(aTSigmaPlot);
+ plotterTop.region(1).plot(aTMeanPlot);
+ plotterTop.style().dataStyle().fillStyle().setColor("yellow");
+
+ // Setup the plotterTop.
+ plotterTop2 = aida.analysisFactory().createPlotterFactory().create();
+ plotterTop2.setTitle("HPS ECal Hit Time ");
+ plotterFrameTop.addPlotter(plotterTop2);
+ plotterTop2.createRegions(1, 3);
+
+ plotterTop2.setStyle(plotter2.style());
+ style = plotterTop2.region(0).style();
+ style.setParameter("hist2DStyle", "colorMap");
+ style.dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+ style = plotterTop2.region(1).style();
+ style.setParameter("hist2DStyle", "colorMap");
+ style.dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+ plotterTop2.region(0).plot(tTSigmaPlot);
+ plotterTop2.region(1).plot(tTMeanPlot);
+
+
+ // Setup the plotter.
+ plotterTop3 = aida.analysisFactory().createPlotterFactory().create();
+ plotterTop3.setTitle("HPS ECal for Time Outliers ");
+ plotterFrameTop.addPlotter(plotterTop3);
+ plotterTop3.createRegions(1, 3);
+
+ plotterTop3.setStyle(plotter3.style());
+ style = plotterTop3.region(0).style();
+ style.setParameter("hist2DStyle", "colorMap");
+ style.dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+ style = plotterTop3.region(1).style();
+ style.setParameter("hist2DStyle", "colorMap");
+ style.dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+ plotterTop3.region(0).plot(tTTOutSigmaPlot);
+ plotterTop3.region(1).plot(tTTOutMeanPlot);
+
+ // Setup the plotter.
+ plotterTop4 = aida.analysisFactory().createPlotterFactory().create();
+ plotterTop4.setTitle("HPS ECal Amplitude for Time Outliers ");
+ plotterFrameTop.addPlotter(plotterTop4);
+ plotterTop4.createRegions(1, 3);
+
+ plotterTop4.setStyle(plotter4.style());
+ style = plotterTop4.region(0).style();
+ style.setParameter("hist2DStyle", "colorMap");
+ style.dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+ style = plotterTop4.region(1).style();
+ style.setParameter("hist2DStyle", "colorMap");
+ style.dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+ plotterTop4.region(0).plot(aTTOutSigmaPlot);
+ plotterTop4.region(1).plot(aTTOutMeanPlot);
+
+ plotterTop.region(2).plot(aTPlots[-5 + 23][2 + 5 - 1]);
+ plotterTop2.region(2).plot(tTPlots[-5 + 23][2 + 5 - 1]);
+ plotterTop3.region(2).plot(tTPlots[-5 + 23][2 + 5 - 1]);
+ plotterTop4.region(2).plot(aTPlots[-5 + 23][2 + 5 - 1]);
+
+
+
+
+
+
+
+
+ plotterFrameBot = new AIDAFrame();
+ plotterFrameBot.setTitle("HPS Bottom Trig ECal Crystal Filter Plots");
+
+ xComboBot = new JComboBox(xListBot);
+ xComboBot.addActionListener(this);
+ xLabelBot = new JLabel("x");
+ xLabelBot.setLabelFor(xComboBot);
+ plotterFrameBot.getControlsPanel().add(xLabelBot);
+ plotterFrameBot.getControlsPanel().add(xComboBot);
+ yComboBot = new JComboBox(yListBot);
+ yComboBot.addActionListener(this);
+ yLabelBot = new JLabel("y");
+ yLabelBot.setLabelFor(yComboBot);
+ plotterFrameBot.getControlsPanel().add(yLabelBot);
+ plotterFrameBot.getControlsPanel().add(yComboBot);
+ blankButtonBot = new JButton("Hide histogram");
+ plotterFrameBot.getControlsPanel().add(blankButtonBot);
+ blankButtonBot.addActionListener(this);
+
+ // Setup the plotterBot.
+ plotterBot = aida.analysisFactory().createPlotterFactory().create();
+ plotterBot.setTitle("HPS ECal Amplitude");
+ plotterFrameBot.addPlotter(plotterBot);
+ plotterBot.createRegions(1, 3);
+ plotterBot.setStyle(plotter.style());
+ style = plotterBot.region(0).style();
+ style.setParameter("hist2DStyle", "colorMap");
+ style.dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+ style = plotterBot.region(1).style();
+ style.setParameter("hist2DStyle", "colorMap");
+ style.dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+ plotterBot.region(0).plot(aBSigmaPlot);
+ plotterBot.region(1).plot(aBMeanPlot);
+ plotterBot.style().dataStyle().fillStyle().setColor("yellow");
+
+ // Setup the plotterBot.
+ plotterBot2 = aida.analysisFactory().createPlotterFactory().create();
+ plotterBot2.setTitle("HPS ECal Hit Time ");
+ plotterFrameBot.addPlotter(plotterBot2);
+ plotterBot2.createRegions(1, 3);
+
+ plotterBot2.setStyle(plotter2.style());
+ style = plotterBot2.region(0).style();
+ style.setParameter("hist2DStyle", "colorMap");
+ style.dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+ style = plotterBot2.region(1).style();
+ style.setParameter("hist2DStyle", "colorMap");
+ style.dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+ plotterBot2.region(0).plot(tBSigmaPlot);
+ plotterBot2.region(1).plot(tBMeanPlot);
+
+
+ // Setup the plotter.
+ plotterBot3 = aida.analysisFactory().createPlotterFactory().create();
+ plotterBot3.setTitle("HPS ECal for Time Outliers ");
+ plotterFrameBot.addPlotter(plotterBot3);
+ plotterBot3.createRegions(1, 3);
+
+ plotterBot3.setStyle(plotter3.style());
+ style = plotterBot3.region(0).style();
+ style.setParameter("hist2DStyle", "colorMap");
+ style.dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+ style = plotterBot3.region(1).style();
+ style.setParameter("hist2DStyle", "colorMap");
+ style.dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+ plotterBot3.region(0).plot(tBTOutSigmaPlot);
+ plotterBot3.region(1).plot(tBTOutMeanPlot);
+
+ // Setup the plotter.
+ plotterBot4 = aida.analysisFactory().createPlotterFactory().create();
+ plotterBot4.setTitle("HPS ECal Amplitude for Time Outliers ");
+ plotterFrameBot.addPlotter(plotterBot4);
+ plotterBot4.createRegions(1, 3);
+
+ plotterBot4.setStyle(plotter4.style());
+ style = plotterBot4.region(0).style();
+ style.setParameter("hist2DStyle", "colorMap");
+ style.dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+ style = plotterBot4.region(1).style();
+ style.setParameter("hist2DStyle", "colorMap");
+ style.dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+ plotterBot4.region(0).plot(aBTOutSigmaPlot);
+ plotterBot4.region(1).plot(aBTOutMeanPlot);
+
+ plotterBot.region(2).plot(aBPlots[-5 + 23][2 + 5 - 1]);
+ plotterBot2.region(2).plot(tBPlots[-5 + 23][2 + 5 - 1]);
+ plotterBot3.region(2).plot(tBPlots[-5 + 23][2 + 5 - 1]);
+ plotterBot4.region(2).plot(aBPlots[-5 + 23][2 + 5 - 1]);
+ //xCombo.setSelectedIndex(-5 + 23);
+ //yCombo.setSelectedIndex(2 + 5 - 1);
+
+
+
+
+
+ plotterFrame.pack();
+ if (!hide) {
+ plotterFrame.setVisible(true);
+ }
+
+
+
+ plotterFrameTop.pack();
+ if (!hide) {
+ plotterFrameTop.setVisible(true);
+ }
+
+
+
+
+ plotterFrameBot.pack();
+ if (!hide) {
+ plotterFrameBot.setVisible(true);
+ }
+
+
+
+ xComboBot.setSelectedIndex(-5 + 23);
+ yComboBot.setSelectedIndex(2 + 5 - 1);
+
+
+
+ xComboTop.setSelectedIndex(-5 + 23);
+ yComboTop.setSelectedIndex(2 + 5 - 1);
+
+
+
+
+ xCombo.setSelectedIndex(-5 + 23);
+ yCombo.setSelectedIndex(2 + 5 - 1);
+
+
+
+
+ }
+
+ public void printOutliers() {
+
+ //Outliers in time -- threshold is nr of sigma/rms from the mean
+ System.out.printf("Crystals with time RMS more than %.1f times the RMS(<RMS>)=%.1f from <RMS>=%.1f for all crystals\n", tTOutNSigmaThr, tSigmaPlot.rms(), tSigmaPlot.mean());
+
+ for (int iside = 0; iside < 3; ++iside) {
+ System.out.println("-- Side " + iside);
+ pWriter.printf("# Side %d\n", iside);
+ for (int x = -23; x <= 23; x++) { // slot
+ for (int y = -5; y <= 5; y++) { // crate
+
+ boolean ok = false;
+ if (iside == 0) {
+ if (tTOutSigmaPlot.binEntries(tTOutSigmaPlot.coordToIndexX(x), tTOutSigmaPlot.coordToIndexY(y)) > 0) {
+ ok = true;
+ }
+ } else if (iside == 1) {
+ if (tTTOutSigmaPlot.binEntries(tTTOutSigmaPlot.coordToIndexX(x), tTTOutSigmaPlot.coordToIndexY(y)) > 0) {
+ ok = true;
+ }
+
+ } else if (iside == 2) {
+ if (tBTOutSigmaPlot.binEntries(tBTOutSigmaPlot.coordToIndexX(x), tBTOutSigmaPlot.coordToIndexY(y)) > 0) {
+ ok = true;
+ }
+ }
+ if (ok) {
+ IIdentifierHelper helper = EcalConditions.getHelper();
+ IExpandedIdentifier expId = new ExpandedIdentifier(helper.getIdentifierDictionary().getNumberOfFields());
+ //expId.setValue(helper.getFieldIndex("system"), ecal.getSystemID());
+ expId.setValue(helper.getFieldIndex("ix"), x);
+ expId.setValue(helper.getFieldIndex("iy"), y);
+ Long id = helper.pack(expId).getValue();
+
+
+ System.out.printf("[%d,%d]\t%d\t%d\t%d\tTime:%f +- %f\tAmp:%f +- %f\n", x, y, EcalConditions.getCrate(id), EcalConditions.getSlot(id), EcalConditions.getChannel(id), tPlots[x + 23][y + 5].mean(), tPlots[x + 23][y + 5].rms(), aPlots[x + 23][y + 5].mean(), aPlots[x + 23][y + 5].rms());
+
+ pWriter.printf("%d %d\n", x, y);
+ }
+
+ }
+ }
+ }
+ }
+
+ @Override
+ public void endOfData() {
+
+ //Redraw one final time and use those values to print out the outlying crystals
+ redraw();
+ printOutliers();
+ //plotterFrame.dispose();
+ if (calWindow > 0) {
+ for (int crate = 1; crate < 3; crate++) {
+ for (short slot = 0; slot < 20; slot++) {
+ for (short ch = 0; ch < 16; ch++) {
+ Long id = EcalConditions.daqToPhysicalID(crate, slot, ch);
+ IIdentifierHelper helper = EcalConditions.getHelper();
+ if (id == null) {
+ continue;
+ }
+ IIdentifier compactId = new Identifier(id);
+ int x = helper.getValue(compactId, "ix");
+ int y = helper.getValue(compactId, "iy");
+ System.out.printf("%d\t%d\t%d\t%f\t%f\n", crate, slot, ch, aPlots[x + 23][y + 5].mean(), aPlots[x + 23][y + 5].rms());
+ }
+ }
+ }
+ }
+ try {
+ closeFile();
+ } catch (IOException ex) {
+ Logger.getLogger(EcalCrystalFilter.class.getName()).log(Level.SEVERE, null, ex);
+ }
+
+
+ if (!"".equals(outputPlotFileName)) {
+ try {
+ aida.saveAs(outputPlotFileName);
+ } catch (IOException ex) {
+ Logger.getLogger(EcalCrystalFilter.class.getName()).log(Level.SEVERE, "Couldn't save aida plots to file " + outputPlotFileName, ex);
+ }
+ }
+ //displayFastTrackingPlots();
+
+ }
+
+// @Override
+ public void reset() {
+ if (plotter != null) {
+ plotter.hide();
+ plotter.destroyRegions();
+ for (int x = -23; x <= 23; x++) { // slot
+ for (int y = -5; y <= 5; y++) { // crate
+ aPlots[x + 23][y + 5].reset();
+ }
+ }
+ }
+ }
+
+ @Override
+ public void process(EventHeader event) {
+
+ getTrigger(event);
+
+
+ boolean isTop, isBot, isAll;
+ for (int iside = 0; iside < 3; ++iside) {
+
+ isAll = false;
+ isTop = false;
+ isBot = false;
+
+ //System.out.println("Side " + iside + " Trigger " + _trigger[0] + "," + _trigger[1]);
+
+
+ if (iside == 0) {
+ isAll = true;
+ } else if (iside == 1) {
+ if (_trigger[0] > 0) {
+ isTop = true;
+ } else {
+ continue;
+ }
+ } else if (iside == 2) {
+ if (_trigger[1] > 0) {
+ isBot = true;
+ } else {
+ continue;
+ }
+ }
+
+ //System.out.println("isTop " + isTop + " isBot " + isBot);
+
+
+ if (event.hasCollection(RawTrackerHit.class, inputCollection)) {
+ List<RawTrackerHit> hits = event.get(RawTrackerHit.class, inputCollection);
+ for (RawTrackerHit hit : hits) {
+
+
+ int y = hit.getIdentifierFieldValue("iy");
+ int x = hit.getIdentifierFieldValue("ix");
+
+
+ //System.out.println("RawTrackerHit: iside " + iside + " trigger " + _trigger[0] + ", " + _trigger[1] + " isBot " + isBot + " isTop " + isTop + " iy " + y);
+
+ //Only look at the opposite half of what triggered
+ if (isAll) {
+ }
+ if (isTop) {
+ if (y > 0) {
+ continue;
+ }
+ }
+ if (isBot) {
+ if (y < 0) {
+ continue;
+ }
+ }
+
+
+
+ //System.out.println("RawTrackerHit: ===> fill");
+
+
+ if (calWindow > 0) {
+ for (int i = 0; i < calWindow; i++) {
+
+ if (isAll) {
+ aPlots[x + 23][y + 5].fill(hit.getADCValues()[i]);
+ }
+ if (isTop) {
+ aTPlots[x + 23][y + 5].fill(hit.getADCValues()[i]);
+ }
+ if (isBot) {
+ aBPlots[x + 23][y + 5].fill(hit.getADCValues()[i]);
+ }
+
+ }
+ } else {
+ for (int i = 0; i < hit.getADCValues().length; i++) {
+ if (isAll) {
+ aPlots[x + 23][y + 5].fill(hit.getADCValues()[i]);
+ }
+ if (isTop) {
+ aTPlots[x + 23][y + 5].fill(hit.getADCValues()[i]);
+ }
+ if (isBot) {
+ aBPlots[x + 23][y + 5].fill(hit.getADCValues()[i]);
+ }
+
+ }
+ }
+ }
+ if (eventRefreshRate > 0 && ++eventn % eventRefreshRate == 0) {
+ redraw();
+ }
+ }
+
+ if (event.hasCollection(BaseRawCalorimeterHit.class, inputCollection)) {
+ List<BaseRawCalorimeterHit> hits = event.get(BaseRawCalorimeterHit.class, inputCollection);
+ for (BaseRawCalorimeterHit hit : hits) {
+ int x = hit.getIdentifierFieldValue("ix");
+ int y = hit.getIdentifierFieldValue("iy");
+
+
+ //System.out.println("BaseRawCalorimeterHit: iside " + iside + " trigger " + _trigger[0] + ", " + _trigger[1] + " isBot " + isBot + " isTop " + isTop + " iy " + y );
+
+ //Only look at the opposite half of what triggered
+ if (isAll) {
+ }
+ if (isTop) {
+ if (y > 0) {
+ continue;
+ }
+ }
+ if (isBot) {
+ if (y < 0) {
+ continue;
+ }
+ }
+
+ //System.out.println("BaseRawCalorimeterHit: ===> fill");
+
+
+ if (isAll) {
+ aPlots[x + 23][y + 5].fill(hit.getAmplitude());
+ tPlots[x + 23][y + 5].fill(hit.getTimeStamp() / 64);
+ }
+ if (isTop) {
+ aTPlots[x + 23][y + 5].fill(hit.getAmplitude());
+ tTPlots[x + 23][y + 5].fill(hit.getTimeStamp() / 64);
+ }
+ if (isBot) {
+ aBPlots[x + 23][y + 5].fill(hit.getAmplitude());
+ tBPlots[x + 23][y + 5].fill(hit.getTimeStamp() / 64);
+ }
+
+ }
+ if (eventRefreshRate > 0 && ++eventn % eventRefreshRate == 0) {
+ redraw();
+ }
+ }
+
+ if (event.hasCollection(CalorimeterHit.class, inputCollection)) {
+ List<CalorimeterHit> hits = event.get(CalorimeterHit.class, inputCollection);
+ for (CalorimeterHit hit : hits) {
+ int x = hit.getIdentifierFieldValue("ix");
+ int y = hit.getIdentifierFieldValue("iy");
+
+ //System.out.println("CalorimeterHit: iside " + iside + " trigger " + _trigger[0] + ", " + _trigger[1] + " isBot " + isBot + " isTop " + isTop + " iy " + y );
+
+
+
+ //Only look at the opposite half of what triggered
+ if (isAll) {
+ }
+ if (isTop) {
+ if (y > 0) {
+ continue;
+ }
+ }
+ if (isBot) {
+ if (y < 0) {
+ continue;
+ }
+ }
+
+ //System.out.println("CalorimeterHit: ===> fill");
+ if (isAll) {
+ aPlots[x + 23][y + 5].fill(hit.getRawEnergy());
+ tPlots[x + 23][y + 5].fill(hit.getTime() / 4.0);
+ }
+ if (isTop) {
+ aTPlots[x + 23][y + 5].fill(hit.getRawEnergy());
+ tTPlots[x + 23][y + 5].fill(hit.getTime() / 4.0);
+ }
+ if (isBot) {
+ aBPlots[x + 23][y + 5].fill(hit.getRawEnergy());
+ tBPlots[x + 23][y + 5].fill(hit.getTime() / 4.0);
+ }
+ }
+ if (eventRefreshRate > 0 && ++eventn % eventRefreshRate == 0) {
+ redraw();
+ }
+ }
+ }
+ }
+
+ private void clearTrigger() {
+ _trigger[0] = 0;
+ _trigger[1] = 0;
+ }
+
+ private void getTrigger(EventHeader event) {
+
+ clearTrigger();
+ if (event.hasCollection(TriggerData.class, "TriggerBank")) {
+ List<TriggerData> triggerDataList = event.get(TriggerData.class, "TriggerBank");
+ if (triggerDataList.isEmpty() == false) {
+ TriggerData triggerData = triggerDataList.get(0);
+ int topTrig = triggerData.getTopTrig();
+ int botTrig = triggerData.getBotTrig();
+ _trigger[0] = topTrig > 0 ? 1 : 0;
+ _trigger[1] = botTrig > 0 ? 1 : 0;
+ } else {
+ System.out.println("Event has EMPTY trigger list!!");
+ _trigger[0] = 0;
+ _trigger[1] = 0;
+ }
+ } else {
+ System.out.println("Event has NO trigger bank!!");
+ _trigger[0] = 0;
+ _trigger[1] = 0;
+ }
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent ae) {
+ if (ae.getSource() == blankButton) {
+ plotter.region(2).clear();
+ plotter2.region(2).clear();
+ /*
+ plotter3.region(2).clear();
+ plotter4.region(2).clear();
+
+
+ */
+ } else if (ae.getSource() == blankButtonTop) {
+ plotterTop.region(2).clear();
+ plotterTop2.region(2).clear();
+
+ } else if (ae.getSource() == blankButtonBot) {
+ plotterBot.region(2).clear();
+ plotterBot2.region(2).clear();
+
+ } else {
+ Integer x, y;
+ x = (Integer) xCombo.getSelectedItem();
+ y = (Integer) yCombo.getSelectedItem();
+ plotter.region(2).clear();
+ plotter.region(2).plot(aPlots[x + 23][y + 5]);
+ plotter2.region(2).clear();
+ plotter2.region(2).plot(tPlots[x + 23][y + 5]);
+// ((PlotterRegion) plotter.region(2)).getPlot().setAllowUserInteraction(false);
+// ((PlotterRegion) plotter.region(2)).getPlot().setAllowPopupMenus(false);
+ plotter3.region(2).clear();
+ plotter3.region(2).plot(tPlots[x + 23][y + 5]);
+ plotter4.region(2).clear();
+ plotter4.region(2).plot(aPlots[x + 23][y + 5]);
+
+
+ //Integer x, y;
+ x = (Integer) xComboTop.getSelectedItem();
+ y = (Integer) yComboTop.getSelectedItem();
+
+ plotterTop.region(2).clear();
+ plotterTop.region(2).plot(aTPlots[x + 23][y + 5]);
+ plotterTop2.region(2).clear();
+ plotterTop2.region(2).plot(tTPlots[x + 23][y + 5]);
+// ((PlotterRegion) plotter.region(2)).getPlot().setAllowUserInteraction(false);
+// ((PlotterRegion) plotter.region(2)).getPlot().setAllowPopupMenus(false);
+ plotterTop3.region(2).clear();
+ plotterTop3.region(2).plot(tTPlots[x + 23][y + 5]);
+ plotterTop4.region(2).clear();
+ plotterTop4.region(2).plot(aTPlots[x + 23][y + 5]);
+
+ //Integer x, y;
+ x = (Integer) xComboBot.getSelectedItem();
+ y = (Integer) yComboBot.getSelectedItem();
+
+ plotterBot.region(2).clear();
+ plotterBot.region(2).plot(aBPlots[x + 23][y + 5]);
+ plotterBot2.region(2).clear();
+ plotterBot2.region(2).plot(tBPlots[x + 23][y + 5]);
+// ((PlotterRegion) plotter.region(2)).getPlot().setAllowUserInteraction(false);
+// ((PlotterRegion) plotter.region(2)).getPlot().setAllowPopupMenus(false);
+ plotterBot3.region(2).clear();
+ plotterBot3.region(2).plot(tBPlots[x + 23][y + 5]);
+ plotterBot4.region(2).clear();
+ plotterBot4.region(2).plot(aBPlots[x + 23][y + 5]);
+
+ }
+ }
+
+ public void redraw() {
+// aSigmaPlot.reset();
+// aMeanPlot.reset();
+// tSigmaPlot.reset();
+// tMeanPlot.reset();
+ aTOutSigmaPlot.reset();
+ aTOutMeanPlot.reset();
+ tTOutSigmaPlot.reset();
+ tTOutMeanPlot.reset();
+ aTTOutSigmaPlot.reset();
+ aTTOutMeanPlot.reset();
+ tTTOutSigmaPlot.reset();
+ tTTOutMeanPlot.reset();
+ aBTOutSigmaPlot.reset();
+ aBTOutMeanPlot.reset();
+ tBTOutSigmaPlot.reset();
+ tBTOutMeanPlot.reset();
+ for (int x = -23; x <= 23; x++) { // slot
+ for (int y = -5; y <= 5; y++) { // crate
+ //System.out.println("redraw x,y " + x + "," + y + " tT " + tTPlots[x + 23][y + 5].entries() + " tB " + tBPlots[x + 23][y + 5].entries());
+ if (aPlots[x + 23][y + 5].entries() > 10) {
+ aSigmaPlot.fill(aPlots[x + 23][y + 5].rms());
+ aMeanPlot.fill(aPlots[x + 23][y + 5].mean());
+
+ }
+ if (aTPlots[x + 23][y + 5].entries() > 10) {
+
+ aTSigmaPlot.fill(aTPlots[x + 23][y + 5].rms());
+ aTMeanPlot.fill(aTPlots[x + 23][y + 5].mean());
+
+ }
+ if (aBPlots[x + 23][y + 5].entries() > 10) {
+
+
+ aBSigmaPlot.fill(aBPlots[x + 23][y + 5].rms());
+ aBMeanPlot.fill(aBPlots[x + 23][y + 5].mean());
+ }
+
+ if (tPlots[x + 23][y + 5].entries() > 10) {
[truncated at 1000 lines; 51 more skipped]
java/sandbox/ecal-recon/src/main/java/org/hps/recon/ecal
--- java/sandbox/ecal-recon/src/main/java/org/hps/recon/ecal/EcalEdepToTriggerConverterDriver.java (rev 0)
+++ java/sandbox/ecal-recon/src/main/java/org/hps/recon/ecal/EcalEdepToTriggerConverterDriver.java 2014-03-25 23:35:20 UTC (rev 346)
@@ -0,0 +1,208 @@
+package org.hps.recon.ecal;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.lcsim.event.CalorimeterHit;
+import org.lcsim.event.EventHeader;
+import org.lcsim.geometry.Detector;
+import org.lcsim.hps.util.RandomGaussian;
+import org.lcsim.util.Driver;
+
+/**
+ *
+ * @version $Id: HPSEcalRawConverterDriver.java,v 1.2 2012/05/03 00:17:54
+ * phansson Exp $
+ */
+public class EcalEdepToTriggerConverterDriver extends Driver {
+
+ private String ecalReadoutName = "EcalHits";
+ private String inputCollection = "EcalHits";
+ private String readoutCollection = "EcalCalHits";
+ private String triggerCollection = "EcalTriggerHits";
+ private boolean applyBadCrystalMap = true;
+ private double tp = 14.0;
+ private double readoutPeriod = 4.0;
+ private int readoutThreshold = 50;
+ private int triggerThreshold = 80;
+ private int truncateScale = 128;
+ private double pulseIntegral = tp * Math.E / readoutPeriod;
+ private double gainScale = 1.0; //gain miscalibration factor
+ private double _gain = -1.0; //constant gain, activated if >0
+ private boolean addNoise = false;
+ private double pePerMeV = 2.0; //photoelectrons per MeV, used to calculate noise
+
+ public EcalEdepToTriggerConverterDriver() {
+ }
+
+ public void setTp(double tp) {
+ this.tp = tp;
+ }
+
+ public void setAddNoise(boolean addNoise) {
+ this.addNoise = addNoise;
+ }
+
+ public void setReadoutCollection(String readoutCollection) {
+ this.readoutCollection = readoutCollection;
+ }
+
+ public void setTriggerCollection(String triggerCollection) {
+ this.triggerCollection = triggerCollection;
+ }
+
+ public void setInputCollection(String inputCollection) {
+ this.inputCollection = inputCollection;
+ }
+
+ public void setApplyBadCrystalMap(boolean apply) {
+ this.applyBadCrystalMap = apply;
+ }
+
+ public void setTruncateScale(int truncateScale) {
+ this.truncateScale = truncateScale;
+ }
+
+ public void setConstantGain(double gain) {
+ this._gain = gain;
+ }
+
+ @Override
+ public void startOfData() {
+ if (readoutCollection == null) {
+ throw new RuntimeException("The parameter ecalCollectionName was not set!");
+ }
+ }
+
+ @Override
+ public void detectorChanged(Detector detector) {
+ }
+
+ public boolean isBadCrystal(CalorimeterHit hit) {
+ return EcalConditions.badChannelsLoaded() ? EcalConditions.isBadChannel(hit.getCellID()) : false;
+ }
+
+ @Override
+ public void process(EventHeader event) {
+ ArrayList<CalorimeterHit> triggerHits = new ArrayList<CalorimeterHit>();
+ ArrayList<CalorimeterHit> readoutHits = new ArrayList<CalorimeterHit>();
+
+ if (event.hasCollection(CalorimeterHit.class, inputCollection)) {
+ List<CalorimeterHit> hits = event.get(CalorimeterHit.class, inputCollection);
+
+ for (CalorimeterHit hit : hits) {
+ if (applyBadCrystalMap && isBadCrystal(hit)) {
+ continue;
+ }
+ double amplitude = hitAmplitude(hit);
+ CalorimeterHit triggerHit = makeTriggerHit(hit, amplitude);
+ if (triggerHit != null) {
+ triggerHits.add(triggerHit);
+// System.out.format("trigger hit: %f %f\n", amplitude, triggerHit.getRawEnergy());
+ }
+ CalorimeterHit readoutHit = makeReadoutHit(hit, amplitude);
+ if (readoutHit != null) {
+ readoutHits.add(readoutHit);
+// System.out.format("readout hit: %f %f\n", amplitude, readoutHit.getRawEnergy());
+ }
+ }
+ }
+ int flags = 0;
+ event.put(triggerCollection, triggerHits, CalorimeterHit.class, flags, ecalReadoutName);
+ event.put(readoutCollection, readoutHits, CalorimeterHit.class, flags, ecalReadoutName);
+ }
+
+ public CalorimeterHit makeTriggerHit(CalorimeterHit hit, double amplitude) {
+
+// double time = readoutPeriod * (Math.random() - 1);
+ double time = 0 - hit.getTime();
+ double triggerIntegral = 0;
+ boolean overThreshold = false;
+ while (true) {
+ double currentValue = amplitude * pulseAmplitude(time);
+ if (!overThreshold && currentValue > triggerThreshold) {
+ overThreshold = true;
+ }
+ if (overThreshold) {
+ triggerIntegral += amplitude * pulseAmplitude(time);
+ if (currentValue < triggerThreshold) {
+ break;
+ }
+ }
+ time += readoutPeriod;
+
+ if (time > 200.0) {
+ break;
+ }
+ }
+
+// System.out.format("trigger: %f %f\n", amplitude, triggerIntegral);
+
+ int truncatedIntegral = (int) Math.floor(triggerIntegral / truncateScale);
+ if (truncatedIntegral > 0) {
+ return new HPSCalorimeterHit(truncatedIntegral, hit.getTime(), hit.getCellID(), 0);
+ }
+ return null;
+ }
+
+ public CalorimeterHit makeReadoutHit(CalorimeterHit hit, double amplitude) {
+ if (amplitude < readoutThreshold) {
+ return null;
+ }
+
+// double integral = hit.getRawEnergy()/ECalUtils.GeV * gainScale;
+ double gain = _gain > 0 ? _gain : EcalConditions.physicalToGain(hit.getCellID());
+ double integral = amplitude * gain * pulseIntegral * gainScale * ECalUtils.MeV / ECalUtils.GeV;
+
+// double thresholdCrossingTime = 0 - hit.getTime();
+// while (true) {
+// double currentValue = amplitude * pulseAmplitude(thresholdCrossingTime);
+// if (currentValue > readoutThreshold) {
+// break;
+// }
+// thresholdCrossingTime += readoutPeriod;
+//
+// if (thresholdCrossingTime > 200.0) {
+// break;
+// }
+// }
+//
+// double readoutIntegral = 0;
+// for (int i = 0; i < 35; i++) {
+// readoutIntegral += amplitude * pulseAmplitude(thresholdCrossingTime + (i - 5) * readoutPeriod);
+// }
+//// double integral = readoutIntegral * HPSEcalConditions.physicalToGain(id);
+// System.out.format("dumb: %f, full: %f\n",hit.getRawEnergy() * 1000.0,readoutIntegral * HPSEcalConditions.physicalToGain(id));
+
+// System.out.format("readout: %f %f\n", amplitude, integral);
+ CalorimeterHit h = new HPSCalorimeterHit(integral, hit.getTime(), hit.getCellID(), 0);
+ return h;
+ }
+
+ private double hitAmplitude(CalorimeterHit hit) {
+ double energyAmplitude = hit.getRawEnergy();
+ if (addNoise) {
+ //add preamp noise and photoelectron Poisson noise in quadrature
+ double noise = Math.sqrt(Math.pow(EcalConditions.physicalToNoise(hit.getCellID()) * EcalConditions.physicalToGain(hit.getCellID()) * ECalUtils.MeV, 2) + hit.getRawEnergy() * ECalUtils.MeV / pePerMeV);
+ energyAmplitude += RandomGaussian.getGaussian(0, noise);
+ }
+
+ double gain = _gain > 0 ? _gain : EcalConditions.physicalToGain(hit.getCellID());
+// System.out.format("amplitude: %f %f %f %f\n", hit.getRawEnergy(), energyAmplitude, gain, (energyAmplitude / ECalUtils.MeV) / (gain * pulseIntegral));
+ return (energyAmplitude / ECalUtils.MeV) / (gain * pulseIntegral);
+ }
+
+ private double pulseAmplitude(double time) {
+ if (time <= 0.0) {
+ return 0.0;
+ }
+ if (tp > 0.0) {
+ return (time / tp) * Math.exp(1.0 - time / tp);
+ } else {
+ if (time < -tp) {
+ return 1.0;
+ } else {
+ return 0.0;
+ }
+ }
+ }
+}
java/sandbox/ecal-recon/src/main/java/org/hps/recon/ecal
--- java/sandbox/ecal-recon/src/main/java/org/hps/recon/ecal/EcalRawConverter.java (rev 0)
+++ java/sandbox/ecal-recon/src/main/java/org/hps/recon/ecal/EcalRawConverter.java 2014-03-25 23:35:20 UTC (rev 346)
@@ -0,0 +1,117 @@
+package org.hps.recon.ecal;
+
+import org.lcsim.event.CalorimeterHit;
+import org.lcsim.event.RawCalorimeterHit;
+import org.lcsim.event.RawTrackerHit;
+import org.lcsim.event.base.BaseRawCalorimeterHit;
+
+/**
+ *
+ * @version $Id: HPSEcalRawConverterDriver.java,v 1.2 2012/05/03 00:17:54
+ * phansson Exp $
+ */
+public class EcalRawConverter {
+
+ private boolean debug = false;
+ private boolean constantGain = false;
+ private double gain;
+ private boolean use2014Gain = false;
+
+ public EcalRawConverter() {
+ }
+
+ public void setGain(double gain) {
+ constantGain = true;
+ this.gain = gain;
+ }
+
+ public void setUse2014Gain(boolean use2014Gain) {
+ this.use2014Gain = use2014Gain;
+ }
+
+ private short sumADC(RawTrackerHit hit) {
+ //Sum all pedestal subtracted ADC values
+ //return scale * (amplitude + 0.5) + pedestal;
+ if (debug) {
+ System.out.println("Summing ADC for hit: " + hit.toString());
+ }
+ double pedestal = EcalConditions.physicalToPedestal(hit.getCellID());
+ short sum = 0;
+ short samples[] = hit.getADCValues();
+ for (int isample = 0; isample < samples.length; ++isample) {
+ sum += (samples[isample] - pedestal);
+ if (debug) {
+ System.out.println("Sample " + isample + " " + samples[isample] + " pedestal " + pedestal + " (" + sum + ")");
+ }
+ }
+ return sum;
+ }
+
+ public CalorimeterHit HitDtoA(RawTrackerHit hit) {
+ double time = hit.getTime();
+ long id = hit.getCellID();
+ double rawEnergy = adcToEnergy(sumADC(hit), id);
+// double[] pos = hit.getDetectorElement().getGeometry().getPosition().v();
+ CalorimeterHit h = new HPSCalorimeterHit(rawEnergy + 0.0000001, time, id, 0);
+ //+0.0000001 is a horrible hack to ensure rawEnergy!=BaseCalorimeterHit.UNSET_CORRECTED_ENERGY
+ return h;
+ }
+
+ public CalorimeterHit HitDtoA(RawCalorimeterHit hit, int window) {
+ if (hit.getTimeStamp() % 64 != 0) {
+ System.out.println("unexpected timestamp " + hit.getTimeStamp());
+ }
+ double time = hit.getTimeStamp() / 16.0;
+ long id = hit.getCellID();
+ double adcSum = hit.getAmplitude() - window * EcalConditions.physicalToPedestal(id);
+ double rawEnergy = adcToEnergy(adcSum, id);
+ CalorimeterHit h = new HPSCalorimeterHit(rawEnergy + 0.0000001, time, id, 0);
+ //+0.0000001 is a horrible hack to ensure rawEnergy!=BaseCalorimeterHit.UNSET_CORRECTED_ENERGY
+ return h;
+ }
+
+ public RawCalorimeterHit HitAtoD(CalorimeterHit hit, int window) {
+ int time = (int) (Math.round(hit.getTime() / 4.0) * 64.0);
+ long id = hit.getCellID();
+ int amplitude;
+ if (constantGain) {
+ amplitude = (int) Math.round((hit.getRawEnergy() / ECalUtils.MeV) / gain + window * EcalConditions.physicalToPedestal(id));
+ } else {
+ amplitude = (int) Math.round((hit.getRawEnergy() / ECalUtils.MeV) / EcalConditions.physicalToGain(id) + window * EcalConditions.physicalToPedestal(id));
+ }
+ RawCalorimeterHit h = new BaseRawCalorimeterHit(id, amplitude, time);
+ return h;
+ }
+
+ /*
+ * return energy (units of GeV) corresponding to the ADC sum and crystal ID
+ */
+ private double adcToEnergy(double adcSum, long cellID) {
+ if (use2014Gain) {
+ if (constantGain) {
+ return adcSum * ECalUtils.gainFactor * ECalUtils.ecalReadoutPeriod;
+ } else {
+ return EcalConditions.physicalToGain(cellID) * adcSum * ECalUtils.gainFactor * ECalUtils.ecalReadoutPeriod; // should not be used for the moment (2014/02)
+ }
+ } else {
+ if (constantGain) {
+ return gain * adcSum * ECalUtils.MeV;
+ } else {
+ return EcalConditions.physicalToGain(cellID) * adcSum * ECalUtils.MeV; //gain is defined as MeV/integrated ADC
+ }
+ }
+ }
+ /*
+ public static CalorimeterHit HitDtoA(RawCalorimeterHit hit, int window, double g) {
+ if (hit.getTimeStamp() % 64 != 0) {
+ System.out.println("unexpected timestamp " + hit.getTimeStamp());
+ }
+ double time = hit.getTimeStamp() / 16.0;
+ long id = hit.getCellID();
+ double rawEnergy = g * (hit.getAmplitude() - window * EcalConditions.physicalToPedestal(id)) * ECalUtils.MeV;
+ CalorimeterHit h = new HPSCalorimeterHit(rawEnergy + 0.0000001, time, id, 0);
+ //+0.0000001 is a horrible hack to ensure rawEnergy!=BaseCalorimeterHit.UNSET_CORRECTED_ENERGY
+ return h;
+ }
+ */
+}
\ No newline at end of file
java/sandbox/ecal-recon/src/main/java/org/hps/recon/ecal
--- java/sandbox/ecal-recon/src/main/java/org/hps/recon/ecal/EcalRawConverterDriver.java (rev 0)
+++ java/sandbox/ecal-recon/src/main/java/org/hps/recon/ecal/EcalRawConverterDriver.java 2014-03-25 23:35:20 UTC (rev 346)
@@ -0,0 +1,165 @@
+package org.hps.recon.ecal;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.lcsim.event.CalorimeterHit;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.RawCalorimeterHit;
+import org.lcsim.event.RawTrackerHit;
+import org.lcsim.geometry.Detector;
+import org.lcsim.util.Driver;
+import org.lcsim.lcio.LCIOConstants;
+
+/**
+ *
+ * @version $Id: HPSEcalRawConverterDriver.java,v 1.2 2012/05/03 00:17:54
+ * phansson Exp $
+ */
+public class EcalRawConverterDriver extends Driver {
+
+ EcalRawConverter converter = null;
+ String rawCollectionName = "EcalReadoutHits";
+ String ecalReadoutName = "EcalHits";
+ String ecalCollectionName = "EcalCalHits";
+ int integralWindow = 35;
+ boolean debug = false;
+ double threshold = Double.NEGATIVE_INFINITY;
+ boolean applyBadCrystalMap = true;
+ boolean dropBadFADC = false;
+ private boolean runBackwards = false;
+
+ public EcalRawConverterDriver() {
+ converter = new EcalRawConverter();
+ }
+
+ public void setUse2014Gain(boolean use2014Gain) {
+ converter.setUse2014Gain(use2014Gain);
+ }
+
+ public void setRunBackwards(boolean runBackwards) {
+ this.runBackwards = runBackwards;
+ }
+
+ public void setDropBadFADC(boolean dropBadFADC) {
+ this.dropBadFADC = dropBadFADC;
+ }
+
+ public void setThreshold(double threshold) {
+ this.threshold = threshold;
+ }
+
+ public void setGain(double gain) {
+ converter.setGain(gain);
+ }
+
+ public void setIntegralWindow(int integralWindow) {
+ this.integralWindow = integralWindow;
+ }
+
+ public void setEcalCollectionName(String ecalCollectionName) {
+ this.ecalCollectionName = ecalCollectionName;
+ }
+
+ public void setRawCollectionName(String rawCollectionName) {
+ this.rawCollectionName = rawCollectionName;
+ }
+
+ public void setApplyBadCrystalMap(boolean apply) {
+ this.applyBadCrystalMap = apply;
+ }
+
+ public void setDebug(boolean debug) {
+ this.debug = debug;
+ }
+
+ @Override
+ public void startOfData() {
+ if (ecalCollectionName == null) {
+ throw new RuntimeException("The parameter ecalCollectionName was not set!");
+ }
+ }
+
+ @Override
+ public void detectorChanged(Detector detector) {
+ }
+
+ public static boolean isBadCrystal(CalorimeterHit hit) {
+ return EcalConditions.badChannelsLoaded() ? EcalConditions.isBadChannel(hit.getCellID()) : false;
+ }
+
+ public static boolean isBadFADC(CalorimeterHit hit) {
+ long daqID = EcalConditions.physicalToDaqID(hit.getCellID());
+ return (EcalConditions.getCrate(daqID) == 1 && EcalConditions.getSlot(daqID) == 3);
+ }
+
+ @Override
+ public void process(EventHeader event) {
+ int flags = 0;
+ flags += 1 << LCIOConstants.RCHBIT_TIME; //store cell ID
+
+ if (!runBackwards) {
+ ArrayList<CalorimeterHit> newHits = new ArrayList<CalorimeterHit>();
+
+ // Get the list of ECal hits.
+ if (event.hasCollection(RawTrackerHit.class, rawCollectionName)) {
+ List<RawTrackerHit> hits = event.get(RawTrackerHit.class, rawCollectionName);
+
+ for (RawTrackerHit hit : hits) {
+ CalorimeterHit newHit = converter.HitDtoA(hit);
+ if (applyBadCrystalMap && isBadCrystal(newHit)) {
+ continue;
+ }
+ if (dropBadFADC && isBadFADC(newHit)) {
+ continue;
+ }
+ if (newHit.getRawEnergy() > threshold) {
+ newHits.add(newHit);
+ }
+ }
+ event.put(ecalCollectionName, newHits, CalorimeterHit.class, flags, ecalReadoutName);
+ }
+ if (event.hasCollection(RawCalorimeterHit.class, rawCollectionName)) {
+ List<RawCalorimeterHit> hits = event.get(RawCalorimeterHit.class, rawCollectionName);
+
+ for (RawCalorimeterHit hit : hits) {
+ if (debug) {
+ System.out.format("old hit energy %d\n", hit.getAmplitude());
+ }
+ CalorimeterHit newHit = converter.HitDtoA(hit, integralWindow);
+ if (newHit.getRawEnergy() > threshold) {
+ if (applyBadCrystalMap && isBadCrystal(newHit)) {
+ continue;
+ }
+ if (dropBadFADC && isBadFADC(newHit)) {
+ continue;
+ }
+ if (debug) {
+ System.out.format("new hit energy %f\n", newHit.getRawEnergy());
+ }
+ newHits.add(newHit);
+ }
+ }
+ event.put(ecalCollectionName, newHits, CalorimeterHit.class, flags, ecalReadoutName);
+ }
+ } else {
+ ArrayList<RawCalorimeterHit> newHits = new ArrayList<RawCalorimeterHit>();
+ if (event.hasCollection(CalorimeterHit.class, ecalCollectionName)) {
+ List<CalorimeterHit> hits = event.get(CalorimeterHit.class, ecalCollectionName);
+
+ for (CalorimeterHit hit : hits) {
+ if (debug) {
+ System.out.format("old hit energy %f\n", hit.getRawEnergy());
+ }
+ RawCalorimeterHit newHit = converter.HitAtoD(hit, integralWindow);
+ if (newHit.getAmplitude() > 0) {
+ if (debug) {
+ System.out.format("new hit energy %d\n", newHit.getAmplitude());
+ }
+ newHits.add(newHit);
+ }
+ }
+ event.put(rawCollectionName, newHits, RawCalorimeterHit.class, flags, ecalReadoutName);
+ }
+ }
+ }
+}
java/sandbox/ecal-recon/src/main/java/org/hps/recon/ecal
--- java/sandbox/ecal-recon/src/main/java/org/hps/recon/ecal/EcalReadoutToTriggerConverterDriver.java (rev 0)
+++ java/sandbox/ecal-recon/src/main/java/org/hps/recon/ecal/EcalReadoutToTriggerConverterDriver.java 2014-03-25 23:35:20 UTC (rev 346)
@@ -0,0 +1,189 @@
+package org.hps.recon.ecal;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.lcsim.event.CalorimeterHit;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.base.BaseRawCalorimeterHit;
+import org.lcsim.geometry.Detector;
+import org.lcsim.util.Driver;
+
+/**
+ *
+ * @version $Id: HPSEcalRawConverterDriver.java,v 1.2 2012/05/03 00:17:54
+ * phansson Exp $
+ */
+public class EcalReadoutToTriggerConverterDriver extends Driver {
+
+ String rawCollectionName = "EcalReadoutHits";
+ String ecalReadoutName = "EcalHits";
+ String ecalCollectionName = "EcalCalHits";
+ int integralWindow = 30;
+ boolean debug = false;
+ double threshold = Double.NEGATIVE_INFINITY;
+ boolean applyBadCrystalMap = true;
+ boolean dropBadFADC = false;
+ double tp = 14.0;
+ double readoutPeriod = 4.0;
+ private int readoutThreshold = 50;
+ private int triggerThreshold = 80;
+ private double timeShift = 0;
+ private int truncateScale = 128;
+
+ public EcalReadoutToTriggerConverterDriver() {
+ }
+
+ public void setTp(double tp) {
+ this.tp = tp;
+ }
+
+ public void setDropBadFADC(boolean dropBadFADC) {
+ this.dropBadFADC = dropBadFADC;
+ }
+
+ public void setThreshold(double threshold) {
+ this.threshold = threshold;
+ }
+
+ public void setIntegralWindow(int integralWindow) {
+ this.integralWindow = integralWindow;
+ }
+
+ public void setEcalCollectionName(String ecalCollectionName) {
+ this.ecalCollectionName = ecalCollectionName;
+ }
+
+ public void setRawCollectionName(String rawCollectionName) {
+ this.rawCollectionName = rawCollectionName;
+ }
+
+ public void setApplyBadCrystalMap(boolean apply) {
+ this.applyBadCrystalMap = apply;
+ }
+
+ public void setTruncateScale(int truncateScale) {
+ this.truncateScale = truncateScale;
+ }
+
+ @Override
+ public void startOfData() {
+ if (ecalCollectionName == null) {
+ throw new RuntimeException("The parameter ecalCollectionName was not set!");
+ }
+ }
+
+ @Override
+ public void detectorChanged(Detector detector) {
+ }
+
+ public boolean isBadCrystal(CalorimeterHit hit) {
+ return EcalConditions.badChannelsLoaded() ? EcalConditions.isBadChannel(hit.getCellID()) : false;
+ }
+
+ public boolean isBadFADC(CalorimeterHit hit) {
+ long daqID = EcalConditions.physicalToDaqID(hit.getCellID());
+ return (EcalConditions.getCrate(daqID) == 1 && EcalConditions.getSlot(daqID) == 3);
+ }
+
+ @Override
+ public void process(EventHeader event) {
+ ArrayList<CalorimeterHit> newHits = new ArrayList<CalorimeterHit>();
+
+ if (event.hasCollection(BaseRawCalorimeterHit.class, rawCollectionName)) {
+ List<BaseRawCalorimeterHit> hits = event.get(BaseRawCalorimeterHit.class, rawCollectionName);
+
+ for (BaseRawCalorimeterHit hit : hits) {
+ CalorimeterHit newHit = HitDtoA(hit, integralWindow);
+ if (newHit != null && newHit.getRawEnergy() > threshold) {
+ if (applyBadCrystalMap && isBadCrystal(newHit)) {
+ continue;
+ }
+ if (dropBadFADC && isBadFADC(newHit)) {
+ continue;
+ }
+ newHits.add(newHit);
+ }
+ }
+ }
+ int flags = 0;
+ event.put(ecalCollectionName, newHits, CalorimeterHit.class, flags, ecalReadoutName);
+ }
+
+ public CalorimeterHit HitDtoA(BaseRawCalorimeterHit hit, int window) {
+ double integral = tp * Math.E / readoutPeriod;
+ double readoutIntegral = (hit.getAmplitude() - window * EcalConditions.physicalToPedestal(hit.getCellID()));
+ double amplitude = readoutIntegral / integral;
+
+// double time = readoutPeriod * (Math.random() - 1);
+ double time = 0 - timeShift;
+ timeShift += 0.01;
+ if (timeShift > readoutPeriod) {
+ timeShift = 0;
+ }
+ double triggerIntegral = 0;
+ boolean overThreshold = false;
+// double readoutTime = -1;
+// double triggerTime = -1;
+ while (true) {
+ double currentValue = amplitude * pulseAmplitude(time);
+// if (readoutTime < 0 && currentValue > readoutThreshold) {
+// readoutTime = time;
+// }
+ if (!overThreshold && currentValue > triggerThreshold) {
+ overThreshold = true;
+// triggerTime = time;
+ }
+ if (overThreshold) {
+ triggerIntegral += amplitude * pulseAmplitude(time);
+ if (currentValue < triggerThreshold) {
+ break;
+ }
+ }
+ time += readoutPeriod;
+
+ if (time > 200.0) {
+ break;
+ }
+ }
+
+// System.out.format("%f %f %f\n", readoutIntegral, amplitude, triggerIntegral);
+
+ if (hit.getTimeStamp() % 64 != 0) {
+ System.out.println("unexpected timestamp " + hit.getTimeStamp());
+ }
+ int truncatedIntegral = (int) Math.floor(triggerIntegral / truncateScale) * truncateScale;
+ double hitTime = hit.getTimeStamp() / 16.0;
+// if (readoutTime >= 0 && triggerTime >= 0) {
+// hitTime += triggerTime - readoutTime;
+// }
+ long id = hit.getCellID();
+// Hep3Vector pvec = hit.getDetectorElement().getGeometry().getPosition();
+// double [] pos = new double[3];
+// pos[0] = pvec.x();
+// pos[1] = pvec.y();
+// pos[2] = pvec.z();
+// if (truncatedIntegral<=0) return null;
+ if (truncatedIntegral <= 0) {
+ truncatedIntegral = 0;
+ }
+ CalorimeterHit h = new HPSCalorimeterHit(truncatedIntegral, hitTime, id, 0);
+// CalorimeterHit h = new HPSRawCalorimeterHit(triggerIntegral + 0.0000001, hit.getPosition(), hitTime, id, 0);
+ //+0.0000001 is a horrible hack to ensure rawEnergy!=BaseCalorimeterHit.UNSET_CORRECTED_ENERGY
+ return h;
+ }
+
+ private double pulseAmplitude(double time) {
+ if (time <= 0.0) {
+ return 0.0;
+ }
+ if (tp > 0.0) {
+ return (time / tp) * Math.exp(1.0 - time / tp);
+ } else {
+ if (time < -tp) {
+ return 1.0;
+ } else {
+ return 0.0;
+ }
+ }
+ }
+}
java/sandbox/ecal-recon/src/main/java/org/hps/recon/ecal
--- java/sandbox/ecal-recon/src/main/java/org/hps/recon/ecal/EcalTriggerFilterDriver.java (rev 0)
+++ java/sandbox/ecal-recon/src/main/java/org/hps/recon/ecal/EcalTriggerFilterDriver.java 2014-03-25 23:35:20 UTC (rev 346)
@@ -0,0 +1,108 @@
+package org.hps.recon.ecal;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Queue;
+import java.util.concurrent.ArrayBlockingQueue;
+import org.lcsim.event.CalorimeterHit;
+import org.lcsim.event.EventHeader;
+import org.lcsim.geometry.Detector;
+import org.lcsim.util.Driver;
+
+/**
+ * Changes ECal hit IDs to match what the test run trigger sees.
+ * @version $Id: HPSEcalRawConverterDriver.java,v 1.2 2012/05/03 00:17:54
+ * phansson Exp $
+ */
+public class EcalTriggerFilterDriver extends Driver {
+
+ private String ecalReadoutName = "EcalHits";
+ private String inputCollection = "EcalReadoutHits";
+ private String outputCollection = "EcalCalHits";
+ private int topDelay = 0;
+ private int bottomDelay = 5;
+ private Queue<List<CalorimeterHit>> topHitsQueue = null;
+ private Queue<List<CalorimeterHit>> bottomHitsQueue = null;
+
+ public EcalTriggerFilterDriver() {
+ }
+
+ public void setOutputCollection(String outputCollection) {
+ this.outputCollection = outputCollection;
+ }
+
+ public void setInputCollection(String inputCollection) {
+ this.inputCollection = inputCollection;
+ }
+
+ @Override
+ public void startOfData() {
+ if (outputCollection == null) {
+ throw new RuntimeException("The parameter ecalCollectionName was not set!");
+ }
+
+ topHitsQueue = new ArrayBlockingQueue<List<CalorimeterHit>>(topDelay + 1);
+ for (int i = 0; i < topDelay; i++) {
+ topHitsQueue.add(new ArrayList<CalorimeterHit>());
+ }
+ bottomHitsQueue = new ArrayBlockingQueue<List<CalorimeterHit>>(bottomDelay + 1);
+ for (int i = 0; i < bottomDelay; i++) {
+ bottomHitsQueue.add(new ArrayList<CalorimeterHit>());
+ }
+ }
+
+ @Override
+ public void detectorChanged(Detector detector) {
+ }
+
+ @Override
+ public void process(EventHeader event) {
+ if (event.hasCollection(CalorimeterHit.class, inputCollection)) {
+ ArrayList<CalorimeterHit> newHits = new ArrayList<CalorimeterHit>();
+
+ ArrayList<CalorimeterHit> topHits = new ArrayList<CalorimeterHit>();
+ ArrayList<CalorimeterHit> bottomHits = new ArrayList<CalorimeterHit>();
+
+ List<CalorimeterHit> hits = event.get(CalorimeterHit.class, inputCollection);
+ for (CalorimeterHit hit : hits) {
+ CalorimeterHit newHit = filterHit(hit);
+ if (newHit != null) {
+ if (hit.getIdentifierFieldValue("iy") > 0) { //should really be checking newHit, but it doesn't have metadata yet
+ topHits.add(newHit);
+ } else {
+ bottomHits.add(newHit);
+ }
+ }
+ }
+ topHitsQueue.add(topHits);
+ bottomHitsQueue.add(bottomHits);
+ newHits.addAll(topHitsQueue.poll());
+ newHits.addAll(bottomHitsQueue.poll());
+ int flags = 0;
+ event.put(outputCollection, newHits, CalorimeterHit.class, flags, ecalReadoutName);
+ }
+ }
+
+ private CalorimeterHit filterHit(CalorimeterHit hit) {
+ int ix = hit.getIdentifierFieldValue("ix");
+ int iy = hit.getIdentifierFieldValue("iy");
+ long daqID = EcalConditions.physicalToDaqID(hit.getCellID());
+ int crate = EcalConditions.getCrate(daqID);
+ short slot = EcalConditions.getSlot(daqID);
+ short channel = EcalConditions.getChannel(daqID);
+
+ int delay = iy>0?topDelay:bottomDelay;
+ // no triggers from crate 1, slot 3
+ if (crate == 1 && slot == 3) {
+ return null;
+ }
+
+ // flip quadrant
+ if (ix > 0 && iy > 0) {
+ ix = 24 - ix;
+ }
+ long newID = EcalConditions.makePhysicalID(ix, iy);
+ //make new hit; set position to null so it gets recalculated
+ return new HPSCalorimeterHit(hit.getRawEnergy(), hit.getTime()+delay*4, newID, hit.getType());
+ }
+}
java/sandbox/ecal-recon/src/main/java/org/hps/recon/ecal
--- java/sandbox/ecal-recon/src/main/java/org/hps/recon/ecal/FADCConverterDriver.java (rev 0)
+++ java/sandbox/ecal-recon/src/main/java/org/hps/recon/ecal/FADCConverterDriver.java 2014-03-25 23:35:20 UTC (rev 346)
@@ -0,0 +1,101 @@
+package org.hps.recon.ecal;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.RawTrackerHit;
+import org.lcsim.event.base.BaseRawCalorimeterHit;
+import org.lcsim.geometry.Detector;
+import org.lcsim.util.Driver;
+
+/**
+ *
+ * @version $Id: FADCConverterDriver.java,v 1.4 2013/02/25 22:39:24 meeg Exp $
+ */
+public class FADCConverterDriver extends Driver {
+
+ String rawCollectionName = "EcalReadoutHits";
+ String ecalReadoutName = "EcalHits";
+ String ecalCollectionName = "EcalIntegralHits";
+ boolean debug = false;
+ int numSamplesBefore = 5;
+ int numSamplesAfter = 30;
+ int threshold = 50;
+
+ public FADCConverterDriver() {
+ }
+
+ public void setThreshold(int threshold) {
+ this.threshold = threshold;
+ }
+
+ public void setEcalReadoutName(String ecalReadoutName) {
+ this.ecalReadoutName = ecalReadoutName;
+ }
+
+ public void setNumSamplesAfter(int numSamplesAfter) {
+ this.numSamplesAfter = numSamplesAfter;
+ }
+
+ public void setNumSamplesBefore(int numSamplesBefore) {
+ this.numSamplesBefore = numSamplesBefore;
+ }
+
+ public void setEcalCollectionName(String ecalCollectionName) {
+ this.ecalCollectionName = ecalCollectionName;
+ }
+
+ public void setRawCollectionName(String rawCollectionName) {
+ this.rawCollectionName = rawCollectionName;
+ }
+
+ @Override
+ public void startOfData() {
+ if (ecalCollectionName == null) {
+ throw new RuntimeException("The parameter ecalCollectionName was not set!");
+ }
+ }
+
+ @Override
+ public void detectorChanged(Detector detector) {
+ }
+
+ @Override
+ public void process(EventHeader event) {
+ ArrayList<BaseRawCalorimeterHit> readoutHits = new ArrayList<BaseRawCalorimeterHit>();
+ ArrayList<BaseRawCalorimeterHit> triggerHits = new ArrayList<BaseRawCalorimeterHit>();
+
+ // Get the list of ECal hits.
+ if (event.hasCollection(RawTrackerHit.class, rawCollectionName)) {
+ List<RawTrackerHit> hits = event.get(RawTrackerHit.class, rawCollectionName);
+
+ for (RawTrackerHit hit : hits) {
+ short[] window = hit.getADCValues();
+ long id = hit.getCellID();
+ //do DAQ readout
+ double crystalThreshold = EcalConditions.physicalToPedestal(id) + threshold;
+ int adcSum = 0;
+ int pointerOffset = 0;
+ int numSamplesToRead = 0;
+ int thresholdCrossing = 0;
+ for (int i = 0; i < window.length; i++) {
+ if (numSamplesToRead != 0) {
+ adcSum += window[i - pointerOffset];
+ numSamplesToRead--;
+ if (numSamplesToRead == 0) {
+ readoutHits.add(new BaseRawCalorimeterHit(id, adcSum, 64*thresholdCrossing));
+ }
+ } else if ((i == 0 || window[i - 1] <= crystalThreshold) && window[i] > crystalThreshold) {
+ thresholdCrossing = i;
+ pointerOffset = Math.min(numSamplesBefore, i);
+ numSamplesToRead = pointerOffset + Math.min(numSamplesAfter, window.length - i - pointerOffset - 1);
+ adcSum = 0;
+ }
+ }
+ //do trigger readout
+ }
+ }
+ int flags = 0;
+ event.put(ecalCollectionName, readoutHits, BaseRawCalorimeterHit.class, flags, ecalReadoutName);
+ }
+}
java/sandbox/ecal-recon/src/main/java/org/hps/recon/ecal
--- java/sandbox/ecal-recon/src/main/java/org/hps/recon/ecal/GTPEcalClusterer.java (rev 0)
+++ java/sandbox/ecal-recon/src/main/java/org/hps/recon/ecal/GTPEcalClusterer.java 2014-03-25 23:35:20 UTC (rev 346)
@@ -0,0 +1,365 @@
+package org.hps.recon.ecal;
+
+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.EventHeader;
+import org.lcsim.geometry.Detector;
+import org.lcsim.geometry.subdetector.HPSEcal3;
+import org.lcsim.geometry.subdetector.HPSEcal3.NeighborMap;
+import org.lcsim.lcio.LCIOConstants;
+import org.lcsim.util.Driver;
+
+/**
+ * Class
+ * <code>GTPCalorimeterClusterer</code> processes events and converts hits into
+ * clusters, where appropriate. It uses the modified 2014 clustering algorithm.
+ *
+ * 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.
+ *
+ * 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 GTPEcalClusterer extends Driver {
+
+ /**
+ * <b>calorimeter</b><br/><br/>
+ * <code>private HPSEcal3 <b>calorimeter</b></code><br/><br/>
+ * The sub-detector representing the calorimeter.
+ */
+ private HPSEcal3 calorimeter;
+ /**
+ * <b>ecalName</b><br/><br/>
+ * <code>private String <b>ecalName</b></code><br/><br/>
+ * The name of the calorimeter sub-detector stored in the
+ * <code>
+ * Detector</code> object for this run.
+ */
+ String ecalName;
+ /**
+ * <b>clusterCollectionName</b><br/><br/>
+ * <code>private String <b>clusterCollectionName</b></code><br/><br/>
+ * The name of the LCIO collection name in which the clusters will be
+ * stored.
+ */
+ String clusterCollectionName = "EcalClusters";
+ /**
+ * <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.
+ */
+ int clusterWindow = 2;
+ /**
+ * <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>ecalCollectionName</b><br/><br/>
+ * <code>private String <b>ecalCollectionName</b></code><br/><br/>
+ * The name of LCIO collection containing the calorimeter hits that are to
+ * be used for clustering.
+ */
+ String ecalCollectionName;
+ /**
+ * <b>neighborMap</b><br/><br/>
+ * <code>private NeighborMap <b>neighborMap</b></code><br/><br/>
+ * Maps the
+ * <code>long</code> crystal ID to the set of crystal IDs of the crystals
+ * which are adjacent to the key.
+ */
+ private NeighborMap neighborMap = null;
+ /**
+ * <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.
+ */
+ double seedEnergyThreshold = 0.05;
+
+ /**
+ * <b>detectorChanged</b><br/><br/>
+ * <code>public void <b>detectorChanged</b>(Detector detector)</code><br/><br/>
+ * Initializes detector-dependent parameters for clustering. Method is
+ * responsible for determining which crystals are valid cluster centers
+ * (stored in
+ * <code>validCrystals</code>), defining the detector object (stored in
+ * <code>calorimeter</code>), defining the detector ID decoder (stored in
+ * <code>decoder</code>), and defining the mapping of crystal IDs to the
+ * crystal's neighbors (defined in
+ * <code>neighborMap</code>).
+ *
+ * @param detector - The new detector to use.
+ */
+ @Override
+ public void detectorChanged(Detector detector) {
+ // Get the calorimeter object.
+ calorimeter = (HPSEcal3) detector.getSubdetector(ecalName);
+
+ // Get a map to associate crystals with their neighbors.
+ neighborMap = calorimeter.getNeighborMap();
+ }
+
+ /**
+ * <b>getClusters</b><br/><br/>
+ * <code>public List<HPSEcalCluster> <b>getClusters</b>()</code><br/><br/>
+ * 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.
+ */
+ public List<HPSEcalCluster> getClusters() {
+ // Generate a list for storing clusters.
+ List<HPSEcalCluster> clusters = new ArrayList<HPSEcalCluster>();
+
+ // 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.
+ HPSEcalCluster cluster = new HPSEcalCluster(currentHit);
+ 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.
+ addLoop:
+ 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 {
+ 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 {
+ cluster.addHit(neighborHit);
+ }
+ }
+ }
+ }
+
+ // Add the cluster to the list of clusters.
+ clusters.add(cluster);
+ }
+
+ // Return the generated list of clusters.
+ return clusters;
+ }
+
+ /**
+ * <b>process</b><br/><br/>
+ * <code>public void <b>process</b>(EventHeader event)</code><br/><br/>
+ * 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.
+ */
+ @Override
+ public void process(EventHeader event) {
+ // Only run the clusterer if this event has the calorimeter hit collection.
+ // This ensures this driver makes clusters in sync with the FADC readout cycle.
+ if (event.hasCollection(CalorimeterHit.class, ecalCollectionName)) {
+ // Get the list of calorimeter hits from the event.
+ List<CalorimeterHit> hitList = event.get(CalorimeterHit.class, ecalCollectionName);
+
+ // 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 : hitList) {
+ 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<HPSEcalCluster> clusterList = getClusters();
+
+ // Store the cluster list in the LCIO collection.
+ int flag = 1 << LCIOConstants.CLBIT_HITS;
+ event.put(clusterCollectionName, clusterList, HPSEcalCluster.class, flag);
+ }
+ }
+
+ /**
+ * <b>setEcalCollectionName</b><br/><br/>
+ * <code>public void <b>setEcalCollectionName</b>(String ecalCollectionName)</code><br/><br/>
+ * Sets the name of the LCIO collection containing the calorimeter hits
+ * which should be used for clustering.
+ *
+ * @param ecalCollectionName - The appropriate collection name.
+ */
+ public void setEcalCollectionName(String ecalCollectionName) {
+ this.ecalCollectionName = ecalCollectionName;
+ }
+
+ /**
+ * <b>setClusterCollectionName</b><br/><br/>
+ * <code>public void <b>setClusterCollectionName</b>(String clusterCollectionName)</code><br/><br/>
+ * Sets the name of the LCIO collection in which the clusters should be
+ * stored.
+ *
+ * @param clusterCollectionName - The desired collection name.
+ */
+ public void setClusterCollectionName(String clusterCollectionName) {
+ this.clusterCollectionName = clusterCollectionName;
+ }
+
+ /**
+ * <b>setEcalName</b><br/><br/>
+ * <code>public void <b>setEcalName</b>(String ecalName)</code><br/><br/>
+ * Sets the name of the calorimeter sub-detector stored in the
+ * <code>Detector</code> object that is to be used for this run.
+ *
+ * @param ecalName - The calorimeter's name.
+ */
+ public void setEcalName(String ecalName) {
+ this.ecalName = ecalName;
+ }
+
+ /**
+ * <b>setClusterWindow</b><br/><br/>
+ * <code>public void <b>setClusterWindow</b>(int clusterWindow)</code><br/><br/>
+ * 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.
+ */
+ public 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;
+ }
+ }
+
+ /**
+ * <b>setSeedEnergyThreshold</b><br/><br/>
+ * <code>public void <b>setSeedEnergyThreshold</b>(double seedEnergyThreshold)</code><br/><br/>
+ * Sets the minimum energy threshold below which hits will not be considered
+ * as cluster centers.
+ *
+ * @param seedEnergyThreshold - The minimum energy for a cluster center.
+ */
+ public 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;
+ }
+ }
+
+ /**
+ * <b>startOfData</b><br/><br/>
+ * <code>public void <b>startOfData</b>()</code><br/><br/>
+ * Initializes the clusterer. This ensures that the collection name for the
+ * calorimeter hits from which clusters are to be generated, along with the
+ * calorimeter name, have been defined. Method also initializes the event
+ * hit buffer.
+ */
+ @Override
+ public void startOfData() {
+ // Make sure that there is a cluster collection name into
+ // which clusters may be placed.
+ if (ecalCollectionName == null) {
+ throw new RuntimeException("The parameter ecalCollectionName was not set!");
+ }
+
+ // Make sure that there is a calorimeter detector.
+ if (ecalName == null) {
+ throw new RuntimeException("The parameter ecalName was not set!");
+ }
+
+ // 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));
+ }
+ }
+}
java/sandbox/ecal-recon/src/main/java/org/hps/recon/ecal
--- java/sandbox/ecal-recon/src/main/java/org/hps/recon/ecal/HPSCalorimeterHit.java (rev 0)
+++ java/sandbox/ecal-recon/src/main/java/org/hps/recon/ecal/HPSCalorimeterHit.java 2014-03-25 23:35:20 UTC (rev 346)
@@ -0,0 +1,72 @@
+package org.hps.recon.ecal;
+
+import hep.physics.vec.Hep3Vector;
+import java.util.Comparator;
+import org.lcsim.detector.IDetectorElement;
+import org.lcsim.detector.IDetectorElementContainer;
+import org.lcsim.event.CalorimeterHit;
+import org.lcsim.event.base.BaseCalorimeterHit;
+
+/**
+ * An implementation of CalorimeterHit, with a constructor that sets rawEnergy
+ * for use in ECalReadout
+ *
+ * @author Sho Uemura
+ * @version $Id: HPSCalorimeterHit.java,v 1.1 2013/02/25 22:39:24 meeg Exp $
+ */
+public class HPSCalorimeterHit extends BaseCalorimeterHit {
+
+ /**
+ * Fully qualified constructor that sets rawEnergy
+ *
+ * @param energy Raw energy for this cell
+ * @param position Global Cartesian coordinate for this cell
+ * @param time Time of energy deposition
+ * @param id Cell ID
+ * @param type Type
+ */
+ public HPSCalorimeterHit(double energy, double time, long id, int type) {
+ this.rawEnergy = energy;
+// if (position != null) {
+// this.positionVec = new BasicHep3Vector(position);
+// } else {
+// positionVec = null;
+// }
+ this.time = time;
+ this.id = id;
+ this.type = type;
+ }
+
+ @Override
+ public IDetectorElement getDetectorElement() {
+ if (de == null) {
+// findDetectorElementByPosition();
+ IDetectorElementContainer detectorElements = EcalConditions.getSubdetector().getDetectorElement().findDetectorElement(getIdentifier());
+ if (detectorElements.size() != 1) {
+ throw new RuntimeException("Expected exactly one DetectorElement matching ID " + getIdentifier() + ", got " + detectorElements.size());
+ } else {
+ de = detectorElements.get(0);
+ }
+ }
+ // setupDetectorElement();
+ return de;
+ }
+
+ @Override
+ public double[] getPosition() {
+ return getPositionVec().v();
+ }
+
+ @Override
+ public Hep3Vector getPositionVec() {
+ return this.getDetectorElement().getGeometry().getPosition();
+ }
+
+ static class TimeComparator implements Comparator<CalorimeterHit> {
+
+ @Override
+ public int compare(CalorimeterHit o1, CalorimeterHit o2) {
+ return Double.compare(o1.getTime(), o2.getTime());
+ }
+ }
+}
java/sandbox/ecal-recon/src/main/java/org/hps/recon/ecal
--- java/sandbox/ecal-recon/src/main/java/org/hps/recon/ecal/HPSEcalCluster.java (rev 0)
+++ java/sandbox/ecal-recon/src/main/java/org/hps/recon/ecal/HPSEcalCluster.java 2014-03-25 23:35:20 UTC (rev 346)
@@ -0,0 +1,422 @@
+package org.hps.recon.ecal;
+
+import hep.physics.vec.BasicHep3Vector;
+import hep.physics.vec.Hep3Vector;
+import hep.physics.vec.VecOp;
+import java.util.List;
+import org.lcsim.detector.IGeometryInfo;
+import org.lcsim.detector.solids.Trd;
+import org.lcsim.event.CalorimeterHit;
+import org.lcsim.event.base.BaseCluster;
+
+/**
+ * Cluster with position defined by seed hit (for 1-bit trigger)
+ *
+ * @author Sho Uemura <[log in to unmask]>
+ * @version $Id: HPSEcalCluster.java,v 1.11 2013/02/25 22:39:24 meeg Exp $
+ */
+public class HPSEcalCluster extends BaseCluster {
+
+ private CalorimeterHit seedHit = null;
+ private long cellID;
+
+ static final double eCriticalW = 800.0*ECalUtils.MeV/(74+1);
+ static final double radLenW = 8.8; //mm
+ double[] electronPosAtDepth = new double[3];
+ private boolean needsElectronPosCalculation = true;
+ double[] photonPosAtDepth = new double[3];
+ private boolean needsPhotonPosCalculation = true;
+
+ public HPSEcalCluster(Long cellID) {
+ this.cellID = cellID;
+ }
+
+ public HPSEcalCluster(CalorimeterHit seedHit) {
+ this.seedHit = seedHit;
+ this.cellID = seedHit.getCellID();
+ }
+
+ public CalorimeterHit getSeedHit() {
+ if (seedHit == null) {
+ CalorimeterHit hit = hits.get(0);
+ if (hit == null) {
+ throw new RuntimeException("HPSEcalCluster has no hits");
+ }
+ seedHit = new HPSCalorimeterHit(0.0, 0.0, cellID, hit.getType());
+ seedHit.setMetaData(hit.getMetaData());
+ }
+ return seedHit;
+ }
+
+// public double[] getPosition() {
+// return getSeedHit().getPosition();
+// }
+//
+ @Override
+ public double[] getPosition() {
+ //Electron by default!?
+ return this.getPositionAtShowerMax(true);
+ }
+
+ public double[] getPositionAtShowerMax(boolean isElectron) {
+ if( isElectron) {
+ if(needsElectronPosCalculation) {
+ this.calcPositionAtShowerMax(true);
+ }
+ return this.electronPosAtDepth;
+ }
+ else {
+ if(needsPhotonPosCalculation) {
+ this.calcPositionAtShowerMax(false);
+ }
+ return this.photonPosAtDepth;
+ }
+ }
+
+ public void calcPositionAtShowerMax(boolean isElectron) {
+ double E = this.getEnergy();
+ double y = E/eCriticalW;
+ double Cj = isElectron ? -0.5 : 0.5;
+ double tmax = Math.log(y) + Cj; //Maximum of dE/dt profile in units of rad. len.
+ double dmax = tmax*radLenW; //mm
+ if(isElectron) {
+ electronPosAtDepth = calculatePositionAtDepth(dmax);
+ } else {
+ photonPosAtDepth = calculatePositionAtDepth(dmax);
+ }
+
+ }
+
+
+
+ public double[] calculatePositionAtDepth(double dmax)
+ {
+ return this.calculatePositionAtDepth(this.getCalorimeterHits(), dmax);
+ }
+
+ public double[] calculatePositionAtDepth(List<CalorimeterHit> hits, double dmax)
+ {
+ //copy from package org.lcsim.recon.cluster.util.TensorClusterPropertyCalculator;
+
+ double positionErrorLocal[] = new double[6];
+ double directionErrorLocal[] = new double[6];
+ double shapeParametersLocal[] = new double[6];
+ double positionLocal[] = new double[3];
+ double ithetaLocal;
+ double iphiLocal;
+
+
+ double[] mm_NE = new double[3];
+ double[] mm_CE = new double[3];
+ double[][] mm_PA = new double[3][3];
+ for(int i=0;i<3;++i)
+ {
+ mm_NE[i] = 0.;
+ mm_CE[i] = 0.;
+ for(int j=0;j<3;++j)
+ {mm_PA[i][j]= 0.;}
+ }
+ double Etot = 0.0;
+ double Exx = 0.0;
+ double Eyy = 0.0;
+ double Ezz = 0.0;
+ double Exy = 0.0;
+ double Eyz = 0.0;
+ double Exz = 0.0;
+ double CEx = 0.0;
+ double CEy = 0.0;
+ double CEz = 0.0;
+ double CEr = 0.0;
+ double E1 = 0.0;
+ double E2 = 0.0;
+ double E3 = 0.0;
+ double NE1 = 0.0;
+ double NE2 = 0.0;
+ double NE3 = 0.0;
+ double Tr = 0.0;
+ double M = 0.0;
+ double Det = 0.0;
+ int nhits = hits.size();
+ for(int i=0;i<hits.size();i++)
+ {
+ CalorimeterHit hit = hits.get(i);
+ // CalorimeterIDDecoder decoder = hit.getDecoder();
+ // decoder.setID(hit.getCellID());
+ // double[] pos = new double[3];
+ // pos[0] = decoder.getX();
+ // pos[1] = decoder.getY();
+ // pos[2] = decoder.getZ();
+ //double[] pos = hit.getPosition();
+ //Find position at shower max
+ IGeometryInfo geom = hit.getDetectorElement().getGeometry();
+ double[] pos = geom.transformLocalToGlobal(VecOp.add(geom.transformGlobalToLocal(geom.getPosition()),(Hep3Vector)new BasicHep3Vector(0,0,dmax-1*((Trd)geom.getLogicalVolume().getSolid()).getZHalfLength()))).v();
+
+// System.out.println("global pos " + global_pos.toString());
+// System.out.println("local pos " + local_pos.toString());
+// System.out.println("local pos tmax " + local_pos_tmax.toString());
+// System.out.println("global pos tmax " + global_pos_tmax.toString());
+//
+ //pos = global_pos_tmax.v();
+
+ double E = hit.getCorrectedEnergy();
+ Etot += E;
+ CEx += E*pos[0];
+ CEy += E*pos[1];
+ CEz += E*pos[2];
+ Exx += E*(pos[1]*pos[1] + pos[2]*pos[2]);
+ Eyy += E*(pos[0]*pos[0] + pos[2]*pos[2]);
+ Ezz += E*(pos[1]*pos[1] + pos[0]*pos[0]);
+ Exy -= E*pos[0]*pos[1];
+ Eyz -= E*pos[1]*pos[2];
+ Exz -= E*pos[0]*pos[2];
+ }
+ CEx = CEx/Etot;
+ CEy = CEy/Etot;
+ CEz = CEz/Etot;
+ double CErSq = CEx*CEx + CEy*CEy + CEz*CEz;
+ CEr = Math.sqrt(CErSq);
+ // now go to center of energy coords.
+ if (nhits > 3 )
+ {
+ Exx = Exx - Etot*(CErSq - CEx*CEx);
+ Eyy = Eyy - Etot*(CErSq - CEy*CEy);
+ Ezz = Ezz - Etot*(CErSq - CEz*CEz);
+ Exy = Exy + Etot*CEx*CEy;
+ Eyz = Eyz + Etot*CEy*CEz;
+ Exz = Exz + Etot*CEz*CEx;
+
+ //
+ Tr = Exx + Eyy + Ezz;
+ double Dxx = Eyy*Ezz - Eyz*Eyz;
+ double Dyy = Ezz*Exx - Exz*Exz;
+ double Dzz = Exx*Eyy - Exy*Exy;
+ M = Dxx + Dyy + Dzz;
+ double Dxy = Exy*Ezz - Exz*Eyz;
+ double Dxz = Exy*Eyz - Exz*Eyy;
+ Det = Exx*Dxx - Exy*Dxy + Exz*Dxz;
+ double xt = Tr*Tr - 3*M;
+ double sqrtxt = Math.sqrt(xt);
+ // eqn to solve for eigenvalues is x**3 - x**2*Tr + x*M - Det = 0
+ // crosses y axis at -Det and inflection points are
+
+ double mE1 = 0.;
+ double mE2 = 0.;
+ double mE3 = 0.;
+ double a = (3*M - Tr*Tr)/3.;
+ double b = (-2*Tr*Tr*Tr + 9*Tr*M -27*Det)/27.;
+ double test = b*b/4. + a*a*a/27.;
+ if(test >= 0.01)
+ {
+ //System.out.println("AbstractCluster: Only 1 real root!!!");
+ //System.out.println(" nhits = " + nhits + "\n");
+ //System.out.println(" a,b,test = " + a + " " + b + " " + test + "\n");
+ }
+ else
+ {
+ double temp;
+ if(test >= 0.)temp = 1.;
+ else temp = Math.sqrt(b*b*27./(-a*a*a*4.));
+ if(b > 0.)temp = -temp;
+ double phi = Math.acos(temp);
+ double temp1 = 2.*Math.sqrt(-a/3.);
+ mE1 = Tr/3. + 2.*Math.sqrt(-a/3.)*Math.cos(phi/3.);
+ mE2 = Tr/3. + 2.*Math.sqrt(-a/3.)*Math.cos(phi/3. + 2.*Math.PI/3.);
+ mE3 = Tr/3. + 2.*Math.sqrt(-a/3.)*Math.cos(phi/3. + 4.*Math.PI/3.);
+ }
+ if(mE1 < mE2)
+ {
+ if(mE1 < mE3)
+ {
+ E1 = mE1;
+ if(mE2 < mE3)
+ {
+ E2 = mE2;
+ E3 = mE3;
+ }
+ else
+ {
+ E2 = mE3;
+ E3 = mE2;
+ }
+ }
+ else
+ {
+ E1 = mE3;
+ E2 = mE1;
+ E3 = mE2;
+ }
+ }
+ else
+ {
+ if(mE2 < mE3)
+ {
+ E1 = mE2;
+ if(mE1 < mE3)
+ {
+ E2 = mE1;
+ E3 = mE3;
+ }
+ else
+ {
+ E2 = mE3;
+ E3 = mE1;
+ }
+ }
+ else
+ {
+ E1 = mE3;
+ E2 = mE2;
+ E3 = mE1;
+ }
+ }
+
+ NE1 = E1/Etot;
+ NE2 = E2/Etot;
+ NE3 = E3/Etot;
+ double[] EV = new double[3];
+ EV[0] = E1;
+ EV[1] = E2;
+ EV[2] = E3;
+ // Now calculate principal axes
+ // For eigenvalue EV, the axis is (nx, ny, nz) where:
+ // (Exx - EV)nx + (Exy)ny + (Exz)nz = 0
+ // (Eyx)nx + (Eyy - EV)ny + (Eyz)nz = 0
+ // (Ezx)nx + (Ezy)ny + (Ezz - EV)nz = 0
+ // Setting nx = 1, we have:
+ // (Exx - EV) + (Exy)ny + (Exz)nz = 0
+ // (Eyx) + (Eyy - EV)ny + (Eyz)nz = 0
+ // (Ezx) + (Ezy)ny + (Ezz - EV)nz = 0
+ // and so
+ // (Exy)ny = EV - Exx - (Exz)nz => ny = (EV - Exx - Exz*nz)/Exy
+ // What if Exy = 0? Then provided Eyz is non-zero we can write:
+ // (Ezx) + (Ezy)ny + (Ezz - EV)nz = 0
+ // ny = (Exz - (Ezz-EV)*nz)/Eyz
+ // What if Exy = 0 and Eyz = 0 but (Eyy - EV) is non-zero?
+ // (Eyy - EV)ny + (Eyz)nz = 0
+ // ny = -(Eyz*nz)/(Eyy-EV)
+
+ // In the pathological case where Exz = Eyz = Ezz = 0:
+ // (Exx - EV)nx + (Exy)ny = 0 => ny/nx = -(Exx-EV)/Exy
+ // (Eyx)nx + (Eyy - EV)ny = 0 => ny/nx = -Eyx/(Eyy-EV)
+ // (EV)nz = 0
+ // so
+ // -ny/nx = (EV-Exx)/Exy = Eyx/(EV-Eyy)
+ // But watch out for order! Recalculate eigenvalues for this pathological case.
+ // (EV-Exx)(EV-Eyy) = Eyx*Exy
+ // EV^2 - EV(Exx+Eyy) + Exx*Eyy - Eyx*Exy = 0
+ //
+ // In another pathological case, Exz = Exy = 0:
+ // (Exx - EV)nx = 0
+ // (Eyy - EV)ny + (Eyz)nz = 0 => ny/nz = -(Eyz)/(Eyy-EV)
+ // (Ezy)ny + (Ezz - EV)nz = 0 => ny/nz = -(Ezz-EV)/(Ezy)
+ // so we cannot set nx = 1. Instead, write:
+ // -ny/nz = (Eyz)/(Eyy-EV) = (Ezz-EV)/(Ezy)
+ // Then
+ // (Eyz)(Ezy) = (Eyy-EV)(Ezz-EV)
+ // (Eyz)^2 = (Eyy)(Ezz) - (Eyy)(EV) - (Ezz)(EV) + (EV)^2
+ // EV^2 - EV(Eyy+Ezz) + Eyy*Ezz - Eyz*Eyz = 0
+
+ // Handle pathological case
+ if (Exz == 0.0 && Eyz == 0.0) {
+ // Recompute eigenvectors.
+ EV[0] = 0.5*(Exx+Eyy) + 0.5*Math.sqrt((Exx+Eyy)*(Exx+Eyy) + 4.0*Exy*Exy);
+ EV[1] = 0.5*(Exx+Eyy) - 0.5*Math.sqrt((Exx+Eyy)*(Exx+Eyy) + 4.0*Exy*Exy);
+ EV[2] = 0.0;
+ for( int i = 0 ; i < 2 ; i++ ) {
+ double nx_over_ny = Exy / (Exx-EV[i]);
+ double nx_unnormalized = nx_over_ny;
+ double ny_unnormalized = 1.0;
+ double norm = Math.sqrt(nx_unnormalized*nx_unnormalized + ny_unnormalized*ny_unnormalized);
+ mm_PA[i][0] = ny_unnormalized/norm;
+ mm_PA[i][1] = nx_unnormalized/norm;
+ mm_PA[i][2] = 0.0;
+ }
+ // ... and now set third eigenvector to the z direction:
+ mm_PA[2][0] = 0.0;
+ mm_PA[2][1] = 0.0;
+ mm_PA[2][2] = 1.0;
+ } else if (Exz == 0.0 && Exy == 0.0) {
+ // Another pathological case
+ EV[0] = 0.5*(Eyy+Ezz) + 0.5*Math.sqrt((Eyy+Ezz)*(Eyy+Ezz) + 4.0*Eyz*Eyz);
+ EV[1] = 0.5*(Eyy+Ezz) - 0.5*Math.sqrt((Eyy+Ezz)*(Eyy+Ezz) + 4.0*Eyz*Eyz);
+ EV[2] = 0.0;
+ for( int i = 0 ; i < 2 ; i++ ) {
+ double ny_over_nz = Eyz / (Eyy-EV[i]);
+ double ny_unnormalized = ny_over_nz;
+ double nz_unnormalized = 1.0;
+ double norm = Math.sqrt(ny_unnormalized*ny_unnormalized + nz_unnormalized*nz_unnormalized);
+ mm_PA[i][0] = nz_unnormalized/norm;
+ mm_PA[i][1] = ny_unnormalized/norm;
+ mm_PA[i][2] = 0.0;
+ }
+ mm_PA[2][0] = 0.0;
+ mm_PA[2][1] = 0.0;
+ mm_PA[2][2] = 1.0;
+ } else {
+ for( int i = 0 ; i < 3 ; i++ )
+ {
+ double[] C = new double[3];
+ C[0] = 1.0;
+ C[2] = (Exy*Exy + (Eyy - EV[i])*(EV[i] - Exx))/
+ ((Eyy - EV[i])*Exz - Eyz*Exy);
+ C[1] = (EV[i] - Exx - Exz*C[2])/Exy;
+ if (Exy == 0.0) {
+ // Recompute
+ if (Eyz != 0.0) {
+ // ny = (Exz - (Ezz-EV)*nz)/Eyz
+ C[1] = (Exz - (Ezz-EV[i])*C[2])/Eyz;
+ } else {
+ // ny = -(Eyz*nz)/(Eyy-EV)
+ C[1] = -(Eyz*C[2])/(Eyy-EV[i]);
+ }
+ }
+ double norm = Math.sqrt(C[0]*C[0] + C[1]*C[1] + C[2]*C[2]);
+ mm_PA[i][0] = C[0]/norm;
+ mm_PA[i][1] = C[1]/norm;
+ mm_PA[i][2] = C[2]/norm;
+ }
+ }
+ }
+ mm_NE[0] = NE1;
+ mm_NE[1] = NE2;
+ mm_NE[2] = NE3;
+ mm_CE[0] = CEx;
+ mm_CE[1] = CEy;
+ mm_CE[2] = CEz;
+ for(int i=0;i<6;i++)
+ {
+ positionErrorLocal[i] = 0.;
+ directionErrorLocal[i] = 0.;
+ shapeParametersLocal[i] = 0.;
+ }
+ for(int i=0;i<3;i++)
+ {
+ positionLocal[i] = mm_CE[i];
+ shapeParametersLocal[i] = mm_NE[i];
+ }
+ if(nhits > 3)
+ {
+ double dr = Math.sqrt( (position[0]+mm_PA[0][0])*(position[0]+mm_PA[0][0]) +
+ (position[1]+mm_PA[0][1])*(position[1]+mm_PA[0][1]) +
+ (position[2]+mm_PA[0][2])*(position[2]+mm_PA[0][2]) ) -
+ Math.sqrt( (position[0])*(position[0]) +
+ (position[1])*(position[1]) +
+ (position[2])*(position[2]) ) ;
+ double sign = 1.;
+ if(dr < 0.)sign = -1.;
+ itheta = Math.acos(sign*mm_PA[0][2]);
+ iphi = Math.atan2(sign*mm_PA[0][1],sign*mm_PA[0][0]);
+ }
+ else
+ {
+ itheta = 999.;
+ iphi = 999.;
+ }
+
+ return positionLocal;
+ }
+
+
+
+
+}
java/sandbox/ecal-recon/src/main/java/org/hps/recon/ecal
--- java/sandbox/ecal-recon/src/main/java/org/hps/recon/ecal/HPSRawCalorimeterHit.java (rev 0)
+++ java/sandbox/ecal-recon/src/main/java/org/hps/recon/ecal/HPSRawCalorimeterHit.java 2014-03-25 23:35:20 UTC (rev 346)
@@ -0,0 +1,60 @@
+package org.hps.recon.ecal;
+
+import java.util.Comparator;
+import org.lcsim.event.CalorimeterHit;
+import org.lcsim.event.RawCalorimeterHit;
+
+/**
+ *
+ * @author Sho Uemura <[log in to unmask]>
+ * @version $Id: HPSRawCalorimeterHit.java,v 1.9 2013/02/25 22:39:24 meeg Exp $
+ */
+public class HPSRawCalorimeterHit implements RawCalorimeterHit {
+
+ long cellID;
+ int amplitude;
+ int timeStamp;
+ int windowSize;
+ CalorimeterHit analogHit = null;
+
+ public HPSRawCalorimeterHit(long cellID, int amplitude, int timeStamp, int windowSize) {
+ this.cellID = cellID;
+ this.amplitude = amplitude;
+ this.timeStamp = timeStamp;
+ this.windowSize = windowSize;
+ }
+
+ @Override
+ public long getCellID() {
+ return cellID;
+ }
+
+ @Override
+ public int getAmplitude() {
+ return amplitude;
+ }
+
+ @Override
+ public int getTimeStamp() {
+ return timeStamp;
+ }
+
+ public int getWindowSize() {
+ return windowSize;
+ }
+
+ public CalorimeterHit getAnalogHit() {
+ return analogHit;
+ }
+
+ public void setAnalogHit(CalorimeterHit analogHit) {
+ this.analogHit = analogHit;
+ }
+
+ public static class TimeComparator implements Comparator<RawCalorimeterHit> {
+
+ public int compare(RawCalorimeterHit o1, RawCalorimeterHit o2) {
+ return o1.getTimeStamp() - o2.getTimeStamp();
+ }
+ }
+}
\ No newline at end of file
java/sandbox/ecal-recon/src/main/java/org/hps/recon/ecal
--- java/sandbox/ecal-recon/src/main/java/org/hps/recon/ecal/TriggerData.java (rev 0)
+++ java/sandbox/ecal-recon/src/main/java/org/hps/recon/ecal/TriggerData.java 2014-03-25 23:35:20 UTC (rev 346)
@@ -0,0 +1,111 @@
+package org.hps.recon.ecal;
+
+import org.lcsim.event.GenericObject;
+
+/**
+ *
+ * @author Sho Uemura <[log in to unmask]>
+ * @version $Id: TriggerData.java,v 1.3 2012/08/03 23:14:39 meeg Exp $
+ */
+public class TriggerData implements GenericObject {
+
+ public static final int OR_TRIG = 3;
+ public static final int TOP_TRIG = 4;
+ public static final int BOT_TRIG = 5;
+ public static final int AND_TRIG = 6;
+ public static final int TIME = 7;
+ public static final int TRIG_BANK_SIZE = 8;
+ public static final String TRIG_COLLECTION = "TriggerBank";
+ private int[] bank;
+
+ public TriggerData(int[] bank) {
+ this.bank = bank;
+ }
+
+ public int getTime() {
+ return getIntVal(TIME);
+ }
+
+ public int getOrTrig() {
+ return getIntVal(OR_TRIG);
+ }
+
+ public int getTopTrig() {
+ return getIntVal(TOP_TRIG);
+ }
+
+ public int getBotTrig() {
+ return getIntVal(BOT_TRIG);
+ }
+
+ public int getAndTrig() {
+ return getIntVal(AND_TRIG);
+ }
+
+ public int[] getBank() {
+ return bank;
+ }
+
+ public static int getTime(GenericObject object) {
+ return object.getIntVal(TIME);
+ }
+
+ public static int getOrTrig(GenericObject object) {
+ return object.getIntVal(OR_TRIG);
+ }
+
+ public static int getTopTrig(GenericObject object) {
+ return object.getIntVal(TOP_TRIG);
+ }
+
+ public static int getBotTrig(GenericObject object) {
+ return object.getIntVal(BOT_TRIG);
+ }
+
+ public static int getAndTrig(GenericObject object) {
+ return object.getIntVal(AND_TRIG);
+ }
+
+ public static int[] getBank(GenericObject object) {
+ int[] bank = new int[8];
+ for (int i = 0; i < 8; i++) {
+ bank[i] = object.getIntVal(i);
+ }
+ return bank;
+ }
+
+ @Override
+ public int getNInt() {
+ return TRIG_BANK_SIZE;
+ }
+
+ @Override
+ public int getNFloat() {
+ return 0;
+ }
+
+ @Override
+ public int getNDouble() {
+ return 0;
+ }
+
+ @Override
+ public int getIntVal(int index) {
+ return bank[index];
+ }
+
+ @Override
+ public float getFloatVal(int index) {
+ throw new UnsupportedOperationException("No float values in " + this.getClass().getSimpleName());
+ }
+
+ @Override
+ public double getDoubleVal(int index) {
+ throw new UnsupportedOperationException("No double values in " + this.getClass().getSimpleName());
+ }
+
+ @Override
+ public boolean isFixedSize() {
+ return true;
+ }
+}
SVNspam 0.1