LISTSERV mailing list manager LISTSERV 16.5

Help for HPS-SVN Archives


HPS-SVN Archives

HPS-SVN Archives


HPS-SVN@LISTSERV.SLAC.STANFORD.EDU


View:

Message:

[

First

|

Previous

|

Next

|

Last

]

By Topic:

[

First

|

Previous

|

Next

|

Last

]

By Author:

[

First

|

Previous

|

Next

|

Last

]

Font:

Proportional Font

LISTSERV Archives

LISTSERV Archives

HPS-SVN Home

HPS-SVN Home

HPS-SVN  March 2015

HPS-SVN March 2015

Subject:

r2418 - in /java/trunk/analysis/src/main/java/org/hps/analysis/trigger: ./ event/ util/

From:

[log in to unmask]

Reply-To:

Notification of commits to the hps svn repository <[log in to unmask]>

Date:

Thu, 12 Mar 2015 22:09:00 -0000

Content-Type:

text/plain

Parts/Attachments:

Parts/Attachments

text/plain (1849 lines)

Author: [log in to unmask]
Date: Thu Mar 12 15:08:54 2015
New Revision: 2418

Log:
Implemented a series of bug fixes for the trigger diagnostics. Simulated triggers are now only used for verification in the same cases where the SSP will output triggers. This ensures that we avoid finding a large number of match failures for triggers that we would not expect to be reported. Additionally, fixed the statistical counters to properly track statistics. They had become inaccurate due to the changes in the data structure implemented when adding the trigger fix and monitoring application integration code.

Modified:
    java/trunk/analysis/src/main/java/org/hps/analysis/trigger/TriggerDiagnosticDriver.java
    java/trunk/analysis/src/main/java/org/hps/analysis/trigger/event/ClusterMatchEvent.java
    java/trunk/analysis/src/main/java/org/hps/analysis/trigger/event/ClusterMatchStatus.java
    java/trunk/analysis/src/main/java/org/hps/analysis/trigger/event/ClusterMatchedPair.java
    java/trunk/analysis/src/main/java/org/hps/analysis/trigger/event/TriggerMatchEvent.java
    java/trunk/analysis/src/main/java/org/hps/analysis/trigger/event/TriggerMatchStatus.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/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	Thu Mar 12 15:08:54 2015
@@ -1,10 +1,14 @@
 package org.hps.analysis.trigger;
+
+import hep.aida.IHistogram1D;
+import hep.aida.IHistogram2D;
 
 import java.awt.Point;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.util.ArrayList;
 import java.util.Calendar;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -25,8 +29,6 @@
 import org.hps.analysis.trigger.util.Trigger;
 import org.hps.analysis.trigger.util.TriggerDiagnosticUtil;
 import org.hps.readout.ecal.TriggerModule;
-import org.hps.readout.ecal.daqconfig.ConfigurationManager;
-import org.hps.readout.ecal.daqconfig.DAQConfig;
 import org.hps.readout.ecal.triggerbank.AbstractIntData;
 import org.hps.readout.ecal.triggerbank.SSPCluster;
 import org.hps.readout.ecal.triggerbank.SSPData;
@@ -35,11 +37,16 @@
 import org.hps.readout.ecal.triggerbank.SSPSinglesTrigger;
 import org.hps.readout.ecal.triggerbank.SSPTrigger;
 import org.hps.readout.ecal.triggerbank.TIData;
+import org.hps.readout.ecal.daqconfig.ConfigurationManager;
+import org.hps.readout.ecal.daqconfig.DAQConfig;
+import org.hps.readout.ecal.daqconfig.PairTriggerConfig;
+import org.hps.readout.ecal.daqconfig.SinglesTriggerConfig;
 import org.lcsim.event.CalorimeterHit;
 import org.lcsim.event.Cluster;
 import org.lcsim.event.EventHeader;
 import org.lcsim.event.GenericObject;
 import org.lcsim.util.Driver;
+import org.lcsim.util.aida.AIDA;
 
 public class TriggerDiagnosticDriver extends Driver {
 	// Store the LCIO collection names for the needed objects.
@@ -62,6 +69,10 @@
 	private int activeTrigger = -1;
 	private TriggerModule[] singlesTrigger = new TriggerModule[2];
 	private TriggerModule[] pairsTrigger = new TriggerModule[2];
+	private boolean[][] singlesCutsEnabled = new boolean[2][3];
+	private boolean[][] pairCutsEnabled = new boolean[2][7];
+	private boolean[] singlesTriggerEnabled = new boolean[2];
+	private boolean[] pairTriggerEnabled = new boolean[2];
 	
 	// Verification settings.
 	private int nsa = 100;
@@ -69,13 +80,14 @@
 	private int windowWidth = 200;
 	private int hitAcceptance = 1;
 	private int noiseThreshold = 50;
+	private double energyAcceptance = 0.003;
 	private long localWindowStart = 0;
 	private boolean readDAQConfig = false;
-	private double energyAcceptance = 0.03;
 	private int localWindowThreshold = 10 * 1000;
 	private boolean performClusterVerification = true;
 	private boolean performSinglesTriggerVerification = true;
 	private boolean performPairTriggerVerification = true;
+	private boolean enforceTimeCompliance = false;
 	
 	// Efficiency tracking variables.
 	private ClusterMatchStatus clusterRunStats = new ClusterMatchStatus();
@@ -113,12 +125,91 @@
 	private static final int ENERGY_SLOPE = TriggerDiagnosticUtil.PAIR_ENERGY_SLOPE;
 	private static final int COPLANARITY  = TriggerDiagnosticUtil.PAIR_COPLANARITY;
     
+	// Temporary AIDA Plots
+	private static final int RECON   = 0;
+	private static final int SSP     = 1;
+	private static final int ALL     = 0;
+	private static final int MATCHED = 1;
+	private static final int FAILED  = 2;
+	private AIDA aida = AIDA.defaultInstance();
+	private IHistogram1D[][] clusterHitPlot = {
+			{
+				aida.histogram1D("Trigger Diagnostics :: Recon Cluster Hit Count (All)",     9, 0.5, 9.5),
+				aida.histogram1D("Trigger Diagnostics :: Recon Cluster Hit Count (Matched)", 9, 0.5, 9.5),
+				aida.histogram1D("Trigger Diagnostics :: Recon Cluster Hit Count (Failed)",  9, 0.5, 9.5)
+			},
+			{
+				aida.histogram1D("Trigger Diagnostics :: SSP Cluster Hit Count (All)",     9, 0.5, 9.5),
+				aida.histogram1D("Trigger Diagnostics :: SSP Cluster Hit Count (Matched)", 9, 0.5, 9.5),
+				aida.histogram1D("Trigger Diagnostics :: SSP Cluster Hit Count (Failed)",  9, 0.5, 9.5)
+			}
+	};
+	private IHistogram1D[][] clusterEnergyPlot = {
+			{
+				aida.histogram1D("Trigger Diagnostics :: Recon Cluster Energy (All)",     300, 0.0, 3.0),
+				aida.histogram1D("Trigger Diagnostics :: Recon Cluster Energy (Matched)", 300, 0.0, 3.0),
+				aida.histogram1D("Trigger Diagnostics :: Recon Cluster Energy (Failed)",  300, 0.0, 3.0)
+			},
+			{
+				aida.histogram1D("Trigger Diagnostics :: SSP Cluster Energy (All)",     300, 0.0, 3.0),
+				aida.histogram1D("Trigger Diagnostics :: SSP Cluster Energy (Matched)", 300, 0.0, 3.0),
+				aida.histogram1D("Trigger Diagnostics :: SSP Cluster Energy (Failed)",  300, 0.0, 3.0)
+			}
+	};
+	private IHistogram1D[][] clusterTimePlot = {
+			{
+				aida.histogram1D("Trigger Diagnostics :: Recon Cluster Time (All)",     115, 0, 460),
+				aida.histogram1D("Trigger Diagnostics :: Recon Cluster Time (Matched)", 115, 0, 460),
+				aida.histogram1D("Trigger Diagnostics :: Recon Cluster Time (Failed)",  115, 0, 460)
+			},
+			{
+				aida.histogram1D("Trigger Diagnostics :: SSP Cluster Time (All)",     115, 0, 460),
+				aida.histogram1D("Trigger Diagnostics :: SSP Cluster Time (Matched)", 115, 0, 460),
+				aida.histogram1D("Trigger Diagnostics :: SSP Cluster Time (Failed)",  115, 0, 460)
+			}
+	};
+	private IHistogram2D[][] clusterPositionPlot = {
+			{
+				aida.histogram2D("Trigger Diagnostics :: Recon Cluster Position (All)",     47, -23.5, 23.5, 11, -5.5, 5.5),
+				aida.histogram2D("Trigger Diagnostics :: Recon Cluster Position (Matched)", 47, -23.5, 23.5, 11, -5.5, 5.5),
+				aida.histogram2D("Trigger Diagnostics :: Recon Cluster Position (Failed)",  47, -23.5, 23.5, 11, -5.5, 5.5)
+			},
+			{
+				aida.histogram2D("Trigger Diagnostics :: SSP Cluster Position (All)",     47, -23.5, 23.5, 11, -5.5, 5.5),
+				aida.histogram2D("Trigger Diagnostics :: SSP Cluster Position (Matched)", 47, -23.5, 23.5, 11, -5.5, 5.5),
+				aida.histogram2D("Trigger Diagnostics :: SSP Cluster Position (Failed)",  47, -23.5, 23.5, 11, -5.5, 5.5)
+			}
+	};
+	private IHistogram2D[] energyhitDiffPlot = {
+		aida.histogram2D("Trigger Diagnostics :: Recon-SSP Energy-Hit Difference (All)",     60, -0.060, 0.060, 6, -3, 3),
+		aida.histogram2D("Trigger Diagnostics :: Recon-SSP Energy-Hit Difference (Matched)", 60, -0.060, 0.060, 6, -3, 3),
+		aida.histogram2D("Trigger Diagnostics :: Recon-SSP Energy-Hit Difference (Failed)",  60, -0.060, 0.060, 6, -3, 3)
+	};
+	
+	
 	/**
 	 * Define the trigger modules. This should be replaced by parsing
 	 * the DAQ configuration at some point.
 	 */
 	@Override
 	public void startOfData() {
+		// By default, all triggers and cuts are enabled.
+		for(int i = 0; i < 2; i++) {
+			// Enable the triggers.
+			pairTriggerEnabled[i] = true;
+			singlesTriggerEnabled[i] = true;
+			
+			// Enable the singles cuts.
+			for(int j = 0; j < singlesCutsEnabled.length; j++) {
+				singlesCutsEnabled[i][j] = true;
+			}
+			
+			// Enable the pair cuts.
+			for(int j = 0; j < pairCutsEnabled.length; j++) {
+				pairCutsEnabled[i][j] = true;
+			}
+		}
+		
 		// If the DAQ configuration should be read, attach a listener
 		// to track when it updates.
 		if(readDAQConfig) {
@@ -137,6 +228,33 @@
 					nsb = daq.getFADCConfig().getNSB();
 					windowWidth = daq.getFADCConfig().getWindowWidth();
 					
+					// Get the trigger configurations from the DAQ.
+					SinglesTriggerConfig[] singles = { daq.getSSPConfig().getSingles1Config(),
+							daq.getSSPConfig().getSingles2Config() };
+					PairTriggerConfig[] pairs = { daq.getSSPConfig().getPair1Config(),
+							daq.getSSPConfig().getPair2Config() };
+					
+					// Update the enabled/disabled statuses.
+					for(int i = 0; i < 2; i++) {
+						// Set the trigger enabled status.
+						pairTriggerEnabled[i] = pairs[i].isEnabled();
+						singlesTriggerEnabled[i] = singles[i].isEnabled();
+						
+						// Set the singles cut statuses.
+						singlesCutsEnabled[i][ENERGY_MIN] = singles[i].getEnergyMinCutConfig().isEnabled();
+						singlesCutsEnabled[i][ENERGY_MAX] = singles[i].getEnergyMaxCutConfig().isEnabled();
+						singlesCutsEnabled[i][HIT_COUNT] = singles[i].getHitCountCutConfig().isEnabled();
+						
+						// Set the pair cut statuses.
+						pairCutsEnabled[i][ENERGY_MIN] = pairs[i].getEnergyMinCutConfig().isEnabled();
+						pairCutsEnabled[i][ENERGY_MAX] = pairs[i].getEnergyMaxCutConfig().isEnabled();
+						pairCutsEnabled[i][HIT_COUNT] = pairs[i].getHitCountCutConfig().isEnabled();
+						pairCutsEnabled[i][3 + ENERGY_SUM] = pairs[i].getEnergySumCutConfig().isEnabled();
+						pairCutsEnabled[i][3 + ENERGY_DIFF] = pairs[i].getEnergyDifferenceCutConfig().isEnabled();
+						pairCutsEnabled[i][3 + ENERGY_SLOPE] = pairs[i].getEnergySlopeCutConfig().isEnabled();
+						pairCutsEnabled[i][3 + COPLANARITY] = pairs[i].getCoplanarityCutConfig().isEnabled();
+					}
+					
 					// Print a DAQ configuration settings header.
 					System.out.println();
 					System.out.println();
@@ -154,51 +272,6 @@
 		System.out.println("======================================================================");
 		System.out.println("=== Cluster/Trigger Verification Settings ============================");
 		System.out.println("======================================================================");
-		
-		// Set the FADC settings.
-		nsa = 100;
-		nsb = 20;
-		windowWidth = 400;
-		
-		/*
-		// Define the first singles trigger.
-		singlesTrigger[0] = new TriggerModule();
-		singlesTrigger[0].setCutValue(TriggerModule.CLUSTER_TOTAL_ENERGY_LOW, 0.010);
-		singlesTrigger[0].setCutValue(TriggerModule.CLUSTER_TOTAL_ENERGY_HIGH, 8.191);
-		singlesTrigger[0].setCutValue(TriggerModule.CLUSTER_HIT_COUNT_LOW, 2);
-		
-		// Define the second singles trigger.
-		singlesTrigger[1] = new TriggerModule();
-		singlesTrigger[1].setCutValue(TriggerModule.CLUSTER_TOTAL_ENERGY_LOW, 0.010);
-		singlesTrigger[1].setCutValue(TriggerModule.CLUSTER_TOTAL_ENERGY_HIGH, 0.050);
-		singlesTrigger[1].setCutValue(TriggerModule.CLUSTER_HIT_COUNT_LOW, 2);
-		
-		// Define the first pairs trigger.
-		pairsTrigger[0] = new TriggerModule();
-		pairsTrigger[0].setCutValue(TriggerModule.CLUSTER_TOTAL_ENERGY_LOW, 0.020);
-		pairsTrigger[0].setCutValue(TriggerModule.CLUSTER_TOTAL_ENERGY_HIGH, 0.055);
-		pairsTrigger[0].setCutValue(TriggerModule.CLUSTER_HIT_COUNT_LOW, 1);
-		pairsTrigger[0].setCutValue(TriggerModule.PAIR_ENERGY_SUM_LOW, 0.010);
-		pairsTrigger[0].setCutValue(TriggerModule.PAIR_ENERGY_SUM_HIGH, 2.000);
-		pairsTrigger[0].setCutValue(TriggerModule.PAIR_ENERGY_DIFFERENCE_HIGH, 1.200);
-		pairsTrigger[0].setCutValue(TriggerModule.PAIR_ENERGY_SLOPE_LOW, 0.400);
-		pairsTrigger[0].setCutValue(TriggerModule.PAIR_ENERGY_SLOPE_F, 0.0055);
-		pairsTrigger[0].setCutValue(TriggerModule.PAIR_COPLANARITY_HIGH, 40);
-		pairsTrigger[0].setCutValue(TriggerModule.PAIR_TIME_COINCIDENCE, 16);
-		
-		// Define the second pairs trigger.
-		pairsTrigger[1] = new TriggerModule();
-		pairsTrigger[1].setCutValue(TriggerModule.CLUSTER_TOTAL_ENERGY_LOW, 0.010);
-		pairsTrigger[1].setCutValue(TriggerModule.CLUSTER_TOTAL_ENERGY_HIGH, 1.800);
-		pairsTrigger[1].setCutValue(TriggerModule.CLUSTER_HIT_COUNT_LOW, 2);
-		pairsTrigger[1].setCutValue(TriggerModule.PAIR_ENERGY_SUM_LOW, 0.020);
-		pairsTrigger[1].setCutValue(TriggerModule.PAIR_ENERGY_SUM_HIGH, 2.000);
-		pairsTrigger[1].setCutValue(TriggerModule.PAIR_ENERGY_DIFFERENCE_HIGH, 1.200);
-		pairsTrigger[1].setCutValue(TriggerModule.PAIR_ENERGY_SLOPE_LOW, 0.400);
-		pairsTrigger[1].setCutValue(TriggerModule.PAIR_ENERGY_SLOPE_F, 0.0055);
-		pairsTrigger[1].setCutValue(TriggerModule.PAIR_COPLANARITY_HIGH, 40);
-		pairsTrigger[1].setCutValue(TriggerModule.PAIR_TIME_COINCIDENCE, 16);
-		*/
 		
 		// Define the first singles trigger.
 		singlesTrigger[0] = new TriggerModule();
@@ -310,61 +383,63 @@
 			else { System.out.printf("(%7.3f%%)%n" , (100.0 * triggerRunStats[triggerType].getMatchedReconTriggers() / triggerRunStats[triggerType].getReconTriggerCount())); }
 			
 			// Print the individual cut performances.
-			int halfSSPTriggers = triggerRunStats[triggerType].getSSPSimTriggerCount() / 2;
 			if(triggerType == 0) {
 			for(int triggerNum = 0; triggerNum < 2; triggerNum++) {
+				int sspTriggerCount = triggerRunStats[0].getTotalSSPTriggers(triggerNum);
+				System.out.println();
+				System.out.printf("\tTrigger %d Individual Cut Failure Rate:%n", (triggerNum + 1));
+				if(sspTriggerCount == 0) {
+						System.out.printf("\t\tCluster Energy Lower Bound :: %" + spaces + "d / %" + spaces + "d%n",
+								triggerRunStats[0].getCutFailures(triggerNum, ENERGY_MIN), sspTriggerCount);
+						System.out.printf("\t\tCluster Energy Upper Bound :: %" + spaces + "d / %" + spaces + "d%n",
+								triggerRunStats[0].getCutFailures(triggerNum, ENERGY_MAX), sspTriggerCount);
+						System.out.printf("\t\tCluster Hit Count          :: %" + spaces + "d / %" + spaces + "d%n",
+								triggerRunStats[0].getCutFailures(triggerNum, HIT_COUNT), sspTriggerCount);
+					} else {
+						System.out.printf("\t\tCluster Energy Lower Bound :: %" + spaces + "d / %" + spaces + "d (%7.3f%%)%n",
+								triggerRunStats[0].getCutFailures(triggerNum, ENERGY_MIN), sspTriggerCount,
+								(100.0 * triggerRunStats[0].getCutFailures(triggerNum, ENERGY_MIN) / sspTriggerCount));
+						System.out.printf("\t\tCluster Energy Upper Bound :: %" + spaces + "d / %" + spaces + "d (%7.3f%%)%n",
+								triggerRunStats[0].getCutFailures(triggerNum, ENERGY_MAX), sspTriggerCount,
+								(100.0 * triggerRunStats[0].getCutFailures(triggerNum, ENERGY_MAX) / sspTriggerCount));
+						System.out.printf("\t\tCluster Hit Count          :: %" + spaces + "d / %" + spaces + "d (%7.3f%%)%n",
+								triggerRunStats[0].getCutFailures(triggerNum, HIT_COUNT), sspTriggerCount,
+								(100.0 * triggerRunStats[0].getCutFailures(triggerNum, HIT_COUNT) / sspTriggerCount));
+					}
+				}
+			} else {
+				for(int triggerNum = 0; triggerNum < 2; triggerNum++) {
+					int sspTriggerCount = triggerRunStats[1].getTotalSSPTriggers(triggerNum);
 					System.out.println();
 					System.out.printf("\tTrigger %d Individual Cut Failure Rate:%n", (triggerNum + 1));
-					if(triggerRunStats[0].getSSPSimTriggerCount() == 0) {
-						System.out.printf("\t\tCluster Energy Lower Bound :: %" + spaces + "d / %" + spaces + "d%n",
-								triggerRunStats[0].getCutFailures(triggerNum, ENERGY_MIN), halfSSPTriggers);
-						System.out.printf("\t\tCluster Energy Upper Bound :: %" + spaces + "d / %" + spaces + "d%n",
-								triggerRunStats[0].getCutFailures(triggerNum, ENERGY_MAX), halfSSPTriggers);
-						System.out.printf("\t\tCluster Hit Count          :: %" + spaces + "d / %" + spaces + "d%n",
-								triggerRunStats[0].getCutFailures(triggerNum, HIT_COUNT), halfSSPTriggers);
-					} else {
-						System.out.printf("\t\tCluster Energy Lower Bound :: %" + spaces + "d / %" + spaces + "d (%7.3f%%)%n",
-								triggerRunStats[0].getCutFailures(triggerNum, ENERGY_MIN), halfSSPTriggers,
-								(100.0 * triggerRunStats[0].getCutFailures(triggerNum, ENERGY_MIN) / halfSSPTriggers));
-						System.out.printf("\t\tCluster Energy Upper Bound :: %" + spaces + "d / %" + spaces + "d (%7.3f%%)%n",
-								triggerRunStats[0].getCutFailures(triggerNum, ENERGY_MAX), halfSSPTriggers,
-								(100.0 * triggerRunStats[0].getCutFailures(triggerNum, ENERGY_MAX) / halfSSPTriggers));
-						System.out.printf("\t\tCluster Hit Count          :: %" + spaces + "d / %" + spaces + "d (%7.3f%%)%n",
-								triggerRunStats[0].getCutFailures(triggerNum, HIT_COUNT), halfSSPTriggers,
-								(100.0 * triggerRunStats[0].getCutFailures(triggerNum, HIT_COUNT) / halfSSPTriggers));
-					}
-				}
-			} else {
-				for(int triggerNum = 0; triggerNum < 2; triggerNum++) {
-					System.out.println();
-					System.out.printf("\tTrigger %d Individual Cut Failure Rate:%n", (triggerNum + 1));
-					if(triggerRunStats[1].getSSPSimTriggerCount() == 0) {
+					if(sspTriggerCount == 0) {
 						System.out.printf("\t\tPair Energy Sum            :: %" + spaces + "d / %" + spaces + "d%n",
-								triggerRunStats[1].getCutFailures(triggerNum, ENERGY_SUM), halfSSPTriggers);
+								triggerRunStats[1].getCutFailures(triggerNum, ENERGY_SUM), sspTriggerCount);
 						System.out.printf("\t\tPair Energy Difference     :: %" + spaces + "d / %" + spaces + "d%n",
-								triggerRunStats[1].getCutFailures(triggerNum, ENERGY_DIFF), halfSSPTriggers);
+								triggerRunStats[1].getCutFailures(triggerNum, ENERGY_DIFF), sspTriggerCount);
 						System.out.printf("\t\tPair Energy Slope          :: %" + spaces + "d / %" + spaces + "d%n",
-								triggerRunStats[1].getCutFailures(triggerNum, ENERGY_SLOPE), halfSSPTriggers);
+								triggerRunStats[1].getCutFailures(triggerNum, ENERGY_SLOPE), sspTriggerCount);
 						System.out.printf("\t\tPair Coplanarity           :: %" + spaces + "d / %" + spaces + "d%n",
-								triggerRunStats[1].getCutFailures(triggerNum, COPLANARITY), halfSSPTriggers);
+								triggerRunStats[1].getCutFailures(triggerNum, COPLANARITY), sspTriggerCount);
 					} else {
 						System.out.printf("\t\tPair Energy Sum            :: %" + spaces + "d / %" + spaces + "d (%7.3f%%)%n",
-								triggerRunStats[1].getCutFailures(triggerNum, ENERGY_SUM), halfSSPTriggers,
-								(100.0 * triggerRunStats[1].getCutFailures(triggerNum, ENERGY_SUM) / halfSSPTriggers));
+								triggerRunStats[1].getCutFailures(triggerNum, ENERGY_SUM), sspTriggerCount,
+								(100.0 * triggerRunStats[1].getCutFailures(triggerNum, ENERGY_SUM) / sspTriggerCount));
 						System.out.printf("\t\tPair Energy Difference     :: %" + spaces + "d / %" + spaces + "d (%7.3f%%)%n",
-								triggerRunStats[1].getCutFailures(triggerNum, ENERGY_DIFF), halfSSPTriggers,
-								(100.0 * triggerRunStats[1].getCutFailures(triggerNum, ENERGY_DIFF) / halfSSPTriggers));
+								triggerRunStats[1].getCutFailures(triggerNum, ENERGY_DIFF), sspTriggerCount,
+								(100.0 * triggerRunStats[1].getCutFailures(triggerNum, ENERGY_DIFF) / sspTriggerCount));
 						System.out.printf("\t\tPair Energy Slope          :: %" + spaces + "d / %" + spaces + "d (%7.3f%%)%n",
-								triggerRunStats[1].getCutFailures(triggerNum, ENERGY_SLOPE), halfSSPTriggers,
-								(100.0 * triggerRunStats[1].getCutFailures(triggerNum, ENERGY_SLOPE) / halfSSPTriggers));
+								triggerRunStats[1].getCutFailures(triggerNum, ENERGY_SLOPE), sspTriggerCount,
+								(100.0 * triggerRunStats[1].getCutFailures(triggerNum, ENERGY_SLOPE) / sspTriggerCount));
 						System.out.printf("\t\tPair Coplanarity           :: %" + spaces + "d / %" + spaces + "d (%7.3f%%)%n",
-								triggerRunStats[1].getCutFailures(triggerNum, COPLANARITY), halfSSPTriggers,
-								(100.0 * triggerRunStats[1].getCutFailures(triggerNum, COPLANARITY) / halfSSPTriggers));
+								triggerRunStats[1].getCutFailures(triggerNum, COPLANARITY), sspTriggerCount,
+								(100.0 * triggerRunStats[1].getCutFailures(triggerNum, COPLANARITY) / sspTriggerCount));
 					}
 				}
 			}
 		}
 		
+		System.out.println();
 		this.efficiencyRunStats.printModule();
 	}
 	
@@ -374,7 +449,7 @@
 	@Override
 	public void process(EventHeader event) {
 		// ==========================================================
-		// ==== Initialize the Event ================================
+		// ==== Event Pre-Initialization ============================
 		// ==========================================================
         
 		// If DAQ settings are to be used, check if they are initialized
@@ -385,12 +460,6 @@
 			}
 		}
 		
-        // Print the verification header.
-		OutputLogger.printNewLine(2);
-		OutputLogger.println("======================================================================");
-		OutputLogger.println("==== Cluster/Trigger Verification ====================================");
-		OutputLogger.println("======================================================================");
-		
 		// Increment the total event count.
 		totalEvents++;
 		
@@ -400,12 +469,57 @@
 		singlesEfficiencyFail = false;
 		pairInternalFail = false;
 		pairEfficiencyFail = false;
+		OutputLogger.clearLog();
+		
+		
+		
+		// ==========================================================
+		// ==== Output GTP Information ==============================
+		// ==========================================================
+		
+        // Print the verification header.
+		OutputLogger.printNewLine(2);
+		OutputLogger.println("======================================================================");
+		OutputLogger.println("==== FADC/GTP Readout ================================================");
+		OutputLogger.println("======================================================================");
+		
+		OutputLogger.println("FADC Hits:");
+		for(CalorimeterHit hit : event.get(CalorimeterHit.class, "EcalCalHits")) {
+			int ix = hit.getIdentifierFieldValue("ix");
+			int iy = hit.getIdentifierFieldValue("iy");
+			OutputLogger.printf("\tHit at (%3d, %3d) with %7.3f GeV at time %3.0f ns%n", ix, iy, hit.getCorrectedEnergy(), hit.getTime());
+		}
+		OutputLogger.printNewLine(2);
+		OutputLogger.println("GTP Clusters:");
+		for(Cluster cluster : event.get(Cluster.class, clusterCollectionName)) {
+			OutputLogger.printf("\t%s%n", TriggerDiagnosticUtil.clusterToString(cluster));
+			for(CalorimeterHit hit : cluster.getCalorimeterHits()) {
+				int ix = hit.getIdentifierFieldValue("ix");
+				int iy = hit.getIdentifierFieldValue("iy");
+				OutputLogger.printf("\t\t> (%3d, %3d) :: %7.3f GeV%n", ix, iy, hit.getCorrectedEnergy());
+			}
+		}
+		
+		
+		
+		// ==========================================================
+		// ==== Initialize the Event ================================
+		// ==========================================================
+		
+        // Print the verification header.
+		OutputLogger.printNewLine(2);
+		OutputLogger.println("======================================================================");
+		OutputLogger.println("==== Cluster/Trigger Verification ====================================");
+		OutputLogger.println("======================================================================");
 		
 		
 		
 		// ==========================================================
 		// ==== Obtain SSP and TI Banks =============================
 		// ==========================================================
+		
+		// Output the event number and information.
+		OutputLogger.printf("Event Number %d (%d)%n", totalEvents, event.getEventNumber());
 		
 		// Get the SSP clusters.
 		if(event.hasCollection(GenericObject.class, bankCollectionName)) {
@@ -653,6 +767,10 @@
 		energyAcceptance = window;
 	}
 	
+	public void setEnforceStrictTimeCompliance(boolean state) {
+		enforceTimeCompliance = state;
+	}
+	
 	public void setReadDAQConfig(boolean state) {
 		readDAQConfig = state;
 	}
@@ -679,15 +797,170 @@
 		OutputLogger.println("=== Cluster Verification =============================================");
 		OutputLogger.println("======================================================================");
 		
+		
+		
+		// ==========================================================
+		// ==== Perform Cluster Matching ============================
+		// ==========================================================
+		
 		// Track the number of cluster pairs that were matched and that
 		// failed by failure type.
 		ClusterMatchEvent event = new ClusterMatchEvent();
 		
-		
-		
-		// ==========================================================
-		// ==== Produce the Cluster Position Mappings ===============
-		// ==========================================================
+		if(enforceTimeCompliance) {
+			event = matchClustersTimeCompliant(reconClusters, sspClusters, energyAcceptance, hitAcceptance);
+		} else {
+			event = matchClusters(reconClusters, sspClusters, energyAcceptance, hitAcceptance);
+		}
+		
+		// Add the event results to the global results.
+		clusterRunStats.addEvent(event, reconClusters, sspClusters);
+		clusterLocalStats.addEvent(event, reconClusters, sspClusters);
+		
+		
+		
+		// ==========================================================
+		// ==== Output Event Summary ================================
+		// ==========================================================
+		
+		// Print the valid reconstructed clusters and populate their
+		// distribution graphs.
+		OutputLogger.println();
+		OutputLogger.println("Verified Reconstructed Clusters:");
+		if(!reconClusters.isEmpty()) {
+			for(Cluster reconCluster : reconClusters) {
+				OutputLogger.printf("\t%s%n", TriggerDiagnosticUtil.clusterToString(reconCluster));
+			}
+		} else { OutputLogger.println("\tNone"); }
+		
+		// Print the SSP clusters and populate their distribution graphs.
+		OutputLogger.println("SSP Clusters:");
+		if(!sspClusters.isEmpty()) {
+			for(SSPCluster sspCluster : sspClusters) {
+				OutputLogger.printf("\t%s%n", TriggerDiagnosticUtil.clusterToString(sspCluster));
+			}
+		} else { OutputLogger.println("\tNone"); }
+		
+		// Print the matched clusters.
+		OutputLogger.println("Matched Clusters:");
+		if(event.getMatchedPairs().size() != 0) {
+			// Iterate over the matched pairs.
+			for(ClusterMatchedPair pair : event.getMatchedPairs()) {
+				// If the pair is a match, print it out.
+				if(pair.isMatch()) {
+					OutputLogger.printf("\t%s --> %s%n",
+							TriggerDiagnosticUtil.clusterToString(pair.getReconstructedCluster()),
+							TriggerDiagnosticUtil.clusterToString(pair.getSSPCluster()));
+				}
+			}
+		}
+		 else { OutputLogger.println("\tNone"); }
+		
+		// Get the number of position failures.
+		//int failPosition = event.getPositionFailures();
+		//if(sspClusters == null || sspClusters.isEmpty()) {
+		//	failPosition = (reconClusters == null ? 0 : reconClusters.size());
+		//}
+		
+		// Print event statistics.
+		OutputLogger.println();
+		OutputLogger.println("Event Statistics:");
+		OutputLogger.printf("\tRecon Clusters     :: %d%n", reconClusters.size());
+		OutputLogger.printf("\tClusters Matched   :: %d%n", event.getMatches());
+		OutputLogger.printf("\tFailed (Position)  :: %d%n", event.getPositionFailures());
+		OutputLogger.printf("\tFailed (Time)      :: %d%n", event.getTimeFailures());
+		OutputLogger.printf("\tFailed (Energy)    :: %d%n", event.getEnergyFailures());
+		OutputLogger.printf("\tFailed (Hit Count) :: %d%n", event.getHitCountFailures());
+		OutputLogger.printf("\tCluster Efficiency :: %3.0f%%%n", 100.0 * event.getMatches() / reconClusters.size());
+		
+		// Note whether there was a cluster match failure.
+		if(event.isFailState() || event.getMatches() - reconClusters.size() != 0) {
+			clusterFail = true;
+		}
+		
+		
+		
+		// TEMP :: Populate the cluster diagnostic plots.
+		
+		// Populate the ALL cluster plots.
+		for(Cluster cluster : reconClusters) {
+			clusterHitPlot[RECON][ALL].fill(cluster.getCalorimeterHits().size());
+			clusterEnergyPlot[RECON][ALL].fill(cluster.getEnergy());
+			clusterTimePlot[RECON][ALL].fill(cluster.getCalorimeterHits().get(0).getTime());
+			Point position = TriggerDiagnosticUtil.getClusterPosition(cluster);
+			clusterPositionPlot[RECON][ALL].fill(position.x, position.y);
+		}
+		for(SSPCluster cluster : sspClusters) {
+			clusterHitPlot[SSP][ALL].fill(cluster.getHitCount());
+			clusterEnergyPlot[SSP][ALL].fill(cluster.getEnergy());
+			clusterTimePlot[SSP][ALL].fill(cluster.getTime());
+			clusterPositionPlot[SSP][ALL].fill(cluster.getXIndex(), cluster.getYIndex());
+		}
+		
+		// Populate the matched and failed plots.
+		for(ClusterMatchedPair pair : event.getMatchedPairs()) {
+			 if(pair.getFirstElement() != null && pair.getSecondElement() != null) {
+				double energyDiff = pair.getSecondElement().getEnergy() - pair.getFirstElement().getEnergy();
+				int hitDiff = pair.getSecondElement().getHitCount() - pair.getFirstElement().getCalorimeterHits().size();
+				energyhitDiffPlot[ALL].fill(energyDiff, hitDiff);
+			 }
+			
+			if(pair.isMatch()) {
+				if(pair.getFirstElement() != null) {
+					clusterHitPlot[RECON][MATCHED].fill(pair.getFirstElement().getCalorimeterHits().size());
+					clusterEnergyPlot[RECON][MATCHED].fill(pair.getFirstElement().getEnergy());
+					clusterTimePlot[RECON][MATCHED].fill(pair.getFirstElement().getCalorimeterHits().get(0).getTime());
+					Point position = TriggerDiagnosticUtil.getClusterPosition(pair.getFirstElement());
+					clusterPositionPlot[RECON][MATCHED].fill(position.x, position.y);
+				} if(pair.getSecondElement() != null) {
+					clusterHitPlot[SSP][MATCHED].fill(pair.getSecondElement().getHitCount());
+					clusterEnergyPlot[SSP][MATCHED].fill(pair.getSecondElement().getEnergy());
+					clusterTimePlot[SSP][MATCHED].fill(pair.getSecondElement().getTime());
+					clusterPositionPlot[SSP][MATCHED].fill(pair.getSecondElement().getXIndex(), pair.getSecondElement().getYIndex());
+				} if(pair.getFirstElement() != null && pair.getSecondElement() != null) {
+					double energyDiff = pair.getSecondElement().getEnergy() - pair.getFirstElement().getEnergy();
+					int hitDiff = pair.getSecondElement().getHitCount() - pair.getFirstElement().getCalorimeterHits().size();
+					energyhitDiffPlot[MATCHED].fill(energyDiff, hitDiff);
+				}
+			} else {
+				if(pair.getFirstElement() != null) {
+					clusterHitPlot[RECON][FAILED].fill(pair.getFirstElement().getCalorimeterHits().size());
+					clusterEnergyPlot[RECON][FAILED].fill(pair.getFirstElement().getEnergy());
+					clusterTimePlot[RECON][FAILED].fill(pair.getFirstElement().getCalorimeterHits().get(0).getTime());
+					Point position = TriggerDiagnosticUtil.getClusterPosition(pair.getFirstElement());
+					clusterPositionPlot[RECON][FAILED].fill(position.x, position.y);
+				} if(pair.getSecondElement() != null) {
+					clusterHitPlot[SSP][FAILED].fill(pair.getSecondElement().getHitCount());
+					clusterEnergyPlot[SSP][FAILED].fill(pair.getSecondElement().getEnergy());
+					clusterTimePlot[SSP][FAILED].fill(pair.getSecondElement().getTime());
+					clusterPositionPlot[SSP][FAILED].fill(pair.getSecondElement().getXIndex(), pair.getSecondElement().getYIndex());
+				} if(pair.getFirstElement() != null && pair.getSecondElement() != null) {
+					double energyDiff = pair.getSecondElement().getEnergy() - pair.getFirstElement().getEnergy();
+					int hitDiff = pair.getSecondElement().getHitCount() - pair.getFirstElement().getCalorimeterHits().size();
+					energyhitDiffPlot[FAILED].fill(energyDiff, hitDiff);
+				}
+			}
+		}
+	}
+	
+	/**
+     * Performs cluster matching between a collection of reconstructed
+	 * clusters and a collection of SSP clusters with an algorithm that
+	 * ignores the times reported for each cluster.
+	 * @param reconClusters - A collection of reconstructed clusters.
+	 * @param sspClusters - A collection of SSP clusters.
+	 * @param energyWindow - The window of allowed deviation between
+	 * the reconstructed cluster and SSP cluster energies.
+	 * @param hitWindow - The window of allowed deviation between
+	 * the reconstructed cluster and SSP cluster hit counts.
+	 * @return Returns the cluster matching results stored inside a
+	 * <code>clusterMatchEvent</code> object.
+	 */
+	private static final ClusterMatchEvent matchClusters(Collection<Cluster> reconClusters,
+			Collection<SSPCluster> sspClusters, double energyWindow, int hitWindow) {
+		// Track the number of cluster pairs that were matched and that
+		// failed by failure type.
+		ClusterMatchEvent event = new ClusterMatchEvent();
 		
 		// Create maps to link cluster position to the list of clusters
 		// that were found at that location.
@@ -726,12 +999,6 @@
 			// Add the cluster to the list.
 			sspList.add(sspCluster);
 		}
-		
-		
-		
-		// ==========================================================
-		// ==== Perform Cluster Matching ============================
-		// ==========================================================
 		
 		// For each reconstructed cluster, attempt to match the clusters
 		// with SSP clusters at the same position.
@@ -749,17 +1016,11 @@
 			// reason of position. The remainder of the loop may be
 			// skipped, since there is nothing to check.
 			if(sspList == null || sspList.isEmpty()) {
-				clusterFail = true;
 				for(Cluster cluster : reconList) {
 					event.pairFailPosition(cluster, null);
 				}
 				continue positionLoop;
 			}
-			
-			// If there are more reconstructed clusters than there are
-			// SSP clusters, than a number equal to the difference must
-			// fail by means of positions.
-			if(sspList.size() < reconList.size()) { clusterFail = true; }
 			
 			// Get all possible permutations of SSP clusters.
 			List<List<Pair<Cluster, SSPCluster>>> permutations = getPermutations(reconList, sspList);
@@ -794,20 +1055,31 @@
 					// If either cluster in the pair is null, there
 					// are not enough clusters to perform this match.
 					if(pair.getFirstElement() == null || pair.getSecondElement() == null) {
+						// Log the result.
 						OutputLogger.printf(" [ %18s ]%n", "failure: unpaired");
-						perm.pairFailPosition(pair.getFirstElement(), pair.getSecondElement());
+						
+						// An unpaired SSP cluster does not necessarily
+						// represent a problem. Often, this just means
+						// that the SSP cluster's matching reconstructed
+						// cluster is outside the verification window.
+						if(pair.getSecondElement() == null) {
+							perm.pairFailPosition(pair.getFirstElement(), pair.getSecondElement());
+						}
+						
+						// Skip the rest of the checks.
 						continue pairLoop;
 					}
 					
 					// Check if the reconstructed cluster has an energy
 					// within the allotted threshold of the SSP cluster.
-					if(pair.getSecondElement().getEnergy() >= pair.getFirstElement().getEnergy() * (1 - energyAcceptance) &&
-							pair.getSecondElement().getEnergy() <= pair.getFirstElement().getEnergy() * (1 + energyAcceptance)) {
+					if(pair.getSecondElement().getEnergy() >= pair.getFirstElement().getEnergy() - energyWindow &&
+							pair.getSecondElement().getEnergy() <= pair.getFirstElement().getEnergy() + energyWindow) {
+						
 						// Check that the hit count of the reconstructed
 						// is within the allotted threshold of the SSP
 						// cluster.
-						if(pair.getSecondElement().getHitCount() >= pair.getFirstElement().getCalorimeterHits().size() - hitAcceptance &&
-								pair.getSecondElement().getHitCount() <= pair.getFirstElement().getCalorimeterHits().size() + hitAcceptance) {
+						if(pair.getSecondElement().getHitCount() >= pair.getFirstElement().getCalorimeterHits().size() - hitWindow &&
+								pair.getSecondElement().getHitCount() <= pair.getFirstElement().getCalorimeterHits().size() + hitWindow) {
 							// Designate the pair as a match.
 							perm.pairMatch(pair.getFirstElement(), pair.getSecondElement());
 							OutputLogger.printf(" [ %18s ]%n", "success: matched");
@@ -844,69 +1116,113 @@
 			event.addEvent(bestPerm);
 		} // End Crystal Position Loop
 		
-		// Add the event results to the global results.
-		clusterRunStats.addEvent(event, reconClusters, sspClusters);
-		clusterLocalStats.addEvent(event, reconClusters, sspClusters);
-		
-		
-		
-		// ==========================================================
-		// ==== Output Event Summary ================================
-		// ==========================================================
-		
-		// Print the valid reconstructed clusters and populate their
-		// distribution graphs.
-		OutputLogger.println();
-		OutputLogger.println("Verified Reconstructed Clusters:");
-		if(!reconClusters.isEmpty()) {
-			for(Cluster reconCluster : reconClusters) {
-				OutputLogger.printf("\t%s%n", TriggerDiagnosticUtil.clusterToString(reconCluster));
-			}
-		} else { OutputLogger.println("\tNone"); }
-		
-		// Print the SSP clusters and populate their distribution graphs.
-		OutputLogger.println("SSP Clusters:");
-		if(!sspClusters.isEmpty()) {
+		// Return the cluster match summary.
+		return event;
+	}
+	
+	/**
+	 * Performs cluster matching between a collection of reconstructed
+	 * clusters and a collection of SSP clusters using the strictly
+	 * time-compliant algorithm.
+	 * @param reconClusters - A collection of reconstructed clusters.
+	 * @param sspClusters - A collection of SSP clusters.
+	 * @param energyWindow - The window of allowed deviation between
+	 * the reconstructed cluster and SSP cluster energies.
+	 * @param hitWindow - The window of allowed deviation between
+	 * the reconstructed cluster and SSP cluster hit counts.
+	 * @return Returns the cluster matching results stored inside a
+	 * <code>clusterMatchEvent</code> object.
+	 */
+	private static final ClusterMatchEvent matchClustersTimeCompliant(Collection<Cluster> reconClusters,
+			Collection<SSPCluster> sspClusters, double energyWindow, int hitWindow) {
+		// Track the number of cluster pairs that were matched and that
+		// failed by failure type.
+		ClusterMatchEvent event = new ClusterMatchEvent();
+		
+		// Store the clusters which have been successfully paired.
+		Set<SSPCluster> sspMatched = new HashSet<SSPCluster>(sspClusters.size());
+		
+		// Find reconstructed/SSP cluster matched pairs.
+		reconLoop:
+		for(Cluster reconCluster : reconClusters) {
+			// Track whether a position-matched cluster was found.
+			boolean matchedPosition = false;
+			
+			// VERBOSE :: Output the cluster being matched.
+			OutputLogger.printf("Considering %s%n", TriggerDiagnosticUtil.clusterToString(reconCluster));
+			
+			// Search through the SSP clusters for a matching cluster.
+			sspLoop:
 			for(SSPCluster sspCluster : sspClusters) {
-				OutputLogger.printf("\t%s%n", TriggerDiagnosticUtil.clusterToString(sspCluster));
-			}
-		} else { OutputLogger.println("\tNone"); }
-		
-		// Print the matched clusters.
-		OutputLogger.println("Matched Clusters:");
-		if(event.getMatchedPairs().size() != 0) {
-			// Iterate over the matched pairs.
-			for(ClusterMatchedPair pair : event.getMatchedPairs()) {
-				// If the pair is a match, print it out.
-				if(pair.isMatch()) {
-					OutputLogger.printf("\t%s --> %s%n",
-							TriggerDiagnosticUtil.clusterToString(pair.getReconstructedCluster()),
-							TriggerDiagnosticUtil.clusterToString(pair.getSSPCluster()));
-				}
-			}
-		}
-		 else { OutputLogger.println("\tNone"); }
-		
-		// Get the number of position failures.
-		int failPosition = event.getPositionFailures();
-		if(sspClusters == null || sspClusters.isEmpty()) {
-			failPosition = (reconClusters == null ? 0 : reconClusters.size());
-		}
-		
-		// Print event statistics.
-		OutputLogger.println();
-		OutputLogger.println("Event Statistics:");
-		OutputLogger.printf("\tRecon Clusters     :: %d%n", reconClusters.size());
-		OutputLogger.printf("\tClusters Matched   :: %d%n", event.getMatches());
-		OutputLogger.printf("\tFailed (Position)  :: %d%n", failPosition);
-		OutputLogger.printf("\tFailed (Energy)    :: %d%n", event.getEnergyFailures());
-		OutputLogger.printf("\tFailed (Hit Count) :: %d%n", event.getHitCountFailures());
-		OutputLogger.printf("\tCluster Efficiency :: %3.0f%%%n", 100.0 * event.getMatches() / reconClusters.size());
-		
-		// Note whether there was a cluster match failure.
-		if(event.getMatches() - reconClusters.size() != 0) {
-			clusterFail = true;
-		}
+				// VERBOSE :: Output the SSP cluster being considered.
+				OutputLogger.printf("\t%s ", TriggerDiagnosticUtil.clusterToString(sspCluster));
+				
+				// If this cluster has been paired, skip it.
+				if(sspMatched.contains(sspCluster)) {
+					OutputLogger.printf("[ %7s; %9s ]%n", "fail", "matched");
+					continue sspLoop;
+				}
+				
+				// Matched clusters must have the same position.
+				if(TriggerDiagnosticUtil.getXIndex(reconCluster) != sspCluster.getXIndex()
+						|| TriggerDiagnosticUtil.getYIndex(reconCluster) != sspCluster.getYIndex()) {
+					OutputLogger.printf("[ %7s; %9s ]%n", "fail", "position");
+					continue sspLoop;
+				}
+				
+				// Note that a cluster was found at this position.
+				matchedPosition = true;
+				
+				// Matched clusters must have the same time-stamp.
+				if(reconCluster.getCalorimeterHits().get(0).getTime() != sspCluster.getTime()) {
+					OutputLogger.printf("[ %7s; %9s ]%n", "fail", "time");
+					continue sspLoop;
+				}
+				
+				// Clusters that pass all of the above checks are the
+				// same cluster.
+				sspMatched.add(sspCluster);
+				
+				// Check that the clusters are sufficiently close in
+				// energy to one another.
+				if(sspCluster.getEnergy() >= reconCluster.getEnergy() - energyWindow
+						&& sspCluster.getEnergy() <= reconCluster.getEnergy() + energyWindow) {
+					// If a cluster matches in energy, check that it
+					// is also sufficiently close in hit count.
+					if(sspCluster.getHitCount() >= reconCluster.getCalorimeterHits().size() - hitWindow &&
+							sspCluster.getHitCount() <= reconCluster.getCalorimeterHits().size() + hitWindow) {
+						// The cluster is a match.
+						event.pairMatch(reconCluster, sspCluster);
+						OutputLogger.printf("[ %7s; %9s ]%n", "success", "matched");
+						continue reconLoop;
+					} else {
+						event.pairFailHitCount(reconCluster, sspCluster);
+						OutputLogger.printf("[ %7s; %9s ]%n", "fail", "hit count");
+						continue reconLoop;
+					} // End hit count check.
+				} else {
+					event.pairFailEnergy(reconCluster, sspCluster);
+					OutputLogger.printf("[ %7s; %9s ]%n", "fail", "energy");
+					continue reconLoop;
+				} // End energy check.
+			}// End SSP loop.
+			
+			// If the reconstructed cluster has not been matched, check
+			// if a cluster was found at the same position. If not, then
+			// the cluster fails by reason of position.
+			if(!matchedPosition) {
+				event.pairFailPosition(reconCluster, null);
+			}
+			
+			// Otherwise, the cluster had a potential matched, but the
+			// time-stamps were off. The cluster fails by reason of time.
+			else {
+				event.pairFailTime(reconCluster, null);
+			}
+		} // End recon loop.
+		
+		// Return the populated match event.
+		return event;
 	}
 	
 	/**
@@ -1002,9 +1318,9 @@
 		OutputLogger.println("SSP Cluster " + (isSingles ? "Singles" : "Pair") + " Triggers");
 		for(int triggerNum = 0; triggerNum < 2; triggerNum++) {
 			for(Trigger<?> simTrigger : sspTriggerList.get(triggerNum)) {
-				OutputLogger.printf("\tTrigger %d :: %s :: %s%n",
+				OutputLogger.printf("\tTrigger %d :: %s :: %3.0f :: %s%n",
 						(triggerNum + 1), triggerPositionString(simTrigger),
-						simTrigger.toString());
+						getTriggerTime(simTrigger), simTrigger.toString());
 			}
 		}
 		if(sspTriggerList.get(0).size() + sspTriggerList.get(1).size() == 0) {
@@ -1015,9 +1331,9 @@
 		OutputLogger.println("Reconstructed Cluster " + (isSingles ? "Singles" : "Pair") + " Triggers");
 		for(int triggerNum = 0; triggerNum < 2; triggerNum++) {
 			for(Trigger<?> simTrigger : reconTriggerList.get(triggerNum)) {
-				OutputLogger.printf("\tTrigger %d :: %s :: %s%n",
+				OutputLogger.printf("\tTrigger %d :: %s :: %3.0f :: %s%n",
 						(triggerNum + 1), triggerPositionString(simTrigger),
-						simTrigger.toString());
+						getTriggerTime(simTrigger), simTrigger.toString());
 			}
 		}
 		if(reconTriggerList.get(0).size() + reconTriggerList.get(1).size() == 0) {
@@ -1053,31 +1369,53 @@
 		
 		// Iterate over the triggers.
 		OutputLogger.println();
-		OutputLogger.println("SSP Reported Trigger --> SSP Cluster Trigger Match Status");
+		OutputLogger.println("Matching SSP Reported Triggers to SSP Simulated Trigger:");
 		for(SSPNumberedTrigger sspTrigger : sspTriggers) {
 			// Get the trigger information.
 			int triggerNum = sspTrigger.isFirstTrigger() ? 0 : 1;
-			boolean matchedTrigger = false;
+			OutputLogger.printf("Considering %s%n", sspTrigger.toString());
 			
 			// Iterate over the SSP cluster simulated triggers and
 			// look for a trigger that matches.
 			matchLoop:
 			for(Trigger<?> simTrigger : sspTriggerList.get(triggerNum)) {
-				// If the current SSP trigger has already been
-				// matched, skip it.
-				if(sspTriggerSet.contains(sspTrigger)) { continue matchLoop; }
-				
-				// Otherwise, check whether the reconstructed SSP
-				// cluster trigger matches the SSP trigger.
-				if(compareTriggers(sspTrigger, simTrigger)) {
-					matchedTrigger = true;
-					sspTriggerSet.add(sspTrigger);
-					simTriggerSet.add(simTrigger);
-					event.matchedSSPPair(simTrigger, sspTrigger);
-					break matchLoop;
-				}
-				
-				OutputLogger.printf("\t%s :: Matched: %5b%n", sspTrigger.toString(), matchedTrigger);
+				// VERBOSE :: Output the trigger being considered for
+				//            matching.
+				OutputLogger.printf("\tTrigger %d :: %s :: %3.0f :: %s ",
+						(triggerNum + 1), triggerPositionString(simTrigger),
+						getTriggerTime(simTrigger), simTrigger.toString());
+				
+				// If the current SSP trigger has already been matched,
+				// skip it.
+				if(simTriggerSet.contains(simTrigger)) {
+					OutputLogger.printf("[ %-15s ]%n", "failed; matched");
+					continue matchLoop;
+				}
+				
+				// Check that the triggers have the same time. Triggers
+				// generated from SSP bank clusters should always align
+				// in time.
+				if(sspTrigger.getTime() != getTriggerTime(simTrigger)) {
+					OutputLogger.printf("[ %-15s ]%n", "failed; time");
+					continue matchLoop;
+				}
+				
+				// Check whether the trigger cuts match.
+				boolean[] matchedCuts = triggerCutMatch(simTrigger, sspTrigger);
+				for(int i = 0; i < matchedCuts.length; i++) {
+					if(!matchedCuts[i]) {
+						OutputLogger.printf("[ %-15s ]%n", String.format("failed; cut %d", i));
+						continue matchLoop;
+					}
+				}
+				
+				// If all the cuts match, along with the time and the
+				// trigger number, than these triggers are a match.
+				sspTriggerSet.add(sspTrigger);
+				simTriggerSet.add(simTrigger);
+				event.matchedSSPPair(simTrigger, sspTrigger);
+				OutputLogger.printf("[ %-15s ]%n", "success");
+				break matchLoop;
 			}
 		}
 		
@@ -1132,7 +1470,6 @@
 				// If there was no match found, it means that there were
 				// no triggers that were both unmatched and at the same
 				// time as this simulated trigger.
-				
 				if(bestMatch == null) {
 					if(isSingles) { singlesInternalFail = true; }
 					else { pairInternalFail = true; }
@@ -1213,10 +1550,9 @@
 		
 		// Get the number of SSP and reconstructed cluster simulated
 		// triggers.
-		
 		int sspSimTriggers = sspTriggerList.get(0).size() + sspTriggerList.get(1).size();
 		int reconSimTriggers = reconTriggerList.get(0).size() + reconTriggerList.get(1).size();
-		int halfSimTriggers = sspSimTriggers / 2;
+		int[] sspTriggerCount = { sspTriggerList.get(0).size(), sspTriggerList.get(1).size() };
 		
 		// Print event statistics.
 		OutputLogger.println();
@@ -1245,16 +1581,19 @@
 			for(int triggerNum = 0; triggerNum < 2; triggerNum++) {
 				OutputLogger.printf("Trigger %d Individual Cut Failure Rate:%n", (triggerNum + 1));
 				if(sspSimTriggers == 0) {
-					OutputLogger.printf("\tCluster Energy Lower Bound :: %d / %d%n", event.getCutFailures(triggerNum, ENERGY_MIN), halfSimTriggers);
-					OutputLogger.printf("\tCluster Energy Upper Bound :: %d / %d%n", event.getCutFailures(triggerNum, ENERGY_MAX), halfSimTriggers);
-					OutputLogger.printf("\tCluster Hit Count          :: %d / %d%n", event.getCutFailures(triggerNum, HIT_COUNT), halfSimTriggers);
+					OutputLogger.printf("\tCluster Energy Lower Bound :: %d / %d%n", event.getCutFailures(triggerNum, ENERGY_MIN), sspTriggerCount[triggerNum]);
+					OutputLogger.printf("\tCluster Energy Upper Bound :: %d / %d%n", event.getCutFailures(triggerNum, ENERGY_MAX), sspTriggerCount[triggerNum]);
+					OutputLogger.printf("\tCluster Hit Count          :: %d / %d%n", event.getCutFailures(triggerNum, HIT_COUNT), sspTriggerCount[triggerNum]);
 				} else {
 					OutputLogger.printf("\tCluster Energy Lower Bound :: %d / %d (%3.0f%%)%n",
-							event.getCutFailures(triggerNum, ENERGY_MIN), halfSimTriggers, (100.0 * event.getCutFailures(triggerNum, ENERGY_MIN) / halfSimTriggers));
+							event.getCutFailures(triggerNum, ENERGY_MIN), sspTriggerCount[triggerNum],
+							(100.0 * event.getCutFailures(triggerNum, ENERGY_MIN) / sspTriggerCount[triggerNum]));
 					OutputLogger.printf("\tCluster Energy Upper Bound :: %d / %d (%3.0f%%)%n",
-							event.getCutFailures(triggerNum, ENERGY_MAX), halfSimTriggers, (100.0 * event.getCutFailures(triggerNum, ENERGY_MAX) / halfSimTriggers));
+							event.getCutFailures(triggerNum, ENERGY_MAX), sspTriggerCount[triggerNum],
+							(100.0 * event.getCutFailures(triggerNum, ENERGY_MAX) / sspTriggerCount[triggerNum]));
 					OutputLogger.printf("\tCluster Hit Count          :: %d / %d (%3.0f%%)%n",
-							event.getCutFailures(triggerNum, HIT_COUNT), halfSimTriggers, (100.0 * event.getCutFailures(triggerNum, HIT_COUNT) / halfSimTriggers));
+							event.getCutFailures(triggerNum, HIT_COUNT), sspTriggerCount[triggerNum],
+							(100.0 * event.getCutFailures(triggerNum, HIT_COUNT) / sspTriggerCount[triggerNum]));
 				}
 				OutputLogger.printf("\tExcess Reported Triggers   :: %d%n", sspReportedExtras / 2);
 			}
@@ -1270,20 +1609,24 @@
 			for(int triggerNum = 0; triggerNum < 2; triggerNum++) {
 				OutputLogger.println();
 				OutputLogger.printf("Trigger %d Individual Cut Failure Rate:%n", (triggerNum + 1));
-				if(sspSimTriggers == 0) {
-					OutputLogger.printf("\tPair Energy Sum            :: %d / %d%n", event.getCutFailures(triggerNum, ENERGY_SUM), halfSimTriggers);
-					OutputLogger.printf("\tPair Energy Difference     :: %d / %d%n", event.getCutFailures(triggerNum, ENERGY_DIFF), halfSimTriggers);
-					OutputLogger.printf("\tPair Energy Slope          :: %d / %d%n", event.getCutFailures(triggerNum, ENERGY_SLOPE), halfSimTriggers);
-					OutputLogger.printf("\tPair Coplanarity           :: %d / %d%n", event.getCutFailures(triggerNum, COPLANARITY), halfSimTriggers);
+				if(sspTriggerCount[triggerNum] == 0) {
+					OutputLogger.printf("\tPair Energy Sum            :: %d / %d%n", event.getCutFailures(triggerNum, ENERGY_SUM), sspTriggerCount[triggerNum]);
+					OutputLogger.printf("\tPair Energy Difference     :: %d / %d%n", event.getCutFailures(triggerNum, ENERGY_DIFF), sspTriggerCount[triggerNum]);
+					OutputLogger.printf("\tPair Energy Slope          :: %d / %d%n", event.getCutFailures(triggerNum, ENERGY_SLOPE), sspTriggerCount[triggerNum]);
+					OutputLogger.printf("\tPair Coplanarity           :: %d / %d%n", event.getCutFailures(triggerNum, COPLANARITY), sspTriggerCount[triggerNum]);
 				} else {
 					OutputLogger.printf("\tPair Energy Sum            :: %d / %d (%3.0f%%)%n",
-							event.getCutFailures(triggerNum, ENERGY_SUM), halfSimTriggers, (100.0 * event.getCutFailures(triggerNum, ENERGY_SUM) / halfSimTriggers));
+							event.getCutFailures(triggerNum, ENERGY_SUM), sspTriggerCount[triggerNum],
+							(100.0 * event.getCutFailures(triggerNum, ENERGY_SUM) / sspTriggerCount[triggerNum]));
 					OutputLogger.printf("\tPair Energy Difference     :: %d / %d (%3.0f%%)%n",
-							event.getCutFailures(triggerNum, ENERGY_DIFF), halfSimTriggers, (100.0 * event.getCutFailures(triggerNum, ENERGY_DIFF) / halfSimTriggers));
+							event.getCutFailures(triggerNum, ENERGY_DIFF), sspTriggerCount[triggerNum],
+							(100.0 * event.getCutFailures(triggerNum, ENERGY_DIFF) / sspTriggerCount[triggerNum]));
 					OutputLogger.printf("\tPair Energy Slope          :: %d / %d (%3.0f%%)%n",
-							event.getCutFailures(triggerNum, ENERGY_SLOPE), halfSimTriggers, (100.0 * event.getCutFailures(triggerNum, ENERGY_SLOPE) / halfSimTriggers));
+							event.getCutFailures(triggerNum, ENERGY_SLOPE), sspTriggerCount[triggerNum],
+							(100.0 * event.getCutFailures(triggerNum, ENERGY_SLOPE) / sspTriggerCount[triggerNum]));
 					OutputLogger.printf("\tPair Coplanarity           :: %d / %d (%3.0f%%)%n",
-							event.getCutFailures(triggerNum, COPLANARITY), halfSimTriggers, (100.0 * event.getCutFailures(triggerNum, COPLANARITY) / halfSimTriggers));
+							event.getCutFailures(triggerNum, COPLANARITY), sspTriggerCount[triggerNum],
+							(100.0 * event.getCutFailures(triggerNum, COPLANARITY) / sspTriggerCount[triggerNum]));
 				}
 				OutputLogger.printf("\tExcess Reported Triggers   :: %d%n", sspReportedExtras / 2);
 			}
@@ -1298,9 +1641,12 @@
 		}
 		
 		// Note whether the was a trigger match failure.
-		if((event.getMatchedReconTriggers() - reconSimTriggers != 0) || (event.getMatchedSSPTriggers() - sspSimTriggers != 0)) {
+		if(event.getMatchedReconTriggers() - reconSimTriggers != 0) {
 			if(isSingles) { singlesEfficiencyFail = true; }
 			else { pairEfficiencyFail = true; }
+		} if(event.getMatchedSSPTriggers() - sspSimTriggers != 0) {
+			if(isSingles) { singlesInternalFail = true; }
+			else { pairInternalFail = true; }
 		}
 	}
 	
@@ -1312,6 +1658,7 @@
 		// Run the SSP clusters through the singles trigger to determine
 		// whether they pass it or not.
 		for(SSPCluster cluster : sspClusters) {
+			triggerLoop:
 			for(int triggerNum = 0; triggerNum < 2; triggerNum++) {
 				// For a cluster to have formed it is assumed to have passed
 				// the cluster seed energy cuts. This can not be verified
@@ -1332,7 +1679,19 @@
 				trigger.setStateClusterEnergyHigh(passClusterHigh);
 				trigger.setStateHitCount(passHitCount);
 				
-				// Store the trigger.
+				// A trigger will only be reported by the SSP if it
+				// passes all of the enabled cuts for that trigger.
+				// Check whether this trigger meets these conditions.
+				if(singlesCutsEnabled[triggerNum][ENERGY_MIN] && !trigger.getStateClusterEnergyLow()) {
+					continue triggerLoop;
+				} if(singlesCutsEnabled[triggerNum][ENERGY_MAX] && !trigger.getStateClusterEnergyHigh()) {
+					continue triggerLoop;
+				} if(singlesCutsEnabled[triggerNum][HIT_COUNT] && !trigger.getStateHitCount()) {
+					continue triggerLoop;
+				}
+				
+				// If all the necessary checks passed, store the new
+				// trigger for verification.
 				sspSinglesTriggers.get(triggerNum).add(trigger);
 			}
 		}
@@ -1341,6 +1700,7 @@
 		// to determine whether they pass it or not.
 		for(Cluster cluster : reconClusters) {
 			// Simulate each of the cluster singles triggers.
+			triggerLoop:
 			for(int triggerNum = 0; triggerNum < 2; triggerNum++) {
 				// For a cluster to have formed it is assumed to have passed
 				// the cluster seed energy cuts. This can not be verified
@@ -1360,6 +1720,17 @@
 				trigger.setStateClusterEnergyLow(passClusterLow);
 				trigger.setStateClusterEnergyHigh(passClusterHigh);
 				trigger.setStateHitCount(passHitCount);
+				
+				// A trigger will only be reported by the SSP if it
+				// passes all of the enabled cuts for that trigger.
+				// Check whether this trigger meets these conditions.
+				if(singlesCutsEnabled[triggerNum][ENERGY_MIN] && !trigger.getStateClusterEnergyLow()) {
+					continue triggerLoop;
+				} if(singlesCutsEnabled[triggerNum][ENERGY_MAX] && !trigger.getStateClusterEnergyHigh()) {
+					continue triggerLoop;
+				} if(singlesCutsEnabled[triggerNum][HIT_COUNT] && !trigger.getStateHitCount()) {
+					continue triggerLoop;
+				}
 				
 				// Store the trigger.
 				reconSinglesTriggers.get(triggerNum).add(trigger);
@@ -1417,13 +1788,13 @@
 		// Simulate the pair triggers and record the results.
 		for(Cluster[] reconPair : reconPairs) {
 			// Simulate each of the cluster pair triggers.
-			reconTriggerLoop:
+			pairTriggerLoop:
 			for(int triggerIndex = 0; triggerIndex < 2; triggerIndex++) {
 				// Check that the pair passes the time coincidence cut.
 				// If it does not, it is not a valid pair and should be
 				// destroyed.
 				if(!pairsTrigger[triggerIndex].pairTimeCoincidenceCut(reconPair)) {
-					continue reconTriggerLoop;
+					continue pairTriggerLoop;
 				}
 				
 				// For a cluster to have formed it is assumed to have passed
@@ -1460,6 +1831,25 @@
 				trigger.setStateCoplanarity(passPairCoplanarity);
 				trigger.setStateTimeCoincidence(passTimeCoincidence);
 				
+				// A trigger will only be reported by the SSP if it
+				// passes all of the enabled cuts for that trigger.
+				// Check whether this trigger meets these conditions.
+				if(pairCutsEnabled[triggerIndex][ENERGY_MIN] && !trigger.getStateClusterEnergyLow()) {
+					continue pairTriggerLoop;
+				} if(pairCutsEnabled[triggerIndex][ENERGY_MAX] && !trigger.getStateClusterEnergyHigh()) {
+					continue pairTriggerLoop;
+				} if(pairCutsEnabled[triggerIndex][HIT_COUNT] && !trigger.getStateHitCount()) {
+					continue pairTriggerLoop;
+				} if(pairCutsEnabled[triggerIndex][3 + ENERGY_SUM] && !trigger.getStateEnergySum()) {
+					continue pairTriggerLoop;
+				} if(pairCutsEnabled[triggerIndex][3 + ENERGY_DIFF] && !trigger.getStateEnergyDifference()) {
+					continue pairTriggerLoop;
+				} if(pairCutsEnabled[triggerIndex][3 + ENERGY_SLOPE] && !trigger.getStateEnergySlope()) {
+					continue pairTriggerLoop;
+				} if(pairCutsEnabled[triggerIndex][3 + COPLANARITY] && !trigger.getStateCoplanarity()) {
+					continue pairTriggerLoop;
+				}
+				
 				// Add the trigger to the list.
 				reconPairsTriggers.get(triggerIndex).add(trigger);
 			}
@@ -1509,6 +1899,25 @@
 				trigger.setStateCoplanarity(passPairCoplanarity);
 				trigger.setStateTimeCoincidence(passTimeCoincidence);
 				
+				// A trigger will only be reported by the SSP if it
+				// passes all of the enabled cuts for that trigger.
+				// Check whether this trigger meets these conditions.
+				if(pairCutsEnabled[triggerIndex][ENERGY_MIN] && !trigger.getStateClusterEnergyLow()) {
+					continue pairTriggerLoop;
+				} if(pairCutsEnabled[triggerIndex][ENERGY_MAX] && !trigger.getStateClusterEnergyHigh()) {
+					continue pairTriggerLoop;
+				} if(pairCutsEnabled[triggerIndex][HIT_COUNT] && !trigger.getStateHitCount()) {
+					continue pairTriggerLoop;
+				} if(pairCutsEnabled[triggerIndex][3 + ENERGY_SUM] && !trigger.getStateEnergySum()) {
+					continue pairTriggerLoop;
+				} if(pairCutsEnabled[triggerIndex][3 + ENERGY_DIFF] && !trigger.getStateEnergyDifference()) {
+					continue pairTriggerLoop;
+				} if(pairCutsEnabled[triggerIndex][3 + ENERGY_SLOPE] && !trigger.getStateEnergySlope()) {
+					continue pairTriggerLoop;
+				} if(pairCutsEnabled[triggerIndex][3 + COPLANARITY] && !trigger.getStateCoplanarity()) {
+					continue pairTriggerLoop;
+				}
+				
 				// Add the trigger to the list.
 				sspPairsTriggers.get(triggerIndex).add(trigger);
 			}
@@ -1524,8 +1933,9 @@
 	private void logSettings() {
 		// Output general settings.
 		System.out.println("Cluster Verification Settings");
-		System.out.printf("\tEnergy Threshold       :: %1.2f%%%n", energyAcceptance);
-		System.out.printf("\tHit Threshold          :: %1d%n", hitAcceptance);
+		System.out.printf("\tHit Threshold          :: %1d hit(s)%n", hitAcceptance);
+		System.out.printf("\tEnergy Threshold       :: %5.3f GeV%n",  energyAcceptance);
+		System.out.println();
 		
 		// Output window settings.
 		System.out.println("FADC Timing Window Settings");
@@ -1544,28 +1954,45 @@
 			System.out.println("\tCluster verification will not be performed!");
 			performClusterVerification = false;
 		}
+		System.out.println();
 		
 		// Output the singles trigger settings.
 		for(int i = 0; i < 2; i++) {
-			System.out.printf("Singles Trigger %d Settings%n", (i + 1));
-			System.out.printf("\tCluster Energy Low     :: %.3f GeV%n", singlesTrigger[i].getCutValue(TriggerModule.CLUSTER_TOTAL_ENERGY_LOW));
-			System.out.printf("\tCluster Energy High    :: %.3f GeV%n", singlesTrigger[i].getCutValue(TriggerModule.CLUSTER_TOTAL_ENERGY_HIGH));
-			System.out.printf("\tCluster Hit Count      :: %.0f hits%n", singlesTrigger[i].getCutValue(TriggerModule.CLUSTER_HIT_COUNT_LOW));
+			// 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%n", (i + 1));
-			System.out.printf("\tCluster Energy Low     :: %.3f GeV%n", pairsTrigger[i].getCutValue(TriggerModule.CLUSTER_TOTAL_ENERGY_LOW));
-			System.out.printf("\tCluster Energy High    :: %.3f GeV%n", pairsTrigger[i].getCutValue(TriggerModule.CLUSTER_TOTAL_ENERGY_HIGH));
-			System.out.printf("\tCluster Hit Count      :: %.0f hits%n", pairsTrigger[i].getCutValue(TriggerModule.CLUSTER_HIT_COUNT_LOW));
-			System.out.printf("\tPair Energy Sum Low    :: %.3f GeV%n", pairsTrigger[i].getCutValue(TriggerModule.PAIR_ENERGY_SUM_LOW));
-			System.out.printf("\tPair Energy Sum Low    :: %.3f GeV%n", pairsTrigger[i].getCutValue(TriggerModule.PAIR_ENERGY_SUM_HIGH));
-			System.out.printf("\tPair Energy Difference :: %.3f GeV%n", pairsTrigger[i].getCutValue(TriggerModule.PAIR_ENERGY_DIFFERENCE_HIGH));
-			System.out.printf("\tPair Energy Slope      :: %.3f GeV%n", pairsTrigger[i].getCutValue(TriggerModule.PAIR_ENERGY_SLOPE_LOW));
-			System.out.printf("\tPair Energy Slope F    :: %.3f GeV / mm%n", pairsTrigger[i].getCutValue(TriggerModule.PAIR_ENERGY_SLOPE_F));
-			System.out.printf("\tPair Coplanarity       :: %.0f Degrees%n", pairsTrigger[i].getCutValue(TriggerModule.PAIR_COPLANARITY_HIGH));
-			System.out.printf("\tPair Time Coincidence  :: %.0f ns%n", pairsTrigger[i].getCutValue(TriggerModule.PAIR_TIME_COINCIDENCE));
+			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    :: %.3f 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();
 		}
 	}
 	
@@ -1578,122 +2005,6 @@
 	 */
 	private final boolean isVerifiable(Cluster reconCluster) {
 		return TriggerDiagnosticUtil.isVerifiable(reconCluster, nsa, nsb, windowWidth);
-	}
-	
-	/**
-	 * Compares an SSP trigger with a simulated trigger. Note that only
-	 * certain class combinations are supported. Triggers of the type
-	 * <code>SSPSinglesTrigger</code> may be compared with triggers of
-	 * the type <code>SinglesTrigger<SSPCluster></code> and triggers of
-	 * the type <code>SSPPairTrigger</code> may be compared to either
-	 * <code>PairTrigger<SSPCluster[]></code> triggers objects.
-	 * @param bankTrigger - The SSP bank trigger.
-	 * @param simTrigger - The simulated trigger.
-	 * @return Returns <code>true</code> if the triggers are valid
-	 * matches and <code>false</code> if they are not.
-	 * @throws IllegalArgumentException Occurs if the trigger types
-	 * are not of a supported type.
-	 */
-	@SuppressWarnings("unchecked")
-	private static final boolean compareTriggers(SSPNumberedTrigger bankTrigger, Trigger<?> simTrigger) throws IllegalArgumentException {
-		// Get the classes of the arguments. This is used to check the
-		// generic type of the Trigger<?> object, and means that the
-		// "unchecked" warnings can be safely ignored.
-		Object source = simTrigger.getTriggerSource();
-		
-		// If the combination of classes is supported, pass the triggers
-		// to the appropriate handler.
-		if(bankTrigger instanceof SSPSinglesTrigger && simTrigger instanceof SinglesTrigger && source instanceof SSPCluster) {
-			return compareSSPSinglesTriggers((SSPSinglesTrigger) bankTrigger, (SinglesTrigger<SSPCluster>) simTrigger);
-		} else if(bankTrigger instanceof SSPPairTrigger && simTrigger instanceof PairTrigger && source instanceof SSPCluster[]) {
-			return compareSSPPairTriggers((SSPPairTrigger) bankTrigger, (PairTrigger<SSPCluster[]>) simTrigger);
-		}
-		
-		// Otherwise, the trigger combination is not supported. Produce
-		// and exception.
-		throw new IllegalArgumentException(String.format("Trigger type \"%s\" can not be compared to trigger type \"%s\" with source type \"%s\".",
-				bankTrigger.getClass().getSimpleName(), simTrigger.getClass().getSimpleName(), source.getClass().getSimpleName()));
-	}
-	
-	/**
-	 * Compares a trigger from the SSP bank to a trigger simulated on
-	 * an SSP cluster.
-	 * @param bankTrigger - The trigger from the SSP bank.
-	 * @param simTrigger - The trigger from the simulation.
-	 * @return Returns <code>true</code> if the triggers match and
-	 * <code>false</code> if they do not.
-	 */
-	private static final boolean compareSSPSinglesTriggers(SSPSinglesTrigger bankTrigger, SinglesTrigger<SSPCluster> simTrigger) {
-		// The bank trigger and simulated trigger must have the same
-		// time. This is equivalent to the time of the triggering cluster.
-		if(bankTrigger.getTime() != simTrigger.getTriggerSource().getTime()) {
-			return false;
-		}
-		
-		// If the time stamp is the same, check that the trigger flags
-		// are all the same. Start with cluster energy low.
-		if(bankTrigger.passCutEnergyMin() != simTrigger.getStateClusterEnergyLow()) {
-			return false;
-		}
-		
-		// Check cluster energy high.
-		if(bankTrigger.passCutEnergyMax() != simTrigger.getStateClusterEnergyHigh()) {
-			return false;
-		}
-		
-		// Check cluster hit count.
-		if(bankTrigger.passCutHitCount() != simTrigger.getStateHitCount()) {
-			return false;
-		}
-		
-		// If all of the tests are successful, the triggers match.
-		return true;
-	}
-	
-	/**
-	 * Compares a trigger from the SSP bank to a trigger simulated on
-	 * an SSP cluster.
-	 * @param bankTrigger - The trigger from the SSP bank.
-	 * @param simTrigger - The trigger from the simulation.
-	 * @return Returns <code>true</code> if the triggers match and
-	 * <code>false</code> if they do not.
-	 */
-	private static final boolean compareSSPPairTriggers(SSPPairTrigger bankTrigger, PairTrigger<SSPCluster[]> simTrigger) {
-		// Get the time of the bottom cluster in the pair.
-		int simTime = 0;
-		if(simTrigger.getTriggerSource()[0].getYIndex() < 0) {
-			simTime = simTrigger.getTriggerSource()[0].getTime();
-		} else {
-			simTime = simTrigger.getTriggerSource()[1].getTime();
-		}
-		
-		// The bank trigger and simulated trigger must have the same
-		// time. This is equivalent to the time of the triggering cluster.
-		if(bankTrigger.getTime() != simTime) { return false; }
-		
-		// If the time stamp is the same, check that the trigger flags
-		// are all the same. Start with energy sum.
-		if(bankTrigger.passCutEnergySum() != simTrigger.getStateEnergySum()) {
-			return false;
-		}
-		
-		// Check pair energy difference.
-		if(bankTrigger.passCutEnergyDifference() != simTrigger.getStateEnergyDifference()) {
-			return false;
-		}
-		
-		// Check pair energy slope.
-		if(bankTrigger.passCutEnergySlope() != simTrigger.getStateEnergySlope()) {
-			return false;
-		}
-		
-		// Check pair coplanarity.
-		if(bankTrigger.passCutCoplanarity() != simTrigger.getStateCoplanarity()) {
-			return false;
-		}
-		
-		// If all of the tests are successful, the triggers match.
-		return true;
 	}
 	
 	/**

Modified: java/trunk/analysis/src/main/java/org/hps/analysis/trigger/event/ClusterMatchEvent.java
 =============================================================================
--- java/trunk/analysis/src/main/java/org/hps/analysis/trigger/event/ClusterMatchEvent.java	(original)
+++ java/trunk/analysis/src/main/java/org/hps/analysis/trigger/event/ClusterMatchEvent.java	Thu Mar 12 15:08:54 2015
@@ -21,6 +21,7 @@
 	private int failPosition = 0;
 	private int failEnergy = 0;
 	private int failHitCount = 0;
+	private int failTime = 0;
 	
 	// Store all of the pairs.
 	private List<ClusterMatchedPair> pairList = new ArrayList<ClusterMatchedPair>();
@@ -46,6 +47,7 @@
 			if(cmp.isPositionFailState()) { failPosition++; }
 			if(cmp.isEnergyFailState()) { failEnergy++; }
 			if(cmp.isHitCountFailState()) { failHitCount++; }
+			if(cmp.isTimeFailState()) { failTime++; }
 		}
 	}
 	
@@ -100,6 +102,26 @@
 	}
 	
 	/**
+	 * Gets the number of cluster pairs stored in this event that are
+	 * marked with time fail states.
+	 * @return Returns the number of instances of this state as an
+	 * <code>int</code> primitive.
+	 */
+	public int getTimeFailures() {
+		return failTime;
+	}
+	
+	/**
+	 * Indicates whether at least one cluster pair in the event created
+	 * a fail state.
+	 * @return Returns <code>true</code> if not all clusters matched and
+	 * <code>false</code> otherwise.
+	 */
+	public boolean isFailState() {
+		return (failEnergy > 0) || (failHitCount > 0) || (failTime > 0) || (failPosition > 0);
+	}
+	
+	/**
 	 * Adds a reconstructed/SSP cluster pair and marks it as having an
 	 * energy fail state.
 	 * @param reconCluster - The reconstructed cluster.
@@ -134,6 +156,17 @@
 	
 	/**
 	 * Adds a reconstructed/SSP cluster pair and marks it as having a
+	 * time fail state.
+	 * @param reconCluster - The reconstructed cluster.
+	 * @param sspCluster - The SSP cluster.
+	 */
+	public void pairFailTime(Cluster reconCluster, SSPCluster sspCluster) {
+		failTime++;
+		pairList.add(new ClusterMatchedPair(reconCluster, sspCluster, TriggerDiagnosticUtil.CLUSTER_STATE_FAIL_TIME));
+	}
+	
+	/**
+	 * Adds a reconstructed/SSP cluster pair and marks it as having a
 	 * match state.
 	 * @param reconCluster - The reconstructed cluster.
 	 * @param sspCluster - The SSP cluster.

Modified: java/trunk/analysis/src/main/java/org/hps/analysis/trigger/event/ClusterMatchStatus.java
 =============================================================================
--- java/trunk/analysis/src/main/java/org/hps/analysis/trigger/event/ClusterMatchStatus.java	(original)
+++ java/trunk/analysis/src/main/java/org/hps/analysis/trigger/event/ClusterMatchStatus.java	Thu Mar 12 15:08:54 2015
@@ -1,11 +1,7 @@
 package org.hps.analysis.trigger.event;
 
-import java.awt.Point;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 
-import org.hps.analysis.trigger.util.TriggerDiagnosticUtil;
 import org.hps.readout.ecal.triggerbank.SSPCluster;
 import org.lcsim.event.Cluster;
 
@@ -16,27 +12,6 @@
  * @author Kyle McCarty
  */
 public class ClusterMatchStatus extends ClusterStatModule {
-	// Plot binning values.
-	private static final int TIME_BIN = 4;
-	private static final double ENERGY_BIN = 0.01;
-	private static final int TIME_BIN_HALF = TIME_BIN / 2;
-	private static final double ENERGY_BIN_HALF = ENERGY_BIN / 2;
-	
-	// Track plotting values for reconstructed and SSP clusters.
-	private Map<Integer, Integer> sspHitCountBins = new HashMap<Integer, Integer>();
-	private Map<Integer, Integer> reconHitCountBins = new HashMap<Integer, Integer>();
-	private Map<Point, Integer> sspPositionBins = new HashMap<Point, Integer>();
-	private Map<Point, Integer> reconPositionBins = new HashMap<Point, Integer>();
-	private Map<Integer, Integer> sspEnergyBins = new HashMap<Integer, Integer>();
-	private Map<Integer, Integer> reconEnergyBins = new HashMap<Integer, Integer>();
-	
-	// Track plotting values for cluster matching results.
-	private Map<Point, Integer> failPositionBins = new HashMap<Point, Integer>();
-	private Map<Point, Integer> allHenergyBins = new HashMap<Point, Integer>();
-	private Map<Point, Integer> failHenergyBins = new HashMap<Point, Integer>();
-	private Map<Integer, Integer> allTimeBins = new HashMap<Integer, Integer>();
-	private Map<Integer, Integer> failTimeBins = new HashMap<Integer, Integer>();
-	
     public void addEvent(ClusterMatchEvent event, List<Cluster> reconClusters, List<SSPCluster> sspClusters) {
     	// Update the number of reconstructed and SSP clusters
 		// that have been seen so far.
@@ -57,91 +32,6 @@
 		if(sspClusters == null || sspClusters.isEmpty()) {
 			failPosition += (reconClusters == null ? 0 : reconClusters.size());
 		}
-    	
-    	// Update the plotting information for reconstructed clusters.
-		for(Cluster cluster : reconClusters) {
-			// Update the hit count bin data.
-			Integer hitCountCount = reconHitCountBins.get(cluster.getCalorimeterHits().size());
-			if(hitCountCount == null) { reconHitCountBins.put(cluster.getCalorimeterHits().size(), 1); }
-			else { reconHitCountBins.put(cluster.getCalorimeterHits().size(), hitCountCount + 1); }
-			
-			// Update the position bin data.
-			Point clusterPosition = TriggerDiagnosticUtil.getClusterPosition(cluster);
-			Integer positionCount = reconPositionBins.get(clusterPosition);
-			if(positionCount == null) { reconPositionBins.put(clusterPosition, 1); }
-			else { reconPositionBins.put(clusterPosition, positionCount + 1); }
-			
-			// Update the energy bin data.
-			int energyBin = (int) Math.floor(cluster.getEnergy() / ENERGY_BIN);
-			Integer energyCount = reconEnergyBins.get(energyBin);
-			if(energyCount == null) { reconEnergyBins.put(energyBin, 1); }
-			else { reconEnergyBins.put(energyBin, energyCount + 1); }
-		}
-		
-    	// Update the plotting information for SSP clusters.
-		for(SSPCluster cluster : sspClusters) {
-			// Update the hit count bin data.
-			Integer hitCountCount = sspHitCountBins.get(cluster.getHitCount());
-			if(hitCountCount == null) { sspHitCountBins.put(cluster.getHitCount(), 1); }
-			else { sspHitCountBins.put(cluster.getHitCount(), hitCountCount + 1); }
-			
-			// Update the position bin data.
-			Point clusterPosition = TriggerDiagnosticUtil.getClusterPosition(cluster);
-			Integer positionCount = sspPositionBins.get(clusterPosition);
-			if(positionCount == null) { sspPositionBins.put(clusterPosition, 1); }
-			else { sspPositionBins.put(clusterPosition, positionCount + 1); }
-			
-			// Update the energy bin data.
-			int energyBin = (int) Math.floor(cluster.getEnergy() / ENERGY_BIN);
-			Integer energyCount = sspEnergyBins.get(energyBin);
-			if(energyCount == null) { sspEnergyBins.put(energyBin, 1); }
-			else { sspEnergyBins.put(energyBin, energyCount + 1); }
-		}
-		
-		// Update the plotting information for SSP/reconstructed cluster
-		// pairs.
-		pairLoop:
-		for(ClusterMatchedPair pair : event.getMatchedPairs()) {
-			// If one of the pairs is null, then it is unmatched cluster
-			// and may be skipped.
-			if(pair.getReconstructedCluster() == null || pair.getSSPCluster() == null) {
-				continue pairLoop;
-			}
-			
-			// Populate the bins for the "all" plots.
-			// Update the match time plots.
-			int timeBin = (int) Math.floor(TriggerDiagnosticUtil.getClusterTime(pair.getReconstructedCluster()) / TIME_BIN);
-			Integer timeCount = allTimeBins.get(timeBin);
-			if(timeCount == null) { allTimeBins.put(timeBin, 1); }
-			else { allTimeBins.put(timeBin, timeCount + 1); }
-			
-			// Update the energy/hit difference plots.
-			int hitBin = getHitCountDifference(pair.getSSPCluster(), pair.getReconstructedCluster());
-			int energyBin = (int) Math.floor(getEnergyPercentDifference(pair.getSSPCluster(), pair.getReconstructedCluster()) / ENERGY_BIN);
-			Point henergyBin = new Point(hitBin, energyBin);
-			Integer henergyCount = allHenergyBins.get(henergyBin);
-			if(henergyCount == null) { allHenergyBins.put(henergyBin, 1); }
-			else { allHenergyBins.put(henergyBin, henergyCount + 1); }
-			
-			// Populate the bins for the "fail" plots.
-			if(!pair.isMatch()) {
-				// Update the failed cluster position bins.
-				Point clusterPosition = TriggerDiagnosticUtil.getClusterPosition(pair.getReconstructedCluster());
-				Integer positionCount = failPositionBins.get(clusterPosition);
-				if(positionCount == null) { failPositionBins.put(clusterPosition, 1); }
-				else { failPositionBins.put(clusterPosition, positionCount + 1); }
-				
-				// Update the failed match time plots.
-				timeCount = failTimeBins.get(timeBin);
-				if(timeCount == null) { failTimeBins.put(timeBin, 1); }
-				else { failTimeBins.put(timeBin, timeCount + 1); }
-				
-				// Update the failed energy/hit difference plots.
-				henergyCount = failHenergyBins.get(henergyBin);
-				if(henergyCount == null) { failHenergyBins.put(henergyBin, 1); }
-				else { failHenergyBins.put(henergyBin, henergyCount + 1); }
-			}
-		}
     }
     
 	/**
@@ -150,21 +40,7 @@
 	 */
     @Override
 	public void clear() {
-		// Clear statistical data.
 		super.clear();
-		
-		// Clear plot collections.
-		sspHitCountBins.clear();
-		reconHitCountBins.clear();
-		sspPositionBins.clear();
-		reconPositionBins.clear();
-		sspEnergyBins.clear();
-		reconEnergyBins.clear();
-		failPositionBins.clear();
-		allHenergyBins.clear();
-		failHenergyBins.clear();
-		allTimeBins.clear();
-		failTimeBins.clear();
 	}
     
     /**
@@ -175,26 +51,4 @@
     public ClusterStatModule cloneStatModule() {
     	return new ClusterStatModule(this);
     }
-	
-	/**
-	 * Solves the equation <code>|E_ssp / E_recon|</code>.
-	 * @param sspCluster - The SSP cluster.
-	 * @param reconCluster - The reconstructed cluster.
-	 * @return Returns the solution to the equation as a <code>double
-	 * </code> primitive.
-	 */
-	private static final double getEnergyPercentDifference(SSPCluster sspCluster, Cluster reconCluster) {
-		return Math.abs((sspCluster.getEnergy() / reconCluster.getEnergy()));
-	}
-    
-	/**
-	 * Gets the difference in hit count between an SSP cluster and a
-	 * reconstructed cluster.
-	 * @param sspCluster - The SSP cluster.
-	 * @param reconCluster - The reconstructed cluster.
-	 * @return Returns the difference as an <code>int</code> primitive.
-	 */
-	private static final int getHitCountDifference(SSPCluster sspCluster, Cluster reconCluster) {
-		return sspCluster.getHitCount() - TriggerDiagnosticUtil.getHitCount(reconCluster);
-	}
 }

Modified: java/trunk/analysis/src/main/java/org/hps/analysis/trigger/event/ClusterMatchedPair.java
 =============================================================================
--- java/trunk/analysis/src/main/java/org/hps/analysis/trigger/event/ClusterMatchedPair.java	(original)
+++ java/trunk/analysis/src/main/java/org/hps/analysis/trigger/event/ClusterMatchedPair.java	Thu Mar 12 15:08:54 2015
@@ -97,13 +97,23 @@
 	}
 	
 	/**
-	 * Indicates whether the recon/SSP pair failed to match due to a
-	 * the cluster positions not aligning.
+	 * Indicates whether the recon/SSP pair failed to match due to the
+	 * cluster positions not aligning.
 	 * @return Returns <code>true</code> if the pair match state is a
 	 * position fail state and <code>false</code> otherwise.
 	 */
 	public boolean isPositionFailState() {
 		return (state == TriggerDiagnosticUtil.CLUSTER_STATE_FAIL_POSITION);
+	}
+	
+	/**
+	 * Indicates whether the recon/SSP pair failed to match due to the
+	 * cluster time-stamps not aligning.
+	 * @return Returns <code>true</code> if the pair match state is a
+	 * time fail state and <code>false</code> otherwise.
+	 */
+	public boolean isTimeFailState() {
+		return (state == TriggerDiagnosticUtil.CLUSTER_STATE_FAIL_TIME);
 	}
 	
 	/**

Modified: java/trunk/analysis/src/main/java/org/hps/analysis/trigger/event/TriggerMatchEvent.java
 =============================================================================
--- java/trunk/analysis/src/main/java/org/hps/analysis/trigger/event/TriggerMatchEvent.java	(original)
+++ java/trunk/analysis/src/main/java/org/hps/analysis/trigger/event/TriggerMatchEvent.java	Thu Mar 12 15:08:54 2015
@@ -50,7 +50,7 @@
 	 * @return Returns the value as an <code>int</code> primitive.
 	 */
 	public int getMatchedReconTriggers() {
-		return reconPairList.size();
+		return reconTriggersMatched[0] + reconTriggersMatched[1];
 	}
 	
 	/**
@@ -61,7 +61,7 @@
 	 */
 	public int getMatchedReconTriggers(int triggerNumber) {
 		// Validate the arguments.
-		if(triggerNumber !=0 && triggerNumber != 1) {
+		if(triggerNumber != 0 && triggerNumber != 1) {
 			throw new IndexOutOfBoundsException("Trigger number must be 0 or 1.");
 		}
 		
@@ -75,7 +75,7 @@
 	 * @return Returns the value as an <code>int</code> primitive.
 	 */
 	public int getMatchedSSPTriggers() {
-		return sspPairList.size();
+		return sspInternalMatched[0] + sspInternalMatched[1];
 	}
 	
 	/**
@@ -86,7 +86,7 @@
 	 */
 	public int getMatchedSSPTriggers(int triggerNumber) {
 		// Validate the arguments.
-		if(triggerNumber !=0 && triggerNumber != 1) {
+		if(triggerNumber != 0 && triggerNumber != 1) {
 			throw new IndexOutOfBoundsException("Trigger number must be 0 or 1.");
 		}
 		
@@ -122,12 +122,8 @@
 	 * @param sspTrigger - The SSP bank trigger.
 	 */
 	public void matchedSSPPair(Trigger<?> simTrigger, SSPNumberedTrigger sspTrigger) {
-		// A null SSP trigger means that no match was found. This is
-		// treated as a failure due to time, which is not tracked.
-		if(sspTrigger != null) {
-			sspInternalMatched[sspTrigger.isFirstTrigger() ? 0 : 1]++;
-			sspPairList.add(new TriggerMatchedPair(simTrigger, sspTrigger, new boolean[] { true, true, true, true }));
-		}
+		sspInternalMatched[sspTrigger.isFirstTrigger() ? 0 : 1]++;
+		sspPairList.add(new TriggerMatchedPair(simTrigger, sspTrigger, new boolean[] { true, true, true, true }));
 	}
 	
 	/**
@@ -139,17 +135,14 @@
 	 * which did not.
 	 */
 	public void matchedSSPPair(Trigger<?> simTrigger, SSPNumberedTrigger sspTrigger, boolean[] cutsMatched) {
-		// Store the full cut array.
-		boolean[] cutArray = cutsMatched;
-		
-		// If the array is size 3, it is the a singles trigger. Update
-		// it to an array of size 4 for compatibility.
-		if(cutsMatched.length == 3) {
-			boolean[] tempArray = { true, true, true, true };
-			for(int cutIndex = 0; cutIndex < cutsMatched.length; cutIndex++) {
-				tempArray[cutIndex] = cutsMatched[cutIndex];
-			}
-			cutArray = tempArray;
+		// The cut values must be stored in an array of size four, but
+		// singles triggers use arrays of size 3. If the array is not
+		// of the appropriate size, resize it.
+		boolean[] cutArray;
+		if(cutsMatched.length == 4) {
+			cutArray = cutsMatched;
+		} else {
+			cutArray = new boolean[] { cutsMatched[0], cutsMatched[1], cutsMatched[2], true };
 		}
 		
 		// Add the trigger pair to the list.

Modified: java/trunk/analysis/src/main/java/org/hps/analysis/trigger/event/TriggerMatchStatus.java
 =============================================================================
--- java/trunk/analysis/src/main/java/org/hps/analysis/trigger/event/TriggerMatchStatus.java	(original)
+++ java/trunk/analysis/src/main/java/org/hps/analysis/trigger/event/TriggerMatchStatus.java	Thu Mar 12 15:08:54 2015
@@ -11,6 +11,10 @@
  * @author Kyle McCarty <[log in to unmask]>
  */
 public class TriggerMatchStatus extends TriggerStatModule {
+	// Track the number of triggers seen.
+	private int[] sspTriggersSeen = new int[2];
+	private int[] reconTriggersSeen = new int[2];
+	
 	/**
 	 * Adds the statistical data stored in a trigger comparison event
 	 * into this status tracking module.
@@ -33,6 +37,12 @@
 		sspTriggers += sspSimTriggers.get(0).size() + sspSimTriggers.get(1).size();
 		this.reconTriggers += reconTriggers.get(0).size() + reconTriggers.get(1).size();
 		reportedTriggers += sspBankTriggers.size();
+		
+		// Fill the specific trigger counters.
+		for(int triggerNum = 0; triggerNum < 2; triggerNum++) {
+			sspTriggersSeen[triggerNum] += sspSimTriggers.get(triggerNum).size();
+			reconTriggersSeen[triggerNum] += reconTriggers.get(triggerNum).size();
+		}
 		
 		// Increment the count for each cut failure type.
 		for(int triggerNum = 0; triggerNum < 2; triggerNum++) {
@@ -62,4 +72,52 @@
 	public TriggerStatModule cloneStatModule() {
     	return new TriggerStatModule(this);
     }
+	
+	/**
+	 * Gets the number of reconstructed triggers seen for a specific
+	 * trigger number.
+	 * @param triggerNum - The trigger number.
+	 * @return Returns the total number of reconstructed triggers seen
+	 * by the indicated trigger number. 
+	 */
+	public int getTotalReconTriggers(int triggerNum) {
+		return getSSPTriggerCount(false, triggerNum);
+	}
+	
+	/**
+	 * Gets the number of SSP bank triggers seen for a specific trigger
+	 * number.
+	 * @param triggerNum - The trigger number.
+	 * @return Returns the total number of SSP bank triggers seen by
+	 * the indicated trigger number. 
+	 */
+	public int getTotalSSPTriggers(int triggerNum) {
+		return getSSPTriggerCount(true, triggerNum);
+	}
+	
+	/**
+	 * Gets the total number of triggers seen for a specific trigger
+	 * source type and number.
+	 * @param isSSP - Whether the trigger source is SSP bank clusters.
+	 * @param triggerNum - The trigger number.
+	 * @return Returns the trigger count.
+	 */
+	private final int getSSPTriggerCount(boolean isSSP, int triggerNum) {
+		// Make sure the trigger number is valid.
+		validateTriggerNumber(triggerNum);
+		
+		// Return the triggers.
+		if(isSSP) { return sspTriggersSeen[triggerNum]; }
+		else { return reconTriggersSeen[triggerNum]; }
+	}
+	
+	/**
+	 * Produces an exception if the trigger number argument is invalid.
+	 * @param triggerNum - The trigger number to validate.
+	 */
+	private static final void validateTriggerNumber(int triggerNum) {
+		if(triggerNum < 0 || triggerNum > 2) {
+			throw new IndexOutOfBoundsException(String.format("Trigger number \"%d\" is invalid", triggerNum));
+		}
+	}
 }

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	Thu Mar 12 15:08:54 2015
@@ -19,7 +19,8 @@
 	public static final byte CLUSTER_STATE_FAIL_POSITION  = 1;
 	public static final byte CLUSTER_STATE_FAIL_ENERGY    = 2;
 	public static final byte CLUSTER_STATE_FAIL_HIT_COUNT = 3;
-	public static final byte CLUSTER_STATE_FAIL_UNKNOWN   = 4;
+	public static final byte CLUSTER_STATE_FAIL_TIME      = 4;
+	public static final byte CLUSTER_STATE_FAIL_UNKNOWN   = 5;
 	
 	// Trigger match cut IDs.
 	public static final int SINGLES_ENERGY_MIN = 0;

Top of Message | Previous Page | Permalink

Advanced Options


Options

Log In

Log In

Get Password

Get Password


Search Archives

Search Archives


Subscribe or Unsubscribe

Subscribe or Unsubscribe


Archives

November 2017
August 2017
July 2017
January 2017
December 2016
November 2016
October 2016
September 2016
August 2016
July 2016
June 2016
May 2016
April 2016
March 2016
February 2016
January 2016
December 2015
November 2015
October 2015
September 2015
August 2015
July 2015
June 2015
May 2015
April 2015
March 2015
February 2015
January 2015
December 2014
November 2014
October 2014
September 2014
August 2014
July 2014
June 2014
May 2014
April 2014
March 2014
February 2014
January 2014
December 2013
November 2013

ATOM RSS1 RSS2



LISTSERV.SLAC.STANFORD.EDU

Secured by F-Secure Anti-Virus CataList Email List Search Powered by the LISTSERV Email List Manager

Privacy Notice, Security Notice and Terms of Use