Author: mccaky Date: Wed Oct 29 22:34:27 2014 New Revision: 1337 Log: Updated Moller trigger driver with prescaling and proper trigger cut values. Added preliminary hardware diagnostic plots to primary trigger driver. Modified: java/trunk/ecal-readout-sim/src/main/java/org/hps/readout/ecal/FADCPrimaryTriggerDriver.java java/trunk/ecal-readout-sim/src/main/java/org/hps/readout/ecal/MollerTriggerDriver.java Modified: java/trunk/ecal-readout-sim/src/main/java/org/hps/readout/ecal/FADCPrimaryTriggerDriver.java ============================================================================= --- java/trunk/ecal-readout-sim/src/main/java/org/hps/readout/ecal/FADCPrimaryTriggerDriver.java (original) +++ java/trunk/ecal-readout-sim/src/main/java/org/hps/readout/ecal/FADCPrimaryTriggerDriver.java Wed Oct 29 22:34:27 2014 @@ -21,7 +21,8 @@ * The code for generating trigger pairs and handling the coincidence * window comes from <code>FADCTriggerDriver</code>. * - * @author Kyle McCarty + * @author Kyle McCarty <[log in to unmask]> + * @author Sho Uemura <[log in to unmask]> * @see FADCTriggerDriver */ public class FADCPrimaryTriggerDriver extends TriggerDriver { @@ -46,7 +47,7 @@ private int pairCoincidence = 2; // Maximum allowed time difference between clusters. (4 ns clock-cycles) private double energySlopeParamF = 0.005500; // A parameter value used for the energy slope calculation. private double originX = 1393.0 * Math.tan(0.03052); // ECal mid-plane, defined by photon beam position (30.52 mrad) at ECal face (z=1393 mm) - private int backgroundLevel = -1; // Automatically sets the cuts to achieve a predetermined background rate. + private int backgroundLevel = -1; // Automatically sets the cuts to achieve a predetermined background rate. // ================================================================== // ==== Driver Internal Variables =================================== @@ -94,7 +95,16 @@ IHistogram2D clusterDistributionSingle = aida.histogram2D("Trigger Plots :: Cluster Seed Distribution (Passed Single Cuts)", 46, -23, 23, 11, -5.5, 5.5); IHistogram2D clusterDistributionAll = aida.histogram2D("Trigger Plots :: Cluster Seed Distribution (Passed All Cuts)", 46, -23, 23, 11, -5.5, 5.5); - IHistogram1D hotCrystalEnergy = aida.histogram1D("Trigger Plots :: Hot Crystal Energy Distribution", 176, 0.0, 2.2); + // ================================================================== + // ==== Hardware Diagnostic Variables =============================== + // ================================================================== + IHistogram2D diagClusters = aida.histogram2D("Diagnostic Plots :: Cluster Seed Distribution", 46, -23, 23, 11, -5.5, 5.5); + IHistogram1D diagHitCount = aida.histogram1D("Diagnostic Plots :: Cluster Hit Count Distribution", 9, 1, 10); + IHistogram1D diagTotalEnergy = aida.histogram1D("Diagnostic Plots :: Cluster Total Energy Distribution", 176, 0.0, 2.2); + // TODO: Implement cluster latency plot. + + private boolean verbose = false; + /** * Prints out the results of the trigger at the end of the run. @@ -118,6 +128,19 @@ System.out.printf("%n"); System.out.printf("\tTrigger Count :: %d%n", numTriggers); + // Print the trigger cuts. + System.out.printf("%nCut Values:%n"); + System.out.printf("\tSeed Energy Low :: %.2f%n", seedEnergyLow); + System.out.printf("\tSeed Energy High :: %.2f%n", seedEnergyHigh); + System.out.printf("\tCluster Energy Low :: %.2f%n", clusterEnergyLow); + System.out.printf("\tCluster Energy High :: %.2f%n", clusterEnergyHigh); + System.out.printf("\tCluster Hit Count :: %d%n", minHitCount); + System.out.printf("\tPair Energy Sum Low :: %.2f%n", energySumLow); + System.out.printf("\tPair Energy Sum High :: %.2f%n", energySumHigh); + System.out.printf("\tPair Energy Difference :: %.2f%n", energyDifferenceHigh); + System.out.printf("\tPair Energy Slope :: %.2f%n", energySlopeLow); + System.out.printf("\tPair Coplanarity :: %.2f%n", coplanarityHigh); + // Run the superclass method. super.endOfData(); } @@ -151,10 +174,9 @@ int ix = cluster.getSeedHit().getIdentifierFieldValue("ix"); int iy = cluster.getSeedHit().getIdentifierFieldValue("iy"); - // If the cluster is in the "hot" region, write out its - // energy to a special plot. - if((iy == 1 || iy == -1) && (ix == -1 || ix == 1 || ix == 2)) { - hotCrystalEnergy.fill(clusterEnergy, 1); + // VERBOSE :: Note that a cluster is being processed. + if(verbose) { + System.out.printf("%nProcessing cluster at (% 2d, % 2d)%n", ix, iy); } // Correct for "hole" on the x-axis for plotting. @@ -174,8 +196,18 @@ clusterDistribution100.fill(ix, iy, 1); } + // Populate the diagnostic plots. + diagClusters.fill(ix, iy, 1); + diagTotalEnergy.fill(clusterEnergy, 1); + diagHitCount.fill(hitCount, 1); + // ==== Seed Hit Energy Cut ==================================== // ============================================================= + // VERBOSE :: Print the seed energy comparison check. + if(verbose) { + System.out.printf("\tSeed Energy Cut :: %.3f < %.3f < %.3f --> %b%n", seedEnergyLow, seedEnergy, seedEnergyHigh, clusterSeedEnergyCut(cluster)); + } + // If the cluster fails the cut, skip to the next cluster. if(!clusterSeedEnergyCut(cluster)) { continue clusterLoop; } @@ -184,6 +216,11 @@ // ==== Cluster Hit Count Cut ================================== // ============================================================= + // VERBOSE :: Print the hit count comparison check. + if(verbose) { + System.out.printf("\tHit Count Cut :: %d >= %d --> %b%n", hitCount, minHitCount, clusterHitCountCut(cluster)); + } + // If the cluster fails the cut, skip to the next cluster. if(!clusterHitCountCut(cluster)) { continue clusterLoop; } @@ -192,6 +229,11 @@ // ==== Cluster Total Energy Cut =============================== // ============================================================= + // VERBOSE :: Print the cluster energy comparison check. + if(verbose) { + System.out.printf("\tCluster Energy Cut :: %.3f < %.3f < %.3f --> %b%n", clusterEnergyLow, clusterEnergy, clusterEnergyHigh, clusterTotalEnergyCut(cluster)); + } + // If the cluster fails the cut, skip to the next cluster. if(!clusterTotalEnergyCut(cluster)) { continue clusterLoop; } @@ -661,7 +703,7 @@ private void setBackgroundCuts(int backgroundLevel) { // Make sure that the background level is valid. - if(backgroundLevel < 1 || backgroundLevel > 10) { + if(backgroundLevel < 0 || backgroundLevel > 10) { throw new RuntimeException(String.format("Trigger cuts are undefined for background level %d.", backgroundLevel)); } @@ -761,6 +803,17 @@ energySlopeLow = 0.5; coplanarityHigh = 65; minHitCount = 2; + } else if(backgroundLevel == 0) { + seedEnergyLow = 0.100; + seedEnergyHigh = 6.6; + clusterEnergyLow = 0.100; + clusterEnergyHigh = 1.500; + energySumLow = 0.000; + energySumHigh = 1.900; + energyDifferenceHigh = 2.200; + energySlopeLow = 1.10; + coplanarityHigh = 35; + minHitCount = 1; } } Modified: java/trunk/ecal-readout-sim/src/main/java/org/hps/readout/ecal/MollerTriggerDriver.java ============================================================================= --- java/trunk/ecal-readout-sim/src/main/java/org/hps/readout/ecal/MollerTriggerDriver.java (original) +++ java/trunk/ecal-readout-sim/src/main/java/org/hps/readout/ecal/MollerTriggerDriver.java Wed Oct 29 22:34:27 2014 @@ -30,7 +30,7 @@ * supports a verbose mode where it will output more details with every * event to help with diagnostics. * - * @author Kyle McCarty + * @author Kyle McCarty <[log in to unmask]> */ public class MollerTriggerDriver extends TriggerDriver { @@ -55,7 +55,10 @@ } @Override - public void process(EventHeader event) { super.process(event); } + public void process(EventHeader event) { + // Run the superclass process event. + super.process(event); + } @Override public void startOfData() { @@ -74,20 +77,39 @@ // Initialize the seed distribution diagnostic plots. clusterDistribution = aida.histogram2D("Trigger Plots :: Cluster Seed Distribution", 46, -23, 23, 11, -5.5, 5.5); aClusterDistribution = aida.histogram2D("Trigger Plots :: Cluster Seed Distribution (Passed All Cuts)", 46, -23, 23, 11, -5.5, 5.5); + clusterDistribution100 = aida.histogram2D("Trigger Plots :: Cluster Seed Distribution (Over 100 MeV)", 46, -23, 23, 11, -5.5, 5.5); // Initialize the seed percentage of cluster energy. seedPercent = aida.histogram1D("Analysis Plots :: Seed Percentage of Total Energy", 400, 0.0, 1.0); + // Initialize the momentum angle plot. + momentumAngle = aida.histogram2D("Trigger Plots :: Particle Momentum Distribution (t = 0)", 500, -0.01, 0.06, 500, -0.04, 0.04); + aMomentumAngle = aida.histogram2D("Trigger Plots :: Particle Momentum Distribution (t = 0, Passed All Cuts)", 500, -0.01, 0.06, 500, -0.04, 0.04); + // Add the allowed seed crystal positions to the seed set. - // y = +/- 1, x = -11 -> -15 - for(int ix = -15; ix <= -11; ix++) { - allowedSeedSet.add(new Point(ix, 1)); - allowedSeedSet.add(new Point(ix, -1)); - } // y = +/- 2, x = -9 -> -15 - for(int ix = -15; ix <= -9; ix++) { - allowedSeedSet.add(new Point(ix, 2)); - allowedSeedSet.add(new Point(ix, -2)); - } + if(useVersionOne) { + // Add the allowed seed crystal positions to the seed set. + // y = +/- 1, x = -11 -> -15 + for(int ix = -15; ix <= -11; ix++) { + allowedSeedSet.add(new Point(ix, 1)); + allowedSeedSet.add(new Point(ix, -1)); + } // y = +/- 2, x = -9 -> -15 + for(int ix = -15; ix <= -9; ix++) { + allowedSeedSet.add(new Point(ix, 2)); + allowedSeedSet.add(new Point(ix, -2)); + } + } + else { + // y = +/- 1, x = -11 -> -13 + for(int ix = -13; ix <= -11; ix++) { + allowedSeedSet.add(new Point(ix, 1)); + allowedSeedSet.add(new Point(ix, -1)); + } // y = +/- 2, x = -10 -> -14 + for(int ix = -14; ix <= -10; ix++) { + allowedSeedSet.add(new Point(ix, 2)); + allowedSeedSet.add(new Point(ix, -2)); + } + } } @Override @@ -139,6 +161,7 @@ clusterTotalEnergy.fill(cluster.getEnergy()); clusterSeedEnergy.fill(cluster.getSeedHit().getCorrectedEnergy()); clusterDistribution.fill(ix > 0 ? ix - 1 : ix, iy, 1); + if(cluster.getSeedHit().getCorrectedEnergy() > 0.100) { clusterDistribution100.fill(ix > 0 ? ix - 1 : ix, iy, 1); } // VERBOSE :: Output the single cluster trigger thresholds. if(verbose) { @@ -178,20 +201,31 @@ // Require that the cluster pass each of the cuts in // order to qualify for a trigger. if(totalEnergyCut && seedEnergyCut && hitCountCut && positionCut) { - // Add the clusters to the cut histograms. - aClusterHitCount.fill(cluster.getCalorimeterHits().size()); - aClusterTotalEnergy.fill(cluster.getEnergy()); - aClusterSeedEnergy.fill(cluster.getSeedHit().getCorrectedEnergy()); - aClusterDistribution.fill(ix > 0 ? ix - 1 : ix, iy, 1); - - // Increment the trigger count. - triggers++; - - // VERBOSE :: Indicate that a trigger occurred. - if(verbose) { System.out.printf("\tTriggered!%n%n"); } - - // Return a trigger. - return true; + // Increment the number of events that have passed + // the cuts. + passedEvents++; + + // If the number of passed events exceeds the prescaling + // threshold, throw a trigger. + if(passedEvents >= prescale) { + // Reset the number of passed events. + passedEvents = 0; + + // Add the clusters to the cut histograms. + aClusterHitCount.fill(cluster.getCalorimeterHits().size()); + aClusterTotalEnergy.fill(cluster.getEnergy()); + aClusterSeedEnergy.fill(cluster.getSeedHit().getCorrectedEnergy()); + aClusterDistribution.fill(ix > 0 ? ix - 1 : ix, iy, 1); + + // Increment the trigger count. + triggers++; + + // VERBOSE :: Indicate that a trigger occurred. + if(verbose) { System.out.printf("\tTriggered!%n%n"); } + + // Return a trigger. + return true; + } } } @@ -331,6 +365,16 @@ } /** + * Sets the number of events that must pass the trigger before a + * proper trigger flag is thrown. + * @param prescale - The number of passing events before a trigger + * will be thrown. + */ + public void setPrescale(int prescale) { + this.prescale = prescale; + } + + /** * Toggles whether the driver will output its actions to the console * during run time or not. * @param verbose - <code>true</code> indicates that the console @@ -339,6 +383,18 @@ public void setVerbose(boolean verbose) { this.verbose = verbose; } + + /** + * Toggles whether the more inclusive acceptance region version 1 + * is used, or the slightly smaller and more exclusive acceptance + * region version 2. + * @param useVersionOne - <code>true</code> indicates that version + * 1 of the acceptance region should be used and <code>false</code> + * that version 2 should be used. + */ + public void setUseVersionOne(boolean useVersionOne) { + this.useVersionOne = useVersionOne; + } // ================================================================== // ==== AIDA Plots ================================================== @@ -351,86 +407,85 @@ IHistogram1D clusterHitCount; IHistogram1D clusterSeedEnergy; IHistogram1D clusterTotalEnergy; - IHistogram1D pClusterHitCount; - IHistogram2D pClusterDistribution; - IHistogram1D pClusterSeedEnergy; - IHistogram1D pClusterTotalEnergy; IHistogram1D seedPercent; + IHistogram2D momentumAngle; + IHistogram2D aMomentumAngle; + IHistogram2D clusterDistribution100; // ================================================================== // ==== Variables =================================================== // ================================================================== /** - * <b>aida</b><br/><br/> - * <code>private AIDA <b>aida</b></code><br/><br/> * Factory for generating histograms. */ private AIDA aida = AIDA.defaultInstance(); /** - * <b>allowedSeedSet</b><br/><br/> - * <code>private Set<Point> <b>allowedSeedSet</b></code><br/><br/> * Contains all allowed seed crystal indices. Seeds outside of this * set will be rejected and not produce a trigger. */ private Set<Point> allowedSeedSet = new HashSet<Point>(); /** - * <b>clusterCollectionName</b><br/><br/> - * <code>private String <b>clusterCollectionName</b></code><br/><br/> * The name of the LCIO collection containing <code>HPSEcalCluster * </code> objects. */ private String clusterCollectionName = "EcalClusters"; /** - * <b>clusterHitCountThreshold</b><br/><br/> - * <code>private int <b>clusterHitCountThreshold</b></code><br/><br/> * Defines the minimum number of hits required for a cluster to * be used in triggering. */ - private int clusterHitCountThreshold = 0; - - /** - * <b>clusterSeedEnergyThresholdLow</b><br/><br/> - * <code>private double <b>clusterSeedEnergyThresholdLow</b></code><br/><br/> + private int clusterHitCountThreshold = 5; + + /** * Defines the threshold for the cluster seed energy under which * a cluster will be rejected. */ - private double clusterSeedEnergyThresholdLow = 0.00; - - /** - * <b>clusterSeedEnergyThresholdHigh</b><br/><br/> - * <code>private double <b>clusterSeedEnergyThresholdHigh</b></code><br/><br/> + private double clusterSeedEnergyThresholdLow = 0.300; + + /** * Defines the threshold for the cluster seed energy above which * a cluster will be rejected. */ - private double clusterSeedEnergyThresholdHigh = Double.MAX_VALUE; - - /** - * <b>clusterTotalEnergyThresholdLow</b><br/><br/> - * <code>private double <b>clusterTotalEnergyThreshold</b></code><br/><br/> + private double clusterSeedEnergyThresholdHigh = 0.700; + + /** * Defines the threshold for the total cluster energy under which * a cluster will be rejected. */ - private double clusterTotalEnergyThresholdLow = 0.0; - - /** - * <b>clusterTotalEnergyThresholdHigh</b><br/><br/> - * <code>private double <b>clusterTotalEnergyThresholdHigh</b></code><br/><br/> + private double clusterTotalEnergyThresholdLow = 0.600; + + /** * Defines the threshold for the total cluster energy above which * a cluster will be rejected. */ - private double clusterTotalEnergyThresholdHigh = Double.MAX_VALUE; - - /** - * <b>verbose</b><br/><br/> - * <code>private boolean <b>verbose</b></code><br/><br/> + private double clusterTotalEnergyThresholdHigh = 0.775; + + /** + * The number of events that have passed the trigger cuts. This is + * used to determine when a trigger should be thrown for prescaling. + */ + private int passedEvents = 0; + + /** + * Indicates how many events must pass the trigger cuts before a + * trigger is thrown. + */ + private int prescale = 100; + + /** * Sets whether the driver outputs its clustering decisions to the * console or not. */ private boolean verbose = false; + + /** + * Indicates whether trigger region version 1 or version 2 should + * be used. + */ + private boolean useVersionOne = false; private int triggers = 0; // Track the number of triggers. private int allClusters = 0; // Track the number of clusters processed.