Author: [log in to unmask] Date: Wed Jan 14 13:56:44 2015 New Revision: 1932 Log: moved position calculations within code Modified: java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/ReconClusterer.java Modified: java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/ReconClusterer.java ============================================================================= --- java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/ReconClusterer.java (original) +++ java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/ReconClusterer.java Wed Jan 14 13:56:44 2015 @@ -1,4 +1,8 @@ package org.hps.recon.ecal.cluster; + +import hep.physics.vec.BasicHep3Vector; +import hep.physics.vec.Hep3Vector; +import hep.physics.vec.VecOp; import java.awt.Point; import java.util.ArrayList; @@ -12,6 +16,8 @@ import org.hps.recon.ecal.cluster.AbstractClusterer; import org.hps.recon.ecal.cluster.ClusterType; import org.hps.recon.ecal.cluster.Clusterer; +import org.lcsim.detector.IGeometryInfo; +import org.lcsim.detector.solids.Trd; import org.lcsim.event.CalorimeterHit; import org.lcsim.event.Cluster; import org.lcsim.event.EventHeader; @@ -68,10 +74,6 @@ List<CalorimeterHit> rejectedHitList = new ArrayList<CalorimeterHit>(); - // A Comparator that sorts CalorimeterHit objects from highest to - // lowest energy. - private static final EnergyComparator ENERGY_COMP = new EnergyComparator(); - ReconClusterer() { super(new String[] { "hitEnergyThreshold", "seedEnergyThreshold", "clusterEnergyThreshold", "minTime", "timeWindow" }, new double[] { 0.0075, 0.1, 0.3, 0.0, 20.0 }); @@ -112,14 +114,11 @@ // ArrayList<CalorimeterHit> rejectedHitList = new ArrayList<CalorimeterHit>(); rejectedHitList = new ArrayList<CalorimeterHit>(); - correctedPositionMap.clear(); - // Sort the list of hits by energy. - Collections.sort(hitList, ENERGY_COMP); - + ClusterUtilities.sortHitsUniqueEnergy(hitList); + // Filter the hit list of any hits that fail to pass the // designated threshold. - for (int index = hitList.size() - 1; index >= 0; index--) { // If the hit is below threshold or outside of time window, kill it. if ((hitList.get(index).getCorrectedEnergy() < hitEnergyThreshold) || (useTimeCut && (hitList.get(index).getTime() < minTime || hitList.get(index).getTime() > (minTime + timeWindow)))) { @@ -153,7 +152,7 @@ HashMap<CalorimeterHit, CalorimeterHit> hitToSeed = new HashMap<CalorimeterHit, CalorimeterHit>(); // Loop through all calorimeter hits to locate seeds and perform - // first pass calculations for component and common hits. + // first pass calculations for component and common hits. for (int ii = 0; ii <= hitList.size() - 1; ii++) { CalorimeterHit hit = hitList.get(ii); @@ -398,157 +397,13 @@ clusterList.remove(checkcluster); j--; } - else { + else { + // Computer the position of the cluster and set it. + calculatePosition(checkcluster); continue; } } return clusterList; - } - //TODO: Move this to a separate position/cluster calculator - /* - * All hits are sorted from above. The next part of the code is for calculating energies and - * positions. - */ -/* - // Cluster Position as per HPS Note 2014-001 - // Create map with seed as key to position/centroid value - Map<CalorimeterHit, double[]> rawSeedPosition = new HashMap<CalorimeterHit, double[]>(); - Map<CalorimeterHit, double[]> corrSeedPosition = new HashMap<CalorimeterHit, double[]>(); - - // top level iterates through seeds - for (Map.Entry<CalorimeterHit, Double> entryS : seedEnergyTot.entrySet()) { - // get the seed for this iteration - CalorimeterHit seedP = entryS.getKey(); - - double xCl = 0.0; // calculated cluster x position, prior to correction - double yCl = 0.0; // calculated cluster y position - double eNumX = 0.0; - double eNumY = 0.0; - double eDen = 0.0; - double w0 = 3.1; - - // iterate through hits corresponding to seed - for (Map.Entry<CalorimeterHit, CalorimeterHit> entryP : hitSeedMap.entrySet()) { - if (entryP.getValue() == seedP) { - // ///////////////////////////// - // This block fills a map with crystal to center of face of crystal - // Get the hit indices as a Point. - int ix = entryP.getKey().getIdentifierFieldValue("ix"); - int iy = entryP.getKey().getIdentifierFieldValue("iy"); - Point hitIndex = new Point(ix, iy); - - // Get the corrected position for this index pair. - double[] position = correctedPositionMap.get(hitIndex); - - // If the result is null, it hasn't been calculated yet. - if (position == null) { - // Calculate the corrected position. - IGeometryInfo geom = entryP.getKey().getDetectorElement().getGeometry(); - double[] pos = geom.transformLocalToGlobal(VecOp.add(geom.transformGlobalToLocal(geom.getPosition()), (Hep3Vector) new BasicHep3Vector(0, 0, -1 * ((Trd) geom.getLogicalVolume().getSolid()).getZHalfLength()))).v(); - - // Convert the result to a Double[] array. - position = new double[3]; - position[0] = pos[0]; - position[1] = pos[1]; - position[2] = pos[2]; - - // Store the result in the map. - correctedPositionMap.put(hitIndex, position); - } - // ///////////////////////////// - - // Use Method 3 weighting scheme described in note: - eNumX += Math.max(0.0, (w0 + Math.log(entryP.getKey().getCorrectedEnergy() / seedEnergyTot.get(seedP)))) * (correctedPositionMap.get(hitIndex)[0] / 10.0); - eNumY += Math.max(0.0, (w0 + Math.log(entryP.getKey().getCorrectedEnergy() / seedEnergyTot.get(seedP)))) * (correctedPositionMap.get(hitIndex)[1] / 10.0); - eDen += Math.max(0.0, (w0 + Math.log(entryP.getKey().getCorrectedEnergy() / seedEnergyTot.get(seedP)))); - } - - } - - xCl = eNumX / eDen; - yCl = eNumY / eDen; - - double[] rawPosition = new double[3]; - rawPosition[0] = xCl * 10.0;// mm - rawPosition[1] = yCl * 10.0;// mm - int ix = seedP.getIdentifierFieldValue("ix"); - int iy = seedP.getIdentifierFieldValue("iy"); - Point hitIndex = new Point(ix, iy); - rawPosition[2] = correctedPositionMap.get(hitIndex)[2]; - - rawSeedPosition.put(seedP, rawPosition); - - }// end of cluster position calculation -*/ - - private static class EnergyComparator implements Comparator<CalorimeterHit> { - /** - * Compares the first hit with respect to the second. This method will compare hits first by - * energy, and then spatially. In the case of equal energy hits, the hit closest to the beam - * gap and closest to the positron side of the detector will be selected. If all of these - * conditions are true, the hit with the positive y-index will be selected. Hits with all - * four conditions matching are the same hit. - * @param hit1 The hit to compare. - * @param hit2 The hit with respect to which the first should be compared. - */ - public int compare(CalorimeterHit hit1, CalorimeterHit hit2) { - // Hits are sorted on a hierarchy by three conditions. First, - // the hits with the highest energy come first. Next, they - // are ranked by vertical proximity to the beam gap, and - // lastly, they are sorted by horizontal proximity to the - // positron side of the detector. - - // Get the hit energies. - double[] e = { hit1.getCorrectedEnergy(), hit2.getCorrectedEnergy() }; - - // Perform the energy comparison. The higher energy hit - // will be ordered first. - if (e[0] < e[1]) { - return 1; - } else if (e[0] > e[1]) { - return -1; - } - - // If the hits are the same energy, we must perform the - // spatial comparisons. - else { - // Get the position with respect to the beam gap. - int[] iy = { Math.abs(hit1.getIdentifierFieldValue("iy")), Math.abs(hit2.getIdentifierFieldValue("iy")) }; - - // The closest hit is first. - if (iy[0] > iy[1]) { - return -1; - } else if (iy[0] < iy[1]) { - return 1; - } - - // Hits that are identical in vertical distance from - // beam gap and energy are differentiated with distance - // horizontally from the positron side of the detector. - else { - // Get the position from the positron side. - int[] ix = { hit1.getIdentifierFieldValue("ix"), hit2.getIdentifierFieldValue("ix") }; - - // The closest hit is first. - if (ix[0] > ix[1]) { - return 1; - } else if (ix[0] < ix[1]) { - return -1; - } - - // If all of these checks are the same, compare - // the raw value for iy. If these are identical, - // then the two hits are the same. Otherwise, sort - // the numerical value of iy. (This removes the - // issue where hits (x, y) and (x, -y) can have - // the same energy and be otherwise seen as the - // same hit from the above checks. - else { - return Integer.compare(hit1.getIdentifierFieldValue("iy"), hit2.getIdentifierFieldValue("iy")); - } - } - } - } } /** @@ -576,6 +431,77 @@ return isSeed; } + /** + * Calculates the position of each cluster with no correction for particle type + * as documented in HPS Note 2014-001. + * @param cluster + */ + private void calculatePosition(Cluster cluster){ + final double w0 = 3.1; + // calculated cluster x position + double xCl = 0.0; + // calculated cluster y position + double yCl = 0.0; + double eNumX = 0.0; + double eNumY = 0.0; + double eDen = 0.0; + List<CalorimeterHit> clusterHits= cluster.getCalorimeterHits(); + for (CalorimeterHit hit : clusterHits){ + // This block fills a map with crystal to center of face of crystal + // Get the hit indices as a Point. + int ix = hit.getIdentifierFieldValue("ix"); + int iy = hit.getIdentifierFieldValue("iy"); + Point hitIndex = new Point(ix, iy); + + // Get the corrected position for this index pair. + double[] position = correctedPositionMap.get(hitIndex); + + if (position == null){ + addToMap(hit); + position = correctedPositionMap.get(hitIndex); + } + + eNumX += Math.max(0.0, (w0 + Math.log(hit.getCorrectedEnergy() / cluster.getEnergy()))) * (correctedPositionMap.get(hitIndex)[0] / 10.0); + eNumY += Math.max(0.0, (w0 + Math.log(hit.getCorrectedEnergy() / cluster.getEnergy()))) * (correctedPositionMap.get(hitIndex)[1] / 10.0); + eDen += Math.max(0.0, (w0 + Math.log(hit.getCorrectedEnergy() / cluster.getEnergy()))); + + }// end for iteration through clusterHits + + xCl = eNumX / eDen; + yCl = eNumY / eDen; + + double[] clusterPosition = new double[3]; + clusterPosition[0] = xCl * 10.0;// mm + clusterPosition[1] = yCl * 10.0;// mm + int ix = clusterHits.get(0).getIdentifierFieldValue("ix"); + int iy = clusterHits.get(0).getIdentifierFieldValue("iy"); + Point hitIndex = new Point(ix, iy); + clusterPosition[2] = correctedPositionMap.get(hitIndex)[2]; + + ((BaseCluster) cluster).setPosition(clusterPosition); + } + + /** + * This constructs a mapping of a crystal to an x,y position at the face of the ecal. + * This fills the correctedPositionMap with the position of a crystal's face from the + * index x,y of the crystal. + * @param hit + */ + private void addToMap(CalorimeterHit hit){ + int ix = hit.getIdentifierFieldValue("ix"); + int iy = hit.getIdentifierFieldValue("iy"); + Point hitIndex = new Point(ix, iy); + // If the result is null, it hasn't been calculated yet. + // Calculate the corrected position. + IGeometryInfo geom = hit.getDetectorElement().getGeometry(); + double[] pos = geom.transformLocalToGlobal(VecOp.add(geom.transformGlobalToLocal(geom.getPosition()), (Hep3Vector) new BasicHep3Vector(0, 0, -1 * ((Trd) geom.getLogicalVolume().getSolid()).getZHalfLength()))).v(); + + // Store the result in the map. + correctedPositionMap.put(hitIndex, pos); + } + + + public ClusterType getClusterType() { return ClusterType.RECON; }