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

HPS-SVN October 2015

Subject:

r3847 - in /java/trunk/analysis/src/main/java/org/hps/analysis/trigger: DataTriggerSimDriver.java SimTriggerData.java SimTriggerModule.java TriggerDiagnosticDriver.java event/TriggerPlotsModule.java

From:

[log in to unmask]

Reply-To:

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

Date:

Fri, 16 Oct 2015 15:16:26 -0000

Content-Type:

text/plain

Parts/Attachments:

Parts/Attachments

text/plain (1412 lines)

Author: [log in to unmask]
Date: Fri Oct 16 08:16:18 2015
New Revision: 3847

Log:
Created a driver that takes in hardware settings, SSP clusters, and reconstructed clusters to create simulated triggers. Also updated the trigger diagnostic driver to use this instead of running the simulation internally.

Added:
    java/trunk/analysis/src/main/java/org/hps/analysis/trigger/DataTriggerSimDriver.java
    java/trunk/analysis/src/main/java/org/hps/analysis/trigger/SimTriggerData.java
    java/trunk/analysis/src/main/java/org/hps/analysis/trigger/SimTriggerModule.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/TriggerPlotsModule.java

Added: java/trunk/analysis/src/main/java/org/hps/analysis/trigger/DataTriggerSimDriver.java
 =============================================================================
--- java/trunk/analysis/src/main/java/org/hps/analysis/trigger/DataTriggerSimDriver.java	(added)
+++ java/trunk/analysis/src/main/java/org/hps/analysis/trigger/DataTriggerSimDriver.java	Fri Oct 16 08:16:18 2015
@@ -0,0 +1,501 @@
+package org.hps.analysis.trigger;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.hps.analysis.trigger.util.PairTrigger;
+import org.hps.analysis.trigger.util.SinglesTrigger;
+import org.hps.analysis.trigger.util.TriggerDiagnosticUtil;
+import org.hps.record.daqconfig.ConfigurationManager;
+import org.hps.record.daqconfig.DAQConfig;
+import org.hps.record.daqconfig.PairTriggerConfig;
+import org.hps.record.daqconfig.SinglesTriggerConfig;
+import org.hps.record.triggerbank.AbstractIntData;
+import org.hps.record.triggerbank.SSPCluster;
+import org.hps.record.triggerbank.SSPData;
+import org.hps.record.triggerbank.TriggerModule;
+import org.lcsim.event.Cluster;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.GenericObject;
+import org.lcsim.util.Driver;
+
+/**
+ * Class <code>DataTriggerSimDriver</code> takes in clusters of both
+ * class <code>Cluster</code> and <code>SSPCluster</code> and performs
+ * a simulation of the hardware trigger on them. The results of this
+ * simulation are then stored in a <code>SimTriggerData</code> object
+ * which is placed on the data stream to allow for other drivers to
+ * access the trigger results.<br/>
+ * <br/>
+ * <code>DataTriggerSimDriver</code> is intended exclusively as a
+ * hardware simulation, and as such, requires that the DAQ configuration
+ * is read before it can function. Thusly, <code>DAQConfigDriver</code>
+ * must exist upstream of this driver for it to initialize. Additionally,
+ * to ensure consistency with data, it is advised that online FADC driver
+ * be employed and the GTP clustering driver be set to draw from the
+ * DAQ configuration as well.<br/>
+ * <br/>
+ * <code>DataTriggerSimDriver</code> requires two input collections.
+ * The first is the bank collection, which contains the TI and SSP
+ * banks. It uses the SSP bank to obtain hardware clusters. It also
+ * requires the reconstructed cluster bank to obtain the clusters that
+ * are simulated from FADC hits. The driver outputs one collection, the
+ * simulated trigger collection, which contains simulated triggers.
+ * This collection consists of one <code>SimTriggerData</code> object
+ * that can be accessed to obtain all simulated trigger types. This
+ * output object is not persisted into LCIO after runtime.
+ * 
+ * @author Kyle McCarty <[log in to unmask]>
+ * @see DAQConfigDriver
+ * @see EcalOnlineRawConverterDriver
+ * @see GTPOnlineClusterDriver
+ * @see SimTriggerData
+ */
+public class DataTriggerSimDriver extends Driver {
+	// Store the LCIO collection names for the needed objects.
+	private boolean filterUnverifiable = false;
+	private String bankCollectionName = "TriggerBank";
+	private String clusterCollectionName = "EcalClusters";
+	private String simTriggerCollectionName = "SimTriggers";
+	
+	// Store the SSP bank.
+	private SSPData sspBank = null;
+	
+	// Store cluster verifiability parameters.
+	private int nsa = 0;
+	private int nsb = 0;
+	private int windowWidth = 0;
+	
+	// Define trigger simulation modules.
+	private boolean[] pairTriggerEnabled = new boolean[2];
+	private boolean[] singlesTriggerEnabled = new boolean[2];
+	private boolean[][] pairCutsEnabled = new boolean[2][7];
+	private boolean[][] singlesCutsEnabled = new boolean[2][3];
+	private TriggerModule[] pairsTrigger = new TriggerModule[2];
+	private TriggerModule[] singlesTrigger = new TriggerModule[2];
+	
+	// Reference variables.
+	private static final int ENERGY_MIN   = TriggerDiagnosticUtil.SINGLES_ENERGY_MIN;
+	private static final int ENERGY_MAX   = TriggerDiagnosticUtil.SINGLES_ENERGY_MAX;
+	private static final int HIT_COUNT    = TriggerDiagnosticUtil.SINGLES_HIT_COUNT;
+	private static final int ENERGY_SUM   = TriggerDiagnosticUtil.PAIR_ENERGY_SUM;
+	private static final int ENERGY_DIFF  = TriggerDiagnosticUtil.PAIR_ENERGY_DIFF;
+	private static final int ENERGY_SLOPE = TriggerDiagnosticUtil.PAIR_ENERGY_SLOPE;
+	private static final int COPLANARITY  = TriggerDiagnosticUtil.PAIR_COPLANARITY;
+	
+	/**
+	 * Connects the driver to the the <code>ConfigurationManager</code>
+	 * in order to obtain the correct trigger information. Trigger
+	 * settings are stored in the <code>TriggerModule</code> objects.
+	 */
+	@Override
+	public void startOfData() {
+		// Define the first singles trigger.
+		singlesTrigger[0] = new TriggerModule();
+		singlesTrigger[0].setCutValue(TriggerModule.CLUSTER_TOTAL_ENERGY_LOW, 0.500);
+		singlesTrigger[0].setCutValue(TriggerModule.CLUSTER_TOTAL_ENERGY_HIGH, 8.191);
+		singlesTrigger[0].setCutValue(TriggerModule.CLUSTER_HIT_COUNT_LOW, 0);
+		
+		// Define the second singles trigger.
+		singlesTrigger[1] = new TriggerModule();
+		singlesTrigger[1].setCutValue(TriggerModule.CLUSTER_TOTAL_ENERGY_LOW, 0.000);
+		singlesTrigger[1].setCutValue(TriggerModule.CLUSTER_TOTAL_ENERGY_HIGH, 8.191);
+		singlesTrigger[1].setCutValue(TriggerModule.CLUSTER_HIT_COUNT_LOW, 0);
+		
+		// Define the first pairs trigger.
+		pairsTrigger[0] = new TriggerModule();
+		pairsTrigger[0].setCutValue(TriggerModule.CLUSTER_TOTAL_ENERGY_LOW, 0.000);
+		pairsTrigger[0].setCutValue(TriggerModule.CLUSTER_TOTAL_ENERGY_HIGH, 8.191);
+		pairsTrigger[0].setCutValue(TriggerModule.CLUSTER_HIT_COUNT_LOW, 0);
+		pairsTrigger[0].setCutValue(TriggerModule.PAIR_ENERGY_SUM_LOW, 0.000);
+		pairsTrigger[0].setCutValue(TriggerModule.PAIR_ENERGY_SUM_HIGH, 8.191);
+		pairsTrigger[0].setCutValue(TriggerModule.PAIR_ENERGY_DIFFERENCE_HIGH, 8.191);
+		pairsTrigger[0].setCutValue(TriggerModule.PAIR_ENERGY_SLOPE_LOW, 0.000);
+		pairsTrigger[0].setCutValue(TriggerModule.PAIR_ENERGY_SLOPE_F, 0.001);
+		pairsTrigger[0].setCutValue(TriggerModule.PAIR_COPLANARITY_HIGH, 180);
+		pairsTrigger[0].setCutValue(TriggerModule.PAIR_TIME_COINCIDENCE, 8);
+		
+		// Define the second pairs trigger.
+		pairsTrigger[1] = new TriggerModule();
+		pairsTrigger[1].setCutValue(TriggerModule.CLUSTER_TOTAL_ENERGY_LOW, 0.000);
+		pairsTrigger[1].setCutValue(TriggerModule.CLUSTER_TOTAL_ENERGY_HIGH, 8.191);
+		pairsTrigger[1].setCutValue(TriggerModule.CLUSTER_HIT_COUNT_LOW, 0);
+		pairsTrigger[1].setCutValue(TriggerModule.PAIR_ENERGY_SUM_LOW, 0.000);
+		pairsTrigger[1].setCutValue(TriggerModule.PAIR_ENERGY_SUM_HIGH, 8.191);
+		pairsTrigger[1].setCutValue(TriggerModule.PAIR_ENERGY_DIFFERENCE_HIGH, 8.191);
+		pairsTrigger[1].setCutValue(TriggerModule.PAIR_ENERGY_SLOPE_LOW, 0.000);
+		pairsTrigger[1].setCutValue(TriggerModule.PAIR_ENERGY_SLOPE_F, 0.001);
+		pairsTrigger[1].setCutValue(TriggerModule.PAIR_COPLANARITY_HIGH, 180);
+		pairsTrigger[1].setCutValue(TriggerModule.PAIR_TIME_COINCIDENCE, 8);
+		
+		// Listen for the configuration manager to provide the real
+		// trigger settings.
+		ConfigurationManager.addActionListener(new ActionListener() {
+			@Override
+			public void actionPerformed(ActionEvent e) {
+				// Get the DAQ configuration.
+				DAQConfig daq = ConfigurationManager.getInstance();
+				
+				// Get cluster verifiability parameters.
+				nsa = daq.getFADCConfig().getNSA();
+				nsb = daq.getFADCConfig().getNSB();
+				windowWidth = daq.getFADCConfig().getWindowWidth();
+				
+				// Load the DAQ settings from the configuration manager.
+				singlesTrigger[0].loadDAQConfiguration(daq.getSSPConfig().getSingles1Config());
+				singlesTrigger[1].loadDAQConfiguration(daq.getSSPConfig().getSingles2Config());
+				pairsTrigger[0].loadDAQConfiguration(daq.getSSPConfig().getPair1Config());
+				pairsTrigger[1].loadDAQConfiguration(daq.getSSPConfig().getPair2Config());
+				
+				// Get the trigger configurations from the DAQ.
+				SinglesTriggerConfig[] singles = { daq.getSSPConfig().getSingles1Config(),
+						daq.getSSPConfig().getSingles2Config() };
+				PairTriggerConfig[] pairs = { daq.getSSPConfig().getPair1Config(),
+						daq.getSSPConfig().getPair2Config() };
+				
+				// Update the enabled/disabled statuses.
+				for(int i = 0; i < 2; i++) {
+					// Set the trigger enabled status.
+					pairTriggerEnabled[i] = pairs[i].isEnabled();
+					singlesTriggerEnabled[i] = singles[i].isEnabled();
+					
+					// Set the singles cut statuses.
+					singlesCutsEnabled[i][ENERGY_MIN] = singles[i].getEnergyMinCutConfig().isEnabled();
+					singlesCutsEnabled[i][ENERGY_MAX] = singles[i].getEnergyMaxCutConfig().isEnabled();
+					singlesCutsEnabled[i][HIT_COUNT] = singles[i].getHitCountCutConfig().isEnabled();
+					
+					// Set the pair cut statuses.
+					pairCutsEnabled[i][ENERGY_MIN] = pairs[i].getEnergyMinCutConfig().isEnabled();
+					pairCutsEnabled[i][ENERGY_MAX] = pairs[i].getEnergyMaxCutConfig().isEnabled();
+					pairCutsEnabled[i][HIT_COUNT] = pairs[i].getHitCountCutConfig().isEnabled();
+					pairCutsEnabled[i][3 + ENERGY_SUM] = pairs[i].getEnergySumCutConfig().isEnabled();
+					pairCutsEnabled[i][3 + ENERGY_DIFF] = pairs[i].getEnergyDifferenceCutConfig().isEnabled();
+					pairCutsEnabled[i][3 + ENERGY_SLOPE] = pairs[i].getEnergySlopeCutConfig().isEnabled();
+					pairCutsEnabled[i][3 + COPLANARITY] = pairs[i].getCoplanarityCutConfig().isEnabled();
+				}
+			}
+		});
+	}
+	
+	/**
+	 * Processes an LCIO event and simulates triggers in the same manner
+	 * as the hardware for both <code>SSPCluster</code> objects as well
+	 * as <code>Cluster</code> objects reconstructed from FADC hits.
+	 * Triggers are then output to the data stream.
+	 * @param event - The <code>EventHeader</code> object representing
+	 * the current LCIO event.
+	 */
+	@Override
+	public void process(EventHeader event) {
+		// If the DAQ configuration manager has not been initialized,
+		// then no action can be performed.
+		if(!ConfigurationManager.isInitialized()) {
+			// Put an empty trigger results module into the data stream.
+			SimTriggerData triggerData = new SimTriggerData();
+			List<SimTriggerData> dataList = new ArrayList<SimTriggerData>(1);
+			dataList.add(triggerData);
+			event.put(simTriggerCollectionName, dataList, SimTriggerData.class, 0);
+			
+			// Nothing further can be done, since trigger settings are
+			// not yet defined.
+			return;
+		}
+		
+		// Get the SSP bank.
+		if(event.hasCollection(GenericObject.class, bankCollectionName)) {
+			// Get the bank list.
+			List<GenericObject> bankList = event.get(GenericObject.class, bankCollectionName);
+			
+			// Search through the banks and get the SSP and TI banks.
+			for(GenericObject obj : bankList) {
+				// If this is an SSP bank, parse it.
+				if(AbstractIntData.getTag(obj) == SSPData.BANK_TAG) {
+					sspBank = new SSPData(obj);
+				}
+			}
+		}
+		
+		// Get a list of SSPClusters.
+		List<SSPCluster> sspClusters = null;
+		if(sspBank != null) { sspClusters = sspBank.getClusters(); }
+		else { sspClusters = new ArrayList<SSPCluster>(0); }
+		
+		// Get reconstructed clusters.
+		List<Cluster> reconClusters = null;
+		if(event.hasCollection(Cluster.class, clusterCollectionName)) {
+			reconClusters = event.get(Cluster.class, clusterCollectionName);
+		}
+		else { reconClusters = new ArrayList<Cluster>(0); }
+		
+		// If only "verifiable" clusters should be used, test all the
+		// reconstructed clusters for verifiability.
+		if(filterUnverifiable) {
+			// Create a list to store the verifiable clusters.
+			List<Cluster> goodClusters = new ArrayList<Cluster>();
+			
+			// Iterate over all the clusters and test them to see if
+			// they are verifiable.
+			for(Cluster cluster : reconClusters) {
+				if(TriggerDiagnosticUtil.isVerifiable(cluster, nsa, nsb, windowWidth)) {
+					goodClusters.add(cluster);
+				}
+			}
+			
+			// Replace the old cluster list with the new one.
+			reconClusters = goodClusters;
+		}
+		
+		// Generate simulated triggers.
+		SimTriggerModule<Cluster> reconModule = constructTriggers(reconClusters, Cluster.class);
+		SimTriggerModule<SSPCluster> sspModule = constructTriggers(sspClusters, SSPCluster.class);
+		
+		// Insert the trigger results in the data stream.
+		SimTriggerData triggerData = new SimTriggerData(reconModule, sspModule);
+		List<SimTriggerData> dataList = new ArrayList<SimTriggerData>(1);
+		dataList.add(triggerData);
+		event.put(simTriggerCollectionName, dataList, SimTriggerData.class, 0);
+	}
+	
+	/**
+	 * Constructs simulated triggers in the same manner as the hardware.
+	 * Method can accept either <code>Cluster</code> objects, any object
+	 * that is a subclass of <code>Cluster</code>, or objects of type
+	 * <code>SSPCluster</code>.
+	 * @param clusters - A <code>List</code> collection of the cluster
+	 * objects from which triggers are to be derived.
+	 * @param clusterType - The class of the cluster objects from which
+	 * triggers are to be derived. This can be <code>Cluster</code>,
+	 * <code>SSPCluster</code>, or a subclass thereof.
+	 * @return Returns a <code>SimTriggerModule</code> object containing
+	 * the simulated trigger results.
+	 * @throws IllegalArgumentException Occurs if the class of the
+	 * cluster objects is not of a supported type.
+	 * 
+	 */
+	private <E> SimTriggerModule<E> constructTriggers(List<E> clusters, Class<E> clusterType) throws IllegalArgumentException {
+		// Verify that the cluster type is supported.
+		if(!clusterType.equals(Cluster.class) && !clusterType.equals(SSPCluster.class)) {
+			throw new IllegalArgumentException("Class \"" + clusterType.getSimpleName() + "\" is not a supported cluster type.");
+		}
+		
+		// Store the singles and pair triggers.
+		List<List<PairTrigger<E[]>>> pairTriggers = new ArrayList<List<PairTrigger<E[]>>>(2);
+		pairTriggers.add(new ArrayList<PairTrigger<E[]>>());
+		pairTriggers.add(new ArrayList<PairTrigger<E[]>>());
+		List<List<SinglesTrigger<E>>> singlesTriggers = new ArrayList<List<SinglesTrigger<E>>>(2);
+		singlesTriggers.add(new ArrayList<SinglesTrigger<E>>());
+		singlesTriggers.add(new ArrayList<SinglesTrigger<E>>());
+		
+		// Run the clusters through the singles trigger to determine
+		// whether or not they pass it.
+		for(E cluster : clusters) {
+			// Simulate each of the cluster singles triggers.
+			triggerLoop:
+			for(int triggerNum = 0; triggerNum < 2; triggerNum++) {
+				// Track whether the cluster passed each singles cut.
+				boolean passSeedLow = true;
+				boolean passSeedHigh = true;
+				boolean passClusterLow = false;
+				boolean passClusterHigh = false;
+				boolean passHitCount = false;
+				
+				// Perform the trigger cuts appropriately for the type
+				// of cluster.
+				if(cluster instanceof Cluster) {
+					// Cast the cluster to the appropriate type.
+					Cluster c = (Cluster) cluster;
+					
+					// Perform each trigger cut.
+					passClusterLow = singlesTrigger[triggerNum].clusterTotalEnergyCutLow(c);
+					passClusterHigh = singlesTrigger[triggerNum].clusterTotalEnergyCutHigh(c);
+					passHitCount = singlesTrigger[triggerNum].clusterHitCountCut(c);
+				} else if(cluster instanceof SSPCluster) {
+					// Cast the cluster to the appropriate type.
+					SSPCluster c = (SSPCluster) cluster;
+					
+					// Perform each trigger cut.
+					passClusterLow = singlesTrigger[triggerNum].clusterTotalEnergyCutLow(c);
+					passClusterHigh = singlesTrigger[triggerNum].clusterTotalEnergyCutHigh(c);
+					passHitCount = singlesTrigger[triggerNum].clusterHitCountCut(c);
+				}
+				
+				// Make a trigger to store the results.
+				SinglesTrigger<E> trigger = new SinglesTrigger<E>(cluster, triggerNum);
+				trigger.setStateSeedEnergyLow(passSeedLow);
+				trigger.setStateSeedEnergyHigh(passSeedHigh);
+				trigger.setStateClusterEnergyLow(passClusterLow);
+				trigger.setStateClusterEnergyHigh(passClusterHigh);
+				trigger.setStateHitCount(passHitCount);
+				
+				// A trigger will only be reported by the SSP if it
+				// passes all of the enabled cuts for that trigger.
+				// Check whether this trigger meets these conditions.
+				if(singlesCutsEnabled[triggerNum][ENERGY_MIN] && !trigger.getStateClusterEnergyLow()) {
+					continue triggerLoop;
+				} if(singlesCutsEnabled[triggerNum][ENERGY_MAX] && !trigger.getStateClusterEnergyHigh()) {
+					continue triggerLoop;
+				} if(singlesCutsEnabled[triggerNum][HIT_COUNT] && !trigger.getStateHitCount()) {
+					continue triggerLoop;
+				}
+				
+				// Store the trigger.
+				singlesTriggers.get(triggerNum).add(trigger);
+			}
+		}
+		
+		// Store cluster pairs.
+		List<E[]> pairs = TriggerModule.getTopBottomPairs(clusters, clusterType);
+		
+		// Simulate the pair triggers and record the results.
+		for(E[] pair : pairs) {
+			// Simulate each of the cluster pair triggers.
+			pairTriggerLoop:
+			for(int triggerIndex = 0; triggerIndex < 2; triggerIndex++) {
+				// Track whether the cluster passed each singles cut.
+				boolean passSeedLow = true;
+				boolean passSeedHigh = true;
+				boolean passClusterLow = false;
+				boolean passClusterHigh = false;
+				boolean passHitCount = false;
+				boolean passPairEnergySumLow = false;
+				boolean passPairEnergySumHigh = false;
+				boolean passPairEnergyDifference = false;
+				boolean passPairEnergySlope = false;
+				boolean passPairCoplanarity = false;
+				boolean passTimeCoincidence = false;
+				
+				// Apply the trigger cuts appropriately according to the
+				// cluster type.
+				if(clusterType.equals(Cluster.class)) {
+					// Cast the cluster object.
+					Cluster[] reconPair = { (Cluster) pair[0], (Cluster) pair[1] };
+					
+					// Check that the pair passes the time coincidence cut.
+					// If it does not, it is not a valid pair and should be
+					// destroyed.
+					if(!pairsTrigger[triggerIndex].pairTimeCoincidenceCut(reconPair)) {
+						continue pairTriggerLoop;
+					}
+					
+					passClusterLow = pairsTrigger[triggerIndex].clusterTotalEnergyCutLow(reconPair[0])
+							&& pairsTrigger[triggerIndex].clusterTotalEnergyCutLow(reconPair[1]);
+					passClusterHigh = pairsTrigger[triggerIndex].clusterTotalEnergyCutHigh(reconPair[0])
+							&& pairsTrigger[triggerIndex].clusterTotalEnergyCutHigh(reconPair[1]);
+					passHitCount = pairsTrigger[triggerIndex].clusterHitCountCut(reconPair[0])
+							&& pairsTrigger[triggerIndex].clusterHitCountCut(reconPair[1]);
+					passPairEnergySumLow = pairsTrigger[triggerIndex].pairEnergySumCutLow(reconPair);
+					passPairEnergySumHigh = pairsTrigger[triggerIndex].pairEnergySumCutHigh(reconPair);
+					passPairEnergyDifference = pairsTrigger[triggerIndex].pairEnergyDifferenceCut(reconPair);
+					passPairEnergySlope = pairsTrigger[triggerIndex].pairEnergySlopeCut(reconPair);
+					passPairCoplanarity = pairsTrigger[triggerIndex].pairCoplanarityCut(reconPair);
+					passTimeCoincidence = pairsTrigger[triggerIndex].pairTimeCoincidenceCut(reconPair);
+				} else if(clusterType.equals(SSPCluster.class)) {
+					// Cast the cluster object.
+					SSPCluster[] sspPair = { (SSPCluster) pair[0], (SSPCluster) pair[1] };
+					
+					// Check that the pair passes the time coincidence cut.
+					// If it does not, it is not a valid pair and should be
+					// destroyed.
+					if(!pairsTrigger[triggerIndex].pairTimeCoincidenceCut(sspPair)) {
+						continue pairTriggerLoop;
+					}
+					
+					// Perform each trigger cut.
+					passClusterLow = pairsTrigger[triggerIndex].clusterTotalEnergyCutLow(sspPair[0])
+							&& pairsTrigger[triggerIndex].clusterTotalEnergyCutLow(sspPair[1]);
+					passClusterHigh = pairsTrigger[triggerIndex].clusterTotalEnergyCutHigh(sspPair[0])
+							&& pairsTrigger[triggerIndex].clusterTotalEnergyCutHigh(sspPair[1]);
+					passHitCount = pairsTrigger[triggerIndex].clusterHitCountCut(sspPair[0])
+							&& pairsTrigger[triggerIndex].clusterHitCountCut(sspPair[1]);
+					passPairEnergySumLow = pairsTrigger[triggerIndex].pairEnergySumCutLow(sspPair);
+					passPairEnergySumHigh = pairsTrigger[triggerIndex].pairEnergySumCutHigh(sspPair);
+					passPairEnergyDifference = pairsTrigger[triggerIndex].pairEnergyDifferenceCut(sspPair);
+					passPairEnergySlope = pairsTrigger[triggerIndex].pairEnergySlopeCut(sspPair);
+					passPairCoplanarity = pairsTrigger[triggerIndex].pairCoplanarityCut(sspPair);
+					passTimeCoincidence = pairsTrigger[triggerIndex].pairTimeCoincidenceCut(sspPair);
+				}
+				
+				// Create a trigger from the results.
+				PairTrigger<E[]> trigger = new PairTrigger<E[]>(pair, triggerIndex);
+				trigger.setStateSeedEnergyLow(passSeedLow);
+				trigger.setStateSeedEnergyHigh(passSeedHigh);
+				trigger.setStateClusterEnergyLow(passClusterLow);
+				trigger.setStateClusterEnergyHigh(passClusterHigh);
+				trigger.setStateHitCount(passHitCount);
+				trigger.setStateEnergySumLow(passPairEnergySumLow);
+				trigger.setStateEnergySumHigh(passPairEnergySumHigh);
+				trigger.setStateEnergyDifference(passPairEnergyDifference);
+				trigger.setStateEnergySlope(passPairEnergySlope);
+				trigger.setStateCoplanarity(passPairCoplanarity);
+				trigger.setStateTimeCoincidence(passTimeCoincidence);
+				
+				// A trigger will only be reported by the SSP if it
+				// passes all of the enabled cuts for that trigger.
+				// Check whether this trigger meets these conditions.
+				if(pairCutsEnabled[triggerIndex][ENERGY_MIN] && !trigger.getStateClusterEnergyLow()) {
+					continue pairTriggerLoop;
+				} if(pairCutsEnabled[triggerIndex][ENERGY_MAX] && !trigger.getStateClusterEnergyHigh()) {
+					continue pairTriggerLoop;
+				} if(pairCutsEnabled[triggerIndex][HIT_COUNT] && !trigger.getStateHitCount()) {
+					continue pairTriggerLoop;
+				} if(pairCutsEnabled[triggerIndex][3 + ENERGY_SUM] && !trigger.getStateEnergySum()) {
+					continue pairTriggerLoop;
+				} if(pairCutsEnabled[triggerIndex][3 + ENERGY_DIFF] && !trigger.getStateEnergyDifference()) {
+					continue pairTriggerLoop;
+				} if(pairCutsEnabled[triggerIndex][3 + ENERGY_SLOPE] && !trigger.getStateEnergySlope()) {
+					continue pairTriggerLoop;
+				} if(pairCutsEnabled[triggerIndex][3 + COPLANARITY] && !trigger.getStateCoplanarity()) {
+					continue pairTriggerLoop;
+				}
+				
+				// Add the trigger to the list.
+				pairTriggers.get(triggerIndex).add(trigger);
+			}
+		}
+		
+		// Create a new simulated trigger module to contain the results.
+		return new SimTriggerModule<E>(singlesTriggers.get(0), singlesTriggers.get(1),
+				pairTriggers.get(0), pairTriggers.get(1));
+	}
+	
+	/**
+	 * Sets the name of the LCIO collection containing the TI and SSP
+	 * banks.
+	 * @param bankCollectionName - The bank collection name.
+	 */
+	public void setBankCollectionName(String bankCollectionName) {
+		this.bankCollectionName = bankCollectionName;
+	}
+	
+	/**
+	 * Sets the name of the LCIO collection containing the simulated
+	 * reconstructed clusters.
+	 * @param clusterCollectionName - The cluster collection name.
+	 */
+	public void setClusterCollectionName(String clusterCollectionName) {
+		this.clusterCollectionName = clusterCollectionName;
+	}
+	
+	/**
+	 * Sets whether or not triggers should be formed using all clusters,
+	 * or only those that where the integration window for the cluster
+	 * is completely within the bounds of the event window.
+	 * @param state - <code>true</code> means that only clusters where
+	 * the entire cluster integration window is within the event time
+	 * window will be used, while <code>false</code> means that all
+	 * clusters will be used.
+	 */
+	public void setFilterUnverifiableClusters(boolean state) {
+		this.filterUnverifiable = state;
+	}
+	
+	/**
+	 * Sets the name of the LCIO collection containing simulated triggers.
+	 * @param triggerCollection - The trigger collection name.
+	 */
+	public void setTriggerCollectionName(String triggerCollection) {
+		this.simTriggerCollectionName = triggerCollection;
+	}
+}

Added: java/trunk/analysis/src/main/java/org/hps/analysis/trigger/SimTriggerData.java
 =============================================================================
--- java/trunk/analysis/src/main/java/org/hps/analysis/trigger/SimTriggerData.java	(added)
+++ java/trunk/analysis/src/main/java/org/hps/analysis/trigger/SimTriggerData.java	Fri Oct 16 08:16:18 2015
@@ -0,0 +1,59 @@
+package org.hps.analysis.trigger;
+
+import org.hps.record.triggerbank.SSPCluster;
+import org.lcsim.event.Cluster;
+
+/**
+ * Class <code>SimTriggerData</code> is a container class that holds
+ * simulated trigger data modules. It is intended to be placed in the
+ * LCIO data stream by the <code>DataTriggerSimDriver</code> to allow
+ * other classes to access triggers simulated from SSP and reconstructed
+ * cluster data.
+ * 
+ * @author Kyle McCarty <[log in to unmask]>
+ */
+public class SimTriggerData {
+	private final SimTriggerModule<Cluster> reconTriggers;
+	private final SimTriggerModule<SSPCluster> sspTriggers;
+	
+	/**
+	 * Instantiates a new <code>SimTriggerData</code> object with empty
+	 * trigger results modules.
+	 */
+	SimTriggerData() {
+		reconTriggers = new SimTriggerModule<Cluster>();
+		sspTriggers = new SimTriggerModule<SSPCluster>();
+	}
+	
+	/**
+	 * Instantiates a new <code>SimTriggerData</code> object that will
+	 * contain the argument trigger modules.
+	 * @param reconTriggers - The simulated reconstructed cluster
+	 * triggers module.
+	 * @param sspTriggers - The simulated SSP cluster triggers module.
+	 */
+	SimTriggerData(SimTriggerModule<Cluster> reconTriggers, SimTriggerModule<SSPCluster> sspTriggers) {
+		this.reconTriggers = reconTriggers;
+		this.sspTriggers = sspTriggers;
+	}
+	
+	/**
+	 * Gets the module containing all simulated SSP trigger data for
+	 * each of the four primary triggers.
+	 * @return Returns the trigger data in a <code>SimTriggerModule</code>
+	 * object.
+	 */
+	public SimTriggerModule<SSPCluster> getSimSSPTriggers() {
+		return sspTriggers;
+	}
+	
+	/**
+	 * Gets the module containing all simulated LCSim trigger data for
+	 * each of the four primary triggers.
+	 * @return Returns the trigger data in a <code>SimTriggerModule</code>
+	 * object.
+	 */
+	public SimTriggerModule<Cluster> getSimReconTriggers() {
+		return reconTriggers;
+	}
+}

Added: java/trunk/analysis/src/main/java/org/hps/analysis/trigger/SimTriggerModule.java
 =============================================================================
--- java/trunk/analysis/src/main/java/org/hps/analysis/trigger/SimTriggerModule.java	(added)
+++ java/trunk/analysis/src/main/java/org/hps/analysis/trigger/SimTriggerModule.java	Fri Oct 16 08:16:18 2015
@@ -0,0 +1,88 @@
+package org.hps.analysis.trigger;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.hps.analysis.trigger.util.PairTrigger;
+import org.hps.analysis.trigger.util.SinglesTrigger;
+
+/**
+ * Class <code>SimTriggerModule</code> is a container class that holds
+ * simulated trigger results for each of the four primary triggers
+ * produced by the <code>DataTriggerSimDriver</code>.
+ * 
+ * @author Kyle McCarty <[log in to unmask]>
+ * @param <E> - The type of clusters from which the triggers were
+ * simulated. This will always be either <code>Cluster</code> or
+ * <code>SSPCluster</code>. 
+ * @see DataTriggerSimDriver
+ */
+public class SimTriggerModule<E> {
+	private final List<SinglesTrigger<E>> singles0;
+	private final List<SinglesTrigger<E>> singles1;
+	private final List<PairTrigger<E[]>> pair0;
+	private final List<PairTrigger<E[]>> pair1;
+	
+	/**
+	 * Constructs a new <code>SimTriggerModule</code> with the no
+	 * triggers results for any triggers.
+	 */
+	SimTriggerModule() {
+		singles0 = new ArrayList<SinglesTrigger<E>>(0);
+		singles1 = new ArrayList<SinglesTrigger<E>>(0);
+		pair0    = new ArrayList<PairTrigger<E[]>>(0);
+		pair1    = new ArrayList<PairTrigger<E[]>>(0);
+	}
+	
+	/**
+	 * Constructs a new <code>SimTriggerModule</code> with the specified
+	 * trigger results for each of the four primary triggers.
+	 * @param singles0Triggers - The results for the singles 0 trigger.
+	 * @param singles1Triggers - The results for the singles 1 trigger.
+	 * @param pair0Triggers - The results for the pair 0 trigger.
+	 * @param pair1Triggers - The results for the pair 1 trigger.
+	 */
+	SimTriggerModule(List<SinglesTrigger<E>> singles0Triggers, List<SinglesTrigger<E>> singles1Triggers,
+			List<PairTrigger<E[]>> pair0Triggers, List<PairTrigger<E[]>> pair1Triggers) {
+		this.singles0 = singles0Triggers;
+		this.singles1 = singles1Triggers;
+		this.pair0    = pair0Triggers;
+		this.pair1    = pair1Triggers;
+	}
+	
+	/**
+	 * Gets the simulated trigger results for the singles 0 trigger.
+	 * @return Returns the trigger results as a <code>List</code> of
+	 * <code>SinglesTrigger</code> objects.
+	 */
+	public List<SinglesTrigger<E>> getSingles0Triggers() {
+		return singles0;
+	}
+	
+	/**
+	 * Gets the simulated trigger results for the singles 1 trigger.
+	 * @return Returns the trigger results as a <code>List</code> of
+	 * <code>SinglesTrigger</code> objects.
+	 */
+	public List<SinglesTrigger<E>> getSingles1Triggers() {
+		return singles1;
+	}
+	
+	/**
+	 * Gets the simulated trigger results for the pair 0 trigger.
+	 * @return Returns the trigger results as a <code>List</code> of
+	 * <code>PairTrigger</code> objects.
+	 */
+	public List<PairTrigger<E[]>> getPair0Triggers() {
+		return pair0;
+	}
+	
+	/**
+	 * Gets the simulated trigger results for the pair 1 trigger.
+	 * @return Returns the trigger results as a <code>List</code> of
+	 * <code>PairTrigger</code> objects.
+	 */
+	public List<PairTrigger<E[]>> getPair1Triggers() {
+		return pair1;
+	}
+}

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	Fri Oct 16 08:16:18 2015
@@ -47,7 +47,6 @@
 import org.lcsim.event.EventHeader;
 import org.lcsim.event.GenericObject;
 import org.lcsim.event.LCRelation;
-import org.lcsim.event.base.MyLCRelation;
 import org.lcsim.lcio.LCIOConstants;
 import org.lcsim.util.Driver;
 import org.lcsim.util.aida.AIDA;
@@ -67,10 +66,7 @@
 	private SSPData sspBank;
 	private List<SSPCluster> sspClusters;
 	private List<Cluster> reconClusters = new ArrayList<Cluster>();
-	private List<List<PairTrigger<Cluster[]>>> reconPairsTriggers = new ArrayList<List<PairTrigger<Cluster[]>>>(2);
-	private List<List<PairTrigger<SSPCluster[]>>> sspPairsTriggers = new ArrayList<List<PairTrigger<SSPCluster[]>>>(2);
-	private List<List<SinglesTrigger<Cluster>>> reconSinglesTriggers = new ArrayList<List<SinglesTrigger<Cluster>>>(2);
-	private List<List<SinglesTrigger<SSPCluster>>> sspSinglesTriggers = new ArrayList<List<SinglesTrigger<SSPCluster>>>(2);
+	private SimTriggerData triggerData = null;
 	
 	// Trigger modules for performing trigger analysis.
 	//private int activeTrigger = -1;
@@ -338,14 +334,6 @@
 		pairsTrigger[1].setCutValue(TriggerModule.PAIR_COPLANARITY_HIGH, 180);
 		pairsTrigger[1].setCutValue(TriggerModule.PAIR_TIME_COINCIDENCE, 8);
 		
-		// Instantiate the triggers lists.
-		for(int triggerNum = 0; triggerNum < 2; triggerNum++) {
-			reconPairsTriggers.add(new ArrayList<PairTrigger<Cluster[]>>());
-			sspPairsTriggers.add(new ArrayList<PairTrigger<SSPCluster[]>>());
-			reconSinglesTriggers.add(new ArrayList<SinglesTrigger<Cluster>>());
-			sspSinglesTriggers.add(new ArrayList<SinglesTrigger<SSPCluster>>());
-		}
-		
 		// Print the initial settings.
 		logSettings();
 	}
@@ -354,7 +342,29 @@
 	 * Prints the total run statistics.
 	 */
 	@Override
-	public void endOfData() { logStatistics(); }
+	public void endOfData() {
+		// Output the statistics.
+		logStatistics();
+		
+		/*
+		// Calculate the values needed for the efficiency histogram.
+		long totalTime = entryList.get(entryList.size()).time / 1000000000;
+		int entries = (int) (totalTime / (localWindowThreshold / 1000000000)) + 1;
+		
+		// Generate a histogram containing the efficiencies.
+		IHistogram1D[] efficiencyHist = new IHistogram1D[5];
+		for(int i = 0; i < 5; i++) {
+			efficiencyHist[i] = aida.histogram1D("Efficiency " + i, entries, 0.0, totalTime + (localWindowThreshold / 1000000000));
+		}
+		
+		// Input the efficiencies.
+		for(EfficiencyEntry entry : entryList) {
+			for(int i = 0; i < 5; i++) {
+				efficiencyHist[i].fill(entry.time / 1000000000, entry.efficiency[i]);
+			}
+		}
+		*/
+	}
 	
 	/**
 	 * Gets the banks and clusters from the event.
@@ -557,14 +567,6 @@
 		// ==== Obtain Reconstructed Clusters =======================
 		// ==========================================================
 		
-		// Clear the list of triggers from previous events.
-		for(int triggerNum = 0; triggerNum < 2; triggerNum++) {
-			sspSinglesTriggers.get(triggerNum).clear();
-			reconSinglesTriggers.get(triggerNum).clear();
-			sspPairsTriggers.get(triggerNum).clear();
-			reconPairsTriggers.get(triggerNum).clear();
-		}
-		
 		// Get the reconstructed clusters.
 		if(event.hasCollection(Cluster.class, clusterCollectionName)) {
 			// Get the reconstructed clusters.
@@ -608,14 +610,18 @@
 		// Perform the cluster verification step.
 		if(performClusterVerification) { clusterVerification(); }
 		
+		// Get the simulated triggers.
+		if(event.hasCollection(SimTriggerData.class, "SimTriggers")) {
+			List<SimTriggerData> stdList = event.get(SimTriggerData.class, "SimTriggers");
+			triggerData = stdList.get(0);
+		}
+		
 		// Construct lists of triggers for the SSP clusters and the
 		// reconstructed clusters.
 		if(performSinglesTriggerVerification) {
-			constructSinglesTriggers();
 			singlesTriggerVerification();
 		}
 		if(performPairTriggerVerification) {
-			constructPairTriggers();
 			pairTriggerVerification();
 		}
 		
@@ -659,18 +665,27 @@
 			// Push the snapshot to the data stream.
 			event.put(diagnosticCollectionName, snapshotList);
 			
-			// Record the efficiencies in this time snapshot.
+			// Store values needed to calculate efficiency.
+			int[] matched = {
+					localStats.getClusterStats().getMatches(),
+					localStats.getTriggerStats().getSingles0Stats().getMatchedReconSimulatedTriggers(),
+					localStats.getTriggerStats().getSingles1Stats().getMatchedReconSimulatedTriggers(),
+					localStats.getTriggerStats().getPair0Stats().getMatchedReconSimulatedTriggers(),
+					localStats.getTriggerStats().getPair1Stats().getMatchedReconSimulatedTriggers()
+			};
+			int[] total = {
+					localStats.getClusterStats().getReconClusterCount(),
+					localStats.getTriggerStats().getSingles0Stats().getReconSimulatedTriggers(),
+					localStats.getTriggerStats().getSingles1Stats().getReconSimulatedTriggers(),
+					localStats.getTriggerStats().getPair0Stats().getReconSimulatedTriggers(),
+					localStats.getTriggerStats().getPair1Stats().getReconSimulatedTriggers()
+			};
+			
+			// Calculate the efficiencies and upper/lower errors.
 			double[] efficiency = new double[5];
-			efficiency[0] = 1.0 * localStats.getClusterStats().getMatches()
-					/ localStats.getClusterStats().getReconClusterCount();
-			efficiency[1] = 1.0 * localStats.getTriggerStats().getSingles0Stats().getMatchedReconSimulatedTriggers()
-					/ localStats.getTriggerStats().getSingles0Stats().getReconSimulatedTriggers();
-			efficiency[2] = 1.0 * localStats.getTriggerStats().getSingles1Stats().getMatchedReconSimulatedTriggers()
-					/ localStats.getTriggerStats().getSingles1Stats().getReconSimulatedTriggers();
-			efficiency[3] = 1.0 * localStats.getTriggerStats().getPair0Stats().getMatchedReconSimulatedTriggers()
-					/ localStats.getTriggerStats().getPair0Stats().getReconSimulatedTriggers();
-			efficiency[4] = 1.0 * localStats.getTriggerStats().getPair1Stats().getMatchedReconSimulatedTriggers()
-					/ localStats.getTriggerStats().getPair1Stats().getReconSimulatedTriggers();
+			for(int i = 0; i < 5; i++) {
+				efficiency[i] = 1.0 * matched[i] / total[i];
+			}
 			
 			// Get the time for the current snapshot. This is the total
 			// run time before the snapshot plus half of the snapshot.
@@ -1219,15 +1234,10 @@
 		
 		// Convert the simulated triggers to generic versions and add
 		// them to the generic list.
-		for(int triggerNum = 0; triggerNum < 2; triggerNum++) {
-			// Get the generic trigger list.
-			List<? extends Trigger<?>> sspTriggers = sspSinglesTriggers.get(triggerNum);
-			List<? extends Trigger<?>> reconTriggers = reconSinglesTriggers.get(triggerNum);
-			
-			// Add it to the generic list.
-			sspTriggerList.add(sspTriggers);
-			reconTriggerList.add(reconTriggers);
-		}
+		sspTriggerList.add(triggerData.getSimSSPTriggers().getSingles0Triggers());
+		sspTriggerList.add(triggerData.getSimSSPTriggers().getSingles1Triggers());
+		reconTriggerList.add(triggerData.getSimReconTriggers().getSingles0Triggers());
+		reconTriggerList.add(triggerData.getSimReconTriggers().getSingles1Triggers());
 		
 		// Run generic trigger verification.
 		triggerVerification(sspTriggerList, reconTriggerList, true);
@@ -1246,15 +1256,10 @@
 		
 		// Convert the simulated triggers to generic versions and add
 		// them to the generic list.
-		for(int triggerNum = 0; triggerNum < 2; triggerNum++) {
-			// Get the generic trigger list.
-			List<? extends Trigger<?>> sspTriggers = sspPairsTriggers.get(triggerNum);
-			List<? extends Trigger<?>> reconTriggers = reconPairsTriggers.get(triggerNum);
-			
-			// Add it to the generic list.
-			sspTriggerList.add(sspTriggers);
-			reconTriggerList.add(reconTriggers);
-		}
+		sspTriggerList.add(triggerData.getSimSSPTriggers().getPair0Triggers());
+		sspTriggerList.add(triggerData.getSimSSPTriggers().getPair1Triggers());
+		reconTriggerList.add(triggerData.getSimReconTriggers().getPair0Triggers());
+		reconTriggerList.add(triggerData.getSimReconTriggers().getPair1Triggers());
 		
 		// Run generic trigger verification.
 		triggerVerification(sspTriggerList, reconTriggerList, false);
@@ -1673,330 +1678,6 @@
 		} if(triggerEvent[0].getFailedSSPSimulatedTriggers() != 0 && triggerEvent[1].getFailedSSPSimulatedTriggers() != 0) {
 			if(isSingles) { singlesInternalFail = true; }
 			else { pairInternalFail = true; }
-		}
-	}
-	
-	/**
-	 * Generates and stores the singles triggers for both reconstructed
-	 * and SSP clusters.
-	 */
-	private void constructSinglesTriggers() {
-		// Run the SSP clusters through the singles trigger to determine
-		// whether they pass it or not.
-		for(SSPCluster cluster : sspClusters) {
-			// Add the cluster to the "NO_CUTS" plots for each singles
-			// TI bit that is active.
-			if(tiBank.isSingle0Trigger()) { globalTriggerPlots.sawCluster(0, cluster); }
-			if(tiBank.isSingle1Trigger()) { globalTriggerPlots.sawCluster(1, cluster); }
-			
-			triggerLoop:
-			for(int triggerNum = 0; triggerNum < 2; triggerNum++) {
-				// For a cluster to have formed it is assumed to have
-				// passed the cluster seed energy cuts. This can not
-				// be verified since the SSP bank does not report
-				// individual hit. 
-				boolean passSeedLow = true;
-				boolean passSeedHigh = true;
-				
-				// The remaining cuts may be acquired from trigger module.
-				boolean passClusterLow = singlesTrigger[triggerNum].clusterTotalEnergyCutLow(cluster);
-				boolean passClusterHigh = singlesTrigger[triggerNum].clusterTotalEnergyCutHigh(cluster);
-				boolean passHitCount = singlesTrigger[triggerNum].clusterHitCountCut(cluster);
-				
-				// Make a trigger to store the results.
-				SinglesTrigger<SSPCluster> trigger = new SinglesTrigger<SSPCluster>(cluster, triggerNum);
-				trigger.setStateSeedEnergyLow(passSeedLow);
-				trigger.setStateSeedEnergyHigh(passSeedHigh);
-				trigger.setStateClusterEnergyLow(passClusterLow);
-				trigger.setStateClusterEnergyHigh(passClusterHigh);
-				trigger.setStateHitCount(passHitCount);
-				
-				// A trigger will only be reported by the SSP if it
-				// passes all of the enabled cuts for that trigger.
-				// Check whether this trigger meets these conditions.
-				if(singlesCutsEnabled[triggerNum][ENERGY_MIN] && !trigger.getStateClusterEnergyLow()) {
-					continue triggerLoop;
-				} if(singlesCutsEnabled[triggerNum][ENERGY_MAX] && !trigger.getStateClusterEnergyHigh()) {
-					continue triggerLoop;
-				} if(singlesCutsEnabled[triggerNum][HIT_COUNT] && !trigger.getStateHitCount()) {
-					continue triggerLoop;
-				}
-				
-				// If all the trigger cuts passed, plot this trigger
-				// in the "triggered" plots.
-				if(trigger.getTriggerState()) {
-					globalTriggerPlots.passedTrigger(trigger);
-				}
-				
-				// If all the necessary checks passed, store the new
-				// trigger for verification.
-				sspSinglesTriggers.get(triggerNum).add(trigger);
-			}
-		}
-		
-		// Run the reconstructed clusters through the singles trigger
-		// to determine whether they pass it or not.
-		for(Cluster cluster : reconClusters) {
-			// Add the cluster to the "NO_CUTS" plots for each singles
-			// TI bit that is active.
-			if(tiBank.isSingle0Trigger()) { globalTriggerPlots.sawCluster(0, cluster); }
-			if(tiBank.isSingle1Trigger()) { globalTriggerPlots.sawCluster(1, cluster); }
-			
-			// Simulate each of the cluster singles triggers.
-			triggerLoop:
-			for(int triggerNum = 0; triggerNum < 2; triggerNum++) {
-				// For a cluster to have formed it is assumed to have passed
-				// the cluster seed energy cuts. This can not be verified
-				// since the SSP bank does not report individual hit. 
-				boolean passSeedLow = true;
-				boolean passSeedHigh = true;
-				
-				// The remaining cuts may be acquired from trigger module.
-				boolean passClusterLow = singlesTrigger[triggerNum].clusterTotalEnergyCutLow(cluster);
-				boolean passClusterHigh = singlesTrigger[triggerNum].clusterTotalEnergyCutHigh(cluster);
-				boolean passHitCount = singlesTrigger[triggerNum].clusterHitCountCut(cluster);
-				
-				// Make a trigger to store the results.
-				SinglesTrigger<Cluster> trigger = new SinglesTrigger<Cluster>(cluster, triggerNum);
-				trigger.setStateSeedEnergyLow(passSeedLow);
-				trigger.setStateSeedEnergyHigh(passSeedHigh);
-				trigger.setStateClusterEnergyLow(passClusterLow);
-				trigger.setStateClusterEnergyHigh(passClusterHigh);
-				trigger.setStateHitCount(passHitCount);
-				
-				// If all the trigger cuts passed, plot this trigger
-				// in the "triggered" plots.
-				if(trigger.getTriggerState()) {
-					globalTriggerPlots.passedTrigger(trigger);
-					singlesCandidates.get(triggerNum).add(trigger.getTriggerSource());
-				}
-				
-				// A trigger will only be reported by the SSP if it
-				// passes all of the enabled cuts for that trigger.
-				// Check whether this trigger meets these conditions.
-				if(singlesCutsEnabled[triggerNum][ENERGY_MIN] && !trigger.getStateClusterEnergyLow()) {
-					continue triggerLoop;
-				} if(singlesCutsEnabled[triggerNum][ENERGY_MAX] && !trigger.getStateClusterEnergyHigh()) {
-					continue triggerLoop;
-				} if(singlesCutsEnabled[triggerNum][HIT_COUNT] && !trigger.getStateHitCount()) {
-					continue triggerLoop;
-				}
-				
-				// Store the trigger.
-				reconSinglesTriggers.get(triggerNum).add(trigger);
-			}
-		}
-	}
-	
-	/**
-	 * Generates and stores the pair triggers for both reconstructed
-	 * and SSP clusters.
-	 */
-	private void constructPairTriggers() {
-		// Store cluster pairs.
-		List<Cluster> topReconClusters = new ArrayList<Cluster>();
-		List<Cluster> bottomReconClusters = new ArrayList<Cluster>();
-		List<Cluster[]> reconPairs = new ArrayList<Cluster[]>();
-		List<SSPCluster> topSSPClusters = new ArrayList<SSPCluster>();
-		List<SSPCluster> bottomSSPClusters = new ArrayList<SSPCluster>();
-		List<SSPCluster[]> sspPairs = new ArrayList<SSPCluster[]>();
-		
-		// Split the clusters into lists of top and bottom clusters.
-		for(Cluster reconCluster : reconClusters) {
-			if(reconCluster.getCalorimeterHits().get(0).getIdentifierFieldValue("iy") > 0) {
-				topReconClusters.add(reconCluster);
-			} else {
-				bottomReconClusters.add(reconCluster);
-			}
-		}
-		for(SSPCluster sspCluster : sspClusters) {
-			if(sspCluster.getYIndex() > 0) {
-				topSSPClusters.add(sspCluster);
-			} else {
-				bottomSSPClusters.add(sspCluster);
-			}
-		}
-		
-		// Form all possible top/bottom cluster pairs.
-		for(Cluster topReconCluster : topReconClusters) {
-			for(Cluster bottomReconCluster : bottomReconClusters) {
-				Cluster[] reconPair = new Cluster[2];
-				reconPair[0] = topReconCluster;
-				reconPair[1] = bottomReconCluster;
-				reconPairs.add(reconPair);
-			}
-		}
-		for(SSPCluster topSSPCluster : topSSPClusters) {
-			for(SSPCluster bottomSSPCluster : bottomSSPClusters) {
-				SSPCluster[] sspPair = new SSPCluster[2];
-				sspPair[0] = topSSPCluster;
-				sspPair[1] = bottomSSPCluster;
-				sspPairs.add(sspPair);
-			}
-		}
-		
-		// Simulate the pair triggers and record the results.
-		for(Cluster[] reconPair : reconPairs) {
-			// Simulate each of the cluster pair triggers.
-			pairTriggerLoop:
-			for(int triggerIndex = 0; triggerIndex < 2; triggerIndex++) {
-				// Check that the pair passes the time coincidence cut.
-				// If it does not, it is not a valid pair and should be
-				// destroyed.
-				if(!pairsTrigger[triggerIndex].pairTimeCoincidenceCut(reconPair)) {
-					continue pairTriggerLoop;
-				}
-				
-				// Add the cluster to the "NO_CUTS" plots for each
-				// singles TI bit that is active.
-				if((triggerIndex == 0 && tiBank.isPair0Trigger()) || (triggerIndex == 1 && tiBank.isPair1Trigger())) {
-					globalTriggerPlots.sawPair(triggerIndex, reconPair);
-				}
-				
-				// For a cluster to have formed it is assumed to have passed
-				// the cluster seed energy cuts. This can not be verified
-				// since the SSP bank does not report individual hit. 
-				boolean passSeedLow = true;
-				boolean passSeedHigh = true;
-				
-				// The remaining cuts may be acquired from trigger module.
-				boolean passClusterLow = pairsTrigger[triggerIndex].clusterTotalEnergyCutLow(reconPair[0])
-						&& pairsTrigger[triggerIndex].clusterTotalEnergyCutLow(reconPair[1]);
-				boolean passClusterHigh = pairsTrigger[triggerIndex].clusterTotalEnergyCutHigh(reconPair[0])
-						&& pairsTrigger[triggerIndex].clusterTotalEnergyCutHigh(reconPair[1]);
-				boolean passHitCount = pairsTrigger[triggerIndex].clusterHitCountCut(reconPair[0])
-						&& pairsTrigger[triggerIndex].clusterHitCountCut(reconPair[1]);
-				boolean passPairEnergySumLow = pairsTrigger[triggerIndex].pairEnergySumCutLow(reconPair);
-				boolean passPairEnergySumHigh = pairsTrigger[triggerIndex].pairEnergySumCutHigh(reconPair);
-				boolean passPairEnergyDifference = pairsTrigger[triggerIndex].pairEnergyDifferenceCut(reconPair);
-				boolean passPairEnergySlope = pairsTrigger[triggerIndex].pairEnergySlopeCut(reconPair);
-				boolean passPairCoplanarity = pairsTrigger[triggerIndex].pairCoplanarityCut(reconPair);
-				boolean passTimeCoincidence = pairsTrigger[triggerIndex].pairTimeCoincidenceCut(reconPair);
-				
-				// Create a trigger from the results.
-				PairTrigger<Cluster[]> trigger = new PairTrigger<Cluster[]>(reconPair, triggerIndex);
-				trigger.setStateSeedEnergyLow(passSeedLow);
-				trigger.setStateSeedEnergyHigh(passSeedHigh);
-				trigger.setStateClusterEnergyLow(passClusterLow);
-				trigger.setStateClusterEnergyHigh(passClusterHigh);
-				trigger.setStateHitCount(passHitCount);
-				trigger.setStateEnergySumLow(passPairEnergySumLow);
-				trigger.setStateEnergySumHigh(passPairEnergySumHigh);
-				trigger.setStateEnergyDifference(passPairEnergyDifference);
-				trigger.setStateEnergySlope(passPairEnergySlope);
-				trigger.setStateCoplanarity(passPairCoplanarity);
-				trigger.setStateTimeCoincidence(passTimeCoincidence);
-				
-				// A trigger will only be reported by the SSP if it
-				// passes all of the enabled cuts for that trigger.
-				// Check whether this trigger meets these conditions.
-				if(pairCutsEnabled[triggerIndex][ENERGY_MIN] && !trigger.getStateClusterEnergyLow()) {
-					continue pairTriggerLoop;
-				} if(pairCutsEnabled[triggerIndex][ENERGY_MAX] && !trigger.getStateClusterEnergyHigh()) {
-					continue pairTriggerLoop;
-				} if(pairCutsEnabled[triggerIndex][HIT_COUNT] && !trigger.getStateHitCount()) {
-					continue pairTriggerLoop;
-				} if(pairCutsEnabled[triggerIndex][3 + ENERGY_SUM] && !trigger.getStateEnergySum()) {
-					continue pairTriggerLoop;
-				} if(pairCutsEnabled[triggerIndex][3 + ENERGY_DIFF] && !trigger.getStateEnergyDifference()) {
-					continue pairTriggerLoop;
-				} if(pairCutsEnabled[triggerIndex][3 + ENERGY_SLOPE] && !trigger.getStateEnergySlope()) {
-					continue pairTriggerLoop;
-				} if(pairCutsEnabled[triggerIndex][3 + COPLANARITY] && !trigger.getStateCoplanarity()) {
-					continue pairTriggerLoop;
-				}
-				
-				// If all the trigger cuts passed, plot this trigger
-				// in the "triggered" plots.
-				if(trigger.getTriggerState()) {
-					globalTriggerPlots.passedTrigger(trigger);
-					LCRelation lcPair = new MyLCRelation(trigger.getTriggerSource()[0], trigger.getTriggerSource()[1]);
-					pairCandidates.get(triggerIndex).add(lcPair);
-				}
-				
-				// Add the trigger to the list.
-				reconPairsTriggers.get(triggerIndex).add(trigger);
-			}
-		}
-		
-		for(SSPCluster[] sspPair : sspPairs) {
-			pairTriggerLoop:
-			for(int triggerIndex = 0; triggerIndex < 2; triggerIndex++) {
-				// Check that the pair passes the time coincidence cut.
-				// If it does not, it is not a valid pair and should be
-				// destroyed.
-				if(!pairsTrigger[triggerIndex].pairTimeCoincidenceCut(sspPair)) {
-					continue pairTriggerLoop;
-				}
-				
-				// Add the cluster to the "NO_CUTS" plots for each
-				// singles TI bit that is active.
-				if((triggerIndex == 0 && tiBank.isPair0Trigger()) || (triggerIndex == 1 && tiBank.isPair1Trigger())) {
-					globalTriggerPlots.sawPair(triggerIndex, sspPair);
-				}
-				
-				// For a cluster to have formed it is assumed to have passed
-				// the cluster seed energy cuts. This can not be verified
-				// since the SSP bank does not report individual hit. 
-				boolean passSeedLow = true;
-				boolean passSeedHigh = true;
-				
-				// The remaining cuts may be acquired from trigger module.
-				boolean passClusterLow = pairsTrigger[triggerIndex].clusterTotalEnergyCutLow(sspPair[0])
-						&& pairsTrigger[triggerIndex].clusterTotalEnergyCutLow(sspPair[1]);
-				boolean passClusterHigh = pairsTrigger[triggerIndex].clusterTotalEnergyCutHigh(sspPair[0])
-						&& pairsTrigger[triggerIndex].clusterTotalEnergyCutHigh(sspPair[1]);
-				boolean passHitCount = pairsTrigger[triggerIndex].clusterHitCountCut(sspPair[0])
-						&& pairsTrigger[triggerIndex].clusterHitCountCut(sspPair[1]);
-				boolean passPairEnergySumLow = pairsTrigger[triggerIndex].pairEnergySumCutLow(sspPair);
-				boolean passPairEnergySumHigh = pairsTrigger[triggerIndex].pairEnergySumCutHigh(sspPair);
-				boolean passPairEnergyDifference = pairsTrigger[triggerIndex].pairEnergyDifferenceCut(sspPair);
-				boolean passPairEnergySlope = pairsTrigger[triggerIndex].pairEnergySlopeCut(sspPair);
-				boolean passPairCoplanarity = pairsTrigger[triggerIndex].pairCoplanarityCut(sspPair);
-				boolean passTimeCoincidence = pairsTrigger[triggerIndex].pairTimeCoincidenceCut(sspPair);
-				
-				// Create a trigger from the results.
-				PairTrigger<SSPCluster[]> trigger = new PairTrigger<SSPCluster[]>(sspPair, triggerIndex);
-				trigger.setStateSeedEnergyLow(passSeedLow);
-				trigger.setStateSeedEnergyHigh(passSeedHigh);
-				trigger.setStateClusterEnergyLow(passClusterLow);
-				trigger.setStateClusterEnergyHigh(passClusterHigh);
-				trigger.setStateHitCount(passHitCount);
-				trigger.setStateEnergySumLow(passPairEnergySumLow);
-				trigger.setStateEnergySumHigh(passPairEnergySumHigh);
-				trigger.setStateEnergyDifference(passPairEnergyDifference);
-				trigger.setStateEnergySlope(passPairEnergySlope);
-				trigger.setStateCoplanarity(passPairCoplanarity);
-				trigger.setStateTimeCoincidence(passTimeCoincidence);
-				
-				// If all the trigger cuts passed, plot this trigger
-				// in the "triggered" plots.
-				if(trigger.getTriggerState()) {
-					globalTriggerPlots.passedTrigger(trigger);
-				}
-				
-				// A trigger will only be reported by the SSP if it
-				// passes all of the enabled cuts for that trigger.
-				// Check whether this trigger meets these conditions.
-				if(pairCutsEnabled[triggerIndex][ENERGY_MIN] && !trigger.getStateClusterEnergyLow()) {
-					continue pairTriggerLoop;
-				} if(pairCutsEnabled[triggerIndex][ENERGY_MAX] && !trigger.getStateClusterEnergyHigh()) {
-					continue pairTriggerLoop;
-				} if(pairCutsEnabled[triggerIndex][HIT_COUNT] && !trigger.getStateHitCount()) {
-					continue pairTriggerLoop;
-				} if(pairCutsEnabled[triggerIndex][3 + ENERGY_SUM] && !trigger.getStateEnergySum()) {
-					continue pairTriggerLoop;
-				} if(pairCutsEnabled[triggerIndex][3 + ENERGY_DIFF] && !trigger.getStateEnergyDifference()) {
-					continue pairTriggerLoop;
-				} if(pairCutsEnabled[triggerIndex][3 + ENERGY_SLOPE] && !trigger.getStateEnergySlope()) {
-					continue pairTriggerLoop;
-				} if(pairCutsEnabled[triggerIndex][3 + COPLANARITY] && !trigger.getStateCoplanarity()) {
-					continue pairTriggerLoop;
-				}
-				
-				// Add the trigger to the list.
-				sspPairsTriggers.get(triggerIndex).add(trigger);
-			}
 		}
 	}
 	

Modified: java/trunk/analysis/src/main/java/org/hps/analysis/trigger/event/TriggerPlotsModule.java
 =============================================================================
--- java/trunk/analysis/src/main/java/org/hps/analysis/trigger/event/TriggerPlotsModule.java	(original)
+++ java/trunk/analysis/src/main/java/org/hps/analysis/trigger/event/TriggerPlotsModule.java	Fri Oct 16 08:16:18 2015
@@ -27,6 +27,7 @@
 	
 	// Class variables.
 	private final double[] energySlopeParamF;
+	private static final double MØLLER_SUM_THRESHOLD = 0.750;
 	
 	// Plots.
 	private AIDA aida = AIDA.defaultInstance();
@@ -38,11 +39,26 @@
 	private IHistogram1D[][][] pairHitCountPlot = new IHistogram1D[2][2][5];
 	private IHistogram1D[][][] pairTimePlot = new IHistogram1D[2][2][5];
 	private IHistogram1D[][][] pairSumPlot = new IHistogram1D[2][2][5];
-        private IHistogram2D[][][] pairSumEnergiesPlot = new IHistogram2D[2][2][5];
+    private IHistogram2D[][][] pairSumEnergiesPlot = new IHistogram2D[2][2][5];
 	private IHistogram1D[][][] pairDiffPlot = new IHistogram1D[2][2][5];
 	private IHistogram1D[][][] pairSlopePlot = new IHistogram1D[2][2][5];
 	private IHistogram1D[][][] pairCoplanarityPlot = new IHistogram1D[2][2][5];
 	private IHistogram1D[][][] pairTriggerTimePlot = new IHistogram1D[2][2][5];
+	
+	private IHistogram1D[] møllerClusterEnergyPlot = new IHistogram1D[2];
+	private IHistogram1D[] møllerHitCountPlot = new IHistogram1D[2];
+	private IHistogram1D[] møllerTimePlot = new IHistogram1D[2];
+	private IHistogram1D[] møllerSumPlot = new IHistogram1D[2];
+    private IHistogram2D[] møllerSumEnergiesPlot = new IHistogram2D[2];
+	private IHistogram1D[] møllerDiffPlot = new IHistogram1D[2];
+	private IHistogram1D[] møllerSlopePlot = new IHistogram1D[2];
+	private IHistogram1D[] møllerCoplanarityPlot = new IHistogram1D[2];
+	private IHistogram1D[] møllerTriggerTimePlot = new IHistogram1D[2];
+    private IHistogram2D[] møllerPositionPlot = new IHistogram2D[2];
+	
+	private IHistogram1D[] tridentClusterEnergyPlot = new IHistogram1D[2];
+	private IHistogram1D[] tridentHitCountPlot = new IHistogram1D[2];
+    private IHistogram2D[] tridentPositionPlot = new IHistogram2D[2];
 	
 	/**
 	 * Instantiates a new <code>TriggerPlotsModule</code> that will use
@@ -77,34 +93,64 @@
 				// of trigger match result.
 				for(int result = 0; result < 5; result++) {
 					// Instantiate the singles trigger plots.
-					singlesClusterEnergyPlot[triggerNum][source][result] = aida.histogram1D(String.format("%s/%s Singles Cluster Energy (%s)",
+					singlesClusterEnergyPlot[triggerNum][source][result] = aida.histogram1D(String.format("%s/%s/Singles Cluster Energy (%s)",
 							singlesDir, sourceType[source], resultType[result]), 300, 0.0, 3.0);
-					singlesHitCountPlot[triggerNum][source][result] = aida.histogram1D(String.format("%s/%s Singles Hit Count (%s)",
+					singlesHitCountPlot[triggerNum][source][result] = aida.histogram1D(String.format("%s/%s/Singles Hit Count (%s)",
 							singlesDir, sourceType[source], resultType[result]), 9, 0.5, 9.5);
-					singlesTriggerTimePlot[triggerNum][source][result] = aida.histogram1D(String.format("%s/%s Singles Trigger Time (%s)",
+					singlesTriggerTimePlot[triggerNum][source][result] = aida.histogram1D(String.format("%s/%s/Singles Trigger Time (%s)",
 							singlesDir, sourceType[source], resultType[result]), 100, 0, 400);
 					
 					// Instantiate the pair trigger plots.
-					pairHitCountPlot[triggerNum][source][result] = aida.histogram1D(String.format("%s/%s Pair Hit Count (%s)",
+					pairHitCountPlot[triggerNum][source][result] = aida.histogram1D(String.format("%s/%s/Pair Hit Count (%s)",
 							pairDir, sourceType[source], resultType[result]), 9, 0.5, 9.5);
-					pairClusterEnergyPlot[triggerNum][source][result] = aida.histogram1D(String.format("%s/%s Pair Cluster Energy (%s)",
+					pairClusterEnergyPlot[triggerNum][source][result] = aida.histogram1D(String.format("%s/%s/Pair Cluster Energy (%s)",
 							pairDir, sourceType[source], resultType[result]), 300, 0.0, 3.0);
-					pairTimePlot[triggerNum][source][result] = aida.histogram1D(String.format("%s/%s Pair Time Coincidence (%s)",
+					pairTimePlot[triggerNum][source][result] = aida.histogram1D(String.format("%s/%s/Pair Time Coincidence (%s)",
 							pairDir, sourceType[source], resultType[result]), 8, 0, 32);
-					pairSumPlot[triggerNum][source][result] = aida.histogram1D(String.format("%s/%s Pair Energy Sum (%s)",
+					pairSumPlot[triggerNum][source][result] = aida.histogram1D(String.format("%s/%s/Pair Energy Sum (%s)",
 							pairDir, sourceType[source], resultType[result]), 300, 0.0, 3.0);
-                                        pairSumEnergiesPlot[triggerNum][source][result] = aida.histogram2D(String.format("%s/%s Pair 2D Energy Sum (%s)",
+                                        pairSumEnergiesPlot[triggerNum][source][result] = aida.histogram2D(String.format("%s/%s/Pair 2D Energy Sum (%s)",
                                                         pairDir, sourceType[source], resultType[result]), 300, 0.0, 3.0, 300, 0.0, 3.0);
-					pairDiffPlot[triggerNum][source][result] = aida.histogram1D(String.format("%s/%s Pair Energy Difference (%s)",
+					pairDiffPlot[triggerNum][source][result] = aida.histogram1D(String.format("%s/%s/Pair Energy Difference (%s)",
 							pairDir, sourceType[source], resultType[result]), 300, 0.0, 3.0);
-					pairSlopePlot[triggerNum][source][result] = aida.histogram1D(String.format("%s/%s Pair Energy Slope (%s)",
+					pairSlopePlot[triggerNum][source][result] = aida.histogram1D(String.format("%s/%s/Pair Energy Slope (%s)",
 							pairDir, sourceType[source], resultType[result]), 300, 0.0, 3.0);
-					pairCoplanarityPlot[triggerNum][source][result] = aida.histogram1D(String.format("%s/%s Pair Coplanarity (%s)",
+					pairCoplanarityPlot[triggerNum][source][result] = aida.histogram1D(String.format("%s/%s/Pair Coplanarity (%s)",
 							pairDir, sourceType[source], resultType[result]), 180, 0, 180);
-					pairTriggerTimePlot[triggerNum][source][result] = aida.histogram1D(String.format("%s/%s Pair Trigger Time (%s)",
+					pairTriggerTimePlot[triggerNum][source][result] = aida.histogram1D(String.format("%s/%s/Pair Trigger Time (%s)",
 							pairDir, sourceType[source], resultType[result]), 100, 0, 400);
 				}
 			}
+			
+			// Instantiate the Møller plots.
+			møllerHitCountPlot[triggerNum] = aida.histogram1D(String.format("%s/Møller/Møller-like Pair Hit Count",
+					pairDir), 9, 0.5, 9.5);
+			møllerClusterEnergyPlot[triggerNum] = aida.histogram1D(String.format("%s/Møller/Møller-like Pair Cluster Energy",
+					pairDir), 300, 0.0, 3.0);
+			møllerTimePlot[triggerNum] = aida.histogram1D(String.format("%s/Møller/Møller-like Pair Time Coincidence",
+					pairDir), 8, 0, 32);
+			møllerSumPlot[triggerNum] = aida.histogram1D(String.format("%s/Møller/Møller-like Pair Energy Sum",
+					pairDir), 300, 0.0, 3.0);
+			møllerSumEnergiesPlot[triggerNum] = aida.histogram2D(String.format("%s/Møller/Møller-like Pair 2D Energy Sum",
+                    pairDir), 300, 0.0, 3.0, 300, 0.0, 3.0);
+            møllerDiffPlot[triggerNum] = aida.histogram1D(String.format("%s/Møller/Møller-like Pair Energy Difference",
+					pairDir), 300, 0.0, 3.0);
+            møllerSlopePlot[triggerNum] = aida.histogram1D(String.format("%s/Møller/Møller-like Pair Energy Slope",
+					pairDir), 300, 0.0, 3.0);
+            møllerCoplanarityPlot[triggerNum] = aida.histogram1D(String.format("%s/Møller/Møller-like Pair Coplanarity",
+					pairDir), 180, 0, 180);
+            møllerTriggerTimePlot[triggerNum] = aida.histogram1D(String.format("%s/Møller/Møller-like Pair Trigger Time",
+					pairDir), 100, 0, 400);
+            møllerPositionPlot[triggerNum] = aida.histogram2D(String.format("%s/Møller/Møller-like Pair Position",
+					pairDir), 46, -23, 23, 11, -5.5, 5.5);
+            
+            // Instantiate the trident plots.
+            tridentHitCountPlot[triggerNum] = aida.histogram1D(String.format("%s/Trident/Trident-like Pair Hit Count",
+            		singlesDir), 9, 0.5, 9.5);
+			tridentClusterEnergyPlot[triggerNum] = aida.histogram1D(String.format("%s/Trident/Trident-like Pair Cluster Energy",
+					singlesDir), 300, 0.0, 3.0);
+            tridentPositionPlot[triggerNum] = aida.histogram2D(String.format("%s/Trident/Trident-like Pair Position",
+            		singlesDir), 46, -23, 23, 11, -5.5, 5.5);
 		}
 	}
 	
@@ -135,18 +181,42 @@
 		processTrigger(trigger, TRIGGERED);
 	}
 	
+	/**
+	 * Indicates that a cluster was seen by a trigger and adds it to
+	 * the "no cuts" plots.
+	 * @param triggerNum - The number of the trigger.
+	 * @param cluster - The cluster that was seen.
+	 */
 	public void sawCluster(int triggerNum, Cluster cluster) {
 		processSingles(triggerNum, NO_CUTS, cluster);
 	}
 	
+	/**
+	 * Indicates that a cluster was seen by a trigger and adds it to
+	 * the "no cuts" plots.
+	 * @param triggerNum - The number of the trigger.
+	 * @param cluster - The cluster that was seen.
+	 */
 	public void sawCluster(int triggerNum, SSPCluster cluster) {
 		processSingles(triggerNum, NO_CUTS, cluster);
 	}
 	
+	/**
+	 * Indicates that a cluster pair was seen by a trigger and adds it
+	 * to the "no cuts" plots.
+	 * @param triggerNum - The number of the trigger.
+	 * @param pair - The cluster pair that was seen.
+	 */
 	public void sawPair(int triggerNum, Cluster[] pair) {
 		processPair(triggerNum, NO_CUTS, pair);
 	}
 	
+	/**
+	 * Indicates that a cluster pair was seen by a trigger and adds it
+	 * to the "no cuts" plots.
+	 * @param triggerNum - The number of the trigger.
+	 * @param pair - The cluster pair that was seen.
+	 */
 	public void sawPair(int triggerNum, SSPCluster[] pair) {
 		processPair(triggerNum, NO_CUTS, pair);
 	}
@@ -237,6 +307,17 @@
 		singlesHitCountPlot[triggerNum][SSP][plotType].fill(TriggerModule.getValueClusterHitCount(cluster));
 		singlesClusterEnergyPlot[triggerNum][SSP][plotType].fill(TriggerModule.getValueClusterTotalEnergy(cluster));
 		singlesTriggerTimePlot[triggerNum][SSP][plotType].fill(cluster.getTime());
+		
+		// Check if this cluster is "trident-like."
+		// TODO: Define "trident-like."
+		boolean processTrident = false;
+		
+		// If this is a trident-like event, add it to the trident plots.
+		if(processTrident) {
+			tridentHitCountPlot[triggerNum].fill(TriggerModule.getValueClusterHitCount(cluster));
+			tridentClusterEnergyPlot[triggerNum].fill(TriggerModule.getValueClusterTotalEnergy(cluster));
+			tridentPositionPlot[triggerNum].fill(cluster.getXIndex() > 0 ? cluster.getXIndex() - 1 : cluster.getXIndex(), cluster.getYIndex());
+		}
 	}
 	
 	/**
@@ -285,9 +366,33 @@
 		// Fill the cluster pair plots.
 		pairTimePlot[triggerNum][SSP][plotType].fill(TriggerModule.getValueTimeCoincidence(pair));
 		pairSumPlot[triggerNum][SSP][plotType].fill(TriggerModule.getValueEnergySum(pair));
-                pairSumEnergiesPlot[triggerNum][SSP][plotType].fill(pair[0].getEnergy(), pair[1].getEnergy());
+        pairSumEnergiesPlot[triggerNum][SSP][plotType].fill(pair[0].getEnergy(), pair[1].getEnergy());
 		pairDiffPlot[triggerNum][SSP][plotType].fill(TriggerModule.getValueEnergyDifference(pair));
 		pairSlopePlot[triggerNum][SSP][plotType].fill(TriggerModule.getValueEnergySlope(pair, energySlopeParamF[triggerNum]));
 		pairCoplanarityPlot[triggerNum][SSP][plotType].fill(TriggerModule.getValueCoplanarity(pair));
+		
+		// Check if this pair is "Møller-like."
+		boolean processMøller = TriggerModule.getValueEnergySum(pair) >= MØLLER_SUM_THRESHOLD;
+		
+		// If the pair is Møller-like, populate the Møller plots.
+		if(processMøller) {
+			// Fill the cluster singles plots.
+			møllerHitCountPlot[triggerNum].fill(TriggerModule.getValueClusterHitCount(pair[0]));
+			møllerHitCountPlot[triggerNum].fill(TriggerModule.getValueClusterHitCount(pair[1]));
+			møllerClusterEnergyPlot[triggerNum].fill(TriggerModule.getValueClusterTotalEnergy(pair[0]));
+			møllerClusterEnergyPlot[triggerNum].fill(TriggerModule.getValueClusterTotalEnergy(pair[1]));
+			møllerTriggerTimePlot[triggerNum].fill(pair[0].getTime());
+			møllerTriggerTimePlot[triggerNum].fill(pair[1].getTime());
+			møllerPositionPlot[triggerNum].fill(pair[0].getXIndex() > 0 ? pair[0].getXIndex() - 1 : pair[0].getXIndex(), pair[0].getYIndex());
+			møllerPositionPlot[triggerNum].fill(pair[1].getXIndex() > 0 ? pair[1].getXIndex() - 1 : pair[1].getXIndex(), pair[1].getYIndex());
+			
+			// Fill the cluster pair plots.
+			møllerTimePlot[triggerNum].fill(TriggerModule.getValueTimeCoincidence(pair));
+			møllerSumPlot[triggerNum].fill(TriggerModule.getValueEnergySum(pair));
+			møllerSumEnergiesPlot[triggerNum].fill(pair[0].getEnergy(), pair[1].getEnergy());
+	        møllerDiffPlot[triggerNum].fill(TriggerModule.getValueEnergyDifference(pair));
+	        møllerSlopePlot[triggerNum].fill(TriggerModule.getValueEnergySlope(pair, energySlopeParamF[triggerNum]));
+	        møllerCoplanarityPlot[triggerNum].fill(TriggerModule.getValueCoplanarity(pair));
+		}
 	}
 }

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