Author: [log in to unmask] Date: Wed Jan 14 08:35:17 2015 New Revision: 1924 Log: updated recon clusterer to use basecluster 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 08:35:17 2015 @@ -1,8 +1,4 @@ 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; @@ -13,12 +9,13 @@ import java.util.Map; import java.util.Set; -import org.hps.recon.ecal.HPSEcalClusterIC; -import org.lcsim.detector.IGeometryInfo; -import org.lcsim.detector.solids.Trd; +import org.hps.recon.ecal.cluster.AbstractClusterer; +import org.hps.recon.ecal.cluster.ClusterType; +import org.hps.recon.ecal.cluster.Clusterer; import org.lcsim.event.CalorimeterHit; import org.lcsim.event.Cluster; import org.lcsim.event.EventHeader; +import org.lcsim.event.base.BaseCluster; /** * <p> @@ -92,7 +89,7 @@ } clusterEnergyThreshold = getCuts().getValue("clusterEnergyThreshold"); minTime = getCuts().getValue("minTime"); - timeWindow = getCuts().getValue("timeWindow"); + timeWindow = getCuts().getValue("timeWindow"); } /** @@ -102,16 +99,12 @@ List<CalorimeterHit> getRejectedHitList() { return this.rejectedHitList; } - - public List<Cluster> createClusters(EventHeader event, List<CalorimeterHit> hits) { - + + + public List<Cluster> createClusters(EventHeader event, List<CalorimeterHit> hits) { // Create a list to store the event hits in. - List<CalorimeterHit> hitList = new ArrayList<CalorimeterHit>(); - List<CalorimeterHit> baseList = hits; - for (CalorimeterHit r : baseList) { - hitList.add(r); - } - + List<CalorimeterHit> hitList = hits; + // Create a list to store the newly created clusters in. ArrayList<Cluster> clusterList = new ArrayList<Cluster>(); @@ -149,17 +142,21 @@ for (CalorimeterHit hit : hitList) { hitMap.put(hit.getCellID(), hit); } + + // Create a map to connect a seed hit to its cluster. + Map<CalorimeterHit, BaseCluster> seedToCluster = new HashMap<CalorimeterHit,BaseCluster>(); // Map a crystal to a list of all clusters in which it is a member. Map<CalorimeterHit, List<CalorimeterHit>> commonHits = new HashMap<CalorimeterHit, List<CalorimeterHit>>(); // Map a crystal to the seed of the cluster of which it is a member. - HashMap<CalorimeterHit, CalorimeterHit> hitSeedMap = new HashMap<CalorimeterHit, CalorimeterHit>(); + 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); + // Get the set of all neighboring crystals to the current hit. Set<Long> neighbors = neighborMap.get(hit.getCellID()); @@ -174,7 +171,7 @@ CalorimeterHit neighborHit = hitMap.get(neighbor); // If it exists, add it to the list. - if (neighborHit != null) { + if (neighborHit != null && hitList.contains(neighborHit)) { neighborHits.add(neighborHit); } } @@ -191,31 +188,41 @@ break seedHitLoop; } } - // If this hit is a seed hit, just map it to itself. - if (isSeed && hit.getCorrectedEnergy() >= seedEnergyThreshold) { - hitSeedMap.put(hit, hit); - } - - // If this hit is a local maximum but does not pass seed threshold, - // remove from hit list and do not cluster. - else if (isSeed && hit.getCorrectedEnergy() < seedEnergyThreshold) { - hitList.remove(ii); - rejectedHitList.add(hit); - ii--; - } + + // Hit is a local maximum + if (isSeed){ + // Seed must pass minimum threshold + if (hit.getCorrectedEnergy() >= seedEnergyThreshold) + { + // Create new cluster + BaseCluster cluster = createBasicCluster(); + clusterList.add(cluster); + seedToCluster.put(hit, cluster); + hitToSeed.put(hit, hit); + + } + // Seed does not pass minimum threshold + else{ + rejectedHitList.add(hit); + hitList.remove(ii); + ii--; + } + }// end if isSeed // If this hit is not a seed hit, see if it should be // attached to any neighboring seed hits. - else { + else { // Sort through the list of neighboring hits. for (CalorimeterHit neighborHit : neighborHits) { // Check whether the neighboring hit is a seed. - if (hitSeedMap.get(neighborHit) == neighborHit) { + // if (seedToCluster.containsKey(neighborHit)) { + if (hitToSeed.get(neighborHit) == neighborHit) { + // If the neighboring hit is a seed hit and the // current hit has been associated with a cluster, // then it is a common hit between its previous // seed and the neighboring seed. - if (hitSeedMap.containsKey(hit)) { + if (hitToSeed.containsKey(hit)) { // Check and see if a list of common seeds // for this hit already exists or not. List<CalorimeterHit> commonHitList = commonHits.get(hit); @@ -228,7 +235,7 @@ // Add the neighbors to the seeds to set of // common seeds. commonHitList.add(neighborHit); - commonHitList.add(hitSeedMap.get(hit)); + commonHitList.add(hitToSeed.get(hit)); // Put the common seed list back into the set. commonHits.put(hit, commonHitList); @@ -239,7 +246,7 @@ // associate it with the neighboring seed and note // that it has been clustered. else { - hitSeedMap.put(hit, neighborHit); + hitToSeed.put(hit, neighborHit); } } } @@ -249,7 +256,7 @@ // Performs second pass calculations for component hits. secondaryHitsLoop: for (CalorimeterHit secondaryHit : hitList) { // Look for hits that already have an associated seed/clustering. - if (!hitSeedMap.containsKey(secondaryHit)) { + if (!hitToSeed.containsKey(secondaryHit)) { continue secondaryHitsLoop; } @@ -267,7 +274,7 @@ // If the neighboring crystal exists and is not already // in a cluster, add it to the list of neighboring hits. - if (secondaryNeighborHit != null && !hitSeedMap.containsKey(secondaryNeighborHit)) { + if (secondaryNeighborHit != null && !hitToSeed.containsKey(secondaryNeighborHit)) { secondaryNeighborHits.add(secondaryNeighborHit); } } @@ -278,20 +285,13 @@ // current secondary hit, then associate the neighboring // hit with the current secondary hit's seed. if (!equalEnergies(secondaryNeighborHit, secondaryHit)) { - hitSeedMap.put(secondaryNeighborHit, hitSeedMap.get(secondaryHit)); - } else { - continue; - } + hitToSeed.put(secondaryNeighborHit, hitToSeed.get(secondaryHit)); + } else {continue;} } } // End component hits loop. - + // Performs second pass calculations for common hits. - commonHitsLoop: for (CalorimeterHit clusteredHit : hitSeedMap.keySet()) { - - // Seed hits are never common hits and can be skipped. - if (hitSeedMap.get(clusteredHit) == clusteredHit) { - continue commonHitsLoop; - } + commonHitsLoop: for (CalorimeterHit clusteredHit : hitToSeed.keySet()) { // Get the current clustered hit's neighboring crystals. Set<Long> clusteredNeighbors = neighborMap.get(clusteredHit.getCellID()); @@ -307,13 +307,13 @@ // If it exists, add it to the neighboring hit list. - if (clusteredNeighborHit != null && hitSeedMap.get(clusteredNeighborHit) != null) { + if (clusteredNeighborHit != null && hitToSeed.get(clusteredNeighborHit) != null) { clusteredNeighborHits.add(clusteredNeighborHit); } } // Get the seed hit associated with this clustered hit. - CalorimeterHit clusteredHitSeed = hitSeedMap.get(clusteredHit); + CalorimeterHit clusteredHitSeed = hitToSeed.get(clusteredHit); // Loop over the clustered neighbor hits. for (CalorimeterHit clusteredNeighborHit : clusteredNeighborHits) { @@ -321,7 +321,7 @@ // is not already associated with the current clustered // hit's seed. - if ((hitSeedMap.get(clusteredNeighborHit) != clusteredHitSeed)) { + if ((hitToSeed.get(clusteredNeighborHit) != clusteredHitSeed)) { // Check for lowest energy hit and that comparison hit is not already common. // If already common, this boundary is already accounted for. if (!equalEnergies(clusteredHit, clusteredNeighborHit) && !commonHits.containsKey(clusteredNeighborHit)) { @@ -338,7 +338,7 @@ // Add the neighbors to the seeds to set of // common seeds. commonHitList.add(clusteredHitSeed); - commonHitList.add(hitSeedMap.get(clusteredNeighborHit)); + commonHitList.add(hitToSeed.get(clusteredNeighborHit)); // Put the common seed list back into the set. commonHits.put(clusteredHit, commonHitList); @@ -347,55 +347,69 @@ } } } // End common hits loop. - + // Remove any common hits from the clustered hits collection. for (CalorimeterHit commonHit : commonHits.keySet()) { - hitSeedMap.remove(commonHit); + hitToSeed.remove(commonHit); + hitList.remove(commonHit); } + + /* + * All hits are sorted from above. The next part of the code is for + * building the output cluster collections. + */ + // Add all hits except for common hits + for (CalorimeterHit ihit : hitList) + { + CalorimeterHit iseed = hitToSeed.get(ihit); + BaseCluster icluster = seedToCluster.get(iseed); + icluster.addHit(ihit); + } + + // Add common hits + for (Map.Entry<CalorimeterHit, List<CalorimeterHit>> commHit : commonHits.entrySet()) + { + CalorimeterHit seedA = commHit.getValue().get(0); + CalorimeterHit seedB = commHit.getValue().get(1); + double eclusterA = seedToCluster.get(seedA).getEnergy(); + double eclusterB = seedToCluster.get(seedB).getEnergy(); + double fractionA = eclusterA / (eclusterA + eclusterB); + double fractionB = eclusterB / (eclusterA + eclusterB); + double hitcontributionA = commHit.getKey().getCorrectedEnergy()*fractionA; + double hitcontributionB = commHit.getKey().getCorrectedEnergy()*fractionB; + + BaseCluster clusterA = seedToCluster.get(seedA); + BaseCluster clusterB = seedToCluster.get(seedB); + + clusterA.addHit(commHit.getKey(), hitcontributionA); + clusterB.addHit(commHit.getKey(), hitcontributionB); + } + + // Remove clusters that do not pass cluster threshold and add to rejectedHitList. + for (int j=0; j <= clusterList.size()-1; j++) + { + Cluster checkcluster = clusterList.get(j); + if (checkcluster.getEnergy() < clusterEnergyThreshold) { + List<CalorimeterHit> clusterHits= checkcluster.getCalorimeterHits(); + for (CalorimeterHit nhit : clusterHits){ + rejectedHitList.add(nhit); + } + clusterList.remove(checkcluster); + j--; + } + else { + 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. */ - - // Create map to contain the total energy of each cluster - Map<CalorimeterHit, Double> seedEnergy = new HashMap<CalorimeterHit, Double>(); - - // Get energy of each cluster, excluding common hits - for (CalorimeterHit iSeed : hitList) { - if (hitSeedMap.get(iSeed) == iSeed) { - seedEnergy.put(iSeed, 0.0); - } - } - - // Putting total cluster energies excluding common hit energies into map with seed keys - for (Map.Entry<CalorimeterHit, CalorimeterHit> entry : hitSeedMap.entrySet()) { - CalorimeterHit eSeed = entry.getValue(); - double eEnergy = seedEnergy.get(eSeed); - eEnergy += entry.getKey().getCorrectedEnergy(); - seedEnergy.put(eSeed, eEnergy); - } - - // Create a map to contain final uncorrected cluster energies including common hit - // distributions. - Map<CalorimeterHit, Double> seedEnergyTot = seedEnergy; - - // Distribute common hit energies with clusters - for (Map.Entry<CalorimeterHit, List<CalorimeterHit>> entry1 : commonHits.entrySet()) { - CalorimeterHit commonCell = entry1.getKey(); - CalorimeterHit seedA = entry1.getValue().get(0); - CalorimeterHit seedB = entry1.getValue().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); - } - +/* // 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[]>(); @@ -465,66 +479,8 @@ rawSeedPosition.put(seedP, rawPosition); }// end of cluster position calculation - - /* - * Outputs results to cluster collection. - */ - // Only write output if something actually exists. - if (hitMap.size() != 0) { - // Loop over seeds - for (Map.Entry<CalorimeterHit, CalorimeterHit> entry2 : hitSeedMap.entrySet()) { - if (entry2.getKey() == entry2.getValue()) { - if (seedEnergyTot.get(entry2.getKey()) < clusterEnergyThreshold) { - // Not clustered for not passing cuts - rejectedHitList.add(entry2.getKey()); - } - - else { - - // FIXME: All of the following should be converted to use the BaseCluster API. --JM - - // New cluster - HPSEcalClusterIC cluster = new HPSEcalClusterIC(entry2.getKey()); - cluster.setType(this.getClusterTypeEncoding()); - clusterList.add(cluster); - // Loop over hits belonging to seeds - for (Map.Entry<CalorimeterHit, CalorimeterHit> entry3 : hitSeedMap.entrySet()) { - if (entry3.getValue() == entry2.getValue()) { - if (rejectedHitList.contains(entry2.getValue())) { - rejectedHitList.add(entry3.getKey()); - } else { - // Add hit to cluster - cluster.addHit(entry3.getKey()); - } - } - } - - for (Map.Entry<CalorimeterHit, List<CalorimeterHit>> entry4 : commonHits.entrySet()) { - if (entry4.getValue().contains(entry2.getKey())) { - // Add shared hits for energy distribution between clusters - cluster.addSharedHit(entry4.getKey()); - // fixes bug for SIO Writer? - cluster.addHit(entry4.getKey()); - } - } - - // Input uncorrected cluster energies - if (seedEnergyTot.values().size() > 0) { - cluster.setEnergy(seedEnergyTot.get(entry2.getKey())); - cluster.setUncorrectedEnergy(seedEnergyTot.get(entry2.getKey())); - } - - // Input uncorrected cluster positions. - cluster.setRawPosition(rawSeedPosition.get(entry2.getKey())); - - }// End checking thresholds and write out. - } - } // End cluster loop - // System.out.println("Number of clusters: "+clusterList.size()); - } // End event output loop. - return clusterList; - } - +*/ + private static class EnergyComparator implements Comparator<CalorimeterHit> { /** * Compares the first hit with respect to the second. This method will compare hits first by @@ -548,10 +504,8 @@ // Perform the energy comparison. The higher energy hit // will be ordered first. if (e[0] < e[1]) { - // FIXME: This should return -1 instead. return 1; } else if (e[0] > e[1]) { - // FIXME: This should return 1. return -1; }