Author: [log in to unmask]
Date: Mon May 11 19:09:31 2015
New Revision: 2957
Log:
Added driver for performing trigger cuts on a readout file, such as data output from a run. This driver assumes that each event contains a wide range (at least 100 ns or so) of clusters and thusly does not need to retain clusters across events for proper management of the time coincidence cut.
Added:
java/trunk/ecal-readout-sim/src/main/java/org/hps/readout/ecal/ReadoutTrigger.java
Added: java/trunk/ecal-readout-sim/src/main/java/org/hps/readout/ecal/ReadoutTrigger.java
=============================================================================
--- java/trunk/ecal-readout-sim/src/main/java/org/hps/readout/ecal/ReadoutTrigger.java (added)
+++ java/trunk/ecal-readout-sim/src/main/java/org/hps/readout/ecal/ReadoutTrigger.java Mon May 11 19:09:31 2015
@@ -0,0 +1,312 @@
+package org.hps.readout.ecal;
+
+import hep.aida.IHistogram1D;
+import hep.aida.IHistogram2D;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.hps.recon.ecal.triggerbank.TriggerModule;
+import org.lcsim.event.Cluster;
+import org.lcsim.event.EventHeader;
+import org.lcsim.util.Driver;
+import org.lcsim.util.aida.AIDA;
+
+/**
+ * Creates distributions from <code>Cluster</code> objects. This is
+ * intended to be used on clusters reconstructed from FADC data from
+ * the hardware readout and should not be used for Monte Carlo.
+ *
+ * @author Kyle McCarty <[log in to unmask]>
+ */
+public class ReadoutTrigger extends Driver {
+ // Define settable parameters.
+ private double energySlopeParamF = 0.0055;
+ private String clusterCollectionName = "EcalClusters";
+
+ // Define internal variables.
+ private TriggerModule trigger = new TriggerModule();
+
+ // Define output plots.
+ private static final int NO_CUTS = 0;
+ private static final int ALL_CUTS = 1;
+ private AIDA aida = AIDA.defaultInstance();
+ private IHistogram1D[] clusterSeedEnergy;
+ private IHistogram1D[] clusterHitCount;
+ private IHistogram1D[] clusterTotalEnergy;
+ private IHistogram1D[] clusterTime;
+ private IHistogram1D[] pairEnergySum;
+ private IHistogram1D[] pairEnergyDifference;
+ private IHistogram1D[] pairCoplanarity;
+ private IHistogram1D[] pairEnergySlope;
+ private IHistogram1D[] pairTime;
+ private IHistogram1D[] pairCoincidence;
+ private IHistogram2D[] clusterDistribution;
+ private IHistogram2D[] pairEnergySum2D;
+ private IHistogram2D[] pairEnergySlope2D;
+
+ /**
+ * Instantiates cluster plots.
+ */
+ @Override
+ public void startOfData() {
+ // Define plot type names.
+ String[] plotType = new String[2];
+ plotType[NO_CUTS] = "";
+ plotType[ALL_CUTS] = " (Passed All Cuts)";
+
+ // Define plot type directories.
+ String[] plotDir = new String[2];
+ plotDir[NO_CUTS] = "NoCuts/";
+ plotDir[ALL_CUTS] = "PassedAll/";
+
+ // Instantiate the plots.
+ for(int i = 0; i < 2; i++) {
+ System.out.println(plotDir[i] + "Cluster Seed Energy" + plotType[i]);
+ clusterSeedEnergy[i] = aida.histogram1D(plotDir[i] + "Cluster Seed Energy" + plotType[i], 88, 0.0, 1.1);
+ clusterSeedEnergy[i].annotation().addItem("xAxisLabel", "Seed Energy (GeV)");
+ clusterSeedEnergy[i].annotation().addItem("yAxisLabel", "Count");
+
+ clusterHitCount[i] = aida.histogram1D(plotDir[i] + "Cluster Hit Count" + plotType[i], 9, 0.5, 9.5);
+ clusterHitCount[i].annotation().addItem("xAxisLabel", "Hit Count");
+ clusterHitCount[i].annotation().addItem("yAxisLabel", "Count");
+
+ clusterTotalEnergy[i] = aida.histogram1D(plotDir[i] + "Cluster Total Energy" + plotType[i], 88, 0.0, 1.1);
+ clusterTotalEnergy[i].annotation().addItem("xAxisLabel", "Cluster Energy (GeV)");
+ clusterTotalEnergy[i].annotation().addItem("yAxisLabel", "Count");
+
+ clusterTime[i] = aida.histogram1D(plotDir[i] + "Cluster Time" + plotType[i], 100, 0.0, 400);
+ clusterTime[i].annotation().addItem("xAxisLabel", "Cluster Time (ns)");
+ clusterTime[i].annotation().addItem("yAxisLabel", "Count");
+
+ pairEnergySum[i] = aida.histogram1D(plotDir[i] + "Pair Energy Sum" + plotType[i], 88, 0.0, 2.2);
+ pairEnergySum[i].annotation().addItem("xAxisLabel", "Energy Sum (GeV)");
+ pairEnergySum[i].annotation().addItem("yAxisLabel", "Count");
+
+ pairEnergyDifference[i] = aida.histogram1D(plotDir[i] + "Pair Energy Difference" + plotType[i], 88, 0.0, 1.1);
+ pairEnergyDifference[i].annotation().addItem("xAxisLabel", "Energy Difference (GeV)");
+ pairEnergyDifference[i].annotation().addItem("yAxisLabel", "Count");
+
+ pairCoplanarity[i] = aida.histogram1D(plotDir[i] + "Pair Coplanarity" + plotType[i], 180, 0.0, 180.0);
+ pairCoplanarity[i].annotation().addItem("xAxisLabel", "Coplanarity Angle (Degrees)");
+ pairCoplanarity[i].annotation().addItem("yAxisLabel", "Count");
+
+ pairEnergySlope[i] = aida.histogram1D(plotDir[i] + "Pair Energy Slope" + plotType[i], 200, 0.0, 4.0);
+ pairEnergySlope[i].annotation().addItem("xAxisLabel", "Energy Slope (GeV)");
+ pairEnergySlope[i].annotation().addItem("yAxisLabel", "Count");
+
+ pairTime[i] = aida.histogram1D(plotDir[i] + "Pair Time" + plotType[i], 100, 0.0, 400);
+ pairTime[i].annotation().addItem("xAxisLabel", "Cluster Time (ns)");
+ pairTime[i].annotation().addItem("yAxisLabel", "Count");
+
+ pairCoincidence[i] = aida.histogram1D(plotDir[i] + "Pair Coincidence" + plotType[i], 8, 0.0, 32);
+ pairCoincidence[i].annotation().addItem("xAxisLabel", "Coincidence Time (ns)");
+ pairCoincidence[i].annotation().addItem("yAxisLabel", "Count");
+
+ clusterDistribution[i] = aida.histogram2D(plotDir[i] + "Cluster Seed Distribution" + plotType[i], 46, -23, 23, 11, -5.5, 5.5);
+ clusterDistribution[i].annotation().addItem("xAxisLabel", "x-Index");
+ clusterDistribution[i].annotation().addItem("yAxisLabel", "y-Index");
+
+ pairEnergySum2D[i] = aida.histogram2D(plotDir[i] + "Pair Energy Sum 2D" + plotType[i], 88, 0.0, 2.2, 88, 0.0, 2.2);
+ pairEnergySum2D[i].annotation().addItem("xAxisLabel", "E1");
+ pairEnergySum2D[i].annotation().addItem("yAxisLabel", "E2");
+
+ pairEnergySlope2D[i] = aida.histogram2D(plotDir[i] + "Pair Energy Slope 2D" + plotType[i], 88, 0.0, 1.1, 200, 0.0, 400);
+ pairEnergySlope2D[i].annotation().addItem("xAxisLabel", "E1");
+ pairEnergySlope2D[i].annotation().addItem("yAxisLabel", "E2");
+ }
+ }
+
+ /**
+ * Produces both uncut and cut distributions from clusters.
+ */
+ @Override
+ public void process(EventHeader event) {
+ // Check for a collection of clusters.
+ if(event.hasCollection(Cluster.class, clusterCollectionName)) {
+ // Get the list of clusters.
+ List<Cluster> clusters = event.get(Cluster.class, clusterCollectionName);
+
+ // Track which clusters have already been plotted.
+ Set<Cluster> plottedClustersUncut = new HashSet<Cluster>(clusters.size());
+ Set<Cluster> plottedClustersCut = new HashSet<Cluster>(clusters.size());
+
+ // Populate a list of cluster pairs.
+ List<Cluster[]> pairs = getClusterPairs(clusters);
+
+ // Process all cluster pairs.
+ pairLoop:
+ for(Cluster[] pair : pairs) {
+ // Get the x and y indices for each cluster in the pair.
+ int[] ix = { pair[0].getCalorimeterHits().get(0).getIdentifierFieldValue("ix"),
+ pair[1].getCalorimeterHits().get(0).getIdentifierFieldValue("ix") };
+ int[] iy = { pair[0].getCalorimeterHits().get(0).getIdentifierFieldValue("iy"),
+ pair[1].getCalorimeterHits().get(0).getIdentifierFieldValue("iy") };
+
+ // Iterate over the clusters in the pair and plot the
+ // cluster singles distributions.
+ for(int clusterIndex = 0; clusterIndex < 2; clusterIndex++) {
+ // Only plot cluster singles distributions for
+ // clusters if they have not already been plotted.
+ // Note that this is needed because the same cluster
+ // can appear across multiple pairs.
+ if(!plottedClustersUncut.contains(pair[clusterIndex])) {
+ clusterSeedEnergy[NO_CUTS].fill(TriggerModule.getValueClusterSeedEnergy(pair[clusterIndex]));
+ clusterTotalEnergy[NO_CUTS].fill(TriggerModule.getValueClusterTotalEnergy(pair[clusterIndex]));
+ clusterHitCount[NO_CUTS].fill(TriggerModule.getValueClusterHitCount(pair[clusterIndex]));
+ clusterDistribution[NO_CUTS].fill(ix[clusterIndex], iy[clusterIndex]);
+ clusterTime[NO_CUTS].fill(pair[clusterIndex].getCalorimeterHits().get(0).getTime());
+ plottedClustersUncut.add(pair[clusterIndex]);
+ }
+ }
+
+ // Plot the cluster pair distributions.
+ pairEnergySum[NO_CUTS].fill(TriggerModule.getValueEnergySum(pair));
+ pairEnergyDifference[NO_CUTS].fill(TriggerModule.getValueEnergyDifference(pair));
+ pairEnergySlope[NO_CUTS].fill(TriggerModule.getValueEnergySlope(pair, energySlopeParamF));
+ pairCoplanarity[NO_CUTS].fill(TriggerModule.getValueCoplanarity(pair));
+ pairTime[NO_CUTS].fill(pair[1].getCalorimeterHits().get(0).getTime());
+ pairCoincidence[NO_CUTS].fill(TriggerModule.getValueTimeCoincidence(pair));
+ pairEnergySum2D[NO_CUTS].fill(pair[0].getEnergy(), pair[1].getEnergy());
+ if(pair[0].getEnergy() < pair[1].getEnergy()) {
+ pairEnergySlope2D[NO_CUTS].fill(pair[0].getEnergy(), TriggerModule.getClusterDistance(pair[0]));
+ } else {
+ pairEnergySlope2D[NO_CUTS].fill(pair[1].getEnergy(), TriggerModule.getClusterDistance(pair[1]));
+ }
+
+ // Perform the cluster singles cuts.
+ if(!(trigger.clusterHitCountCut(pair[0]) && trigger.clusterHitCountCut(pair[1]))) {
+ continue pairLoop;
+ } if(!(trigger.clusterTotalEnergyCut(pair[0]) && trigger.clusterTotalEnergyCut(pair[1]))) {
+ continue pairLoop;
+ } if(!(trigger.clusterSeedEnergyCut(pair[0]) && trigger.clusterSeedEnergyCut(pair[1]))) {
+ continue pairLoop;
+ }
+
+ // Perform the cluster pair cuts.
+ if(!trigger.pairCoplanarityCut(pair)) {
+ continue pairLoop;
+ } if(!trigger.pairEnergyDifferenceCut(pair)) {
+ continue pairLoop;
+ } if(!trigger.pairEnergySlopeCut(pair)) {
+ continue pairLoop;
+ } if(!trigger.pairEnergySumCut(pair)) {
+ continue pairLoop;
+ }
+
+ // Iterate over the clusters in the pair and plot the
+ // cluster singles distributions.
+ for(int clusterIndex = 0; clusterIndex < 2; clusterIndex++) {
+ // Only plot cluster singles distributions for
+ // clusters if they have not already been plotted.
+ // Note that this is needed because the same cluster
+ // can appear across multiple pairs.
+ if(!plottedClustersCut.contains(pair[clusterIndex])) {
+ clusterSeedEnergy[ALL_CUTS].fill(TriggerModule.getValueClusterSeedEnergy(pair[clusterIndex]));
+ clusterTotalEnergy[ALL_CUTS].fill(TriggerModule.getValueClusterTotalEnergy(pair[clusterIndex]));
+ clusterHitCount[ALL_CUTS].fill(TriggerModule.getValueClusterHitCount(pair[clusterIndex]));
+ clusterDistribution[ALL_CUTS].fill(ix[clusterIndex], iy[clusterIndex]);
+ clusterTime[ALL_CUTS].fill(pair[clusterIndex].getCalorimeterHits().get(0).getTime());
+ plottedClustersCut.add(pair[clusterIndex]);
+ }
+ }
+
+ // Plot the cluster pair distributions.
+ pairEnergySum[ALL_CUTS].fill(TriggerModule.getValueEnergySum(pair));
+ pairEnergyDifference[ALL_CUTS].fill(TriggerModule.getValueEnergyDifference(pair));
+ pairEnergySlope[ALL_CUTS].fill(TriggerModule.getValueEnergySlope(pair, energySlopeParamF));
+ pairCoplanarity[ALL_CUTS].fill(TriggerModule.getValueCoplanarity(pair));
+ pairTime[ALL_CUTS].fill(pair[1].getCalorimeterHits().get(0).getTime());
+ pairCoincidence[ALL_CUTS].fill(TriggerModule.getValueTimeCoincidence(pair));
+ pairEnergySum2D[ALL_CUTS].fill(pair[0].getEnergy(), pair[1].getEnergy());
+ if(pair[0].getEnergy() < pair[1].getEnergy()) {
+ pairEnergySlope2D[ALL_CUTS].fill(pair[0].getEnergy(), TriggerModule.getClusterDistance(pair[0]));
+ } else {
+ pairEnergySlope2D[ALL_CUTS].fill(pair[1].getEnergy(), TriggerModule.getClusterDistance(pair[1]));
+ }
+
+ }
+ }
+ }
+
+ public void setClusterCollectionName(String clusterCollectionName) {
+ this.clusterCollectionName = clusterCollectionName;
+ }
+
+ public void setEnergySlopeParamF(double energySlopeParamF) {
+ this.energySlopeParamF = energySlopeParamF;
+ trigger.setCutValue(TriggerModule.PAIR_ENERGY_SLOPE_F, energySlopeParamF);
+ }
+
+ public void setSeedEnergyLow(double value) {
+ trigger.setCutValue(TriggerModule.CLUSTER_SEED_ENERGY_LOW, value);
+ }
+
+ public void setClusterEnergyLow(double value) {
+ trigger.setCutValue(TriggerModule.CLUSTER_TOTAL_ENERGY_LOW, value);
+ }
+
+ public void setClusterEnergyHigh(double value) {
+ trigger.setCutValue(TriggerModule.CLUSTER_TOTAL_ENERGY_HIGH, value);
+ }
+
+ public void setHitCountLow(double value) {
+ trigger.setCutValue(TriggerModule.CLUSTER_HIT_COUNT_LOW, value);
+ }
+
+ public void setEnergySumLow(double value) {
+ trigger.setCutValue(TriggerModule.PAIR_ENERGY_SUM_LOW, value);
+ }
+
+ public void setEnergySumHigh(double value) {
+ trigger.setCutValue(TriggerModule.PAIR_ENERGY_SUM_HIGH, value);
+ }
+
+ public void setEnergyDifferenceHigh(double value) {
+ trigger.setCutValue(TriggerModule.PAIR_ENERGY_DIFFERENCE_HIGH, value);
+ }
+
+ public void setEnergySlopeLow(double value) {
+ trigger.setCutValue(TriggerModule.PAIR_ENERGY_SLOPE_LOW, value);
+ }
+
+ public void setCoplanarityHigh(double value) {
+ trigger.setCutValue(TriggerModule.PAIR_COPLANARITY_HIGH, value);
+ }
+
+ public void setTimeCoincidence(double value) {
+ trigger.setCutValue(TriggerModule.PAIR_TIME_COINCIDENCE, value);
+ }
+
+ /**
+ * Creates all top/bottom pairs from the event data.
+ * @param clusters - A list of clusters from which to form pairs.
+ * @return Returns a <code>List</code> collection that contains
+ * <code>Cluster</code> arrays of size two.
+ */
+ private List<Cluster[]> getClusterPairs(List<Cluster> clusters) {
+ // Separate the clusters into top nad bottom clusters.
+ List<Cluster> topList = new ArrayList<Cluster>();
+ List<Cluster> botList = new ArrayList<Cluster>();
+ for(Cluster cluster : clusters) {
+ if(cluster.getCalorimeterHits().get(0).getIdentifierFieldValue("iy") > 0) {
+ topList.add(cluster);
+ } else {
+ botList.add(cluster);
+ }
+ }
+
+ // Create all possible top/bottom cluster pairs.
+ List<Cluster[]> pairList = new ArrayList<Cluster[]>();
+ for(Cluster topCluster : topList) {
+ for(Cluster botCluster : botList) {
+ pairList.add(new Cluster[] { topCluster, botCluster });
+ }
+ }
+
+ // Return the pairs.
+ return pairList;
+ }
+}
|