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  April 2015

HPS-SVN April 2015

Subject:

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

From:

[log in to unmask]

Reply-To:

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

Date:

Thu, 2 Apr 2015 17:06:01 -0000

Content-Type:

text/plain

Parts/Attachments:

Parts/Attachments

text/plain (2662 lines)

Author: [log in to unmask]
Date: Thu Apr  2 10:05:53 2015
New Revision: 2656

Log:
Updated trigger diagnostic data storage tracking to be both more intuitive and also allow for tracking certain values more specifically.

Added:
    java/trunk/analysis/src/main/java/org/hps/analysis/trigger/data/
    java/trunk/analysis/src/main/java/org/hps/analysis/trigger/data/ClusterEvent.java
    java/trunk/analysis/src/main/java/org/hps/analysis/trigger/data/ClusterMatchedPair.java
    java/trunk/analysis/src/main/java/org/hps/analysis/trigger/data/ClusterStatModule.java
    java/trunk/analysis/src/main/java/org/hps/analysis/trigger/data/DetailedClusterEvent.java
    java/trunk/analysis/src/main/java/org/hps/analysis/trigger/data/DiagnosticSnapshot.java
    java/trunk/analysis/src/main/java/org/hps/analysis/trigger/data/GeneralStatModule.java
    java/trunk/analysis/src/main/java/org/hps/analysis/trigger/data/RunDiagStats.java
    java/trunk/analysis/src/main/java/org/hps/analysis/trigger/data/TriggerDiagStats.java
    java/trunk/analysis/src/main/java/org/hps/analysis/trigger/data/TriggerEvent.java
    java/trunk/analysis/src/main/java/org/hps/analysis/trigger/data/TriggerStatModule.java
Modified:
    java/trunk/analysis/src/main/java/org/hps/analysis/trigger/TriggerDiagnosticDriver.java
    java/trunk/analysis/src/main/java/org/hps/analysis/trigger/event/TriggerEfficiencyModule.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 Apr  2 10:05:53 2015
@@ -7,7 +7,6 @@
 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;
@@ -16,12 +15,12 @@
 import java.util.Map.Entry;
 import java.util.Set;
 
-import org.hps.analysis.trigger.event.ClusterMatchEvent;
-import org.hps.analysis.trigger.event.ClusterMatchStatus;
-import org.hps.analysis.trigger.event.ClusterMatchedPair;
-import org.hps.analysis.trigger.event.TriggerEfficiencyModule;
-import org.hps.analysis.trigger.event.TriggerMatchEvent;
-import org.hps.analysis.trigger.event.TriggerMatchStatus;
+import org.hps.analysis.trigger.data.ClusterMatchedPair;
+import org.hps.analysis.trigger.data.DetailedClusterEvent;
+import org.hps.analysis.trigger.data.DiagnosticSnapshot;
+import org.hps.analysis.trigger.data.RunDiagStats;
+import org.hps.analysis.trigger.data.TriggerDiagStats;
+import org.hps.analysis.trigger.data.TriggerEvent;
 import org.hps.analysis.trigger.event.TriggerPlotsModule;
 import org.hps.analysis.trigger.util.OutputLogger;
 import org.hps.analysis.trigger.util.Pair;
@@ -67,7 +66,8 @@
 	private List<List<SinglesTrigger<SSPCluster>>> sspSinglesTriggers = new ArrayList<List<SinglesTrigger<SSPCluster>>>(2);
 	
 	// Trigger modules for performing trigger analysis.
-	private int activeTrigger = -1;
+	//private int activeTrigger = -1;
+	private boolean[] tiFlags = new boolean[6];
 	private TriggerModule[] singlesTrigger = new TriggerModule[2];
 	private TriggerModule[] pairsTrigger = new TriggerModule[2];
 	private boolean[][] singlesCutsEnabled = new boolean[2][3];
@@ -82,27 +82,16 @@
 	private int hitAcceptance = 1;
 	private int noiseThreshold = 50;
 	private double energyAcceptance = 0.003;
-	private long localWindowStart = 0;
 	private boolean readDAQConfig = false;
-	private int localWindowThreshold = 10 * 1000;
+	private int localWindowThreshold = 1000000000;
 	private boolean performClusterVerification = true;
 	private boolean performSinglesTriggerVerification = true;
 	private boolean performPairTriggerVerification = true;
 	private boolean enforceTimeCompliance = false;
 	
 	// Efficiency tracking variables.
-	private ClusterMatchStatus clusterRunStats = new ClusterMatchStatus();
-	private ClusterMatchStatus clusterLocalStats = new ClusterMatchStatus();
-	private TriggerEfficiencyModule efficiencyRunStats = new TriggerEfficiencyModule();
-	private TriggerEfficiencyModule efficiencyLocalStats = new TriggerEfficiencyModule();
-	private TriggerMatchStatus[] triggerRunStats = { new TriggerMatchStatus(), new TriggerMatchStatus() };
-	private TriggerMatchStatus[] triggerLocalStats = { new TriggerMatchStatus(), new TriggerMatchStatus() };
-	
-	private int failedClusterEvents = 0;
-	private int failedSinglesEvents = 0;
-	private int failedPairEvents = 0;
-	private int totalEvents = 0;
-	private int noiseEvents = 0;
+	private RunDiagStats localStats = new RunDiagStats();
+	private RunDiagStats globalStats = new RunDiagStats();
     
     // Verbose settings.
     private boolean clusterFail = false;
@@ -356,146 +345,168 @@
 		System.out.println("======================================================================");
 		
 		// Print the general event failure rate.
-		int headSpaces = getPrintSpaces(totalEvents, triggerRunStats[0].getEventsOfTypeSeen(0), triggerRunStats[0].getEventsOfTypeSeen(1),
-				triggerRunStats[1].getEventsOfTypeSeen(0), triggerRunStats[1].getEventsOfTypeSeen(1));
+		int headSpaces = getPrintSpaces(globalStats.getEventCount());
 		System.out.println("General Event Statistics:");
 		System.out.printf("\tEvent Start Time      :: %.3f s%n", (startTime / Math.pow(10, 9)));
 		System.out.printf("\tEvent End Time        :: %.3f%n", (endTime / Math.pow(10, 9)));
 		System.out.printf("\tEvent Run Time        :: %.3f%n", ((endTime - startTime) / Math.pow(10, 9)));
 		System.out.printf("\tNoise Events          :: %" + headSpaces + "d / %" + headSpaces + "d (%7.3f%%)%n",
-				noiseEvents, totalEvents, (100.0 * noiseEvents / totalEvents));
+				globalStats.getNoiseEvents(), globalStats.getEventCount(), (100.0 * globalStats.getNoiseEvents() / globalStats.getEventCount()));
 		System.out.printf("\tCluster Events Failed :: %" + headSpaces + "d / %" + headSpaces + "d (%7.3f%%)%n",
-				failedClusterEvents, totalEvents, (100.0 * failedClusterEvents / totalEvents));
+				globalStats.getFailedClusterEventCount(), globalStats.getEventCount(), (100.0 * globalStats.getFailedClusterEventCount() / globalStats.getEventCount()));
 		System.out.printf("\tSingles Events Failed :: %" + headSpaces + "d / %" + headSpaces + "d (%7.3f%%)%n",
-				failedSinglesEvents, totalEvents, (100.0 * failedSinglesEvents / totalEvents));
+				globalStats.getFailedSinglesEventCount(), globalStats.getEventCount(), (100.0 * globalStats.getFailedSinglesEventCount() / globalStats.getEventCount()));
 		System.out.printf("\tPair Events Failed    :: %" + headSpaces + "d / %" + headSpaces + "d (%7.3f%%)%n",
-				failedPairEvents, totalEvents, (100.0 * failedPairEvents / totalEvents));
-		
-		// Print out how many events were triggered by a type along
-		// with how many were verified.
+				globalStats.getFailedPairEventCount(), globalStats.getEventCount(), (100.0 * globalStats.getFailedPairEventCount() / globalStats.getEventCount()));
+		
+		// Print out how many events reported a given TI type, both in
+		// total and hierarchically.
 		System.out.println();
 		System.out.println("Event Triggering Type Verification:");
-		System.out.printf("\tSingles Trigger 1     :: %" + headSpaces + "d / %" + headSpaces + "d",
-				triggerRunStats[0].getEventsOfTypeSeen(0), triggerRunStats[0].getEventsOfType(0));
-		if(triggerRunStats[0].getEventsOfType(0) != 0) {
-			System.out.printf(" (%7.3f%%)%n", (100.0 * triggerRunStats[0].getEventsOfTypeSeen(0) / triggerRunStats[0].getEventsOfType(0)));
-		} else { System.out.println(); }
-		System.out.printf("\tSingles Trigger 2     :: %" + headSpaces + "d / %" + headSpaces + "d",
-				triggerRunStats[0].getEventsOfTypeSeen(1), triggerRunStats[0].getEventsOfType(1));
-		if(triggerRunStats[0].getEventsOfType(0) != 0) {
-			System.out.printf(" (%7.3f%%)%n", (100.0 * triggerRunStats[0].getEventsOfTypeSeen(1) / triggerRunStats[0].getEventsOfType(1)));
-		} else { System.out.println(); }
-		System.out.printf("\tPair Trigger 1        :: %" + headSpaces + "d / %" + headSpaces + "d",
-				triggerRunStats[1].getEventsOfTypeSeen(0), triggerRunStats[0].getEventsOfType(0));
-		if(triggerRunStats[1].getEventsOfType(0) != 0) {
-			System.out.printf(" (%7.3f%%)%n", (100.0 * triggerRunStats[1].getEventsOfTypeSeen(0) / triggerRunStats[1].getEventsOfType(0)));
-		} else { System.out.println(); }
-		System.out.printf("\tPair Trigger 2        :: %" + headSpaces + "d / %" + headSpaces + "d",
-				triggerRunStats[1].getEventsOfTypeSeen(1), triggerRunStats[0].getEventsOfType(1));
-		if(triggerRunStats[1].getEventsOfType(0) != 0) {
-			System.out.printf(" (%7.3f%%)%n", (100.0 * triggerRunStats[1].getEventsOfTypeSeen(1) / triggerRunStats[1].getEventsOfType(1)));
-		} else { System.out.println(); }
+		System.out.printf("\t%15s\t%15s\t%15s%n", "Trigger", "Total", "Hierarchical");
+		System.out.printf("\t%15s\t%15s\t%15s%n", "Pulser", globalStats.getTriggerStats().getTITriggers(TriggerDiagStats.PULSER, false),
+				globalStats.getTriggerStats().getTITriggers(TriggerDiagStats.PULSER, true));
+		System.out.printf("\t%15s\t%15s\t%15s%n", "Cosmic", globalStats.getTriggerStats().getTITriggers(TriggerDiagStats.COSMIC, false),
+				globalStats.getTriggerStats().getTITriggers(TriggerDiagStats.COSMIC, true));
+		System.out.printf("\t%15s\t%15s\t%15s%n", "Singles 1", globalStats.getTriggerStats().getTITriggers(TriggerDiagStats.SINGLES0, false),
+				globalStats.getTriggerStats().getTITriggers(TriggerDiagStats.SINGLES0, true));
+		System.out.printf("\t%15s\t%15s\t%15s%n", "Singles 2", globalStats.getTriggerStats().getTITriggers(TriggerDiagStats.SINGLES1, false),
+				globalStats.getTriggerStats().getTITriggers(TriggerDiagStats.SINGLES1, true));
+		System.out.printf("\t%15s\t%15s\t%15s%n", "Pair 1", globalStats.getTriggerStats().getTITriggers(TriggerDiagStats.PAIR0, false),
+				globalStats.getTriggerStats().getTITriggers(TriggerDiagStats.PAIR0, true));
+		System.out.printf("\t%15s\t%15s\t%15s%n", "Pair 2", globalStats.getTriggerStats().getTITriggers(TriggerDiagStats.PAIR1, false),
+				globalStats.getTriggerStats().getTITriggers(TriggerDiagStats.PAIR1, true));
 		
 		// Print the cluster verification data.
 		System.out.println();
 		System.out.println("Cluster Verification:");
-		System.out.printf("\tRecon Clusters        :: %d%n", clusterRunStats.getReconClusterCount());
-		System.out.printf("\tSSP Clusters          :: %d%n", clusterRunStats.getSSPClusterCount());
-		System.out.printf("\tClusters Matched      :: %d%n", clusterRunStats.getMatches());
-		System.out.printf("\tFailed (Position)     :: %d%n", clusterRunStats.getPositionFailures());
-		System.out.printf("\tFailed (Energy)       :: %d%n", clusterRunStats.getEnergyFailures());
-		System.out.printf("\tFailed (Hit Count)    :: %d%n", clusterRunStats.getHitCountFailures());
-		if(clusterRunStats.getReconClusterCount() == 0) { System.out.printf("\tCluster Efficiency    :: N/A%n"); }
-		else { System.out.printf("\tCluster Efficiency    :: %7.3f%%%n", 100.0 * clusterRunStats.getMatches() / clusterRunStats.getReconClusterCount()); }
+		System.out.printf("\tRecon Clusters        :: %d%n", globalStats.getClusterStats().getReconClusterCount());
+		System.out.printf("\tSSP Clusters          :: %d%n", globalStats.getClusterStats().getSSPClusterCount());
+		System.out.printf("\tClusters Matched      :: %d%n", globalStats.getClusterStats().getMatches());
+		System.out.printf("\tFailed (Position)     :: %d%n", globalStats.getClusterStats().getPositionFailures());
+		System.out.printf("\tFailed (Energy)       :: %d%n", globalStats.getClusterStats().getEnergyFailures());
+		System.out.printf("\tFailed (Hit Count)    :: %d%n", globalStats.getClusterStats().getHitCountFailures());
+		if(globalStats.getClusterStats().getReconClusterCount() == 0) {
+			System.out.printf("\tCluster Efficiency    :: N/A%n");
+		} else {
+			System.out.printf("\tCluster Efficiency    :: %7.3f%%%n",
+					100.0 * globalStats.getClusterStats().getMatches() / globalStats.getClusterStats().getReconClusterCount());
+		}
 		
 		// Print the trigger verification data.
 		for(int triggerType = 0; triggerType < 2; triggerType++) {
-			int spaces = getPrintSpaces(triggerRunStats[triggerType].getSSPSimTriggerCount(),
-					triggerRunStats[triggerType].getReconTriggerCount(), triggerRunStats[triggerType].getSSPBankTriggerCount(),
-					triggerRunStats[triggerType].getMatchedSSPTriggers(), triggerRunStats[triggerType].getMatchedReconTriggers());
+			// Get the trigger data. Type 0 represents singles triggers.
+			TriggerEvent[] triggerData = new TriggerEvent[2];
+			if(triggerType == 0) {
+				triggerData[0] = globalStats.getTriggerStats().getSingles0Stats();
+				triggerData[1] = globalStats.getTriggerStats().getSingles1Stats();
+			} else {
+				triggerData[0] = globalStats.getTriggerStats().getPair0Stats();
+				triggerData[1] = globalStats.getTriggerStats().getPair1Stats();
+			}
+			
+			// Get the basic trigger data.
+			int sspSimTriggers = triggerData[0].getSSPSimulatedTriggers() + triggerData[1].getSSPSimulatedTriggers();
+			int reconSimTriggers = triggerData[0].getReconSimulatedTriggers() + triggerData[1].getReconSimulatedTriggers();
+			int sspReportedTriggers = triggerData[0].getReportedTriggers() + triggerData[1].getReportedTriggers();
+			int sspMatchedTriggers = triggerData[0].getMatchedSSPSimulatedTriggers() + triggerData[1].getMatchedSSPSimulatedTriggers();
+			int reconMatchedTriggers = triggerData[0].getMatchedReconSimulatedTriggers() + triggerData[1].getMatchedReconSimulatedTriggers();
+			
+			// Print the basic trigger statistics.
+			int spaces = getPrintSpaces(sspSimTriggers, reconSimTriggers, sspReportedTriggers);
 			System.out.println();
 			if(triggerType == 0) { System.out.println("Singles Trigger Verification:"); }
 			else { System.out.println("Pair Trigger Verification:"); }
-			System.out.printf("\tSSP Cluster Sim Triggers   :: %" + spaces + "d%n", triggerRunStats[triggerType].getSSPSimTriggerCount());
-			System.out.printf("\tRecon Cluster Sim Triggers :: %" + spaces + "d%n", triggerRunStats[triggerType].getReconTriggerCount());
-			System.out.printf("\tSSP Reported Triggers      :: %" + spaces + "d%n", triggerRunStats[triggerType].getSSPBankTriggerCount());
-			System.out.printf("\tExtra Reported Triggers    :: %" + spaces + "d%n", triggerRunStats[triggerType].getExtraSSPBankTriggers());
-			
-			System.out.printf("\tInternal Efficiency        :: %" + spaces + "d / %" + spaces + "d ",
-					triggerRunStats[triggerType].getMatchedSSPTriggers(), triggerRunStats[triggerType].getSSPSimTriggerCount());
-			if(triggerRunStats[triggerType].getSSPSimTriggerCount() == 0) { System.out.printf("(N/A)%n"); }
-			else {
-				System.out.printf("(%7.3f%%)%n", (100.0 * triggerRunStats[triggerType].getMatchedSSPTriggers() / triggerRunStats[triggerType].getSSPSimTriggerCount()));
-			}
-			
-			System.out.printf("\tTrigger Efficiency         :: %" + spaces + "d / %" + spaces + "d ",
-					triggerRunStats[triggerType].getMatchedReconTriggers(), triggerRunStats[triggerType].getReconTriggerCount());
-			if(triggerRunStats[triggerType].getReconTriggerCount() == 0) { System.out.printf("(N/A)%n"); }
-			else { System.out.printf("(%7.3f%%)%n" , (100.0 * triggerRunStats[triggerType].getMatchedReconTriggers() / triggerRunStats[triggerType].getReconTriggerCount())); }
+			System.out.printf("\tSSP Cluster Sim Triggers   :: %" + spaces + "d%n", sspSimTriggers);
+			System.out.printf("\tRecon Cluster Sim Triggers :: %" + spaces + "d%n", reconSimTriggers);
+			System.out.printf("\tSSP Reported Triggers      :: %" + spaces + "d%n", sspReportedTriggers);
+			
+			System.out.printf("\tInternal Efficiency        :: %" + spaces + "d / %" + spaces + "d ", sspMatchedTriggers, sspSimTriggers);
+			if(sspSimTriggers == 0) { System.out.printf("(N/A)%n"); }
+			else { System.out.printf("(%7.3f%%)%n", (100.0 * sspMatchedTriggers / sspSimTriggers)); }
+			
+			System.out.printf("\tTrigger Efficiency         :: %" + spaces + "d / %" + spaces + "d ", reconMatchedTriggers, reconSimTriggers);
+			if(reconSimTriggers == 0) { System.out.printf("(N/A)%n"); }
+			else { System.out.printf("(%7.3f%%)%n" , (100.0 * reconMatchedTriggers / reconSimTriggers)); }
 			
 			// Print the individual cut performances.
 			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\tUmatched Triggers          :: %" + spaces + "d%n", triggerRunStats[0].getUnmatchedTriggers(triggerNum));
+				for(int triggerNum = 0; triggerNum < 2; triggerNum++) {
+					// Get the appropriate trigger statistics module.
+					TriggerEvent triggerStats;
+					if(triggerNum == 0) { triggerStats = globalStats.getTriggerStats().getSingles0Stats(); }
+					else { triggerStats = globalStats.getTriggerStats().getSingles1Stats(); }
+					
+					// Get the number of SSP triggers for this trigger number.
+					int sspTriggerCount = triggerStats.getSSPSimulatedTriggers();
+					//int sspTriggerCount = triggerRunStats[0].getTotalSSPTriggers(triggerNum);
+				
+					System.out.println();
+					System.out.printf("\tTrigger %d Individual Cut Failure Rate:%n", (triggerNum + 1));
+					System.out.printf("\t\tUmatched Triggers          :: %" + spaces + "d%n", triggerStats.getUnmatchedSSPSimulatedTriggers());
+					//System.out.printf("\t\tUmatched Triggers          :: %" + spaces + "d%n", triggerRunStats[0].getUnmatchedTriggers(triggerNum));
+					if(sspTriggerCount == 0) {
 						System.out.printf("\t\tCluster Energy Lower Bound :: %" + spaces + "d / %" + spaces + "d%n",
-								triggerRunStats[0].getCutFailures(triggerNum, ENERGY_MIN), sspTriggerCount);
+								triggerStats.getSSPCutFailures(ENERGY_MIN), sspTriggerCount);
 						System.out.printf("\t\tCluster Energy Upper Bound :: %" + spaces + "d / %" + spaces + "d%n",
-								triggerRunStats[0].getCutFailures(triggerNum, ENERGY_MAX), sspTriggerCount);
+								triggerStats.getSSPCutFailures(ENERGY_MAX), sspTriggerCount);
 						System.out.printf("\t\tCluster Hit Count          :: %" + spaces + "d / %" + spaces + "d%n",
-								triggerRunStats[0].getCutFailures(triggerNum, HIT_COUNT), sspTriggerCount);
+								triggerStats.getSSPCutFailures(HIT_COUNT), sspTriggerCount);
 					} else {
-						System.out.printf("\t\tUmatched Triggers          :: %" + spaces + "d%n", triggerRunStats[0].getUnmatchedTriggers(triggerNum));
 						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));
+								triggerStats.getSSPCutFailures(ENERGY_MIN), sspTriggerCount,
+								(100.0 * triggerStats.getSSPCutFailures(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));
+								triggerStats.getSSPCutFailures(ENERGY_MAX), sspTriggerCount,
+								(100.0 * triggerStats.getSSPCutFailures(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));
+								triggerStats.getSSPCutFailures(HIT_COUNT), sspTriggerCount,
+								(100.0 * triggerStats.getSSPCutFailures(HIT_COUNT) / sspTriggerCount));
 					}
 				}
 			} else {
 				for(int triggerNum = 0; triggerNum < 2; triggerNum++) {
-					int sspTriggerCount = triggerRunStats[1].getTotalSSPTriggers(triggerNum);
+					// Get the appropriate trigger statistics module.
+					TriggerEvent triggerStats;
+					if(triggerNum == 0) { triggerStats = globalStats.getTriggerStats().getPair0Stats(); }
+					else { triggerStats = globalStats.getTriggerStats().getPair1Stats(); }
+					
+					// Get the number of SSP triggers for this trigger number.
+					int sspTriggerCount = triggerStats.getSSPSimulatedTriggers();
+					
 					System.out.println();
 					System.out.printf("\tTrigger %d Individual Cut Failure Rate:%n", (triggerNum + 1));
+					System.out.printf("\t\tUmatched Triggers          :: %" + spaces + "d%n", triggerStats.getUnmatchedSSPSimulatedTriggers());
 					if(sspTriggerCount == 0) {
-						System.out.printf("\t\tUmatched Triggers          :: %" + spaces + "d%n", triggerRunStats[1].getUnmatchedTriggers(triggerNum));
 						System.out.printf("\t\tPair Energy Sum            :: %" + spaces + "d / %" + spaces + "d%n",
-								triggerRunStats[1].getCutFailures(triggerNum, ENERGY_SUM), sspTriggerCount);
+								triggerStats.getSSPCutFailures(ENERGY_SUM), sspTriggerCount);
 						System.out.printf("\t\tPair Energy Difference     :: %" + spaces + "d / %" + spaces + "d%n",
-								triggerRunStats[1].getCutFailures(triggerNum, ENERGY_DIFF), sspTriggerCount);
+								triggerStats.getSSPCutFailures(ENERGY_DIFF), sspTriggerCount);
 						System.out.printf("\t\tPair Energy Slope          :: %" + spaces + "d / %" + spaces + "d%n",
-								triggerRunStats[1].getCutFailures(triggerNum, ENERGY_SLOPE), sspTriggerCount);
+								triggerStats.getSSPCutFailures(ENERGY_SLOPE), sspTriggerCount);
 						System.out.printf("\t\tPair Coplanarity           :: %" + spaces + "d / %" + spaces + "d%n",
-								triggerRunStats[1].getCutFailures(triggerNum, COPLANARITY), sspTriggerCount);
+								triggerStats.getSSPCutFailures(COPLANARITY), sspTriggerCount);
 					} else {
-						System.out.printf("\t\tUmatched Triggers          :: %" + spaces + "d%n", triggerRunStats[1].getUnmatchedTriggers(triggerNum));
 						System.out.printf("\t\tPair Energy Sum            :: %" + spaces + "d / %" + spaces + "d (%7.3f%%)%n",
-								triggerRunStats[1].getCutFailures(triggerNum, ENERGY_SUM), sspTriggerCount,
-								(100.0 * triggerRunStats[1].getCutFailures(triggerNum, ENERGY_SUM) / sspTriggerCount));
+								triggerStats.getSSPCutFailures(ENERGY_SUM), sspTriggerCount,
+								(100.0 * triggerStats.getSSPCutFailures(ENERGY_SUM) / sspTriggerCount));
 						System.out.printf("\t\tPair Energy Difference     :: %" + spaces + "d / %" + spaces + "d (%7.3f%%)%n",
-								triggerRunStats[1].getCutFailures(triggerNum, ENERGY_DIFF), sspTriggerCount,
-								(100.0 * triggerRunStats[1].getCutFailures(triggerNum, ENERGY_DIFF) / sspTriggerCount));
+								triggerStats.getSSPCutFailures(ENERGY_DIFF), sspTriggerCount,
+								(100.0 * triggerStats.getSSPCutFailures(ENERGY_DIFF) / sspTriggerCount));
 						System.out.printf("\t\tPair Energy Slope          :: %" + spaces + "d / %" + spaces + "d (%7.3f%%)%n",
-								triggerRunStats[1].getCutFailures(triggerNum, ENERGY_SLOPE), sspTriggerCount,
-								(100.0 * triggerRunStats[1].getCutFailures(triggerNum, ENERGY_SLOPE) / sspTriggerCount));
+								triggerStats.getSSPCutFailures(ENERGY_SLOPE), sspTriggerCount,
+								(100.0 * triggerStats.getSSPCutFailures(ENERGY_SLOPE) / sspTriggerCount));
 						System.out.printf("\t\tPair Coplanarity           :: %" + spaces + "d / %" + spaces + "d (%7.3f%%)%n",
-								triggerRunStats[1].getCutFailures(triggerNum, COPLANARITY), sspTriggerCount,
-								(100.0 * triggerRunStats[1].getCutFailures(triggerNum, COPLANARITY) / sspTriggerCount));
+								triggerStats.getSSPCutFailures(COPLANARITY), sspTriggerCount,
+								(100.0 * triggerStats.getSSPCutFailures(COPLANARITY) / sspTriggerCount));
 					}
 				}
 			}
 		}
 		
+		// Print out the trigger efficiency table.
 		System.out.println();
-		this.efficiencyRunStats.printModule();
+		globalStats.getTriggerStats().printEfficiencyTable();
 	}
 	
 	/**
@@ -516,7 +527,8 @@
 		}
 		
 		// Increment the total event count.
-		totalEvents++;
+		localStats.sawEvent(event.getTimeStamp());
+		globalStats.sawEvent(event.getTimeStamp());
 		
 		if(totalEvents%printResultsEveryNEvents == 0){
 			PrintResults();
@@ -582,7 +594,7 @@
 		// ==========================================================
 		
 		// Output the event number and information.
-		OutputLogger.printf("Event Number %d (%d)%n", totalEvents, event.getEventNumber());
+		OutputLogger.printf("Event Number %d (%d)%n", globalStats.getEventCount(), event.getEventNumber());
 		
 		// Get the SSP clusters.
 		if(event.hasCollection(GenericObject.class, bankCollectionName)) {
@@ -600,28 +612,40 @@
 				else if(AbstractIntData.getTag(obj) == TIData.BANK_TAG) {
 					tiBank = new TIData(obj);
 					
+					tiFlags = new boolean[6];
 					if(tiBank.isPulserTrigger()) {
 						OutputLogger.println("Trigger type :: Pulser");
-						activeTrigger = TriggerDiagnosticUtil.TRIGGER_PULSER;
+						tiFlags[TriggerDiagStats.PULSER] = true;
+						//activeTrigger = TriggerDiagnosticUtil.TRIGGER_PULSER;
 					} else if(tiBank.isSingle0Trigger()) {
 						OutputLogger.println("Trigger type :: Singles 1");
-						activeTrigger = TriggerDiagnosticUtil.TRIGGER_SINGLES_1;
+						tiFlags[TriggerDiagStats.SINGLES0] = true;
+						//activeTrigger = TriggerDiagnosticUtil.TRIGGER_SINGLES_1;
 					} else if(tiBank.isSingle1Trigger()) {
 						OutputLogger.println("Trigger type :: Singles 2");
-						activeTrigger = TriggerDiagnosticUtil.TRIGGER_SINGLES_2;
+						tiFlags[TriggerDiagStats.SINGLES1] = true;
+						//activeTrigger = TriggerDiagnosticUtil.TRIGGER_SINGLES_2;
 					} else if(tiBank.isPair0Trigger()) {
 						OutputLogger.println("Trigger type :: Pair 1");
-						activeTrigger = TriggerDiagnosticUtil.TRIGGER_PAIR_1;
+						tiFlags[TriggerDiagStats.PAIR0] = true;
+						//activeTrigger = TriggerDiagnosticUtil.TRIGGER_PAIR_1;
 					} else if(tiBank.isPair1Trigger()) {
 						OutputLogger.println("Trigger type :: Pair 2");
-						activeTrigger = TriggerDiagnosticUtil.TRIGGER_PAIR_2;
+						tiFlags[TriggerDiagStats.PAIR1] = true;
+						//activeTrigger = TriggerDiagnosticUtil.TRIGGER_PAIR_2;
 					} else if(tiBank.isCalibTrigger()) {
 						OutputLogger.println("Trigger type :: Cosmic");
-						activeTrigger = TriggerDiagnosticUtil.TRIGGER_COSMIC;
+						tiFlags[TriggerDiagStats.COSMIC] = true;
+						//activeTrigger = TriggerDiagnosticUtil.TRIGGER_COSMIC;
 					} else {
 						System.err.println("TriggerDiagnosticDriver: Skipping event; no TI trigger source found.");
 						return;
 					}
+					
+					// Pass the TI triggers to the run statistical data
+					// manager object.
+					localStats.getTriggerStats().sawTITriggers(tiFlags);
+					globalStats.getTriggerStats().sawTITriggers(tiFlags);
 				}
 			}
 			
@@ -669,7 +693,8 @@
 		if(event.hasCollection(CalorimeterHit.class, hitCollectionName)) {
 			// Check if there are more hits than the noise threshold.
 			if(event.get(CalorimeterHit.class, hitCollectionName).size() >= noiseThreshold) {
-				noiseEvents++;
+				localStats.sawNoiseEvent();
+				globalStats.sawNoiseEvent();
 				OutputLogger.println("Noise event detected. Skipping event...");
 				if(verbose) { OutputLogger.printLog(); }
 				return;
@@ -745,9 +770,16 @@
 		}
 		
 		// Track how many events failed due to each type of verification.
-		if(clusterFail) { failedClusterEvents++; }
-		if(pairInternalFail || pairEfficiencyFail) { failedPairEvents++; }
-		if(singlesInternalFail || singlesEfficiencyFail) { failedSinglesEvents++; }
+		if(clusterFail) {
+			localStats.failedClusterEvent();
+			globalStats.failedClusterEvent();
+		} if(pairInternalFail || pairEfficiencyFail) {
+			localStats.failedPairEvent();
+			globalStats.failedPairEvent();
+		} if(singlesInternalFail || singlesEfficiencyFail) {
+			localStats.failedSinglesEvent();
+			globalStats.failedSinglesEvent();
+		}
 		
 		
 		
@@ -768,25 +800,17 @@
 		// ==========================================================
 		// ==== Process Local Tracked Variables =====================
 		// ==========================================================
-		if(Calendar.getInstance().getTimeInMillis() - localWindowStart > localWindowThreshold) {
+		if(localStats.getDuration() > localWindowThreshold) {
 			// Write a snapshot of the driver to the event stream.
-			DiagSnapshot snapshot = new DiagSnapshot(clusterLocalStats, clusterRunStats,
-					triggerLocalStats[0], triggerRunStats[0], triggerLocalStats[1],
-					triggerRunStats[1], efficiencyRunStats, efficiencyLocalStats);
+			List<DiagnosticSnapshot> snapshotList = new ArrayList<DiagnosticSnapshot>(2);
+			snapshotList.add(localStats.getSnapshot());
+			snapshotList.add(globalStats.getSnapshot());
 			
 			// Push the snapshot to the data stream.
-			List<DiagSnapshot> snapshotCollection = new ArrayList<DiagSnapshot>(1);
-			snapshotCollection.add(snapshot);
-			event.put(diagnosticCollectionName, snapshotCollection);
+			event.put(diagnosticCollectionName, snapshotList);
 			
 			// Clear the local statistical data.
-			clusterLocalStats.clear();
-			triggerLocalStats[0].clear();
-			triggerLocalStats[1].clear();
-			efficiencyLocalStats.clear();
-			
-			// Update the last write time.
-			localWindowStart = Calendar.getInstance().getTimeInMillis();
+			localStats.clear();
 		}
 	}
 
@@ -884,7 +908,7 @@
 		
 		// Track the number of cluster pairs that were matched and that
 		// failed by failure type.
-		ClusterMatchEvent event = new ClusterMatchEvent();
+		DetailedClusterEvent event;
 		
 		if(enforceTimeCompliance) {
 			event = matchClustersTimeCompliant(reconClusters, sspClusters, energyAcceptance, hitAcceptance);
@@ -893,8 +917,12 @@
 		}
 		
 		// Add the event results to the global results.
-		clusterRunStats.addEvent(event, reconClusters, sspClusters);
-		clusterLocalStats.addEvent(event, reconClusters, sspClusters);
+		localStats.getClusterStats().addEvent(event);
+		globalStats.getClusterStats().addEvent(event);
+		localStats.getClusterStats().sawSSPClusters(sspClusters.size());
+		globalStats.getClusterStats().sawSSPClusters(sspClusters.size());
+		localStats.getClusterStats().sawReconClusters(reconClusters.size());
+		globalStats.getClusterStats().sawReconClusters(reconClusters.size());
 		
 		
 		
@@ -922,9 +950,9 @@
 		
 		// Print the matched clusters.
 		OutputLogger.println("Matched Clusters:");
-		if(event.getMatchedPairs().size() != 0) {
+		if(event.getMatches() != 0) {
 			// Iterate over the matched pairs.
-			for(ClusterMatchedPair pair : event.getMatchedPairs()) {
+			for(ClusterMatchedPair pair : event.getClusterPairs()) {
 				// If the pair is a match, print it out.
 				if(pair.isMatch()) {
 					OutputLogger.printf("\t%s --> %s%n",
@@ -971,7 +999,7 @@
 		}
 		
 		// Populate the matched and failed plots.
-		for(ClusterMatchedPair pair : event.getMatchedPairs()) {
+		for(ClusterMatchedPair pair : event.getClusterPairs()) {
 			 if(pair.getFirstElement() != null && pair.getSecondElement() != null) {
 				double energyDiff = pair.getSecondElement().getEnergy() - pair.getFirstElement().getEnergy();
 				int hitDiff = pair.getSecondElement().getHitCount() - pair.getFirstElement().getCalorimeterHits().size();
@@ -1029,11 +1057,11 @@
 	 * @return Returns the cluster matching results stored inside a
 	 * <code>clusterMatchEvent</code> object.
 	 */
-	private static final ClusterMatchEvent matchClusters(Collection<Cluster> reconClusters,
+	private static final DetailedClusterEvent 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();
+		DetailedClusterEvent event = new DetailedClusterEvent();
 		
 		// Create maps to link cluster position to the list of clusters
 		// that were found at that location.
@@ -1089,9 +1117,7 @@
 			// reason of position. The remainder of the loop may be
 			// skipped, since there is nothing to check.
 			if(sspList == null || sspList.isEmpty()) {
-				for(Cluster cluster : reconList) {
-					event.pairFailPosition(cluster, null);
-				}
+				event.pairFailPosition(reconList.size());
 				continue positionLoop;
 			}
 			
@@ -1104,7 +1130,7 @@
 			OutputLogger.printf("\tPermutations   :: %d%n", permutations.size());
 			
 			// Track the plotted values for the current best permutation.
-			ClusterMatchEvent bestPerm = null;
+			DetailedClusterEvent bestPerm = null;
 			
 			// Iterate over the permutations and find the permutation
 			// that produces the best possible result when compared to
@@ -1115,7 +1141,7 @@
 				permIndex++;
 				
 				// Track the plot values for this permutation.
-				ClusterMatchEvent perm = new ClusterMatchEvent();
+				DetailedClusterEvent perm = new DetailedClusterEvent();
 				
 				// Try to match each pair.
 				pairLoop:
@@ -1206,11 +1232,11 @@
 	 * @return Returns the cluster matching results stored inside a
 	 * <code>clusterMatchEvent</code> object.
 	 */
-	private static final ClusterMatchEvent matchClustersTimeCompliant(Collection<Cluster> reconClusters,
+	private static final DetailedClusterEvent 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();
+		DetailedClusterEvent event = new DetailedClusterEvent();
 		
 		// Store the clusters which have been successfully paired.
 		Set<SSPCluster> sspMatched = new HashSet<SSPCluster>(sspClusters.size());
@@ -1375,7 +1401,7 @@
 		OutputLogger.println("======================================================================");
 		
 		// Track the number of triggers seen and the number found.
-		TriggerMatchEvent event = new TriggerMatchEvent();
+		TriggerEvent[] triggerEvent = { new TriggerEvent(), new TriggerEvent() };
 		
 		// ==========================================================
 		// ==== Output Event Summary ================================
@@ -1386,7 +1412,7 @@
 		if(isSingles) { sspTriggers = sspBank.getSinglesTriggers(); }
 		else { sspTriggers = sspBank.getPairTriggers(); }
 		
-		// Output the SSP cluster singles triggers.
+		// Output the SSP cluster triggers.
 		OutputLogger.println();
 		OutputLogger.println("SSP Cluster " + (isSingles ? "Singles" : "Pair") + " Triggers");
 		for(int triggerNum = 0; triggerNum < 2; triggerNum++) {
@@ -1420,6 +1446,14 @@
 		}
 		if(sspTriggers.size() == 0) { OutputLogger.println("\tNone"); }
 		
+		// Update the trigger event with the counts for each type of
+		// simulated trigger. Reported triggers are counted later when
+		// already iterating over them.
+		for(int triggerNum = 0; triggerNum < 2; triggerNum++) {
+			triggerEvent[triggerNum].sawSSPSimulatedTriggers(tiFlags, sspTriggerList.get(triggerNum).size());
+			triggerEvent[triggerNum].sawReconSimulatedTriggers(tiFlags, reconTriggerList.get(triggerNum).size());
+		}
+		
 		
 		
 		// ==========================================================
@@ -1447,6 +1481,9 @@
 			// Get the trigger information.
 			int triggerNum = sspTrigger.isFirstTrigger() ? 0 : 1;
 			OutputLogger.printf("\t%s%n", sspTrigger.toString());
+			
+			// Note that a bank trigger was seen.
+			triggerEvent[triggerNum].sawReportedTrigger();
 			
 			// Iterate over the SSP cluster simulated triggers and
 			// look for a trigger that matches.
@@ -1487,7 +1524,7 @@
 				// trigger number, than these triggers are a match.
 				sspTriggerSet.add(sspTrigger);
 				simTriggerSet.add(simTrigger);
-				event.matchedSSPPair(simTrigger, sspTrigger);
+				triggerEvent[triggerNum].matchedSSPTrigger(tiFlags);
 				OutputLogger.printf("[ %-15s ]%n", "success");
 				break matchLoop;
 			}
@@ -1578,13 +1615,13 @@
 				if(bestMatch == null) {
 					if(isSingles) { singlesInternalFail = true; }
 					else { pairInternalFail = true; }
-					event.matchedSSPPair(simTrigger, bestMatch, matchedCut);
+					triggerEvent[triggerNum].failedSSPTrigger();
 					OutputLogger.printf("\t\tTrigger %d :: %s :: %3.0f :: %s",
 							(triggerNum + 1), triggerPositionString(simTrigger),
 							getTriggerTime(simTrigger), simTrigger.toString());
 					OutputLogger.println(" --> No Valid Match Found");
 				} else {
-					event.matchedSSPPair(simTrigger, bestMatch, matchedCut);
+					triggerEvent[triggerNum].matchedSSPTrigger(tiFlags, matchedCut);
 					OutputLogger.printf("\t\tTrigger %d :: %s :: %3.0f :: %s",
 							(triggerNum + 1), triggerPositionString(simTrigger),
 							getTriggerTime(simTrigger), simTrigger.toString());
@@ -1607,22 +1644,6 @@
 		OutputLogger.println("Recon Cluster Trigger --> SSP Reported Trigger Match Status");
 		for(int triggerNum = 0; triggerNum < 2; triggerNum++) {
 			for(Trigger<?> simTrigger : reconTriggerList.get(triggerNum)) {
-				// If the trigger number and type align with the event
-				// trigger type, mark that it was seen.
-				if(triggerNum == 1) {
-					if(activeTrigger == TriggerDiagnosticUtil.TRIGGER_SINGLES_1 && isSingles) {
-						event.setSawEventType(true);
-					} else if(activeTrigger == TriggerDiagnosticUtil.TRIGGER_PAIR_1 && !isSingles) {
-						event.setSawEventType(true);
-					}
-				} else {
-					if(activeTrigger == TriggerDiagnosticUtil.TRIGGER_SINGLES_2 && isSingles) {
-						event.setSawEventType(true);
-					} else if(activeTrigger == TriggerDiagnosticUtil.TRIGGER_PAIR_2 && !isSingles) {
-						event.setSawEventType(true);
-					}
-				}
-				
 				OutputLogger.printf("\tTrigger %d :: %s :: %s%n", (triggerNum + 1),
 						triggerPositionString(simTrigger), simTrigger.toString());
 				
@@ -1664,7 +1685,7 @@
 					// If all the trigger flags match, then the
 					// triggers are a match.
 					sspTriggerSet.add(sspTrigger);
-					event.matchedReconPair(simTrigger, sspTrigger);
+					triggerEvent[triggerNum].matchedReconTrigger(tiFlags);
 					OutputLogger.print(" [ success         ]%n");
 					globalTriggerPlots.matchedTrigger(simTrigger);
 					matched = true;
@@ -1690,29 +1711,19 @@
 		// Print event statistics.
 		OutputLogger.println();
 		OutputLogger.println("Event Statistics:");
-		OutputLogger.printf("\tSaw Triggering Event Type  :: ");
-		if(activeTrigger == TriggerDiagnosticUtil.TRIGGER_COSMIC || activeTrigger == TriggerDiagnosticUtil.TRIGGER_PULSER) {
-			OutputLogger.println("Unsupported for Cosmic/Pulser");
-		} else {
-			OutputLogger.println("" + event.sawEventType());
-		}
 		OutputLogger.printf("\tSSP Cluster Sim Triggers   :: %d%n", sspSimTriggers);
 		OutputLogger.printf("\tRecon Cluster Sim Triggers :: %d%n", reconSimTriggers);
 		OutputLogger.printf("\tSSP Reported Triggers      :: %d%n", sspTriggers.size());
-		if(sspSimTriggers == 0) {
-			OutputLogger.printf("\tInternal Efficiency        :: %d / %d (N/A)%n",
-					event.getMatchedSSPTriggers(), sspSimTriggers);
-		} else {
-			OutputLogger.printf("\tInternal Efficiency        :: %d / %d (%3.0f%%)%n",
-					event.getMatchedSSPTriggers(), sspSimTriggers, (100.0 * event.getMatchedSSPTriggers() / sspSimTriggers));
-		}
-		if(reconSimTriggers == 0) {
-			OutputLogger.printf("\tTrigger Efficiency         :: %d / %d (N/A)%n",
-					event.getMatchedReconTriggers(), reconSimTriggers);
-		} else {
-			OutputLogger.printf("\tTrigger Efficiency         :: %d / %d (%3.0f%%)%n",
-					event.getMatchedReconTriggers(), reconSimTriggers, (100.0 * event.getMatchedReconTriggers() / reconSimTriggers));
-		}
+		
+		int matchedSSPTriggers = triggerEvent[0].getMatchedSSPSimulatedTriggers() + triggerEvent[1].getMatchedSSPSimulatedTriggers();
+		OutputLogger.printf("\tInternal Efficiency        :: %d / %d ", matchedSSPTriggers, sspSimTriggers);
+		if(sspSimTriggers == 0) { OutputLogger.printf("(N/A)%n"); }
+		else { OutputLogger.printf("(%3.0f%%)%n", (100.0 * matchedSSPTriggers / sspSimTriggers)); }
+		
+		int matchedReconTriggers = triggerEvent[0].getMatchedReconSimulatedTriggers() + triggerEvent[1].getMatchedReconSimulatedTriggers();
+		OutputLogger.printf("\tTrigger Efficiency         :: %d / %d", matchedReconTriggers, reconSimTriggers);
+		if(reconSimTriggers == 0) { OutputLogger.printf("(N/A)%n"); }
+		else { OutputLogger.printf("(%3.0f%%)%n", (100.0 * matchedReconTriggers / reconSimTriggers)); }
 		
 		// Print the individual cut performances.
 		if(isSingles) {
@@ -1720,70 +1731,64 @@
 			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), 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]);
+					OutputLogger.printf("\tCluster Energy Lower Bound :: %d / %d%n", triggerEvent[triggerNum].getSSPCutFailures(ENERGY_MIN), sspTriggerCount[triggerNum]);
+					OutputLogger.printf("\tCluster Energy Upper Bound :: %d / %d%n", triggerEvent[triggerNum].getSSPCutFailures(ENERGY_MAX), sspTriggerCount[triggerNum]);
+					OutputLogger.printf("\tCluster Hit Count          :: %d / %d%n", triggerEvent[triggerNum].getSSPCutFailures(HIT_COUNT), sspTriggerCount[triggerNum]);
 				} else {
 					OutputLogger.printf("\tCluster Energy Lower Bound :: %d / %d (%3.0f%%)%n",
-							event.getCutFailures(triggerNum, ENERGY_MIN), sspTriggerCount[triggerNum],
-							(100.0 * event.getCutFailures(triggerNum, ENERGY_MIN) / sspTriggerCount[triggerNum]));
+							triggerEvent[triggerNum].getSSPCutFailures(ENERGY_MIN), sspTriggerCount[triggerNum],
+							(100.0 * triggerEvent[triggerNum].getSSPCutFailures(ENERGY_MIN) / sspTriggerCount[triggerNum]));
 					OutputLogger.printf("\tCluster Energy Upper Bound :: %d / %d (%3.0f%%)%n",
-							event.getCutFailures(triggerNum, ENERGY_MAX), sspTriggerCount[triggerNum],
-							(100.0 * event.getCutFailures(triggerNum, ENERGY_MAX) / sspTriggerCount[triggerNum]));
+							triggerEvent[triggerNum].getSSPCutFailures(ENERGY_MAX), sspTriggerCount[triggerNum],
+							(100.0 * triggerEvent[triggerNum].getSSPCutFailures(ENERGY_MAX) / sspTriggerCount[triggerNum]));
 					OutputLogger.printf("\tCluster Hit Count          :: %d / %d (%3.0f%%)%n",
-							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);
+							triggerEvent[triggerNum].getSSPCutFailures(HIT_COUNT), sspTriggerCount[triggerNum],
+							(100.0 * triggerEvent[triggerNum].getSSPCutFailures(HIT_COUNT) / sspTriggerCount[triggerNum]));
+				}
 			}
 			
 			// Update the global trigger tracking variables.
-			triggerRunStats[0].addEvent(activeTrigger, event, reconTriggerList, sspTriggerList, sspTriggers);
-			triggerLocalStats[0].addEvent(activeTrigger, event, reconTriggerList, sspTriggerList, sspTriggers);
-			efficiencyRunStats.addSinglesTriggers(activeTrigger, reconTriggerList);
-			efficiencyLocalStats.addSinglesTriggers(activeTrigger, reconTriggerList);
-			efficiencyRunStats.addEvent(activeTrigger, event);
-			efficiencyLocalStats.addEvent(activeTrigger, event);
+			localStats.getTriggerStats().getSingles0Stats().addEvent(triggerEvent[0]);
+			localStats.getTriggerStats().getSingles1Stats().addEvent(triggerEvent[1]);
+			globalStats.getTriggerStats().getSingles0Stats().addEvent(triggerEvent[0]);
+			globalStats.getTriggerStats().getSingles1Stats().addEvent(triggerEvent[1]);
 		} else {
 			for(int triggerNum = 0; triggerNum < 2; triggerNum++) {
 				OutputLogger.println();
 				OutputLogger.printf("Trigger %d Individual Cut Failure Rate:%n", (triggerNum + 1));
 				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]);
+					OutputLogger.printf("\tPair Energy Sum            :: %d / %d%n", triggerEvent[triggerNum].getSSPCutFailures(ENERGY_SUM), sspTriggerCount[triggerNum]);
+					OutputLogger.printf("\tPair Energy Difference     :: %d / %d%n", triggerEvent[triggerNum].getSSPCutFailures(ENERGY_DIFF), sspTriggerCount[triggerNum]);
+					OutputLogger.printf("\tPair Energy Slope          :: %d / %d%n", triggerEvent[triggerNum].getSSPCutFailures(ENERGY_SLOPE), sspTriggerCount[triggerNum]);
+					OutputLogger.printf("\tPair Coplanarity           :: %d / %d%n", triggerEvent[triggerNum].getSSPCutFailures(COPLANARITY), sspTriggerCount[triggerNum]);
 				} else {
 					OutputLogger.printf("\tPair Energy Sum            :: %d / %d (%3.0f%%)%n",
-							event.getCutFailures(triggerNum, ENERGY_SUM), sspTriggerCount[triggerNum],
-							(100.0 * event.getCutFailures(triggerNum, ENERGY_SUM) / sspTriggerCount[triggerNum]));
+							triggerEvent[triggerNum].getSSPCutFailures(ENERGY_SUM), sspTriggerCount[triggerNum],
+							(100.0 * triggerEvent[triggerNum].getSSPCutFailures(ENERGY_SUM) / sspTriggerCount[triggerNum]));
 					OutputLogger.printf("\tPair Energy Difference     :: %d / %d (%3.0f%%)%n",
-							event.getCutFailures(triggerNum, ENERGY_DIFF), sspTriggerCount[triggerNum],
-							(100.0 * event.getCutFailures(triggerNum, ENERGY_DIFF) / sspTriggerCount[triggerNum]));
+							triggerEvent[triggerNum].getSSPCutFailures(ENERGY_DIFF), sspTriggerCount[triggerNum],
+							(100.0 * triggerEvent[triggerNum].getSSPCutFailures(ENERGY_DIFF) / sspTriggerCount[triggerNum]));
 					OutputLogger.printf("\tPair Energy Slope          :: %d / %d (%3.0f%%)%n",
-							event.getCutFailures(triggerNum, ENERGY_SLOPE), sspTriggerCount[triggerNum],
-							(100.0 * event.getCutFailures(triggerNum, ENERGY_SLOPE) / sspTriggerCount[triggerNum]));
+							triggerEvent[triggerNum].getSSPCutFailures(ENERGY_SLOPE), sspTriggerCount[triggerNum],
+							(100.0 * triggerEvent[triggerNum].getSSPCutFailures(ENERGY_SLOPE) / sspTriggerCount[triggerNum]));
 					OutputLogger.printf("\tPair Coplanarity           :: %d / %d (%3.0f%%)%n",
-							event.getCutFailures(triggerNum, COPLANARITY), sspTriggerCount[triggerNum],
-							(100.0 * event.getCutFailures(triggerNum, COPLANARITY) / sspTriggerCount[triggerNum]));
-				}
-				OutputLogger.printf("\tExcess Reported Triggers   :: %d%n", sspReportedExtras / 2);
+							triggerEvent[triggerNum].getSSPCutFailures(COPLANARITY), sspTriggerCount[triggerNum],
+							(100.0 * triggerEvent[triggerNum].getSSPCutFailures(COPLANARITY) / sspTriggerCount[triggerNum]));
+				}
 			}
 			
 			// Update the global trigger tracking variables.
-			triggerRunStats[1].addEvent(activeTrigger, event, reconTriggerList, sspTriggerList, sspTriggers);
-			triggerLocalStats[1].addEvent(activeTrigger, event, reconTriggerList, sspTriggerList, sspTriggers);
-			efficiencyRunStats.addPairTriggers(activeTrigger, reconTriggerList);
-			efficiencyLocalStats.addSinglesTriggers(activeTrigger, reconTriggerList);
-			efficiencyRunStats.addEvent(activeTrigger, event);
-			efficiencyLocalStats.addEvent(activeTrigger, event);
+			localStats.getTriggerStats().getPair0Stats().addEvent(triggerEvent[0]);
+			localStats.getTriggerStats().getPair1Stats().addEvent(triggerEvent[1]);
+			globalStats.getTriggerStats().getPair0Stats().addEvent(triggerEvent[0]);
+			globalStats.getTriggerStats().getPair1Stats().addEvent(triggerEvent[1]);
 		}
 		
 		// Note whether the was a trigger match failure.
-		if(event.getMatchedReconTriggers() - reconSimTriggers != 0) {
+		if(triggerEvent[0].getFailedReconSimulatedTriggers() != 0 && triggerEvent[1].getFailedReconSimulatedTriggers() != 0) {
 			if(isSingles) { singlesEfficiencyFail = true; }
 			else { pairEfficiencyFail = true; }
-		} if(event.getMatchedSSPTriggers() - sspSimTriggers != 0) {
+		} if(triggerEvent[0].getFailedSSPSimulatedTriggers() != 0 && triggerEvent[1].getFailedSSPSimulatedTriggers() != 0) {
 			if(isSingles) { singlesInternalFail = true; }
 			else { pairInternalFail = true; }
 		}
@@ -2254,7 +2259,7 @@
 	 * @param secondEvent - The second cluster matching event.
 	 * @return Returns the cluster matching event that is better.
 	 */
-	private static final ClusterMatchEvent getBestPermutation(ClusterMatchEvent firstEvent, ClusterMatchEvent secondEvent) {
+	private static final DetailedClusterEvent getBestPermutation(DetailedClusterEvent firstEvent, DetailedClusterEvent secondEvent) {
 		// If both permutations are null, return that.
 		if(firstEvent == null && secondEvent == null) {
 			return null;

Added: java/trunk/analysis/src/main/java/org/hps/analysis/trigger/data/ClusterEvent.java
 =============================================================================
--- java/trunk/analysis/src/main/java/org/hps/analysis/trigger/data/ClusterEvent.java	(added)
+++ java/trunk/analysis/src/main/java/org/hps/analysis/trigger/data/ClusterEvent.java	Thu Apr  2 10:05:53 2015
@@ -0,0 +1,112 @@
+package org.hps.analysis.trigger.data;
+
+/**
+ * Class <code>ClusterEvent</code> tracks reconstructed/SSP cluster
+ * pairs for the purpose of cluster matching. It maintains statistical
+ * information related to how many of each type of cluster was found
+ * as well as how many matched and failed with a given fail state.
+ * 
+ * @author Kyle McCarty <[log in to unmask]>
+ */
+public class ClusterEvent extends ClusterStatModule {
+	/**
+	 * Fuses another <code>ClusterEvent</code> with this object. The
+	 * other event's cluster pairs and states will be added to those
+	 * already in this event.
+	 * @param event - The event to fuse.
+	 */
+	public void addEvent(ClusterEvent event) {
+		// If the event is null, do nothing.
+		if(event == null) { return; }
+		
+		// Add the values stored in the argument event to the counters
+		// in this event.
+		sspClusters   += event.sspClusters;
+		reconClusters += event.reconClusters;
+		matches       += event.matches;
+		failEnergy    += event.failEnergy;
+		failPosition  += event.failPosition;
+		failHitCount  += event.failHitCount;
+	}
+	
+	/**
+	 * 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);
+	}
+	
+	/**
+	 * Notes that a reconstructed cluster and SSP cluster pair failed
+	 * due to energy.
+	 */
+	public void pairFailEnergy() {
+		failEnergy++;
+	}
+	
+	/**
+	 * Notes that a reconstructed cluster and SSP cluster pair failed
+	 * due to hit count.
+	 */
+	public void pairFailHitCount() {
+		failHitCount++;
+	}
+	
+	/**
+	 * Notes that a reconstructed cluster and SSP cluster pair failed
+	 * due to position.
+	 */
+	public void pairFailPosition() {
+		failPosition++;
+	}
+	
+	/**
+	 * Notes that one or more reconstructed cluster and SSP cluster pair
+	 * failed due to position.
+	 * @param count - The number of events that failed in this manner.
+	 */
+	public void pairFailPosition(int count) {
+		// negative values are non-physical.
+		if(count < 0) {
+			throw new IllegalArgumentException("Cluster failure counts must be non-negative.");
+		}
+		
+		// Increment the count.
+		failPosition += count;
+	}
+	
+	/**
+	 * Notes that a reconstructed cluster and SSP cluster pair failed
+	 * due to time.
+	 */
+	public void pairFailTime() {
+		failTime++;
+	}
+	
+	/**
+	 * Notes that a reconstructed cluster and SSP cluster pair was
+	 * successfully matched.
+	 */
+	public void pairMatch() {
+		matches++;
+	}
+	
+	/**
+	 * Increments the number of reconstructed FADC clusters seen.
+	 * @param count - The number of clusters seen.
+	 */
+	public void sawReconClusters(int count) {
+		reconClusters += count;
+	}
+	
+	/**
+	 * Increments the number of SSP bank clusters seen.
+	 * @param count - The number of clusters seen.
+	 */
+	public void sawSSPClusters(int count) {
+		sspClusters += count;
+	}
+}

Added: java/trunk/analysis/src/main/java/org/hps/analysis/trigger/data/ClusterMatchedPair.java
 =============================================================================
--- java/trunk/analysis/src/main/java/org/hps/analysis/trigger/data/ClusterMatchedPair.java	(added)
+++ java/trunk/analysis/src/main/java/org/hps/analysis/trigger/data/ClusterMatchedPair.java	Thu Apr  2 10:05:53 2015
@@ -0,0 +1,127 @@
+package org.hps.analysis.trigger.data;
+
+import org.hps.analysis.trigger.util.Pair;
+import org.hps.analysis.trigger.util.TriggerDiagnosticUtil;
+import org.hps.recon.ecal.triggerbank.SSPCluster;
+import org.lcsim.event.Cluster;
+
+/**
+ * Class <code>ClusterMatchedPair</code> stores a reconstructed cluster
+ * and an SSP bank reported cluster which have been compared for the
+ * purpose of cluster matching. It also tracks what the match state of
+ * the two clusters is.
+ * 
+ * @author Kyle McCarty <[log in to unmask]>
+ */
+public class ClusterMatchedPair extends Pair<Cluster, SSPCluster> {
+	// CLass variables.
+	private final byte state;
+	
+	/**
+	 * Instantiates a new <code>ClusterMatchedPair</code> object from
+	 * the two indicated clusters and marks their match state.
+	 * @param reconCluster - The reconstructed cluster.
+	 * @param sspCluster - The SSP cluster.
+	 * @param state - The pair match state.
+	 */
+	public ClusterMatchedPair(Cluster reconCluster, SSPCluster sspCluster, byte state) {
+		// Set the cluster pairs.
+		super(reconCluster, sspCluster);
+		
+		// If the state is defined, set it. Otherwise, it is unknown.
+		if(state == TriggerDiagnosticUtil.CLUSTER_STATE_MATCHED
+				|| state == TriggerDiagnosticUtil.CLUSTER_STATE_FAIL_POSITION
+				|| state == TriggerDiagnosticUtil.CLUSTER_STATE_FAIL_ENERGY
+				|| state == TriggerDiagnosticUtil.CLUSTER_STATE_FAIL_HIT_COUNT) {
+			this.state = state;
+		} else {
+			this.state = TriggerDiagnosticUtil.CLUSTER_STATE_FAIL_UNKNOWN;
+		}
+	}
+	
+	/**
+	 * Gets the reconstructed cluster of the pair.
+	 * @return Returns the reconstructed cluster a <code>Cluster</cod>
+	 * object.
+	 */
+	public Cluster getReconstructedCluster() {
+		return getFirstElement();
+	}
+	
+	/**
+	 * Gets the SSP cluster of the pair.
+	 * @return Returns the SSP cluster as an <code>SSPCluster</code>
+	 * object.
+	 */
+	public SSPCluster getSSPCluster() {
+		return getSecondElement();
+	}
+	
+	/**
+	 * Gets the raw state identifier.
+	 * @return Returns the state identifier as a <code>byte</code>
+	 * primitive. Valid identifiers are defined in the class
+	 * <code>TriggerDiagnosticUtil</code>.
+	 */
+	public byte getState() {
+		return state;
+	}
+	
+	/**
+	 * Indicates whether the recon/SSP pair failed to not being close
+	 * enough in energy.
+	 * @return Returns <code>true</code> if the pair match state is an
+	 * energy fail state and <code>false</code> otherwise.
+	 */
+	public boolean isEnergyFailState() {
+		return (state == TriggerDiagnosticUtil.CLUSTER_STATE_FAIL_ENERGY);
+	}
+	
+	/**
+	 * Indicates whether the recon/SSP pair failed to match due to not
+	 * being close enough in hit count.
+	 * @return Returns <code>true</code> if the pair match state is a
+	 * hit count fail state and <code>false</code> otherwise.
+	 */
+	public boolean isHitCountFailState() {
+		return (state == TriggerDiagnosticUtil.CLUSTER_STATE_FAIL_HIT_COUNT);
+	}
+	
+	/**
+	 * Indicates whether the recon/SSP pair matched.
+	 * @return Returns <code>true</code> if the pair match state is a
+	 * match state and <code>false</code> otherwise.
+	 */
+	public boolean isMatch() {
+		return (state == TriggerDiagnosticUtil.CLUSTER_STATE_MATCHED);
+	}
+	
+	/**
+	 * 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);
+	}
+	
+	/**
+	 * Indicates whether the recon/SSP pair has no known match state.
+	 * @return Returns <code>true</code> if the pair match state is
+	 * unknown and <code>false</code> otherwise.
+	 */
+	public boolean isUnknownState() {
+		return (state == TriggerDiagnosticUtil.CLUSTER_STATE_FAIL_UNKNOWN);
+	}
+}

Added: java/trunk/analysis/src/main/java/org/hps/analysis/trigger/data/ClusterStatModule.java
 =============================================================================
--- java/trunk/analysis/src/main/java/org/hps/analysis/trigger/data/ClusterStatModule.java	(added)
+++ java/trunk/analysis/src/main/java/org/hps/analysis/trigger/data/ClusterStatModule.java	Thu Apr  2 10:05:53 2015
@@ -0,0 +1,124 @@
+package org.hps.analysis.trigger.data;
+
+/**
+ * Class <code>ClusterStatModule</code> stores the statistical data
+ * for trigger diagnostic cluster matching.
+ * 
+ * @author Kyle McCarty <[log in to unmask]>
+ */
+public class ClusterStatModule {
+	// Track cluster statistics.
+	protected int sspClusters   = 0;
+	protected int reconClusters = 0;
+	protected int matches       = 0;
+	protected int failEnergy    = 0;
+	protected int failPosition  = 0;
+	protected int failHitCount  = 0;
+	protected int failTime      = 0;
+	
+	/**
+	 * Instantiates a <code>ClusterStatModule</code> with no statistics
+	 * stored.
+	 */
+	ClusterStatModule() {  }
+	
+	/**
+	 * Clears all statistical information and resets the object of its
+	 * default, empty state.
+	 */
+	void clear() {
+		sspClusters   = 0;
+		reconClusters = 0;
+		matches       = 0;
+		failEnergy    = 0;
+		failPosition  = 0;
+		failHitCount  = 0;
+		failTime      = 0;
+	}
+	
+	@Override
+	public ClusterStatModule clone() {
+		// Create a clone.
+		ClusterStatModule clone = new ClusterStatModule();
+		
+		// Copy the statistical values to the clone.
+		clone.sspClusters   = sspClusters;
+		clone.reconClusters = reconClusters;
+		clone.matches       = matches;
+		clone.failEnergy    = failEnergy;
+		clone.failPosition  = failPosition;
+		clone.failHitCount  = failHitCount;
+		clone.failTime      = failTime;
+		
+		// Return the clone.
+		return clone;
+	}
+	
+	/**
+	 * Gets the number of cluster pairs stored in this event that are
+	 * marked with energy fail states.
+	 * @return Returns the number of instances of this state as an
+	 * <code>int</code> primitive.
+	 */
+	public int getEnergyFailures() {
+		return failEnergy;
+	}
+	
+	/**
+	 * Gets the number of cluster pairs stored in this event that are
+	 * marked with hit count fail states.
+	 * @return Returns the number of instances of this state as an
+	 * <code>int</code> primitive.
+	 */
+	public int getHitCountFailures() {
+		return failHitCount;
+	}
+	
+	/**
+	 * Gets the number of cluster pairs stored in this event that are
+	 * marked with position fail states.
+	 * @return Returns the number of instances of this state as an
+	 * <code>int</code> primitive.
+	 */
+	public int getMatches() {
+		return matches;
+	}
+	
+	/**
+	 * Gets the number of cluster pairs stored in this event that are
+	 * marked with position fail states.
+	 * @return Returns the number of instances of this state as an
+	 * <code>int</code> primitive.
+	 */
+	public int getPositionFailures() {
+		return failPosition;
+	}
+	
+	/**
+	 * Gets the total number of verifiable reconstructed clusters seen.
+     * @return Returns the cluster count as an <code>int</code>
+     * primitive.
+	 */
+    public int getReconClusterCount() {
+    	return reconClusters;
+    }
+    
+    /**
+     * Gets the total number of SSP bank clusters seen.
+     * @return Returns the cluster count as an <code>int</code>
+     * primitive.
+     */
+    public int getSSPClusterCount() {
+    	return sspClusters;
+    }
+	
+	/**
+	 * 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;
+	}
+}

Added: java/trunk/analysis/src/main/java/org/hps/analysis/trigger/data/DetailedClusterEvent.java
 =============================================================================
--- java/trunk/analysis/src/main/java/org/hps/analysis/trigger/data/DetailedClusterEvent.java	(added)
+++ java/trunk/analysis/src/main/java/org/hps/analysis/trigger/data/DetailedClusterEvent.java	Thu Apr  2 10:05:53 2015
@@ -0,0 +1,96 @@
+package org.hps.analysis.trigger.data;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.hps.analysis.trigger.util.TriggerDiagnosticUtil;
+import org.hps.recon.ecal.triggerbank.SSPCluster;
+import org.lcsim.event.Cluster;
+
+public class DetailedClusterEvent extends ClusterEvent {
+	// Store all of the pairs.
+	private List<ClusterMatchedPair> pairList = new ArrayList<ClusterMatchedPair>();
+	
+	/**
+	 * Fuses another <code>ClusterEvent</code> with this object. The
+	 * other event's cluster pairs and states will be added to those
+	 * already in this event.
+	 * @param event - The event to fuse.
+	 */
+	public void addEvent(ClusterEvent event) {
+		// Run the superclass method.
+		super.addEvent(event);
+		
+		// If the event is null, do nothing.
+		if(event == null) { return; }
+		
+		// Merge the list of cluster pairs, if applicable.
+		if(event instanceof DetailedClusterEvent) {
+			pairList.addAll(((DetailedClusterEvent) event).pairList);
+		}
+	}
+	
+	/**
+	 * Adds a reconstructed/SSP cluster pair and marks it as having an
+	 * energy fail state.
+	 * @param reconCluster - The reconstructed cluster.
+	 * @param sspCluster - The SSP cluster.
+	 */
+	public void pairFailEnergy(Cluster reconCluster, SSPCluster sspCluster) {
+		pairFailEnergy();
+		pairList.add(new ClusterMatchedPair(reconCluster, sspCluster, TriggerDiagnosticUtil.CLUSTER_STATE_FAIL_ENERGY));
+	}
+	
+	/**
+	 * Adds a reconstructed/SSP cluster pair and marks it as having a
+	 * hit count fail state.
+	 * @param reconCluster - The reconstructed cluster.
+	 * @param sspCluster - The SSP cluster.
+	 */
+	public void pairFailHitCount(Cluster reconCluster, SSPCluster sspCluster) {
+		pairFailHitCount();
+		pairList.add(new ClusterMatchedPair(reconCluster, sspCluster, TriggerDiagnosticUtil.CLUSTER_STATE_FAIL_HIT_COUNT));
+	}
+	
+	/**
+	 * Adds a reconstructed/SSP cluster pair and marks it as having a
+	 * position fail state.
+	 * @param reconCluster - The reconstructed cluster.
+	 * @param sspCluster - The SSP cluster.
+	 */
+	public void pairFailPosition(Cluster reconCluster, SSPCluster sspCluster) {
+		pairFailPosition();
+		pairList.add(new ClusterMatchedPair(reconCluster, sspCluster, TriggerDiagnosticUtil.CLUSTER_STATE_FAIL_POSITION));
+	}
+	
+	/**
+	 * 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) {
+		pairFailTime();
+		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.
+	 */
+	public void pairMatch(Cluster reconCluster, SSPCluster sspCluster) {
+		pairMatch();
+		pairList.add(new ClusterMatchedPair(reconCluster, sspCluster, TriggerDiagnosticUtil.CLUSTER_STATE_MATCHED));
+	}
+	
+	/**
+	 * Gets a list of all matched cluster pairs and their match states.
+	 * @return Returns the matched cluster pairs as a <code>List</code>
+	 * of <code>ClusterMatchedPair</code> objects.
+	 */
+	public List<ClusterMatchedPair> getClusterPairs() {
+		return pairList;
+	}
+}

Added: java/trunk/analysis/src/main/java/org/hps/analysis/trigger/data/DiagnosticSnapshot.java
 =============================================================================
--- java/trunk/analysis/src/main/java/org/hps/analysis/trigger/data/DiagnosticSnapshot.java	(added)
+++ java/trunk/analysis/src/main/java/org/hps/analysis/trigger/data/DiagnosticSnapshot.java	Thu Apr  2 10:05:53 2015
@@ -0,0 +1,124 @@
+package org.hps.analysis.trigger.data;
+
+/**
+ * Class <code>DiagnosticSnapshot</code> creates a snapshot of the
+ * trigger diagnostics at a specific time that can be passed to other
+ * classes. It is entirely static and will not change after creation.
+ * 
+ * @author Kyle McCarty <[log in to unmask]>
+ */
+public class DiagnosticSnapshot {
+	// Store the TI trigger information.
+	private int[] tiSeenAll = new int[6];
+	private int[] tiSeenHierarchical = new int[6];
+	
+	// Store the statistical modules.
+	private final GeneralStatModule generalStats;
+	private final ClusterStatModule clusterStats;
+	private final TriggerStatModule[] triggerStats = new TriggerStatModule[4];
+	
+	/**
+	 * Creates a snapshot of the trigger diagnostic results.
+	 * @param stats - The run statistical object.
+	 */
+	DiagnosticSnapshot(RunDiagStats stats) {
+		// Store the statistical modules.
+		generalStats = stats.clone();
+		clusterStats = stats.getClusterStats().clone();
+		triggerStats[0] = stats.getTriggerStats().getSingles0Stats().clone();
+		triggerStats[1] = stats.getTriggerStats().getSingles1Stats().clone();
+		triggerStats[2] = stats.getTriggerStats().getPair0Stats().clone();
+		triggerStats[3] = stats.getTriggerStats().getPair1Stats().clone();
+		
+		// Copy the TI trigger data.
+		for(int triggerType = 0; triggerType < 6; triggerType++) {
+			tiSeenAll[triggerType] = stats.getTriggerStats().getTITriggers(triggerType, false);
+			tiSeenHierarchical[triggerType] = stats.getTriggerStats().getTITriggers(triggerType, true);
+		}
+	}
+	
+	/**
+	 * Gets the general run statistics.
+	 * @return Returns a <code>GeneralStatModule</code> object that
+	 * contains the statistics.
+	 */
+	public GeneralStatModule getGeneralStats() {
+		return generalStats;
+	}
+	
+	/**
+	 * Gets the cluster statistics.
+	 * @return Returns a <code>ClusterStatModule</code> object that
+	 * contains the statistics.
+	 */
+	public ClusterStatModule getClusterStats() {
+		return clusterStats;
+	}
+	
+	/**
+	 * Gets the singles 0 trigger statistics.
+	 * @return Returns a <code>TriggerStatModule</code> object that
+	 * contains the statistics.
+	 */
+	public TriggerStatModule getSingles0Stats() {
+		return triggerStats[0];
+	}
+	
+	/**
+	 * Gets the singles 1 trigger statistics.
+	 * @return Returns a <code>TriggerStatModule</code> object that
+	 * contains the statistics.
+	 */
+	public TriggerStatModule getSingles1Stats() {
+		return triggerStats[1];
+	}
+	
+	/**
+	 * Gets the pair 0 trigger statistics.
+	 * @return Returns a <code>TriggerStatModule</code> object that
+	 * contains the statistics.
+	 */
+	public TriggerStatModule getPair0Stats() {
+		return triggerStats[2];
+	}
+	
+	/**
+	 * Gets the pair 1 trigger statistics.
+	 * @return Returns a <code>TriggerStatModule</code> object that
+	 * contains the statistics.
+	 */
+	public TriggerStatModule getPair1Stats() {
+		return triggerStats[3];
+	}
+	
+	/**
+	 * Gets the total number of events where the TI reported a trigger
+	 * of the specified type.
+	 * @param triggerID - The identifier for the type of trigger.
+	 * @param unique - <code>true</code> returns only the number of
+	 * events where this trigger type was the <i>only</i> type seen by
+	 * the TI while <code>false</code> returns the number of events
+	 * that saw this trigger type without regards for other trigger
+	 * flags.
+	 * @return Returns the count as an <code>int</code>.
+	 */
+	public int getTITriggers(int triggerID, boolean hierarchical) {
+		// Verify the trigger type.
+		validateTriggerType(triggerID);
+		
+		// Increment the counters.
+		if(hierarchical) { return tiSeenHierarchical[triggerID]; }
+		else { return tiSeenAll[triggerID]; }
+	}
+	
+	/**
+	 * Produces an exception if the argument trigger type is not of a
+	 * supported type.
+	 * @param triggerType - The trigger type to verify.
+	 */
+	private static final void validateTriggerType(int triggerType) {
+		if(triggerType < 0 || triggerType > 5) {
+			throw new IndexOutOfBoundsException(String.format("Trigger type \"%d\" is not supported.", triggerType));
+		}
+	}
+}

Added: java/trunk/analysis/src/main/java/org/hps/analysis/trigger/data/GeneralStatModule.java
 =============================================================================
--- java/trunk/analysis/src/main/java/org/hps/analysis/trigger/data/GeneralStatModule.java	(added)
+++ java/trunk/analysis/src/main/java/org/hps/analysis/trigger/data/GeneralStatModule.java	Thu Apr  2 10:05:53 2015
@@ -0,0 +1,103 @@
+package org.hps.analysis.trigger.data;
+
+/**
+ * Class <code>GeneralStatModule</code> stores statistical data that
+ * is not specific to any one part of the diagnostics.
+ * 
+ * @author Kyle McCarty <[log in to unmask]>
+ */
+public class GeneralStatModule {
+	// Store general run statistics.
+	protected long endTime = -1;
+	protected long startTime = -1;
+	protected int totalEvents = 0;
+	protected int noiseEvents = 0;
+	protected int failedPairEvents = 0;
+	protected int failedClusterEvents = 0;
+	protected int failedSinglesEvents = 0;
+	
+	/**
+	 * Clears all of the statistical counters in the object.
+	 */
+	void clear() {
+		endTime = -1;
+		startTime = -1;
+		totalEvents = 0;
+		noiseEvents = 0;
+		failedPairEvents = 0;
+		failedClusterEvents = 0;
+		failedSinglesEvents = 0;
+	}
+	
+	@Override
+	public GeneralStatModule clone() {
+		// Create the a cloned object.
+		GeneralStatModule clone = new GeneralStatModule();
+		
+		// Copy the tracked statistical data to the clone.
+		clone.endTime             = endTime;
+		clone.startTime           = startTime;
+		clone.totalEvents         = totalEvents;
+		clone.noiseEvents         = noiseEvents;
+		clone.failedPairEvents    = failedPairEvents;
+		clone.failedClusterEvents = failedClusterEvents;
+		clone.failedSinglesEvents = failedSinglesEvents;
+		
+		// Return the clone.
+		return clone;
+	}
+	
+	/**
+	 * Gets the length of time, in nanoseconds, over which the events
+	 * represented by this object occurred.
+	 * @return Returns the length of time as a <code>long</code>.
+	 */
+	public long getDuration() {
+		return endTime - startTime;
+	}
+	
+	/**
+	 * Gets the number of events seen.
+	 * @return Returns the number of events as an <code>int</code>.
+	 */
+	public int getEventCount() {
+		return totalEvents;
+	}
+	
+	/**
+	 * Gets the number of events in which at least one cluster was
+	 * not matched.
+	 * @return Returns the number of events as an <code>int</code>.
+	 */
+	public int getFailedClusterEventCount() {
+		return failedClusterEvents;
+	}
+	
+	/**
+	 * Gets the number of events in which at least one pair trigger
+	 * was not matched.
+	 * @return Returns the number of events as an <code>int</code>.
+	 */
+	public int getFailedPairEventCount() {
+		return failedPairEvents;
+	}
+
+	/**
+	 * Gets the number of events in which at least one singles trigger
+	 * was not matched.
+	 * @return Returns the number of events as an <code>int</code>.
+	 */
+	public int getFailedSinglesEventCount() {
+		return failedSinglesEvents;
+	}
+	
+	/**
+	 * Gets the number of events which were ignored due to having too
+	 * many hits in them.
+	 * @return Returns the number of events as an <code>int</code>.
+	 */
+	public int getNoiseEvents() {
+		return noiseEvents;
+	}
+
+}

Added: java/trunk/analysis/src/main/java/org/hps/analysis/trigger/data/RunDiagStats.java
 =============================================================================
--- java/trunk/analysis/src/main/java/org/hps/analysis/trigger/data/RunDiagStats.java	(added)
+++ java/trunk/analysis/src/main/java/org/hps/analysis/trigger/data/RunDiagStats.java	Thu Apr  2 10:05:53 2015
@@ -0,0 +1,97 @@
+package org.hps.analysis.trigger.data;
+
+/**
+ * Class <code>RunDiagStats</code> provides a central repository for
+ * all diagnostic statistics. It allows access and editing of each of
+ * the specific statistical modules and also is able to generate new
+ * diagnostic snapshots.
+ * 
+ * @author Kyle McCarty <[log in to unmask]>
+ */
+public class RunDiagStats extends GeneralStatModule {
+	// Store the statistics for trigger matching.
+	private TriggerDiagStats triggerStats = new TriggerDiagStats();
+	
+	// Store the statistics for cluster matching.
+	private ClusterEvent clusterStats = new ClusterEvent();
+	
+	/**
+	 * Clears all of the statistical counters in the object.
+	 */
+	public void clear() {
+		super.clear();
+		clusterStats.clear();
+		triggerStats.clear();
+	}
+	
+	/**
+	 * Notes that an event failed to match all clusters.
+	 */
+	public void failedClusterEvent() {
+		failedClusterEvents++;
+	}
+	
+	/**
+	 * Notes that an event failed to match all pair triggers.
+	 */
+	public void failedPairEvent() {
+		failedPairEvents++;
+	}
+
+	/**
+	 * Notes that an event failed to match all singles triggers.
+	 */
+	public void failedSinglesEvent() {
+		failedSinglesEvents++;
+	}
+	
+	/**
+	 * Gets the cluster data.
+	 * @return Returns the <code>ClusterEvent</code> object that holds
+	 * the cluster data.
+	 */
+	public ClusterEvent getClusterStats() {
+		return clusterStats;
+	}
+	
+	/**
+	 * Gets a snapshot of the statistical data at the present time. The
+	 * snapshot will remain static and unchanged even if the generating
+	 * object itself is updated.
+	 * @return Returns a snapshot as a <code>DiagnosticSnapshot</code>
+	 * object.
+	 */
+	public DiagnosticSnapshot getSnapshot() {
+		return new DiagnosticSnapshot(this);
+	}
+	
+	/**
+	 * Gets the trigger data.
+	 * @return Returns the <code>TriggerDiagStats</code> object that holds
+	 * the cluster data.
+	 */
+	public TriggerDiagStats getTriggerStats() {
+		return triggerStats;
+	}
+	
+	/**
+	 * Notes that an event occurred.
+	 */
+	public void sawEvent(long eventTime) {
+		// Increment the event count.
+		totalEvents++;
+		
+		// If the start time is not defined, use this as the start time.
+		if(startTime == -1) { startTime = eventTime; }
+		
+		// The end time should always match the most recent event.
+		endTime = eventTime;
+	}
+
+	/**
+	 * Notes that an event was labeled as noise.
+	 */
+	public void sawNoiseEvent() {
+		noiseEvents++;
+	}
+}

Added: java/trunk/analysis/src/main/java/org/hps/analysis/trigger/data/TriggerDiagStats.java
 =============================================================================
--- java/trunk/analysis/src/main/java/org/hps/analysis/trigger/data/TriggerDiagStats.java	(added)
+++ java/trunk/analysis/src/main/java/org/hps/analysis/trigger/data/TriggerDiagStats.java	Thu Apr  2 10:05:53 2015
@@ -0,0 +1,307 @@
+package org.hps.analysis.trigger.data;
+
+import org.hps.analysis.trigger.util.ComponentUtils;
+import org.hps.analysis.trigger.util.TriggerDiagnosticUtil;
+
+public class TriggerDiagStats {
+	// Define TI trigger type identifiers.
+	public static final int SINGLES0 = TriggerStatModule.SINGLES_0;
+	public static final int SINGLES1 = TriggerStatModule.SINGLES_1;
+	public static final int PAIR0    = TriggerStatModule.PAIR_0;
+	public static final int PAIR1    = TriggerStatModule.PAIR_1;
+	public static final int PULSER   = TriggerStatModule.PULSER;
+	public static final int COSMIC   = TriggerStatModule.COSMIC;
+	
+	// Tracks the number of TI triggers seen across all events for only
+	// the TI trigger with the highest priority in the event.
+	private int[] tiSeenHierarchical = new int[6];
+	
+	// Tracks the number of TI triggers across all events.
+	private int[] tiSeenAll = new int[6];
+	
+	// Store the statistics modules for each of the regular triggers.
+	private TriggerEvent[] triggerStats = new TriggerEvent[4];
+	
+	/**
+	 * Instantiates a new <code>TriggerDiagStats</code> object.
+	 */
+	public TriggerDiagStats() {
+		// Instantiate a trigger statistics module for each of the
+		// triggers for which statistics are supported.
+		for(int triggerType = 0; triggerType < 4; triggerType++) {
+			triggerStats[triggerType] = new TriggerEvent();
+		}
+	}
+	
+	/**
+	 * Clears all of the statistical counters in the object.
+	 */
+	void clear() {
+		// Clear the tracked TI trigger data.
+		for(int tiType = 0; tiType < 6; tiType++) {
+			tiSeenAll[tiType] = 0;
+			tiSeenHierarchical[tiType] = 0;
+		}
+		
+		// Clear the trigger statistical modules.
+		for(int triggerType = 0; triggerType < 4; triggerType++) {
+			triggerStats[triggerType].clear();
+		}
+	}
+	
+	/**
+	 * Gets the trigger data for the pair 0 trigger.
+	 * @return Returns the <code>TriggerEvent</code> object that holds
+	 * the trigger data for the pair 0 trigger.
+	 */
+	public TriggerEvent getPair0Stats() {
+		return triggerStats[PAIR0];
+	}
+	
+	/**
+	 * Gets the trigger data for the pair 1 trigger.
+	 * @return Returns the <code>TriggerEvent</code> object that holds
+	 * the trigger data for the pair 1 trigger.
+	 */
+	public TriggerEvent getPair1Stats() {
+		return triggerStats[PAIR1];
+	}
+	
+	/**
+	 * Gets the trigger data for the singles 0 trigger.
+	 * @return Returns the <code>TriggerEvent</code> object that holds
+	 * the trigger data for the singles 0 trigger.
+	 */
+	public TriggerEvent getSingles0Stats() {
+		return triggerStats[SINGLES0];
+	}
+	
+	/**
+	 * Gets the trigger data for the singles 1 trigger.
+	 * @return Returns the <code>TriggerEvent</code> object that holds
+	 * the trigger data for the singles 1 trigger.
+	 */
+	public TriggerEvent getSingles1Stats() {
+		return triggerStats[SINGLES1];
+	}
+	
+	/**
+	 * Gets the total number of events where the TI reported a trigger
+	 * of the specified type.
+	 * @param triggerID - The identifier for the type of trigger.
+	 * @param unique - <code>true</code> returns only the number of
+	 * events where this trigger type was the <i>only</i> type seen by
+	 * the TI while <code>false</code> returns the number of events
+	 * that saw this trigger type without regards for other trigger
+	 * flags.
+	 * @return Returns the count as an <code>int</code>.
+	 */
+	public int getTITriggers(int triggerID, boolean hierarchical) {
+		// Verify the trigger type.
+		validateTriggerType(triggerID);
+		
+		// Increment the counters.
+		if(hierarchical) { return tiSeenHierarchical[triggerID]; }
+		else { return tiSeenAll[triggerID]; }
+	}
+	
+	/**
+	 * Increments the counts tracking the number of TI flags seen.
+	 * @param flags - An array of <code>boolean</code> values of size
+	 * six. This represents one flag for each possible TI trigger type.
+	 */
+	public void sawTITriggers(boolean[] flags) {
+		// There must be six trigger flags and the array must not be
+		// null.
+		if(flags == null) {
+			throw new NullPointerException("TI trigger flags can not be null.");
+		} if(flags.length != 6) {
+			throw new IllegalArgumentException("TI trigger flags must be of size six.");
+		}
+		
+		// Check each TI flag in the order of the flag hierarchy. The
+		// first flag in the hierarchy that is true is recorded in the
+		// hierarchical count. All flags are recorded in the all count.
+		boolean foundHierarchical = false;
+		if(flags[PAIR1]) {
+			tiSeenAll[PAIR1]++;
+			if(!foundHierarchical) {
+				tiSeenHierarchical[PAIR1]++;
+				foundHierarchical = true;
+			}
+		} if(flags[PAIR0]) {
+			tiSeenAll[PAIR0]++;
+			if(!foundHierarchical) {
+				tiSeenHierarchical[PAIR0]++;
+				foundHierarchical = true;
+			}
+		} if(flags[SINGLES1]) {
+			tiSeenAll[SINGLES1]++;
+			if(!foundHierarchical) {
+				tiSeenHierarchical[SINGLES1]++;
+				foundHierarchical = true;
+			}
+		} if(flags[SINGLES0]) {
+			tiSeenAll[SINGLES0]++;
+			if(!foundHierarchical) {
+				tiSeenHierarchical[SINGLES0]++;
+				foundHierarchical = true;
+			}
+		} if(flags[PULSER]) {
+			tiSeenAll[PULSER]++;
+			if(!foundHierarchical) {
+				tiSeenHierarchical[PULSER]++;
+				foundHierarchical = true;
+			}
+		} if(flags[COSMIC]) {
+			tiSeenAll[COSMIC]++;
+			if(!foundHierarchical) {
+				tiSeenHierarchical[COSMIC]++;
+				foundHierarchical = true;
+			}
+		}
+	}
+	
+	/**
+	 * Prints the trigger statistics to the terminal as a table.
+	 */
+	public void printEfficiencyTable() {
+		// Get the trigger statistics tables.
+		int[][] seenStats = new int[6][4];
+		int[][] matchedStats = new int[6][4];
+		TriggerEvent[] triggerEvents = { getSingles0Stats(), getSingles1Stats(), getPair0Stats(), getPair1Stats() };
+		for(int i = 0; i < 4; i++) {
+			for(int j = 0; j < 6; j++) {
+				seenStats[j][i] = triggerEvents[i].getReconSimulatedTriggers(j);
+				matchedStats[j][i] = triggerEvents[i].getMatchedReconSimulatedTriggers(j);
+			}
+		}
+		
+		// Define constant spacing variables.
+		int columnSpacing = 3;
+		
+		// Define table headers.
+		String sourceName = "Source";
+		String seenName = "Trigger Efficiency";
+		
+		// Get the longest column header name.
+		int longestHeader = -1;
+		String[] headerNames = {
+				TriggerDiagnosticUtil.TRIGGER_NAME[0],
+				TriggerDiagnosticUtil.TRIGGER_NAME[1],
+				TriggerDiagnosticUtil.TRIGGER_NAME[2],
+				TriggerDiagnosticUtil.TRIGGER_NAME[3],
+				"TI Highest Type"
+		};
+		for(String triggerName : headerNames) {
+			longestHeader = ComponentUtils.max(longestHeader, triggerName.length());
+		}
+		longestHeader = ComponentUtils.max(longestHeader, sourceName.length());
+		
+		// Determine the spacing needed to display the largest numerical
+		// cell value.
+		int numWidth = -1;
+		int longestCell = -1;
+		for(int eventTriggerID = 0; eventTriggerID < 6; eventTriggerID++) {
+			for(int seenTriggerID = 0; seenTriggerID < 4; seenTriggerID++) {
+				int valueSize = ComponentUtils.getDigits(seenStats[eventTriggerID][seenTriggerID]);
+				int cellSize = valueSize * 2 + 13;
+				if(cellSize > longestCell) {
+					longestCell = cellSize;
+					numWidth = valueSize;
+				}
+			}
+		}
+		
+		// The total column width can then be calculated from the
+		// longer of the header and cell values.
+		int columnWidth = ComponentUtils.max(longestCell, longestHeader);
+		int sourceWidth = ComponentUtils.max(
+				TriggerDiagnosticUtil.TRIGGER_NAME[0].length(), TriggerDiagnosticUtil.TRIGGER_NAME[1].length(),
+				TriggerDiagnosticUtil.TRIGGER_NAME[2].length(), TriggerDiagnosticUtil.TRIGGER_NAME[3].length(),
+				TriggerDiagnosticUtil.TRIGGER_NAME[4].length(), TriggerDiagnosticUtil.TRIGGER_NAME[5].length(),
+				sourceName.length() );
+		
+		// Calculate the total width of the table value header columns.
+		int headerTotalWidth = (headerNames.length * columnWidth)
+				+ ((headerNames.length - 1) * columnSpacing);
+		
+		// Write the table header.
+		String spacingText = ComponentUtils.getChars(' ', columnSpacing);
+		System.out.println(ComponentUtils.getChars(' ', sourceWidth) + spacingText
+				+ getCenteredString(seenName, headerTotalWidth));
+		
+		// Create the format strings for the cell values.
+		String headerFormat = "%-" + sourceWidth + "s" + spacingText;
+		String cellFormat = "%" + numWidth + "d / %" + numWidth + "d (%7.3f)";
+		String nullText = getCenteredString(ComponentUtils.getChars('-', numWidth) + " / "
+				+ ComponentUtils.getChars('-', numWidth) + " (  N/A  )", columnWidth) + spacingText;
+		
+		// Print the column headers.
+		System.out.printf(headerFormat, sourceName);
+		for(String header : headerNames) {
+			System.out.print(getCenteredString(header, columnWidth) + spacingText);
+		}
+		System.out.println();
+		
+		// Write out the value columns.
+		for(int eventTriggerID = 0; eventTriggerID < 6; eventTriggerID++) {
+			// Print out the row header.
+			System.out.printf(headerFormat, TriggerDiagnosticUtil.TRIGGER_NAME[eventTriggerID]);
+			
+			// Print the cell values.
+			for(int seenTriggerID = 0; seenTriggerID < 4; seenTriggerID++) {
+				if(seenTriggerID == eventTriggerID) { System.out.print(nullText); }
+				else {
+					String cellText = String.format(cellFormat, matchedStats[eventTriggerID][seenTriggerID],
+							seenStats[eventTriggerID][seenTriggerID],
+							(100.0 * matchedStats[eventTriggerID][seenTriggerID] / seenStats[eventTriggerID][seenTriggerID]));
+					System.out.print(getCenteredString(cellText, columnWidth) + spacingText);
+				}
+			}
+			
+			// Output the number of events that had only the trigger
+			// type ID for the current trigger type flagged by the TI.
+			System.out.print(getCenteredString("" + getTITriggers(eventTriggerID, true), columnWidth) + spacingText);
+			
+			// Start a new line.
+			System.out.println();
+		}
+	}
+	
+	/**
+	 * Produces a <code>String</code> of the indicated length with the
+	 * text <code>value</code> centered in the middle. Extra length is
+	 * filled through spaces before and after the text.
+	 * @param value - The text to display.
+	 * @param width - The number of spaces to include.
+	 * @return Returns a <code>String</code> of the specified length,
+	 * or the argument text if it is longer.
+	 */
+	private static final String getCenteredString(String value, int width) {
+		// The method can not perform as intended if the argument text
+		// exceeds the requested string length. Just return the text.
+		if(width <= value.length()) {
+			return value;
+		}
+		
+		// Otherwise, get the amount of buffering needed to center the
+		// text and add it around the text to produce the string.
+		else {
+			int buffer = (width - value.length()) / 2;
+			return ComponentUtils.getChars(' ', buffer) + value
+					+ ComponentUtils.getChars(' ', width - buffer - value.length());
+		}
+	}
+	
+	/**
+	 * Produces an exception if the argument trigger type is not of a
+	 * supported type.
+	 * @param triggerType - The trigger type to verify.
+	 */
+	private static final void validateTriggerType(int triggerType) {
+		if(triggerType < 0 || triggerType > 5) {
+			throw new IndexOutOfBoundsException(String.format("Trigger type \"%d\" is not supported.", triggerType));
+		}
+	}
+}

Added: java/trunk/analysis/src/main/java/org/hps/analysis/trigger/data/TriggerEvent.java
 =============================================================================
--- java/trunk/analysis/src/main/java/org/hps/analysis/trigger/data/TriggerEvent.java	(added)
+++ java/trunk/analysis/src/main/java/org/hps/analysis/trigger/data/TriggerEvent.java	Thu Apr  2 10:05:53 2015
@@ -0,0 +1,271 @@
+package org.hps.analysis.trigger.data;
+
+/**
+ * Class <code>TriggerEvent</code> tracks all of the statistics from
+ * a single trigger event. It is an extension of the statistics class
+ * <code>TriggerStatModule</code> which implements methods for altering
+ * the values in the base class.
+ * 
+ * @author Kyle McCarty <[log in to unmask]>
+ */
+public class TriggerEvent extends TriggerStatModule {
+	/**
+	 * Adds the statistics from one event object into this one.
+	 * @param event - The event data to add.
+	 */
+	public void addEvent(TriggerStatModule event) {
+		// Merge the values that do not depend on trigger source type.
+		reportedTriggers += event.reportedTriggers;
+		
+		// Merge each value that depends on the trigger source type.
+		for(int sourceType = 0; sourceType < 2; sourceType++) {
+			simTriggers[sourceType] += event.simTriggers[sourceType];
+			matchedTriggers[sourceType] += event.matchedTriggers[sourceType];
+			unmatchedTriggers[sourceType] += event.unmatchedTriggers[sourceType];
+			
+			// Merge the number of times each cut failed.
+			for(int cutID = 0; cutID < 4; cutID++) {
+				failedCuts[sourceType][cutID] += event.failedCuts[sourceType][cutID];
+			}
+			
+			// Copy the values for the TI flag trigger counters.
+			for(int tiType = 0; tiType < 6; tiType++) {
+				tiTriggersSeen[sourceType][tiType] += event.tiTriggersSeen[sourceType][tiType];
+				tiTriggersMatched[sourceType][tiType] += event.tiTriggersMatched[sourceType][tiType];
+			}
+		}
+	}
+	
+	/**
+	 * Indicates that a reconstructed trigger could not be matched, even
+	 * partially, to an SSP bank trigger.
+	 */
+	public void failedReconTrigger() {
+		unmatchedTriggers[RECON]++;
+	}
+	
+	/**
+	 * Indicates that an SSP simulated trigger could not be matched, even
+	 * partially, to an SSP bank trigger.
+	 */
+	public void failedSSPTrigger() {
+		unmatchedTriggers[SSP]++;
+	}
+
+	/**
+	 * Indicates that a trigger simulated from a reconstructed cluster
+	 * was successfully matched to a trigger in the SSP bank.
+	 * @param tiFlags - An array of size 6 indicating which TI bank
+	 * flags are active and which are not.
+	 * @param triggerTypeID - An identifier indicating the type of
+	 * trigger that was matched.
+	 */
+	public void matchedReconTrigger(boolean[] tiFlags) {
+		matchedTriggers(tiFlags, RECON);
+	}
+	
+	/**
+	 * Indicates that a trigger simulated from a reconstructed cluster
+	 * was partially matched to a trigger in the SSP bank, and notes
+	 * which cuts did and did not match.
+	 * @param tiFlags - An array of size 6 indicating which TI bank
+	 * flags are active and which are not.
+	 * @param triggerTypeID - An identifier indicating the type of
+	 * trigger that was matched.
+	 * @param matchedCuts - An array of size 3 or 4 indicating which
+	 * cuts did and did not align between the triggers.
+	 */
+	public void matchedReconTrigger(boolean[] tiFlags, boolean[] matchedCuts) {
+		matchedTriggers(tiFlags, matchedCuts, RECON);
+	}
+	
+	/**
+	 * Indicates that a trigger simulated from an SSP bank cluster was
+	 * successfully matched to a trigger in the SSP bank.
+	 * @param tiFlags - An array of size 6 indicating which TI bank
+	 * flags are active and which are not.
+	 * @param triggerTypeID - An identifier indicating the type of
+	 * trigger that was matched.
+	 */
+	public void matchedSSPTrigger(boolean[] tiFlags) {
+		matchedTriggers(tiFlags, SSP);
+	}
+	
+	/**
+	 * Indicates that a trigger simulated from an SSP bank cluster was
+	 * partially matched to a trigger in the SSP bank, and notes which
+	 * cuts did and did not match.
+	 * @param tiFlags - An array of size 6 indicating which TI bank
+	 * flags are active and which are not.
+	 * @param triggerTypeID - An identifier indicating the type of
+	 * trigger that was matched.
+	 * @param matchedCuts - An array of size 3 or 4 indicating which
+	 * cuts did and did not align between the triggers.
+	 */
+	public void matchedSSPTrigger(boolean[] tiFlags, boolean[] matchedCuts) {
+		matchedTriggers(tiFlags, matchedCuts, SSP);
+	}
+	
+	/**
+	 * Indicates that a trigger simulated from a reconstructed cluster
+	 * was seen and increments the count for this type of trigger by one.
+	 * @param tiFlags - Whether or not each of the TI bank flags is
+	 * active or not.
+	 */
+	public void sawReconSimulatedTrigger(boolean[] tiFlags) {
+		sawReconSimulatedTriggers(tiFlags, 1);
+	}
+	
+	/**
+	 * Indicates that a number triggers simulated from reconstructed
+	 * clusters were seen and increments the count for this type of
+	 * trigger by the indicated number.
+	 * @param tiFlags - Whether or not each of the TI bank flags is
+	 * active or not.
+	 * @param count - The number of simulated triggers seen.
+	 */
+	public void sawReconSimulatedTriggers(boolean[] tiFlags, int count) {
+		// Increment the total count.
+		simTriggers[RECON] += count;
+		
+		// Increment the TI flag counters.
+		for(int tiType = 0; tiType < 6; tiType++) {
+			if(tiFlags[tiType]) {
+				tiTriggersSeen[RECON][tiType] += count;
+			}
+		}
+	}
+	
+	/**
+	 * Indicates that a trigger from the SSP trigger bank was seen and
+	 * increments the count for this type of trigger by one.
+	 */
+	public void sawReportedTrigger() {
+		sawReportedTriggers(1);
+	}
+	
+	/**
+	 * Indicates that a number triggers from the SSP trigger bank were
+	 * seen and increments the count for this type of trigger by the
+	 * indicated number.
+	 * @param count - The number of simulated triggers seen.
+	 */
+	public void sawReportedTriggers(int count) {
+		reportedTriggers += count;
+	}
+	
+	/**
+	 * Indicates that a trigger simulated from an SSP bank cluster was
+	 * seen and increments the count for this type of trigger by one.
+	 * @param tiFlags - Whether or not each of the TI bank flags is
+	 * active or not.
+	 */
+	public void sawSSPSimulatedTrigger(boolean[] tiFlags) {
+		sawSSPSimulatedTriggers(tiFlags, 1);
+	}
+	
+	/**
+	 * Indicates that a number triggers simulated from SSP bank clusters
+	 * were seen and increments the count for this type of trigger by
+	 * the indicated number.
+	 * @param tiFlags - Whether or not each of the TI bank flags is
+	 * active or not.
+	 * @param count - The number of simulated triggers seen.
+	 */
+	public void sawSSPSimulatedTriggers(boolean[] tiFlags, int count) {
+		// Increment the total count.
+		simTriggers[SSP] += count;
+		
+		// Increment the TI flag counters.
+		for(int tiType = 0; tiType < 6; tiType++) {
+			if(tiFlags[tiType]) {
+				tiTriggersSeen[SSP][tiType] += count;
+			}
+		}
+	}
+	
+	/**
+	 * Indicates that a simulated trigger was successfully matched to
+	 * an SSP bank trigger.
+	 * @param tiFlags - An array of size 6 indicating which TI bank
+	 * flags are active and which are not.
+	 * @param sourceType - Uses <code>SSP</code> for triggers simulated
+	 * from an SSP bank cluster and <code>RECON</code> for triggers that
+	 * were simulated from a reconstructed cluster.
+	 */
+	private final void matchedTriggers(boolean[] tiFlags, int sourceType) {
+		// Increment the total triggers matched.
+		matchedTriggers[sourceType]++;
+		
+		// Increment the triggers matched for this type for each if
+		// the active TI bank flags.
+		for(int tiType = 0; tiType < 6; tiType++) {
+			if(tiFlags[tiType]) {
+				tiTriggersMatched[sourceType][tiType]++;
+			}
+		}
+	}
+	
+	/**
+	 * Indicates that a simulated trigger was partially matched to a
+	 * trigger in the SSP bank, and notes which cuts did and did not
+	 * match.
+	 * @param tiFlags - An array of size 6 indicating which TI bank
+	 * flags are active and which are not.
+	 * @param sourceType - Uses <code>SSP</code> for triggers simulated
+	 * from an SSP bank cluster and <code>RECON</code> for triggers that
+	 * were simulated from a reconstructed cluster.
+	 */
+	private void matchedTriggers(boolean[] tiFlags, boolean[] matchedCuts, int sourceType) {
+		// The matched cuts must be defined.
+		if(matchedCuts == null) {
+			throw new NullPointerException("The matched cuts array must be defined.");
+		}
+		
+		// The matched cuts array must be of either size 3 or 4.
+		if(matchedCuts.length != 3 && matchedCuts.length != 4) {
+			throw new IllegalArgumentException("All triggers must use either three or four cuts.");
+		}
+		
+		// Increment the counters for each cut that was no matched. Also
+		// track whether or not a cut actually failed.
+		boolean cutFailed = false;
+		for(int cutIndex = 0; cutIndex < matchedCuts.length; cutIndex++) {
+			if(!matchedCuts[cutIndex]) {
+				failedCuts[sourceType][cutIndex]++;
+				cutFailed = true;
+			}
+		}
+		
+		// If no cut failed, this is actually a match. Increment the
+		// appropriate counters.
+		if(!cutFailed) {
+			matchedTriggers(tiFlags, sourceType);
+		}
+	}
+	
+	@Deprecated
+	public String getPrintData() {
+		StringBuffer out = new StringBuffer();
+
+		out.append("\n");
+		out.append("Trigger Result\n");
+		out.append("SSP Sim Triggers    :: " + simTriggers[SSP] + "\n");
+		out.append("Recon Sim Triggers  :: " + simTriggers[RECON] + "\n");
+		out.append("Reported Triggers   :: " + reportedTriggers + "\n");
+		out.append(String.format("Internal Efficiency :: %d / %d (%7.3f)%n", matchedTriggers[SSP], simTriggers[SSP],
+				(100.0 * matchedTriggers[SSP] / simTriggers[SSP])));
+		out.append(String.format("Trigger Efficiency  :: %d / %d (%7.3f)%n", matchedTriggers[RECON], simTriggers[RECON],
+				(100.0 * matchedTriggers[RECON] / simTriggers[RECON])));
+		
+		out.append("\n");
+		out.append("Individual Cut Failure Rates\n");
+		out.append("Unmatched Triggers   :: " + unmatchedTriggers[SSP] + "\n");
+		for(int i = 0; i < 4; i++) {
+			out.append(String.format("\tCut %d :: %d / %d (%7.3f)%n", i, failedCuts[SSP][i], simTriggers[SSP],
+					(100.0 * failedCuts[SSP][i] / simTriggers[SSP])));
+		}
+		
+		return out.toString();
+	}
+}

Added: java/trunk/analysis/src/main/java/org/hps/analysis/trigger/data/TriggerStatModule.java
 =============================================================================
--- java/trunk/analysis/src/main/java/org/hps/analysis/trigger/data/TriggerStatModule.java	(added)
+++ java/trunk/analysis/src/main/java/org/hps/analysis/trigger/data/TriggerStatModule.java	Thu Apr  2 10:05:53 2015
@@ -0,0 +1,294 @@
+package org.hps.analysis.trigger.data;
+
+/**
+ * Class <code>TriggerStatModule</code> holds all the statistics from
+ * a single trigger event. The variables in this class are set by the
+ * extending class <code>TriggerEvent</code>, while this object lacks
+ * any external means to alter its values so that it can be used in a
+ * static fashion.
+ * 
+ * @author Kyle McCarty <[log in to unmask]>
+ */
+public class TriggerStatModule {
+	// Store the reference index for SSP simulated triggers and recon
+	// simulated triggers.
+	protected static final int SSP = 0;
+	protected static final int RECON = 1;
+	
+	// Define TI trigger type identifiers.
+	public static final int SINGLES_0 = 0;
+	public static final int SINGLES_1 = 1;
+	public static final int PAIR_0    = 2;
+	public static final int PAIR_1    = 3;
+	public static final int PULSER    = 4;
+	public static final int COSMIC    = 5;
+	
+	// Track the number of simulated triggers seen for each source type.
+	// SSP simulated triggers from the SSP bank clusters. Reconstructed
+	// simulated triggers come from clusters built from FADC data.
+	protected int[] simTriggers = new int[2];
+	
+	// Also track the number of triggers reported by the SSP bank.
+	protected int reportedTriggers = 0;
+	
+	// Track the number of simulated triggers of each type that were
+	// successfully matched.
+	protected int[] matchedTriggers = new int[2];
+	
+	// Track the number of simulated triggers that could not be matched
+	// at all.
+	protected int[] unmatchedTriggers = new int[2];
+	
+	// Track which cuts succeeded and which cuts failed for each type.
+	// Note that this is currently only tracked for SSP cluster triggers.
+	protected int[][] failedCuts = new int[2][4];
+	
+	// Store the number of trigger matches seen over all events that
+	// contain a given TI flag.
+	protected int[][] tiTriggersSeen = new int[2][6];
+	protected int[][] tiTriggersMatched = new int[2][6];
+	
+	/**
+	 * Clears all of the statistical counters in the object.
+	 */
+	void clear() {
+		// Clear all values.
+		for(int sourceType = 0; sourceType < 2; sourceType++) {
+			// Clear the general statistics.
+			simTriggers[sourceType]       = 0;
+			matchedTriggers[sourceType]   = 0;
+			unmatchedTriggers[sourceType] = 0;
+			
+			// Clear the cut failure statistics.
+			for(int cutID = 0; cutID < 4; cutID++) {
+				failedCuts[sourceType][cutID] = 0;
+			}
+			
+			// Clear the TI flag statistics.
+			for(int tiType = 0; tiType < 6; tiType++) {
+				tiTriggersSeen[sourceType][tiType]    = 0;
+				tiTriggersMatched[sourceType][tiType] = 0;
+			}
+		}
+	}
+	
+	@Override
+	public TriggerStatModule clone() {
+		// Make a new statistics module.
+		TriggerStatModule clone = new TriggerStatModule();
+		
+		// Copy the values that do not depend on trigger source type.
+		clone.reportedTriggers = reportedTriggers;
+		
+		// Set each value that depends on the trigger source type.
+		for(int sourceType = 0; sourceType < 2; sourceType++) {
+			clone.simTriggers[sourceType] = simTriggers[sourceType];
+			clone.matchedTriggers[sourceType] = matchedTriggers[sourceType];
+			clone.unmatchedTriggers[sourceType] = unmatchedTriggers[sourceType];
+			
+			// Set the number of times each cut failed.
+			for(int cutID = 0; cutID < 4; cutID++) {
+				clone.failedCuts[sourceType][cutID] = failedCuts[sourceType][cutID];
+			}
+			
+			// Copy the values for the TI flag trigger counters.
+			for(int tiType = 0; tiType < 6; tiType++) {
+				clone.tiTriggersSeen[sourceType][tiType] = tiTriggersSeen[sourceType][tiType];
+				clone.tiTriggersMatched[sourceType][tiType] = tiTriggersMatched[sourceType][tiType];
+			}
+		}
+		
+		// Return the copied clone.
+		return clone;
+	}
+	
+	/**
+	 * Gets the number of simulated triggers from reconstructed clusters
+	 * that were not matched.
+	 * @return Returns the number of triggers as an <code>int</code>.
+	 */
+	public int getFailedReconSimulatedTriggers() {
+		return simTriggers[RECON] - matchedTriggers[RECON];
+	}
+	
+	/**
+	 * Gets the number of simulated triggers from SSP bank clusters
+	 * that were not matched.
+	 * @return Returns the number of triggers as an <code>int</code>.
+	 */
+	public int getFailedSSPSimulatedTriggers() {
+		return simTriggers[SSP] - matchedTriggers[SSP];
+	}
+	
+	/**
+	 * Gets the number of simulated triggers from reconstructed clusters
+	 * that were matched.
+	 * @return Returns the number of triggers as an <code>int</code>.
+	 */
+	public int getMatchedReconSimulatedTriggers() {
+		return matchedTriggers[RECON];
+	}
+	
+	/**
+	 * Gets the number of simulated triggers from reconstructed clusters
+	 * that were matched for a given type of trigger when a given TI
+	 * bank flag was active.
+	 * @param tiTypeID - The identifier for the type of TI bank trigger
+	 * that should be active.
+	 * @param triggerTypeID - The identifier for the type of trigger.
+	 * @return Returns the number of triggers as an <code>int</code>.
+	 */
+	public int getMatchedReconSimulatedTriggers(int tiTypeID) {
+		return tiTriggersMatched[RECON][tiTypeID];
+	}
+	
+	/**
+	 * Gets the number of simulated triggers from SSP bank clusters
+	 * that were matched.
+	 * @return Returns the number of triggers as an <code>int</code>.
+	 */
+	public int getMatchedSSPSimulatedTriggers() {
+		return matchedTriggers[SSP];
+	}
+	
+	/**
+	 * Gets the number of simulated triggers from SSP bank clusters
+	 * that were matched for a given type of trigger when a given TI
+	 * bank flag was active.
+	 * @param tiTypeID - The identifier for the type of TI bank trigger
+	 * that should be active.
+	 * @param triggerTypeID - The identifier for the type of trigger.
+	 * @return Returns the number of triggers as an <code>int</code>.
+	 */
+	public int getMatchedSSPSimulatedTriggers(int tiTypeID) {
+		return tiTriggersMatched[SSP][tiTypeID];
+	}
+	
+	/**
+	 * Gets the number of simulated triggers from reconstructed clusters
+	 * that were matched, but did not see full cut alignment.
+	 * @return Returns the number of triggers as an <code>int</code>.
+	 */
+	public int getPartiallyMatchedReconSimulatedTriggers() {
+		return simTriggers[RECON] - (matchedTriggers[RECON] + unmatchedTriggers[RECON]);
+	}
+	
+	/**
+	 * Gets the number of simulated triggers from SSP bank clusters
+	 * that were matched, but did not see full cut alignment.
+	 * @return Returns the number of triggers as an <code>int</code>.
+	 */
+	public int getPartiallyMatchedSSPSimulatedTriggers() {
+		return simTriggers[SSP] - (matchedTriggers[SSP] + unmatchedTriggers[SSP]);
+	}
+	
+	/**
+	 * Gets the number of times the specified cut failed for triggers
+	 * that were partially matched for triggers simulated from FADC
+	 * reconstructed clusters.
+	 * @param cutIndex - The numerical cut identifier.
+	 * @return Returns the number of triggers as an <code>int</code>.
+	 */
+	public int getReconCutFailures(int cutIndex) {
+		return getCutFailures(RECON, cutIndex);
+	}
+	
+	/**
+	 * Gets the number of simulated triggers from reconstructed clusters
+	 * that were seen.
+	 * @return Returns the number of triggers as an <code>int</code>.
+	 */
+	public int getReconSimulatedTriggers() {
+		return simTriggers[RECON];
+	}
+	
+	/**
+	 * Gets the number of simulated triggers from reconstructed clusters
+	 * that were seen for a given trigger type when a given TI bank
+	 * flag was active.
+	 * @param tiTypeID - The identifier for the type of TI bank trigger
+	 * that should be active.
+	 * @param triggerTypeID - The identifier for the type of trigger.
+	 * @return Returns the number of triggers as an <code>int</code>.
+	 */
+	public int getReconSimulatedTriggers(int tiTypeID) {
+		return tiTriggersSeen[RECON][tiTypeID];
+	}
+	
+	/**
+	 * Gets the number of triggers reported by the SSP bank.
+	 * @return Returns the number of triggers as an <code>int</code>.
+	 */
+	public int getReportedTriggers() {
+		return reportedTriggers;
+	}
+	
+	/**
+	 * Gets the number of times the specified cut failed for triggers
+	 * that were partially matched for triggers simulated from SSP
+	 * bank clusters.
+	 * @param cutIndex - The numerical cut identifier.
+	 * @return Returns the number of triggers as an <code>int</code>.
+	 */
+	public int getSSPCutFailures(int cutIndex) {
+		return getCutFailures(SSP, cutIndex);
+	}
+	
+	/**
+	 * Gets the number of simulated triggers from SSP bank clusters
+	 * that were seen.
+	 * @return Returns the number of triggers as an <code>int</code>.
+	 */
+	public int getSSPSimulatedTriggers() {
+		return simTriggers[SSP];
+	}
+	
+	/**
+	 * Gets the number of simulated triggers from SSP bank clusters
+	 * that were seen for a given trigger type when a given TI bank
+	 * flag was active.
+	 * @param tiTypeID - The identifier for the type of TI bank trigger
+	 * that should be active.
+	 * @param triggerTypeID - The identifier for the type of trigger.
+	 * @return Returns the number of triggers as an <code>int</code>.
+	 */
+	public int getSSPSimulatedTriggers(int tiTypeID) {
+		return tiTriggersSeen[SSP][tiTypeID];
+	}
+	
+	/**
+	 * Gets the number of simulated triggers from reconstructed clusters
+	 * that were completely unmatched.
+	 * @return Returns the number of triggers as an <code>int</code>.
+	 */
+	public int getUnmatchedReconSimulatedTriggers() {
+		return unmatchedTriggers[RECON];
+	}
+	
+	/**
+	 * Gets the number of simulated triggers from SSP bank clusters
+	 * that were completely unmatched.
+	 * @return Returns the number of triggers as an <code>int</code>.
+	 */
+	public int getUnmatchedSSPSimulatedTriggers() {
+		return unmatchedTriggers[SSP];
+	}
+	
+	/**
+	 * Gets the number of times the specified cut failed for triggers
+	 * that were partially matched for triggers simulated from the type
+	 * of cluster indicated.
+	 * @param type - Either <code>SSP</code> or <code>RECON</code>.
+	 * @param cutIndex - The numerical cut identifier.
+	 * @return Returns the number of triggers as an <code>int</code>.
+	 */
+	private int getCutFailures(int type, int cutIndex) {
+		// Ensure that the cut index is valid.
+		if(cutIndex < 0 || cutIndex >= 4) {
+			throw new IndexOutOfBoundsException(String.format("Cut index \"%d\" is not recognized.", cutIndex));
+		}
+		
+		// Return the cut failures.
+		return failedCuts[type][cutIndex];
+	}
+}

Modified: java/trunk/analysis/src/main/java/org/hps/analysis/trigger/event/TriggerEfficiencyModule.java
 =============================================================================
--- java/trunk/analysis/src/main/java/org/hps/analysis/trigger/event/TriggerEfficiencyModule.java	(original)
+++ java/trunk/analysis/src/main/java/org/hps/analysis/trigger/event/TriggerEfficiencyModule.java	Thu Apr  2 10:05:53 2015
@@ -42,7 +42,7 @@
 	 */
 	public void addSinglesTriggers(int eventTriggerType, List<List<? extends Trigger<?>>> singlesTriggers) {
 		// Note the trigger type.
-		int[] triggerType = { TriggerDiagnosticUtil.TRIGGER_SINGLES_1, TriggerDiagnosticUtil.TRIGGER_SINGLES_2 };
+		int[] triggerType = { TriggerDiagnosticUtil.TRIGGER_SINGLES_0, TriggerDiagnosticUtil.TRIGGER_SINGLES_1 };
 		
 		// Track the total number of singles triggers seen.
 		addTriggers(eventTriggerType, singlesTriggers, triggerType);
@@ -57,7 +57,7 @@
 	 */
 	public void addPairTriggers(int eventTriggerType, List<List<? extends Trigger<?>>> pairTriggers) {
 		// Note the trigger type.
-		int[] triggerType = { TriggerDiagnosticUtil.TRIGGER_PAIR_1, TriggerDiagnosticUtil.TRIGGER_PAIR_2 };
+		int[] triggerType = { TriggerDiagnosticUtil.TRIGGER_PAIR_0, TriggerDiagnosticUtil.TRIGGER_PAIR_1 };
 		
 		// Track the total number of singles triggers seen.
 		addTriggers(eventTriggerType, pairTriggers, triggerType);
@@ -242,18 +242,18 @@
 			// triggers this is. Note that this assumes that the trigger
 			// number is stored as either 0 or 1.
 			if(trigger.getTriggerNumber() == 0) {
+				return TriggerDiagnosticUtil.TRIGGER_PAIR_0;
+			} else {
 				return TriggerDiagnosticUtil.TRIGGER_PAIR_1;
-			} else {
-				return TriggerDiagnosticUtil.TRIGGER_PAIR_2;
 			}
 		} else if(trigger instanceof SinglesTrigger) {
 			// Use the trigger number to determine which of the two
 			// triggers this is. Note that this assumes that the trigger
 			// number is stored as either 0 or 1.
 			if(trigger.getTriggerNumber() == 0) {
+				return TriggerDiagnosticUtil.TRIGGER_SINGLES_0;
+			} else {
 				return TriggerDiagnosticUtil.TRIGGER_SINGLES_1;
-			} else {
-				return TriggerDiagnosticUtil.TRIGGER_SINGLES_2;
 			}
 		}
 		

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 Apr  2 10:05:53 2015
@@ -27,9 +27,9 @@
 	public void addEvent(int eventType, TriggerMatchEvent event, List<List<? extends Trigger<?>>> reconTriggers,
 			List<List<? extends Trigger<?>>> sspSimTriggers, List<? extends SSPNumberedTrigger> sspBankTriggers) {
 		// Increment the event type count.
-		if(eventType == TriggerDiagnosticUtil.TRIGGER_SINGLES_1 || eventType == TriggerDiagnosticUtil.TRIGGER_PAIR_1) {
+		if(eventType == TriggerDiagnosticUtil.TRIGGER_SINGLES_0 || eventType == TriggerDiagnosticUtil.TRIGGER_PAIR_0) {
 			triggerTypesSeen[0]++;
-		} else if(eventType == TriggerDiagnosticUtil.TRIGGER_SINGLES_2 || eventType == TriggerDiagnosticUtil.TRIGGER_PAIR_2) {
+		} else if(eventType == TriggerDiagnosticUtil.TRIGGER_SINGLES_1 || eventType == TriggerDiagnosticUtil.TRIGGER_PAIR_1) {
 			triggerTypesSeen[1]++;
 		}
 		
@@ -70,9 +70,9 @@
 		// Check if a trigger of the right time was found.
 		// Get the trigger number and type.
 		if(event.sawEventType()) {
-			if(eventType == TriggerDiagnosticUtil.TRIGGER_SINGLES_1 || eventType == TriggerDiagnosticUtil.TRIGGER_PAIR_1) {
+			if(eventType == TriggerDiagnosticUtil.TRIGGER_SINGLES_0 || eventType == TriggerDiagnosticUtil.TRIGGER_PAIR_0) {
 				triggerTypesFound[0]++;
-			} else if(eventType == TriggerDiagnosticUtil.TRIGGER_SINGLES_2 || eventType == TriggerDiagnosticUtil.TRIGGER_PAIR_2) {
+			} else if(eventType == TriggerDiagnosticUtil.TRIGGER_SINGLES_1 || eventType == TriggerDiagnosticUtil.TRIGGER_PAIR_1) {
 				triggerTypesFound[1]++;
 			}
 		}

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 Apr  2 10:05:53 2015
@@ -2,6 +2,7 @@
 
 import java.awt.Point;
 
+import org.hps.analysis.trigger.data.TriggerStatModule;
 import org.hps.recon.ecal.triggerbank.SSPCluster;
 import org.lcsim.event.CalorimeterHit;
 import org.lcsim.event.Cluster;
@@ -32,13 +33,13 @@
 	public static final int PAIR_COPLANARITY = 3;
 	
 	// Trigger type variables.
-	public static final int TRIGGER_PULSER    = 0;
-	public static final int TRIGGER_COSMIC    = 1;
-	public static final int TRIGGER_SINGLES_1 = 2;
-	public static final int TRIGGER_SINGLES_2 = 3;
-	public static final int TRIGGER_PAIR_1    = 4;
-	public static final int TRIGGER_PAIR_2    = 5;
-	public static final String[] TRIGGER_NAME = { "Pulser", "Cosmic", "Singles 1", "Singles 2", "Pair 1", "Pair 2" };
+	public static final int TRIGGER_PULSER    = TriggerStatModule.PULSER;
+	public static final int TRIGGER_COSMIC    = TriggerStatModule.COSMIC;
+	public static final int TRIGGER_SINGLES_0 = TriggerStatModule.SINGLES_0;
+	public static final int TRIGGER_SINGLES_1 = TriggerStatModule.SINGLES_1;
+	public static final int TRIGGER_PAIR_0    = TriggerStatModule.PAIR_0;
+	public static final int TRIGGER_PAIR_1    = TriggerStatModule.PAIR_1;
+	public static final String[] TRIGGER_NAME = { "Singles 0", "Singles 1", "Pair 0", "Pair 1", "Pulser", "Cosmic" };
 	
 	/**
 	 * Convenience method that writes the position of a cluster in the

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