Author: [log in to unmask]
Date: Tue Dec 6 19:29:12 2016
New Revision: 4601
Log:
Updated trigger diagnostics.
Modified:
java/trunk/analysis/src/main/java/org/hps/analysis/trigger/ClusterDiagnosticDriver.java
java/trunk/analysis/src/main/java/org/hps/analysis/trigger/DataTriggerSimDriver.java
java/trunk/analysis/src/main/java/org/hps/analysis/trigger/TriggerDiagnosticDriver.java
java/trunk/analysis/src/main/java/org/hps/analysis/trigger/util/TriggerDiagnosticUtil.java
Modified: java/trunk/analysis/src/main/java/org/hps/analysis/trigger/ClusterDiagnosticDriver.java
=============================================================================
--- java/trunk/analysis/src/main/java/org/hps/analysis/trigger/ClusterDiagnosticDriver.java (original)
+++ java/trunk/analysis/src/main/java/org/hps/analysis/trigger/ClusterDiagnosticDriver.java Tue Dec 6 19:29:12 2016
@@ -1,11 +1,14 @@
package org.hps.analysis.trigger;
+import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import org.hps.analysis.trigger.util.ClusterMatchedPair;
@@ -80,6 +83,21 @@
* not verify because no two clusters were found with a matching
* seed position. */
private int failedMatchPosition = 0;
+ /** Indicates the number of failed cluster events that have a seed
+ * hit near the seed energy threshold. */
+ private int failedNearSeedThreshold = 0;
+ /** Indicates the number of failed cluster events that occur within
+ * the dead time window of the event start and also have a t = 0
+ * cluster with a hit on the same channel. */
+ private int failedPositionDeadtime = 0;
+ /** Indicates the number of failed cluster events that may have
+ * lost a hit due to deadtime issues. */
+ private int failedHitCountDeadtime = 0;
+ /** Indicates the number of failed cluster events where the energies
+ * were identical, but hit count differed. */
+ private int failedNegativeEnergyHit = 0;
+ // TODO: Add description.
+ private int failedCloneBug = 0;
// === Local window values. =========================================================
// ==================================================================================
@@ -181,12 +199,77 @@
private static final String matchedClustersEnergyDiffPlot = MODULE_HEADER + "Matched Clusters Energy Difference Distribution";
/** Plots the difference in hit count between matched clusters. */
private static final String matchedClustersHitDiffPlot = MODULE_HEADER + "Matched Clusters Hit Count Difference Distribution";
+ /** Plots the difference in energy between matched clusters which failed due to energy. */
+ private static final String failedEnergyEnergyDiffPlot = MODULE_HEADER + "Energy-Match Failure Energy Difference Distribution";
+ /** Plots the difference in energy between matched clusters which failed due to hit count. */
+ private static final String failedHitCountEnergyDiffPlot = MODULE_HEADER + "Hit Count-Match Failure Energy Difference Distribution";
+ /** Plots the difference in hit count between matched clusters which failed due to energy. */
+ private static final String failedEnergyHitDiffPlot = MODULE_HEADER + "Energy-Match Failure Hit Count Difference Distribution";
+ /** Plots the difference in hit count between matched clusters which failed due to hit count. */
+ private static final String failedHitCountHitDiffPlot = MODULE_HEADER + "Hit Count-Match Failure Hit Count Difference Distribution";
/** Plots the 2D difference in energy between matched clusters. */
private static final String matchedClusters2DEnergyDiffPlot = MODULE_HEADER + "Matched Clusters 2D Energy Difference Distribution";
/** Plots the 2D difference in hit count between matched clusters. */
private static final String matchedClusters2DHitDiffPlot = MODULE_HEADER + "Matched Clusters 2D Hit Count Difference Distribution";
-
+ /** Plots the efficiency over the course of the run. **/
private static final String runtimeEfficiencyPlot = MODULE_HEADER + "Matched Clusters Run Time Efficiency";
+
+ private static final Set<Point> getClusterHitIndices(Cluster cluster) {
+ // Store the possible hits in a set. The seed hit is excluded.
+ Set<Point> hitSet = new HashSet<Point>(8);
+
+ // Iterate over the cluster hits and add any existing positions
+ // to the hit set.
+ for(CalorimeterHit hit : cluster.getCalorimeterHits()) {
+ hitSet.add(new Point(hit.getIdentifierFieldValue("ix"), hit.getIdentifierFieldValue("iy")));
+ }
+
+ // Return the set of constituent hits.
+ return hitSet;
+ }
+
+ private static final Set<Point> getClusterPossibleHitIndices(Cluster cluster) {
+ // Get the cluster seed position.
+ int ix = TriggerModule.getClusterXIndex(cluster);
+ int iy = TriggerModule.getClusterYIndex(cluster);
+
+ // Store the possible hits in a set. The seed hit is excluded.
+ Set<Point> hitSet = new HashSet<Point>(8);
+
+ // Get all eight adjacent hits.
+ xLoop:
+ for(int xMod = -1; xMod <= 2; xMod++) {
+ // Get the modified x position.
+ int hix = ix + xMod;
+
+ // Values where |x| > 23 do not exist.
+ if(Math.abs(hix) > 23) { continue xLoop; }
+
+ // Values of x = 0 do not exist. x = 1 and x = -1 are to
+ // be treated as adjacent.
+ if(hix == 0) { hix = ix == -1 ? 1 : -1; }
+
+ yLoop:
+ for(int yMod = -1; yMod <= 2; yMod++) {
+ // Get the modified y position.
+ int hiy = iy + yMod;
+
+ // Values of y = 0 and |y| > 5 do not exist.
+ if(hiy == 0 || Math.abs(hiy) > 5) { continue yLoop; }
+
+ // Add the potential hit position to the set.
+ hitSet.add(new Point(hix, hiy));
+ }
+ }
+
+ // Return the set of possible hit positions.
+ return hitSet;
+ }
+
+ private static final double getRatioError(double num, double sigmaNum, double den, double sigmaDen) {
+ double ratio = num / den;
+ return Math.abs(ratio) * Math.sqrt(Math.pow(sigmaNum / num, 2) + Math.pow(sigmaDen / den, 2));
+ }
/**
* Prints out final run verification statistics and generates
@@ -202,20 +285,108 @@
AIDA.defaultInstance().histogramFactory().divide(matchedClustersEnergyEfficiencyPlot,
AIDA.defaultInstance().histogram1D(matchedClustersEnergyPlot), AIDA.defaultInstance().histogram1D(softwareClustersEnergyPlot));
+ // Calculate errors for efficiencies and failure rates.
+ double sigmaSimCount = Math.sqrt(goodSimulatedClusterCount);
+ double sigmaMatched = Math.sqrt(matchedClusters);
+ double sigmaFailedPosition = Math.sqrt(failedMatchPosition);
+ double sigmaFailedTime = Math.sqrt(failedMatchTime);
+ double sigmaFailedHitCount = Math.sqrt(failedMatchHitCount);
+ double sigmaFailedEnergy = Math.sqrt(failedMatchEnergy);
+ double sigmaFailedNearSeed = Math.sqrt(failedNearSeedThreshold);
+ double sigmaFailedDeadtime = Math.sqrt(failedPositionDeadtime);
+ double sigmaFailedNegative = Math.sqrt(failedNegativeEnergyHit);
+ double sigmaFailedHCDeadtime = Math.sqrt(failedHitCountDeadtime);
+ double sigmaFailedCloneBug = Math.sqrt(failedCloneBug);
+
+ // Get the maximum number of digits needed to display the
+ // largest of the counts. This should always be either the
+ // total number hardware or simulated clusters.
+ String countDisp = "%" + TriggerDiagnosticUtil.getDigits(Math.max(simulatedClusterCount, goodSimulatedClusterCount)) + "d";
+
// Print the global run statistics for cluster verification.
System.out.println("Cluster Verification:");
- System.out.printf("\tSimulated Clusters :: %d%n", simulatedClusterCount);
- System.out.printf("\tUnclipped Sim Clusters :: %d%n", goodSimulatedClusterCount);
- System.out.printf("\tHardware Clusters :: %d%n", hardwareClusterCount);
- System.out.printf("\tClusters Matched :: %d%n", matchedClusters);
- System.out.printf("\tFailed (Position) :: %d%n", failedMatchPosition);
- System.out.printf("\tFailed (Time) :: %d%n", failedMatchTime);
- System.out.printf("\tFailed (Energy) :: %d%n", failedMatchEnergy);
- System.out.printf("\tFailed (Hit Count) :: %d%n", failedMatchHitCount);
- if(simulatedClusterCount == 0) {
- System.out.printf("\tCluster Efficiency :: N/A%n");
+ System.out.printf("\tSimulated Clusters :: " + countDisp + "%n", simulatedClusterCount);
+ System.out.printf("\tUnclipped Sim Clusters :: " + countDisp + "%n", goodSimulatedClusterCount);
+ System.out.printf("\tHardware Clusters :: " + countDisp + "%n", hardwareClusterCount);
+ System.out.printf("\tClusters Matched :: " + countDisp + "%n", matchedClusters);
+
+ System.out.printf("\tFailed (Position) :: " + countDisp, failedMatchPosition);
+ if(failedMatchPosition == 0 || goodSimulatedClusterCount == 0) {
+ System.out.printf(" (%7.3f%% ± %7.3f%%)%n", 0.0, 0.0);
} else {
- System.out.printf("\tCluster Efficiency :: %7.3f%%%n", 100.0 * matchedClusters / goodSimulatedClusterCount);
+ System.out.printf(" (%7.3f%% ± %7.3f%%)%n", 100.0 * failedMatchPosition / goodSimulatedClusterCount,
+ getRatioError(failedMatchPosition, sigmaFailedPosition, goodSimulatedClusterCount, sigmaSimCount));
+ }
+
+ System.out.printf("\t> Failed (Deadtime) :: " + countDisp, failedPositionDeadtime);
+ if(failedPositionDeadtime == 0 || goodSimulatedClusterCount == 0) {
+ System.out.printf(" (%7.3f%% ± %7.3f%%)%n", 0.0, 0.0);
+ } else {
+ System.out.printf(" (%7.3f%% ± %7.3f%%)%n", 100.0 * failedPositionDeadtime / goodSimulatedClusterCount,
+ getRatioError(failedPositionDeadtime, sigmaFailedDeadtime, goodSimulatedClusterCount, sigmaSimCount));
+ }
+
+ System.out.printf("\t> Failed (Clone Bug) :: " + countDisp, failedCloneBug);
+ if(failedPositionDeadtime == 0 || goodSimulatedClusterCount == 0) {
+ System.out.printf(" (%7.3f%% ± %7.3f%%)%n", 0.0, 0.0);
+ } else {
+ System.out.printf(" (%7.3f%% ± %7.3f%%)%n", 100.0 * failedCloneBug / goodSimulatedClusterCount,
+ getRatioError(failedCloneBug, sigmaFailedCloneBug, goodSimulatedClusterCount, sigmaSimCount));
+ }
+
+ System.out.printf("\t> Failed (Seed Thresh) :: " + countDisp, failedNearSeedThreshold);
+ if(failedNearSeedThreshold == 0 || goodSimulatedClusterCount == 0) {
+ System.out.printf(" (%7.3f%% ± %7.3f%%)%n", 0.0, 0.0);
+ } else {
+ System.out.printf(" (%7.3f%% ± %7.3f%%)%n", 100.0 * failedNearSeedThreshold / goodSimulatedClusterCount,
+ getRatioError(failedNearSeedThreshold, sigmaFailedNearSeed, goodSimulatedClusterCount, sigmaSimCount));
+ }
+
+ System.out.printf("\tFailed (Time) :: " + countDisp, failedMatchTime);
+ if(failedMatchTime == 0 || goodSimulatedClusterCount == 0) {
+ System.out.printf(" (%7.3f%% ± %7.3f%%)%n", 0.0, 0.0);
+ } else {
+ System.out.printf(" (%7.3f%% ± %7.3f%%)%n", 100.0 * failedMatchTime / goodSimulatedClusterCount,
+ getRatioError(failedMatchTime, sigmaFailedTime, goodSimulatedClusterCount, sigmaSimCount));
+ }
+
+ System.out.printf("\tFailed (Hit Count) :: " + countDisp, failedMatchHitCount);
+ if(failedMatchHitCount == 0 || goodSimulatedClusterCount == 0) {
+ System.out.printf(" (%7.3f%% ± %7.3f%%)%n", 0.0, 0.0);
+ } else {
+ System.out.printf(" (%7.3f%% ± %7.3f%%)%n", 100.0 * failedMatchHitCount / goodSimulatedClusterCount,
+ getRatioError(failedMatchHitCount, sigmaFailedHitCount, goodSimulatedClusterCount, sigmaSimCount));
+ }
+
+ System.out.printf("\t> Failed (Deadtime) :: " + countDisp, failedHitCountDeadtime);
+ if(failedPositionDeadtime == 0 || goodSimulatedClusterCount == 0) {
+ System.out.printf(" (%7.3f%% ± %7.3f%%)%n", 0.0, 0.0);
+ } else {
+ System.out.printf(" (%7.3f%% ± %7.3f%%)%n", 100.0 * failedHitCountDeadtime / goodSimulatedClusterCount,
+ getRatioError(failedHitCountDeadtime, sigmaFailedHCDeadtime, goodSimulatedClusterCount, sigmaSimCount));
+ }
+
+ System.out.printf("\t> Failed (Negative En) :: " + countDisp, failedNegativeEnergyHit);
+ if(failedNegativeEnergyHit == 0 || goodSimulatedClusterCount == 0) {
+ System.out.printf(" (%7.3f%% ± %7.3f%%)%n", 0.0, 0.0);
+ } else {
+ System.out.printf(" (%7.3f%% ± %7.3f%%)%n", 100.0 * failedNegativeEnergyHit / goodSimulatedClusterCount,
+ getRatioError(failedNegativeEnergyHit, sigmaFailedNegative, goodSimulatedClusterCount, sigmaSimCount));
+ }
+
+ System.out.printf("\tFailed (Energy) :: " + countDisp, failedMatchEnergy);
+ if(failedMatchEnergy == 0 || goodSimulatedClusterCount == 0) {
+ System.out.printf(" (%7.3f%% ± %7.3f%%)%n", 0.0, 0.0);
+ } else {
+ System.out.printf(" (%7.3f%% ± %7.3f%%)%n", 100.0 * failedMatchEnergy / goodSimulatedClusterCount,
+ getRatioError(failedMatchEnergy, sigmaFailedEnergy, goodSimulatedClusterCount, sigmaSimCount));
+ }
+
+ if(simulatedClusterCount == 0 || goodSimulatedClusterCount == 0) {
+ System.out.printf("\tCluster Efficiency :: %7.3f%% ± %7.3f%%%n", 0.0, 0.0);
+ } else {
+ System.out.printf("\tCluster Efficiency :: %7.3f%% ± %7.3f%%%n", 100.0 * matchedClusters / goodSimulatedClusterCount,
+ 100.0 * getRatioError(matchedClusters, sigmaMatched, goodSimulatedClusterCount, sigmaSimCount));
}
// Create and populate the efficiency over time plot.
@@ -303,7 +474,7 @@
if(hits.isEmpty()) { logger.println("\tNone"); }
// Output the simulated clusters from the software.
- logger.printNewLine(2);
+ logger.printNewLine(1);
logger.println("Software Clusters:");
for(Cluster cluster : simulatedClusters) {
logger.printf("\t%s%n", TriggerDiagnosticUtil.clusterToString(cluster));
@@ -314,7 +485,7 @@
if(simulatedClusters.isEmpty()) { logger.println("\tNone"); }
// Output the reported clusters from the hardware.
- logger.printNewLine(2);
+ logger.printNewLine(1);
logger.println("Hardware Clusters:");
for(SSPCluster cluster : hardwareClusters) {
logger.printf("\t%s%n", TriggerDiagnosticUtil.clusterToString(cluster));
@@ -337,7 +508,6 @@
// Iterate through each simulated cluster and keep only the
// clusters safe from pulse-clipping.
List<Cluster> goodSimulatedClusters = new ArrayList<Cluster>();
- logger.printNewLine(2);
logger.println("Simulated Cluster Pulse-Clipping Check:");
for(Cluster cluster : simulatedClusters) {
boolean isSafe = TriggerDiagnosticUtil.isVerifiable(cluster, nsa, nsb, windowWidth);
@@ -374,8 +544,161 @@
if(pair.isMatch()) { matchedClusters++; }
if(pair.isTimeFailState()) { failedMatchTime++; }
if(pair.isEnergyFailState()) { failedMatchEnergy++; }
- if(pair.isHitCountFailState()) { failedMatchHitCount++; }
- if(pair.isPositionFailState()) { failedMatchPosition++; }
+ if(pair.isHitCountFailState()) {
+ // Increment the general hit count fail state count.
+ failedMatchHitCount++;
+
+ // If the simulated cluster is different in hit count,
+ // but has the same energy, it is likely caused by a
+ // near-zero energy hit that registered as negative to
+ // the simulation, and was consequently ignored.
+ if(Math.abs(TriggerModule.getValueClusterTotalEnergy(pair.getReconstructedCluster())
+ - TriggerModule.getValueClusterTotalEnergy(pair.getSSPCluster())) <= energyVerificationThreshold) {
+ failedNegativeEnergyHit++;
+ }
+
+ // Deadtime can also cause a failure in hit count. A
+ // simple check of this is to see if either the cluster
+ // occurred within 32 ns of the event start, or if any
+ // channel that would be included by the cluster for
+ // which there is no hit has a hit within this time
+ // frame that is also within 32 ns of the cluster.
+ else {
+ // Check for the case that the cluster itself is
+ // within the deadtime uncertainty region.
+ if(TriggerModule.getClusterTime(pair.getReconstructedCluster()) < 32) {
+ failedHitCountDeadtime++;
+ }
+
+ // Otherwise, determine which hits are not included
+ // in the cluster and see if a hit exists which could
+ // produce a deadtime error in that channel.
+ else {
+ // Get a list of the hits that could exist in
+ // the cluster.
+ Set<Point> actualHits = getClusterHitIndices(pair.getReconstructedCluster());
+ Set<Point> possibleHits = getClusterPossibleHitIndices(pair.getReconstructedCluster());
+
+ // Iterate over each hit and look for one that
+ // could produce a deadtime error.
+ hitLoop:
+ for(CalorimeterHit hit : hits) {
+ // The hit is required to be within the
+ // first 32 of the event.
+ if(hit.getTime() >= 32) { continue hitLoop; }
+
+ // The hit must be within 32 ns of the
+ // cluster time and also occur before
+ // the cluster time or simultaneously.
+ if((TriggerModule.getClusterTime(pair.getReconstructedCluster()) < hit.getTime())
+ || (TriggerModule.getClusterTime(pair.getReconstructedCluster()) - hit.getTime() >= 32)) {
+ continue hitLoop;
+ }
+
+ // The hit must occur on a channel that
+ // falls within the 3x3 cluster range, and
+ // there must not already be a hit on that
+ // channel in the cluster.
+ Point ixy = new Point(hit.getIdentifierFieldValue("ix"), hit.getIdentifierFieldValue("iy"));
+ if(possibleHits.contains(ixy) && !actualHits.contains(ixy)) {
+ failedHitCountDeadtime++;
+ break hitLoop;
+ }
+ }
+ }
+ }
+ }
+ if(pair.isPositionFailState()) {
+ // Increment the general position fail state count.
+ failedMatchPosition++;
+
+ // If the simulated cluster is within the allowed energy
+ // range of the seed energy threshold, it is likely to
+ // have failed because of energy differences between the
+ // hardware and the simulation. Track these.
+ double energyDifference = Math.abs(TriggerModule.getValueClusterTotalEnergy(pair.getReconstructedCluster())
+ - ConfigurationManager.getInstance().getGTPConfig().getSeedEnergyCutConfig().getLowerBound());
+ if(energyDifference <= energyVerificationThreshold) {
+ failedNearSeedThreshold++;
+ }
+
+ // If the simulated cluster has a seed hit which is
+ // less than 32 ns in time, it is possible that it was
+ // missed by the hardware due to a dead time issue.
+ // This is most likely to the case for any cluster where
+ // there exists a t = 0 cluster with a hit on the same
+ // channel. Check for this case and track the instances
+ // where it occurred.
+ else if(TriggerModule.getClusterTime(pair.getReconstructedCluster()) < 32) {
+ // Get the cluster channel.
+ int ix = TriggerModule.getClusterXIndex(pair.getReconstructedCluster());
+ int iy = TriggerModule.getClusterYIndex(pair.getReconstructedCluster());
+
+ // Check for a t = 0 cluster with a hit on the same
+ // channel.
+ deadtimeLoop:
+ for(Cluster cluster : simulatedClusters) {
+ if(TriggerModule.getClusterTime(cluster) == 0) {
+ if(TriggerModule.getClusterXIndex(cluster) == ix && TriggerModule.getClusterYIndex(cluster) == iy) {
+ failedPositionDeadtime++;
+ break deadtimeLoop;
+ }
+ }
+ }
+ }
+
+ // Check for more complicated fail state causes.
+ else {
+ // The "clone bug" occurs when the hardware reports
+ // a fake cluster at the same position as an existing
+ // cluster, but at the same time as a cluster which
+ // should exist, but is missed.
+ // Check if more than SSP cluster exists at the
+ // same position as another cluster, and one of them
+ // matches in time.
+ double time = TriggerModule.getClusterTime(pair.getReconstructedCluster());
+ Map<Point, Integer> countMap = new HashMap<Point, Integer>();
+ Map<Point, SSPCluster> timeMap = new HashMap<Point, SSPCluster>();
+ for(SSPCluster sspCluster : hardwareClusters) {
+ Point ixy = new Point(TriggerModule.getClusterXIndex(sspCluster), TriggerModule.getClusterYIndex(sspCluster));
+ if(countMap.containsKey(ixy)) { countMap.put(ixy, countMap.get(ixy) + 1); }
+ else { countMap.put(ixy, new Integer(1)); }
+ if(TriggerModule.getClusterTime(sspCluster) == time) { timeMap.put(ixy, sspCluster); }
+ }
+
+ // Check each cluster position. If there are more
+ // clusters than one at that position, and one of
+ // them has the same time as the position failure
+ // cluster, the clone bug could have occurred.
+ unmatchedLoop:
+ for(Map.Entry<Point, Integer> entry : countMap.entrySet()) {
+ // Check that at least two clusters exist at
+ // this position and that one of them matched
+ // the fail state cluster in time.
+ if(entry.getValue() >= 2 && timeMap.containsKey(entry.getKey())) {
+ // Get the matching cluster.
+ SSPCluster cloneTestCluster = timeMap.get(entry.getKey());
+
+ // The cluster that matched the fail state
+ // cluster in time must be itself unmatched.
+ for(ClusterMatchedPair match : matchedPairs) {
+ // If the cluster matching the fail state
+ // cluster in time is matched, this is
+ // not the clone bug.
+ if(match.getSSPCluster() == cloneTestCluster) {
+ continue unmatchedLoop;
+ }
+ }
+
+ // If not match was found for the cluster
+ // that matches the fail state cluster in
+ // time, this is probably the clone bug.
+ failedCloneBug++;
+ break unmatchedLoop;
+ }
+ }
+ }
+ }
}
// Increment the statistics.
@@ -504,12 +827,16 @@
// The hit count comparison plots are binned by individual hit
// and run from 0 to 9 hits.
+ AIDA.defaultInstance().histogram1D(failedEnergyHitDiffPlot, 10, -0.5, 9.5);
+ AIDA.defaultInstance().histogram1D(failedHitCountHitDiffPlot, 10, -0.5, 9.5);
AIDA.defaultInstance().histogram1D(matchedClustersHitDiffPlot, 10, -0.5, 9.5);
AIDA.defaultInstance().histogram2D(matchedClusters2DHitDiffPlot, 10, -0.5, 9.5, 10, -0.5, 9.5);
// The energy difference plots are binned on a reduced energy
// scale, as hits typically are close in energy.
- AIDA.defaultInstance().histogram1D(matchedClustersEnergyDiffPlot, 200, 0, 0.100);
+ AIDA.defaultInstance().histogram1D(failedEnergyEnergyDiffPlot, 67, 0, 0.201);
+ AIDA.defaultInstance().histogram1D(failedHitCountEnergyDiffPlot, 67, 0, 0.201);
+ AIDA.defaultInstance().histogram1D(matchedClustersEnergyDiffPlot, 67, 0, 0.201);
AIDA.defaultInstance().histogram2D(matchedClusters2DEnergyDiffPlot, 34, 0, 0.102, 34, 0, 0.102);
}
@@ -579,6 +906,29 @@
// Return the simulated cluster collection.
return simulatedClusters;
+ }
+
+ /**
+ * Performs the verification check for cluster hit counts.
+ * @param simCluster - The simulated cluster to check.
+ * @param sspCluster - The hardware cluster to check.
+ * @param hitWindow - The range by which hit counts are allowed to
+ * differ between the clusters.
+ * @return Returns <code>true</code> if the hit counts match to
+ * within threshold and <code>false</code> otherwise.
+ */
+ private static final boolean isHitMatch(Cluster simCluster, SSPCluster sspCluster, int hitWindow) {
+ // Get the hit counts for both clusters.
+ double simHitCount = TriggerModule.getClusterHitCount(simCluster);
+ double sspHitCount = TriggerModule.getClusterHitCount(sspCluster);
+
+ // The hardware does not store cluster hit counts as higher than
+ // 7, so if the software hit count is 8 or 9, we must treat it
+ // as 7 instead to match this behavior.
+ if(simHitCount > 7) { simHitCount = 7; }
+
+ // Perform the hit count check.
+ return (sspHitCount >= simHitCount - hitWindow && sspHitCount <= simHitCount + hitWindow);
}
/**
@@ -685,16 +1035,17 @@
// While time and position matched clusters are considered
// to be the same cluster, the clusters must have similar
// energies and hit counts to be properly verified. First
- // perform the energy check. The hardware cluster must
- // match the simulated cluster energy to within a given
+ // perform the hit count check. The hardware cluster must
+ // match the simulated cluster hit count to within a given
// bound.
- if(TriggerModule.getValueClusterTotalEnergy(hardwareCluster) >= TriggerModule.getValueClusterTotalEnergy(simCluster) - energyWindow
- && TriggerModule.getValueClusterTotalEnergy(hardwareCluster) <= TriggerModule.getValueClusterTotalEnergy(simCluster) + energyWindow) {
+ //if(TriggerModule.getClusterHitCount(hardwareCluster) >= TriggerModule.getClusterHitCount(simCluster) - hitWindow &&
+ // TriggerModule.getClusterHitCount(hardwareCluster) <= TriggerModule.getClusterHitCount(simCluster) + hitWindow) {
+ if(isHitMatch(simCluster, hardwareCluster, hitWindow)) {
// Next, check that the hardware cluster matches the
- // simulated cluster in hit count to within a given
+ // simulated cluster in energy to within a given
// bound.
- if(TriggerModule.getClusterHitCount(hardwareCluster) >= TriggerModule.getClusterHitCount(simCluster) - hitWindow &&
- TriggerModule.getClusterHitCount(hardwareCluster) <= TriggerModule.getClusterHitCount(simCluster) + hitWindow) {
+ if(TriggerModule.getValueClusterTotalEnergy(hardwareCluster) >= TriggerModule.getValueClusterTotalEnergy(simCluster) - energyWindow
+ && TriggerModule.getValueClusterTotalEnergy(hardwareCluster) <= TriggerModule.getValueClusterTotalEnergy(simCluster) + energyWindow) {
// The cluster is a match.
pairList.add(new ClusterMatchedPair(simCluster, hardwareCluster, ClusterMatchedPair.CLUSTER_STATE_MATCHED));
logger.printf("[ %7s; %9s ]%n", "success", "matched");
@@ -708,22 +1059,30 @@
continue softwareLoop;
}
- // If the hit counts of the two clusters are not
+ // If the energies of the two clusters are not
// sufficiently close, the clusters fail to verify.
else {
- pairList.add(new ClusterMatchedPair(simCluster, hardwareCluster, ClusterMatchedPair.CLUSTER_STATE_FAIL_HIT_COUNT));
- logger.printf("[ %7s; %9s ]%n", "fail", "hit count");
+ pairList.add(new ClusterMatchedPair(simCluster, hardwareCluster, ClusterMatchedPair.CLUSTER_STATE_FAIL_ENERGY));
+ logger.printf("[ %7s; %9s ]%n", "fail", "energy");
+ AIDA.defaultInstance().histogram1D(failedEnergyHitDiffPlot).fill(Math.abs(TriggerModule.getClusterHitCount(simCluster)
+ - TriggerModule.getClusterHitCount(hardwareCluster)));
+ AIDA.defaultInstance().histogram1D(failedEnergyEnergyDiffPlot).fill(Math.abs(TriggerModule.getValueClusterTotalEnergy(simCluster)
+ - TriggerModule.getValueClusterTotalEnergy(hardwareCluster)));
continue softwareLoop;
- } // End hit count check.
+ } // End energy check.
}
- // If the energies of the two clusters are not
+ // If the hit counts of the two clusters are not
// sufficiently close, the clusters fail to verify.
else {
- pairList.add(new ClusterMatchedPair(simCluster, hardwareCluster, ClusterMatchedPair.CLUSTER_STATE_FAIL_ENERGY));
- logger.printf("[ %7s; %9s ]%n", "fail", "energy");
+ pairList.add(new ClusterMatchedPair(simCluster, hardwareCluster, ClusterMatchedPair.CLUSTER_STATE_FAIL_HIT_COUNT));
+ logger.printf("[ %7s; %9s ]%n", "fail", "hit count");
+ AIDA.defaultInstance().histogram1D(failedHitCountHitDiffPlot).fill(Math.abs(TriggerModule.getClusterHitCount(simCluster)
+ - TriggerModule.getClusterHitCount(hardwareCluster)));
+ AIDA.defaultInstance().histogram1D(failedHitCountEnergyDiffPlot).fill(Math.abs(TriggerModule.getValueClusterTotalEnergy(simCluster)
+ - TriggerModule.getValueClusterTotalEnergy(hardwareCluster)));
continue softwareLoop;
- } // End energy check.
+ } // End hit count check.
} // End hardware loop.
// This point may only be reached if a cluster failed to
Modified: java/trunk/analysis/src/main/java/org/hps/analysis/trigger/DataTriggerSimDriver.java
=============================================================================
--- java/trunk/analysis/src/main/java/org/hps/analysis/trigger/DataTriggerSimDriver.java (original)
+++ java/trunk/analysis/src/main/java/org/hps/analysis/trigger/DataTriggerSimDriver.java Tue Dec 6 19:29:12 2016
@@ -214,9 +214,6 @@
pairCutsEnabled[i][3 + ENERGY_SLOPE] = pairs[i].getEnergySlopeCutConfig().isEnabled();
pairCutsEnabled[i][3 + COPLANARITY] = pairs[i].getCoplanarityCutConfig().isEnabled();
}
-
- // Output the DAQ settings.
- logSettings();
}
});
}
@@ -519,6 +516,7 @@
TriggerModule.getClusterTime(reconPair[1]));
}
+ // Perform each trigger cut.
passClusterLow = pairsTrigger[triggerIndex].clusterTotalEnergyCutLow(reconPair[0])
&& pairsTrigger[triggerIndex].clusterTotalEnergyCutLow(reconPair[1]);
passClusterHigh = pairsTrigger[triggerIndex].clusterTotalEnergyCutHigh(reconPair[0])
@@ -725,64 +723,4 @@
// trigger type.
return Double.MIN_VALUE;
}
-
- /**
- * Outputs all of the verification parameters currently in use by
- * the software. A warning will be issued if the values for NSA and
- * NSB, along with the FADC window, preclude clusters from being
- * verified.
- */
- private void logSettings() {
- // Print a DAQ configuration settings header.
- System.out.println();
- System.out.println();
- System.out.println("======================================================================");
- System.out.println("=== DAQ Configuration Settings =======================================");
- System.out.println("======================================================================");
-
- // Output window settings.
- System.out.println("FADC Timing Window Settings");
- System.out.printf("\tNSB :: %3d ns%n", nsb);
- System.out.printf("\tNSA :: %3d ns%n", nsa);
- System.out.printf("\tFADC Window :: %3d ns%n", windowWidth);
-
- // Output the singles trigger settings.
- for(int i = 0; i < 2; i++) {
- // Print the settings.
- System.out.printf("Singles Trigger %d Settings%23s[%5b]%n", (i + 1), "", singlesTriggerEnabled[i]);
- System.out.printf("\tCluster Energy Low :: %.3f GeV [%5b]%n",
- singlesTrigger[i].getCutValue(TriggerModule.CLUSTER_TOTAL_ENERGY_LOW), singlesCutsEnabled[i][0]);
- System.out.printf("\tCluster Energy High :: %.3f GeV [%5b]%n",
- singlesTrigger[i].getCutValue(TriggerModule.CLUSTER_TOTAL_ENERGY_HIGH), singlesCutsEnabled[i][1]);
- System.out.printf("\tCluster Hit Count :: %.0f hit(s) [%5b]%n",
- singlesTrigger[i].getCutValue(TriggerModule.CLUSTER_HIT_COUNT_LOW), singlesCutsEnabled[i][2]);
- System.out.println();
- }
-
- // Output the pair trigger settings.
- for(int i = 0; i < 2; i++) {
- System.out.printf("Pairs Trigger %d Settings%25s[%5b]%n", (i + 1), "", pairTriggerEnabled[i]);
- System.out.printf("\tCluster Energy Low :: %.3f GeV [%5b]%n",
- pairsTrigger[i].getCutValue(TriggerModule.CLUSTER_TOTAL_ENERGY_LOW), pairCutsEnabled[i][0]);
- System.out.printf("\tCluster Energy High :: %.3f GeV [%5b]%n",
- pairsTrigger[i].getCutValue(TriggerModule.CLUSTER_TOTAL_ENERGY_HIGH), pairCutsEnabled[i][1]);
- System.out.printf("\tCluster Hit Count :: %.0f hit(s) [%5b]%n",
- pairsTrigger[i].getCutValue(TriggerModule.CLUSTER_HIT_COUNT_LOW), pairCutsEnabled[i][2]);
- System.out.printf("\tPair Energy Sum Low :: %.3f GeV [%5b]%n",
- pairsTrigger[i].getCutValue(TriggerModule.PAIR_ENERGY_SUM_LOW), pairCutsEnabled[i][3]);
- System.out.printf("\tPair Energy Sum High :: %.3f GeV [%5b]%n",
- pairsTrigger[i].getCutValue(TriggerModule.PAIR_ENERGY_SUM_HIGH), pairCutsEnabled[i][3]);
- System.out.printf("\tPair Energy Difference :: %.3f GeV [%5b]%n",
- pairsTrigger[i].getCutValue(TriggerModule.PAIR_ENERGY_DIFFERENCE_HIGH), pairCutsEnabled[i][4]);
- System.out.printf("\tPair Energy Slope :: %.3f GeV [%5b]%n",
- pairsTrigger[i].getCutValue(TriggerModule.PAIR_ENERGY_SLOPE_LOW), pairCutsEnabled[i][5]);
- System.out.printf("\tPair Energy Slope F :: %.4f GeV / mm%n",
- pairsTrigger[i].getCutValue(TriggerModule.PAIR_ENERGY_SLOPE_F));
- System.out.printf("\tPair Coplanarity :: %3.0f Degrees [%5b]%n",
- pairsTrigger[i].getCutValue(TriggerModule.PAIR_COPLANARITY_HIGH), pairCutsEnabled[i][6]);
- System.out.printf("\tPair Time Coincidence :: %2.0f ns [%5b]%n",
- pairsTrigger[i].getCutValue(TriggerModule.PAIR_TIME_COINCIDENCE), true);
- System.out.println();
- }
- }
}
Modified: java/trunk/analysis/src/main/java/org/hps/analysis/trigger/TriggerDiagnosticDriver.java
=============================================================================
--- java/trunk/analysis/src/main/java/org/hps/analysis/trigger/TriggerDiagnosticDriver.java (original)
+++ java/trunk/analysis/src/main/java/org/hps/analysis/trigger/TriggerDiagnosticDriver.java Tue Dec 6 19:29:12 2016
@@ -89,6 +89,50 @@
* array index corresponding to the trigger of the same trigger number. */
private TriggerModule[] pairTrigger = new TriggerModule[2];
+ // === Plotting variables. ==========================================================
+ // ==================================================================================
+ /** Defines the basic directory structure for all plots used in the
+ * class. This is instantiated in <code>startOfData</code>. */
+ private String moduleHeader;
+ /** Stores the number of bins used by the efficiency plots for each
+ * conventional trigger cut. Array index corresponds to the ordinal
+ * value of the <code>CutType</code> enumerable for all values for
+ * which <code>isSpecial()</code> is false. Note that this variable
+ * is defined as a function of the variable arrays <code>xMax</code>
+ * and <code>binSize</code> during <code>startOfData()</code>. */
+ private int[] bins = new int[8];
+ /** Stores the x-axis maximum used by the efficiency plots for each
+ * conventional trigger cut. Array index corresponds to the ordinal
+ * value of the <code>CutType</code> enumerable for all values for
+ * which <code>isSpecial()</code> is false. */
+ private double[] xMax = {
+ 2.200, // Seed energy, xMax = 2.2 GeV
+ 2.200, // Cluster energy, xMax = 2.2 GeV
+ 9.5, // Hit count, xMax = 9.5 hits
+ 2.200, // Energy sum, xMax = 2.2 GeV
+ 2.200, // Energy difference, xMax = 2.2 GeV
+ 4.000, // Energy slope, xMax = 4.0 GeV
+ 180.0, // Coplanarity, xMax = 180 degrees
+ 30.0 // Time coincidence, xMax = 30 ns
+ };
+ /** Store the size of a bin used by the efficiency plots for each
+ * conventional trigger cut. Array index corresponds to the ordinal
+ * value of the <code>CutType</code> enumerable for all values for
+ * which <code>isSpecial()</code> is false. */
+ private double[] binSize = {
+ 0.050, // Seed energy, binSize = 50 MeV
+ 0.050, // Cluster energy, binSize = 50 MeV
+ 1, // Hit count, binSize = 1 hit
+ 0.050, // Energy sum, binSize = 50 MeV
+ 0.050, // Energy difference, binSize = 50 MeV
+ 0.050, // Energy slope, binSize = 50 MeV
+ 5, // Coplanarity, binSize = 5 degrees
+ 4 // Time coincidence, binSize = 2 ns
+ };
+ /** Stores a list of all trigger types that are used for plotting
+ * efficiency plots. This is filled in <code>startOfData</code>. */
+ private List<TriggerType> triggerTypes = new ArrayList<TriggerType>(TriggerType.values().length + 1);
+
// === Trigger matching statistics. =================================================
// ==================================================================================
private static final int SOURCE_SIM_CLUSTER = 0;
@@ -158,13 +202,13 @@
// ==================================================================================
/** The number of samples before a pulse-crossing event to integrate
* during hit formation. Used to determine the risk of pulse-clipping. */
- private int nsb = 20;
+ private int nsb = -1;
/** The number of samples after a pulse-crossing event to integrate
* during hit formation. Used to determine the risk of pulse-clipping. */
- private int nsa = 100;
+ private int nsa = -1;
/** The width of the pulse integration window used to form hits.
* Used to determine the risk of pulse-clipping. */
- private int windowWidth = 200;
+ private int windowWidth = -1;
/** The number of hits that must be present in event in order for
* it to be ignored as a "noise event." */
private int noiseEventThreshold = 50;
@@ -203,6 +247,94 @@
*/
private List<Pair<Long, int[][]>> efficiencyPlotEntries = new ArrayList<Pair<Long, int[][]>>();
+ /**
+ * Enumerable <code>CutType</code> represents a type of cut which
+ * against which trigger efficiency may be plotted. It also provides
+ * mechanisms by which a human-readable name may be acquired and
+ * also whether or not the cut is a real trigger cut, or a special
+ * cut used for plotting efficiency only.
+ *
+ * @author Kyle McCarty <[log in to unmask]>
+ */
+ private enum CutType {
+ CLUSTER_SEED_ENERGY("Cluster Seed Energy", true, false), CLUSTER_TOTAL_ENERGY("Cluster Total Energy", true, false),
+ CLUSTER_HIT_COUNT("Cluster Hit Count", true, false), PAIR_ENERGY_SUM("Pair Energy Sum", false, true),
+ PAIR_ENERGY_DIFF("Pair Energy Difference", false, true), PAIR_ENERGY_SLOPE("Pair Energy Slope", false, true),
+ PAIR_COPLANARITY("Pair Coplanarity", false, true), PAIR_TIME_COINCIDENCE("Pair Time Coincidence", false, true),
+ PAIR_LOW_ENERGY("Pair Lower Cluster Energy", false, true, true), PAIR_HIGH_ENERGY("Pair Upper Cluster Energy", false, true, true),
+ EVENT_TIME("Event Time", true, true, true);
+
+ private final String name;
+ private final boolean isPair;
+ private final boolean isSpecial;
+ private final boolean isSingles;
+
+ /**
+ * Instantiates a cut. The cut is assumed to be a real trigger
+ * cut, and not a "special cut" included for plotting purposes.
+ * @param name - The name of the cut in a human-readable form.
+ * @param isSingles - Whether or not this is a singles cut.
+ * <code>true</code> means that it is and <code>false</code>
+ * that it is not.
+ * @param isPair - Whether or not this is a pair cut.
+ * <code>true</code> means that it is and <code>false</code>
+ * that it is not.
+ */
+ private CutType(String name, boolean isSingles, boolean isPair) {
+ this.name = name;
+ isSpecial = false;
+ this.isPair = isPair;
+ this.isSingles = isSingles;
+ }
+
+ /**
+ * Instantiates a cut.
+ * @param name - The name of the cut in a human-readable form.
+ * @param isSingles - Whether or not this is a singles cut.
+ * <code>true</code> means that it is and <code>false</code>
+ * that it is not.
+ * @param isPair - Whether or not this is a pair cut.
+ * <code>true</code> means that it is and <code>false</code>
+ * that it is not.
+ * @param isSpecial - Whether or not the cut is a real trigger
+ * cut or not. <code>true</code> indicates that it is a trigger
+ * cut and <code>false</code> that it is not.
+ */
+ private CutType(String name, boolean isSingles, boolean isPair, boolean isSpecial) {
+ this.name = name;
+ this.isPair = isPair;
+ this.isSingles = isSingles;
+ this.isSpecial = isSpecial;
+ }
+
+ /**
+ * Indicates whether this is a singles cut.
+ * @return Returns <code>true</code> to indicate that it is
+ * and <code>false</code> that it is not.
+ */
+ public boolean isSingles() { return isSingles; }
+
+ /**
+ * Indicates whether this is a pair cut.
+ * @return Returns <code>true</code> to indicate that it is
+ * and <code>false</code> that it is not.
+ */
+ public boolean isPair() { return isPair; }
+
+ /**
+ * Indicates whether this is an actual trigger cut or not. Some
+ * "special cuts" are included because they provide useful data
+ * when efficiency is plotted against them, but they are not
+ * properly trigger cuts.
+ * @return Returns whether or not the cut is a real trigger cut
+ * or not. <code>true</code> indicates that it is a trigger cut
+ * and <code>false</code> that it is not.
+ */
+ public boolean isSpecial() { return isSpecial; }
+
+ @Override
+ public String toString() { return name; }
+ }
/**
* Enumerable <code>TriggerType</code> represents the supported
@@ -249,6 +381,15 @@
public boolean isSinglesTrigger() { return (this.equals(SINGLES0) || this.equals(SINGLES1)); }
/**
+ * Indicates whether this trigger type is a pair trigger.
+ * @return Returns <code>true</code> if the trigger is of type
+ * <code>TriggerType.PAIR0</code> or
+ * <code>TriggerType.PAIR1</code>. Otherwise, returns
+ * <code>false</code>.
+ */
+ public boolean isPairTrigger() { return (this.equals(PAIR0) || this.equals(PAIR1)); }
+
+ /**
* Gets the trigger number for this trigger type.
* @return Returns either <code>0</code> or <code>1</code> as
* appropriate for singles and pair trigger types. For cosmic
@@ -270,7 +411,7 @@
int largestValue = max(hardwareTriggerCount[ALL_TRIGGERS], simTriggerCount[SOURCE_SIM_CLUSTER][ALL_TRIGGERS],
simTriggerCount[SOURCE_SSP_CLUSTER][ALL_TRIGGERS], matchedTriggerCount[SOURCE_SIM_CLUSTER][ALL_TRIGGERS],
matchedTriggerCount[SOURCE_SSP_CLUSTER][ALL_TRIGGERS]);
- int maxChars = getDigits(largestValue);
+ int maxChars = TriggerDiagnosticUtil.getDigits(largestValue);
String charDisplay = "%" + maxChars + "d";
// Calculate the efficiencies and determine the display value.
@@ -319,7 +460,7 @@
matchedTriggerCount[SOURCE_SIM_CLUSTER][trigger.ordinal()], simTriggerCount[SOURCE_SSP_CLUSTER][trigger.ordinal()],
matchedTriggerCount[SOURCE_SSP_CLUSTER][trigger.ordinal()]);
}
- int tiMaxChars = getDigits(tiMaxValue);
+ int tiMaxChars = TriggerDiagnosticUtil.getDigits(tiMaxValue);
// Define the column width and column headers for the TI-bit
// specific efficiencies.
@@ -381,7 +522,6 @@
}
// Create and populate the efficiency over time plot.
- final String moduleHeader = "Trigger Diagnostics/Trigger Verification/" + triggerType.toString() + "/";
AIDA.defaultInstance().cloud2D(moduleHeader + "Software Sim Trigger Efficiency", efficiencyPlotEntries.size());
AIDA.defaultInstance().cloud2D(moduleHeader + "Hardware Sim Trigger Efficiency", efficiencyPlotEntries.size());
for(Pair<Long, int[][]> entry : efficiencyPlotEntries) {
@@ -399,6 +539,24 @@
AIDA.defaultInstance().cloud2D(moduleHeader + "Software Sim Trigger Efficiency").fill(time, softwareEfficiency);
} if(!Double.isNaN(hardwareEfficiency)) {
AIDA.defaultInstance().cloud2D(moduleHeader + "Hardware Sim Trigger Efficiency").fill(time, hardwareEfficiency);
+ }
+ }
+
+ // Create the efficiency plots from the observed and verified
+ // trigger plots, as appropriate.
+ for(TriggerType trigger : triggerTypes) {
+ for(CutType cut : CutType.values()) {
+ // Only process plots appropriate to the trigger type.
+ if((triggerType.isSinglesTrigger() && !cut.isSingles()) || (triggerType.isPairTrigger() && !cut.isPair())) {
+ continue;
+ }
+
+ // Define the plot for the current TI-bit and cut.
+ for(int type = SOURCE_SIM_CLUSTER; type <= SOURCE_SSP_CLUSTER; type++) {
+ AIDA.defaultInstance().histogramFactory().divide(getPlotNameEfficiency(cut, trigger, type),
+ AIDA.defaultInstance().histogram1D(getPlotNameVerified(cut, trigger, type)),
+ AIDA.defaultInstance().histogram1D(getPlotNameTotal(cut, trigger, type)));
+ }
}
}
}
@@ -582,6 +740,22 @@
public void actionPerformed(ActionEvent e) {
// Get the DAQ configuration.
DAQConfig daq = ConfigurationManager.getInstance();
+
+ // If the event time plots are not instantiated, do so.
+ if(nsa == -1) {
+ // Calculate the bin count and x-axis maximum.
+ int bins = (daq.getFADCConfig().getWindowWidth() / 4) + 1;
+ int xMax = daq.getFADCConfig().getWindowWidth() + 2;
+
+ // Instantiate the plots for each trigger bit.
+ for(TriggerType trigger : triggerTypes) {
+ for(int type = SOURCE_SIM_CLUSTER; type <= SOURCE_SSP_CLUSTER; type++) {
+ AIDA.defaultInstance().histogram1D(getPlotNameTotal(CutType.EVENT_TIME, trigger, type), bins, -2, xMax);
+ AIDA.defaultInstance().histogram1D(getPlotNameVerified(CutType.EVENT_TIME, trigger, type), bins, -2, xMax);
+ AIDA.defaultInstance().histogram1D(getPlotNameEfficiency(CutType.EVENT_TIME, trigger, type), bins, -2, xMax);
+ }
+ }
+ }
// Load the DAQ settings from the configuration manager.
singlesTrigger[0].loadDAQConfiguration(daq.getSSPConfig().getSingles1Config());
@@ -631,6 +805,72 @@
pairTrigger[1].setCutValue(TriggerModule.PAIR_ENERGY_SLOPE_F, 0.001);
pairTrigger[1].setCutValue(TriggerModule.PAIR_COPLANARITY_HIGH, 180);
pairTrigger[1].setCutValue(TriggerModule.PAIR_TIME_COINCIDENCE, 8);
+
+ // Set the trigger plots module name.
+ moduleHeader = "Trigger Diagnostics/Trigger Verification/" + triggerType.toString() + "/";
+
+ // Instantiate the trigger efficiency plots. Note that the time
+ // coincidence plot is instantiated in the ConfigurationManager
+ // listener, as it needs to know the event readout window size.
+ for(TriggerType trigger : TriggerType.values()) { triggerTypes.add(trigger); }
+ triggerTypes.add(null);
+ for(TriggerType trigger : triggerTypes) {
+ for(CutType cut : CutType.values()) {
+ // Skip "special" plotting cuts. These are defined in
+ // other locations.
+ if(cut.isSpecial()) { continue; }
+
+ // Make sure that the maximum x-axis values for the efficiency
+ // plots are evenly divisible by the bin size.
+ if(Math.floor(1.0 * xMax[cut.ordinal()] / binSize[cut.ordinal()]) != (xMax[cut.ordinal()] / binSize[cut.ordinal()])) {
+ xMax[cut.ordinal()] = Math.ceil(xMax[cut.ordinal()] / binSize[cut.ordinal()]) * binSize[cut.ordinal()];
+ }
+
+ // Define the bin counts for each plot.
+ bins[cut.ordinal()] = (int) Math.ceil(xMax[cut.ordinal()] / binSize[cut.ordinal()]);
+
+ // Only generate plots appropriate to the trigger type.
+ if((triggerType.isSinglesTrigger() && !cut.isSingles()) || (triggerType.isPairTrigger() && !cut.isPair())) {
+ continue;
+ }
+
+ // Define the plot for the current TI-bit and cut.
+ for(int type = SOURCE_SIM_CLUSTER; type <= SOURCE_SSP_CLUSTER; type++) {
+ AIDA.defaultInstance().histogram1D(getPlotNameTotal(cut, trigger, type), bins[cut.ordinal()],
+ 0.0, bins[cut.ordinal()] * binSize[cut.ordinal()]);
+ AIDA.defaultInstance().histogram1D(getPlotNameVerified(cut, trigger, type), bins[cut.ordinal()],
+ 0.0, bins[cut.ordinal()] * binSize[cut.ordinal()]);
+ AIDA.defaultInstance().histogram1D(getPlotNameEfficiency(cut, trigger, type), bins[cut.ordinal()],
+ 0.0, bins[cut.ordinal()] * binSize[cut.ordinal()]);
+ }
+ }
+
+ // Define the pair cluster high and low energy plots. These
+ // use the same values as the cluster total energy plot.
+ // These plots are only initialized for pair triggers.
+ if(triggerType.isPairTrigger()) {
+ for(int type = SOURCE_SIM_CLUSTER; type <= SOURCE_SSP_CLUSTER; type++) {
+ AIDA.defaultInstance().histogram1D(getPlotNameTotal(CutType.PAIR_LOW_ENERGY, trigger, type),
+ bins[CutType.CLUSTER_TOTAL_ENERGY.ordinal()], 0.0,
+ bins[CutType.CLUSTER_TOTAL_ENERGY.ordinal()] * binSize[CutType.CLUSTER_TOTAL_ENERGY.ordinal()]);
+ AIDA.defaultInstance().histogram1D(getPlotNameVerified(CutType.PAIR_LOW_ENERGY, trigger, type),
+ bins[CutType.CLUSTER_TOTAL_ENERGY.ordinal()], 0.0,
+ bins[CutType.CLUSTER_TOTAL_ENERGY.ordinal()] * binSize[CutType.CLUSTER_TOTAL_ENERGY.ordinal()]);
+ AIDA.defaultInstance().histogram1D(getPlotNameEfficiency(CutType.PAIR_LOW_ENERGY, trigger, type),
+ bins[CutType.CLUSTER_TOTAL_ENERGY.ordinal()], 0.0,
+ bins[CutType.CLUSTER_TOTAL_ENERGY.ordinal()] * binSize[CutType.CLUSTER_TOTAL_ENERGY.ordinal()]);
+ AIDA.defaultInstance().histogram1D(getPlotNameTotal(CutType.PAIR_HIGH_ENERGY, trigger, type),
+ bins[CutType.CLUSTER_TOTAL_ENERGY.ordinal()], 0.0,
+ bins[CutType.CLUSTER_TOTAL_ENERGY.ordinal()] * binSize[CutType.CLUSTER_TOTAL_ENERGY.ordinal()]);
+ AIDA.defaultInstance().histogram1D(getPlotNameVerified(CutType.PAIR_HIGH_ENERGY, trigger, type),
+ bins[CutType.CLUSTER_TOTAL_ENERGY.ordinal()], 0.0,
+ bins[CutType.CLUSTER_TOTAL_ENERGY.ordinal()] * binSize[CutType.CLUSTER_TOTAL_ENERGY.ordinal()]);
+ AIDA.defaultInstance().histogram1D(getPlotNameEfficiency(CutType.PAIR_HIGH_ENERGY, trigger, type),
+ bins[CutType.CLUSTER_TOTAL_ENERGY.ordinal()], 0.0,
+ bins[CutType.CLUSTER_TOTAL_ENERGY.ordinal()] * binSize[CutType.CLUSTER_TOTAL_ENERGY.ordinal()]);
+ }
+ }
+ }
}
/**
@@ -771,6 +1011,9 @@
logger.printf(" [ trigger verified ]%n");
matchedTriggers.add(hardwareTrigger);
+ // Plot the trigger for the verified plots.
+ plotTrigger(simTrigger, tiFlags, true);
+
// Update the verified count for each type of trigger
// for the local and global windows.
if(clusterType == Cluster.class || clusterType == Cluster[].class) {
@@ -879,19 +1122,6 @@
}
/**
- * Gets the number of digits in the base-10 String representation
- * of an integer primitive. Negative signs are not included in the
- * digit count.
- * @param value - The value of which to obtain the length.
- * @return Returns the number of digits in the String representation
- * of the argument value.
- */
- private static final int getDigits(int value) {
- if(value < 0) { return Integer.toString(value).length() - 1; }
- else { return Integer.toString(value).length(); }
- }
-
- /**
* A helper method associated with <code>getTriggerTime</code> that
* handles pair triggers, which have either <code>Cluster[]</code>
* or <code>SSPCluster[]</code> objects as their source type. <b>This
@@ -934,6 +1164,52 @@
} else {
throw new IllegalArgumentException("Ambiguous cluster pair; both top clusters.");
}
+ }
+
+ private final String getPlotName(String footer, CutType cut, TriggerType tiBit, int sourceType) {
+ // Make sure that a cut was defined.
+ if(cut == null) {
+ throw new NullPointerException("Plot cut type was not defined.");
+ }
+
+ // Make sure a valid source type is defined.
+ if(sourceType != SOURCE_SIM_CLUSTER && sourceType != SOURCE_SSP_CLUSTER) {
+ throw new NullPointerException("\"" + sourceType + "\" is not a valid source type index.");
+ }
+
+ // Get the appropriate name for the TI bit.
+ String tiName = getPlotTIName(tiBit);
+
+ // Define the source type name.
+ String sourceName;
+ if(sourceType == SOURCE_SIM_CLUSTER) { sourceName = "Software Sim Distributions/"; }
+ else { sourceName = "Hardware Sim Distributions/"; }
+
+ // Return the name of the coplanarity plot.
+ return moduleHeader + sourceName + tiName + "/" + cut.toString() + footer;
+ }
+
+ private final String getPlotNameEfficiency(CutType cut, TriggerType tiBit, int sourceType) {
+ return getPlotName(" Efficiency", cut, tiBit, sourceType);
+ }
+
+ private final String getPlotNameTotal(CutType cut, TriggerType tiBit, int sourceType) {
+ return getPlotName(" (Observed)", cut, tiBit, sourceType);
+ }
+
+ private final String getPlotNameVerified(CutType cut, TriggerType tiBit, int sourceType) {
+ return getPlotName(" (Verified)", cut, tiBit, sourceType);
+ }
+
+ /**
+ * Returns the name of the trigger type in the argument, or "All"
+ * if a null argument is given.
+ * @param tiBit - The trigger type.
+ * @return Returns either the name of the trigger type or "All."
+ */
+ private static final String getPlotTIName(TriggerType tiBit) {
+ if(tiBit == null) { return "All"; }
+ else { return tiBit.toString(); }
}
/**
@@ -1160,6 +1436,139 @@
// Return the result.
return maxValue;
+ }
+
+ private void plotTrigger(Trigger<?> trigger, boolean[] activeTIBits, boolean verified) {
+ // Which plots are to be populated depends on the type of
+ // trigger. First, handle singles triggers.
+ if(trigger.getTriggerSource() instanceof Cluster || trigger.getTriggerSource() instanceof SSPCluster) {
+ // Define the plot values.
+ int sourceType;
+ double clusterEnergy;
+ double hitCount;
+ double eventTime = getTriggerTime(trigger);
+
+ // Get the values. This will depend on the cluster type.
+ if(trigger.getTriggerSource() instanceof Cluster) {
+ // Fill the plot value variables.
+ Cluster cluster = (Cluster) trigger.getTriggerSource();
+ clusterEnergy = TriggerModule.getValueClusterTotalEnergy(cluster);
+ hitCount = TriggerModule.getClusterHitCount(cluster);
+
+ // Note that the source type is a sim cluster.
+ sourceType = SOURCE_SIM_CLUSTER;
+
+ // Seed energy is also plotted here, as it does not exist
+ // for SSP clusters.
+ double seedEnergy = TriggerModule.getValueClusterSeedEnergy(cluster);
+ for(TriggerType tiBit : triggerTypes) {
+ if(tiBit == null || activeTIBits[tiBit.ordinal()]) {
+ if(verified) {
+ AIDA.defaultInstance().histogram1D(getPlotNameVerified(CutType.CLUSTER_SEED_ENERGY, tiBit, sourceType)).fill(seedEnergy);
+ } else {
+ AIDA.defaultInstance().histogram1D(getPlotNameTotal(CutType.CLUSTER_SEED_ENERGY, tiBit, sourceType)).fill(seedEnergy);
+ }
+ }
+ }
+ } else if(trigger.getTriggerSource() instanceof SSPCluster) {
+ // Fill the plot value variables.
+ SSPCluster cluster = (SSPCluster) trigger.getTriggerSource();
+ clusterEnergy = TriggerModule.getValueClusterTotalEnergy(cluster);
+ hitCount = TriggerModule.getClusterHitCount(cluster);
+
+ // Note that the source type is an SSP cluster.
+ sourceType = SOURCE_SSP_CLUSTER;
+ } else {
+ throw new IllegalArgumentException("Trigger source " + trigger.getTriggerSource().getClass().getSimpleName() + " is not recognized.");
+ }
+
+ // Populate the appropriate trigger plot.
+ for(TriggerType tiBit : triggerTypes) {
+ if(tiBit == null || activeTIBits[tiBit.ordinal()]) {
+ if(verified) {
+ AIDA.defaultInstance().histogram1D(getPlotNameVerified(CutType.EVENT_TIME, tiBit, sourceType)).fill(eventTime);
+ AIDA.defaultInstance().histogram1D(getPlotNameVerified(CutType.CLUSTER_HIT_COUNT, tiBit, sourceType)).fill(hitCount);
+ AIDA.defaultInstance().histogram1D(getPlotNameVerified(CutType.CLUSTER_TOTAL_ENERGY, tiBit, sourceType)).fill(clusterEnergy);
+ } else {
+ AIDA.defaultInstance().histogram1D(getPlotNameTotal(CutType.EVENT_TIME, tiBit, sourceType)).fill(eventTime);
+ AIDA.defaultInstance().histogram1D(getPlotNameTotal(CutType.CLUSTER_HIT_COUNT, tiBit, sourceType)).fill(hitCount);
+ AIDA.defaultInstance().histogram1D(getPlotNameTotal(CutType.CLUSTER_TOTAL_ENERGY, tiBit, sourceType)).fill(clusterEnergy);
+ }
+ }
+ }
+ } else if(trigger.getTriggerSource() instanceof Cluster[] || trigger.getTriggerSource() instanceof SSPCluster[]) {
+ // Define the plot values.
+ int sourceType;
+ double energySum;
+ double energyDiff;
+ double energySlope;
+ double coplanarity;
+ double timeCoincidence;
+ double clusterLow;
+ double clusterHigh;
+ double eventTime = getTriggerTime(trigger);
+
+ // How the values are filled depends on the source cluster
+ // type.
+ if(trigger.getTriggerSource() instanceof Cluster[]) {
+ // Fill the plot value variables.
+ Cluster[] pair = (Cluster[]) trigger.getTriggerSource();
+ energySum = TriggerModule.getValueEnergySum(pair);
+ energyDiff = TriggerModule.getValueEnergyDifference(pair);
+ energySlope = TriggerModule.getValueEnergySlope(pair,
+ pairTrigger[triggerType.getTriggerNumber()].getCutValue(TriggerModule.PAIR_ENERGY_SLOPE_F));
+ coplanarity = TriggerModule.getValueCoplanarity(pair);
+ timeCoincidence = TriggerModule.getValueTimeCoincidence(pair);
+ clusterLow = Math.min(TriggerModule.getValueClusterTotalEnergy(pair[0]), TriggerModule.getValueClusterTotalEnergy(pair[1]));
+ clusterHigh = Math.max(TriggerModule.getValueClusterTotalEnergy(pair[0]), TriggerModule.getValueClusterTotalEnergy(pair[1]));
+
+ // Note that the source type is a sim cluster.
+ sourceType = SOURCE_SIM_CLUSTER;
+ } else if(trigger.getTriggerSource() instanceof SSPCluster[]) {
+ // Fill the plot value variables.
+ SSPCluster[] pair = (SSPCluster[]) trigger.getTriggerSource();
+ energySum = TriggerModule.getValueEnergySum(pair);
+ energyDiff = TriggerModule.getValueEnergyDifference(pair);
+ energySlope = TriggerModule.getValueEnergySlope(pair,
+ pairTrigger[triggerType.getTriggerNumber()].getCutValue(TriggerModule.PAIR_ENERGY_SLOPE_F));
+ coplanarity = TriggerModule.getValueCoplanarity(pair);
+ timeCoincidence = TriggerModule.getValueTimeCoincidence(pair);
+ clusterLow = Math.min(TriggerModule.getValueClusterTotalEnergy(pair[0]), TriggerModule.getValueClusterTotalEnergy(pair[1]));
+ clusterHigh = Math.max(TriggerModule.getValueClusterTotalEnergy(pair[0]), TriggerModule.getValueClusterTotalEnergy(pair[1]));
+
+ // Note that the source type is an SSP cluster.
+ sourceType = SOURCE_SSP_CLUSTER;
+ } else {
+ throw new IllegalArgumentException("Trigger source " + trigger.getTriggerSource().getClass().getSimpleName() + " is not recognized.");
+ }
+
+ // Fill the appropriate plots.
+ for(TriggerType tiBit : triggerTypes) {
+ if(tiBit == null || activeTIBits[tiBit.ordinal()]) {
+ if(verified) {
+ AIDA.defaultInstance().histogram1D(getPlotNameVerified(CutType.EVENT_TIME, tiBit, sourceType)).fill(eventTime);
+ AIDA.defaultInstance().histogram1D(getPlotNameVerified(CutType.PAIR_ENERGY_SUM, tiBit, sourceType)).fill(energySum);
+ AIDA.defaultInstance().histogram1D(getPlotNameVerified(CutType.PAIR_ENERGY_DIFF, tiBit, sourceType)).fill(energyDiff);
+ AIDA.defaultInstance().histogram1D(getPlotNameVerified(CutType.PAIR_ENERGY_SLOPE, tiBit, sourceType)).fill(energySlope);
+ AIDA.defaultInstance().histogram1D(getPlotNameVerified(CutType.PAIR_COPLANARITY, tiBit, sourceType)).fill(coplanarity);
+ AIDA.defaultInstance().histogram1D(getPlotNameVerified(CutType.PAIR_TIME_COINCIDENCE, tiBit, sourceType)).fill(timeCoincidence);
+ AIDA.defaultInstance().histogram1D(getPlotNameVerified(CutType.PAIR_LOW_ENERGY, tiBit, sourceType)).fill(clusterLow);
+ AIDA.defaultInstance().histogram1D(getPlotNameVerified(CutType.PAIR_HIGH_ENERGY, tiBit, sourceType)).fill(clusterHigh);
+ } else {
+ AIDA.defaultInstance().histogram1D(getPlotNameTotal(CutType.EVENT_TIME, tiBit, sourceType)).fill(eventTime);
+ AIDA.defaultInstance().histogram1D(getPlotNameTotal(CutType.PAIR_ENERGY_SUM, tiBit, sourceType)).fill(energySum);
+ AIDA.defaultInstance().histogram1D(getPlotNameTotal(CutType.PAIR_ENERGY_DIFF, tiBit, sourceType)).fill(energyDiff);
+ AIDA.defaultInstance().histogram1D(getPlotNameTotal(CutType.PAIR_ENERGY_SLOPE, tiBit, sourceType)).fill(energySlope);
+ AIDA.defaultInstance().histogram1D(getPlotNameTotal(CutType.PAIR_COPLANARITY, tiBit, sourceType)).fill(coplanarity);
+ AIDA.defaultInstance().histogram1D(getPlotNameTotal(CutType.PAIR_TIME_COINCIDENCE, tiBit, sourceType)).fill(timeCoincidence);
+ AIDA.defaultInstance().histogram1D(getPlotNameTotal(CutType.PAIR_LOW_ENERGY, tiBit, sourceType)).fill(clusterLow);
+ AIDA.defaultInstance().histogram1D(getPlotNameTotal(CutType.PAIR_HIGH_ENERGY, tiBit, sourceType)).fill(clusterHigh);
+ }
+ }
+ }
+ } else {
+ throw new IllegalArgumentException("Trigger type " + trigger.getClass().getSimpleName() + " is not recognized.");
+ }
}
/**
@@ -1312,6 +1721,10 @@
}
}
+ // Print the observed trigger distributions.
+ for(Trigger<?> trigger : softwareSimTriggers) { plotTrigger(trigger, tiFlags, false); }
+ for(Trigger<?> trigger : hardwareSimTriggers) { plotTrigger(trigger, tiFlags, false); }
+
// Run the trigger verification for each simulated trigger type.
logger.printNewLine(2);
logger.println("=== Performing Trigger Verification ==================================");
@@ -1467,4 +1880,22 @@
public void setVerbose(boolean state) {
verbose = state;
}
+
+ public void setClusterSeedEnergyXMax(double value) { xMax[CutType.CLUSTER_SEED_ENERGY.ordinal()] = value; }
+ public void setClusterTotalEnergyXMax(double value) { xMax[CutType.CLUSTER_TOTAL_ENERGY.ordinal()] = value; }
+ public void setClusterHitCountXMax(double value) { xMax[CutType.CLUSTER_HIT_COUNT.ordinal()] = value; }
+ public void setPairEnergySumXMax(double value) { xMax[CutType.PAIR_ENERGY_SUM.ordinal()] = value; }
+ public void setPairEnergyDiffXMax(double value) { xMax[CutType.PAIR_ENERGY_DIFF.ordinal()] = value; }
+ public void setPairEnergySlopeXMax(double value) { xMax[CutType.PAIR_ENERGY_SLOPE.ordinal()] = value; }
+ public void setPairCoplanarityXMax(double value) { xMax[CutType.PAIR_COPLANARITY.ordinal()] = value; }
+ public void setPairTimeCoincidenceXMax(double value) { xMax[CutType.PAIR_TIME_COINCIDENCE.ordinal()] = value; }
+
+ public void setClusterSeedEnergyBinSize(double value) { binSize[CutType.CLUSTER_SEED_ENERGY.ordinal()] = value; }
+ public void setClusterTotalEnergyBinSize(double value) { binSize[CutType.CLUSTER_TOTAL_ENERGY.ordinal()] = value; }
+ public void setClusterHitCountBinSize(double value) { binSize[CutType.CLUSTER_HIT_COUNT.ordinal()] = value; }
+ public void setPairEnergySumBinSize(double value) { binSize[CutType.PAIR_ENERGY_SUM.ordinal()] = value; }
+ public void setPairEnergyDiffBinSize(double value) { binSize[CutType.PAIR_ENERGY_DIFF.ordinal()] = value; }
+ public void setPairEnergySlopeBinSize(double value) { binSize[CutType.PAIR_ENERGY_SLOPE.ordinal()] = value; }
+ public void setPairCoplanarityBinSize(double value) { binSize[CutType.PAIR_COPLANARITY.ordinal()] = value; }
+ public void setPairTimeCoincidenceBinSize(double value) { binSize[CutType.PAIR_TIME_COINCIDENCE.ordinal()] = value; }
}
Modified: java/trunk/analysis/src/main/java/org/hps/analysis/trigger/util/TriggerDiagnosticUtil.java
=============================================================================
--- java/trunk/analysis/src/main/java/org/hps/analysis/trigger/util/TriggerDiagnosticUtil.java (original)
+++ java/trunk/analysis/src/main/java/org/hps/analysis/trigger/util/TriggerDiagnosticUtil.java Tue Dec 6 19:29:12 2016
@@ -60,6 +60,19 @@
}
/**
+ * Gets the number of digits in the base-10 String representation
+ * of an integer primitive. Negative signs are not included in the
+ * digit count.
+ * @param value - The value of which to obtain the length.
+ * @return Returns the number of digits in the String representation
+ * of the argument value.
+ */
+ public static final int getDigits(int value) {
+ if(value < 0) { return Integer.toString(value).length() - 1; }
+ else { return Integer.toString(value).length(); }
+ }
+
+ /**
* Checks whether a cluster is within the safe region of the FADC
* output window.
* @param sspCluster - The cluster to check.
|