Print

Print


Author: [log in to unmask]
Date: Fri Jul 31 19:36:32 2015
New Revision: 3323

Log:
Update Moller/Trident/Elastic analysis code and also added module for easily formatting and saving bulk AIDA files without JAS3.

Added:
    java/trunk/users/src/main/java/org/hps/users/kmccarty/MTETriggerPlotsFormatter.java
    java/trunk/users/src/main/java/org/hps/users/kmccarty/plots/
    java/trunk/users/src/main/java/org/hps/users/kmccarty/plots/FormattedPlot.java
    java/trunk/users/src/main/java/org/hps/users/kmccarty/plots/FormattedPlot1D.java
    java/trunk/users/src/main/java/org/hps/users/kmccarty/plots/FormattedPlot2D.java
    java/trunk/users/src/main/java/org/hps/users/kmccarty/plots/PlotFormatModule.java
Modified:
    java/trunk/users/src/main/java/org/hps/users/kmccarty/MTEAnalysis.java
    java/trunk/users/src/main/java/org/hps/users/kmccarty/TridentTrackDriver.java

Modified: java/trunk/users/src/main/java/org/hps/users/kmccarty/MTEAnalysis.java
 =============================================================================
--- java/trunk/users/src/main/java/org/hps/users/kmccarty/MTEAnalysis.java	(original)
+++ java/trunk/users/src/main/java/org/hps/users/kmccarty/MTEAnalysis.java	Fri Jul 31 19:36:32 2015
@@ -5,17 +5,24 @@
 import hep.physics.vec.VecOp;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
 
+import org.hps.recon.ecal.triggerbank.AbstractIntData;
+import org.hps.recon.ecal.triggerbank.TIData;
 import org.lcsim.event.CalorimeterHit;
 import org.lcsim.event.Cluster;
 import org.lcsim.event.EventHeader;
+import org.lcsim.event.GenericObject;
 import org.lcsim.event.ReconstructedParticle;
 import org.lcsim.util.Driver;
 import org.lcsim.util.aida.AIDA;
 
 public class MTEAnalysis extends Driver {
 	// Define track LCIO information.
+	private String bankCollectionName = "TriggerBank";
 	private String particleCollectionName = "FinalStateParticles";
 	private static final AIDA aida = AIDA.defaultInstance();
 	private IHistogram1D[] chargedTracksPlot = {
@@ -40,11 +47,76 @@
 	private IHistogram1D timePlot = aida.histogram1D("MTE Analysis/Track Cluster Time Distribution", 4000, 0, 400);
 	private IHistogram1D timeCoincidencePlot = aida.histogram1D("MTE Analysis/Møller Time Coincidence Distribution", 1000, 0, 100);
 	private IHistogram1D timeCoincidenceAllCutsPlot = aida.histogram1D("MTE Analysis/Møller Time Coincidence Distribution (All Møller Cuts)", 1000, 0, 100);
+	private TriggerPlotsModule allPlots = new TriggerPlotsModule("All");
+	private TriggerPlotsModule møllerPlots = new TriggerPlotsModule("Møller");
+	private TriggerPlotsModule tridentPlots = new TriggerPlotsModule("Trident");
+	private TriggerPlotsModule elasticPlots = new TriggerPlotsModule("Elastic");
 	private static final int MØLLER  = 0;
 	private static final int TRIDENT = 1;
 	private static final int ELASTIC = 2;
 	private boolean verbose = false;
+	private boolean excludeNoTrackEvents = false;
 	private double timeCoincidenceCut = Double.MAX_VALUE;
+	private Map<String, Integer> møllerBitMap = new HashMap<String, Integer>();
+	private Map<String, Integer> tridentBitMap = new HashMap<String, Integer>();
+	private Map<String, Integer> elasticBitMap = new HashMap<String, Integer>();
+	private int møllerEvents = 0;
+	private int tridentEvents = 0;
+	private int elasticEvents = 0;
+	
+	@Override
+	public void startOfData() {
+		for(int s0 = 0; s0 <= 1; s0++) {
+			for(int s1 = 0; s1 <= 1; s1++) {
+				for(int p0 = 0; p0 <= 1; p0++) {
+					for(int p1 = 0; p1 <= 1; p1++) {
+						for(int pulser = 0; pulser <=1; pulser++) {
+							// Set each "trigger bit."
+							boolean s0bit = (s0 == 1);
+							boolean s1bit = (s1 == 1);
+							boolean p0bit = (p0 == 1);
+							boolean p1bit = (p1 == 1);
+							boolean pulserBit = (p1 == 1);
+							
+							// Generate the bit string.
+							String bitString = getBitString(s0bit, s1bit, p0bit, p1bit, pulserBit);
+							
+							// Set a default value of zero for this bit combination.
+							møllerBitMap.put(bitString, 1);
+							tridentBitMap.put(bitString, 1);
+							elasticBitMap.put(bitString, 1);
+						}
+					}
+				}
+			}
+		}
+	}
+	
+	@Override
+	public void endOfData() {
+		System.out.println("Møller  Events :: " + møllerEvents);
+		System.out.println("Trident Events :: " + tridentEvents);
+		System.out.println("Elastic Events :: " + elasticEvents);
+		
+		System.out.println("Plsr\tS0\tS1\tP0\tP1\tMøller");
+		for(Entry<String, Integer> entry : møllerBitMap.entrySet()) {
+			System.out.println(entry.getKey() + "\t" + entry.getValue());
+		}
+		
+		System.out.println("Plsr\tS0\tS1\tP0\tP1\tTrident");
+		for(Entry<String, Integer> entry : tridentBitMap.entrySet()) {
+			System.out.println(entry.getKey() + "\t" + entry.getValue());
+		}
+		
+		System.out.println("Plsr\tS0\tS1\tP0\tP1\tElastic");
+		for(Entry<String, Integer> entry : elasticBitMap.entrySet()) {
+			System.out.println(entry.getKey() + "\t" + entry.getValue());
+		}
+	}
+	
+	private static final String getBitString(boolean s0, boolean s1, boolean p0, boolean p1, boolean pulser) {
+		return String.format("%d\t%d\t%d\t%d\t%d", (pulser ? 1 : 0), (s0 ? 1 : 0), (s1 ? 1 : 0), (p0 ? 1 : 0), (p1 ? 1 : 0));
+	}
 	
 	@Override
 	public void process(EventHeader event) {
@@ -68,6 +140,29 @@
 				}
 			}
 			
+			// Populate the all cluster plots.
+			List<Cluster> topClusters = new ArrayList<Cluster>();
+			List<Cluster> botClusters = new ArrayList<Cluster>();
+			List<Cluster> clusters = event.get(Cluster.class, "EcalClusters");
+			for(Cluster cluster : clusters) {
+				allPlots.addCluster(cluster);
+				if(cluster.getCalorimeterHits().get(0).getIdentifierFieldValue("iy") > 0) { topClusters.add(cluster); }
+				else { botClusters.add(cluster); }
+			}
+			
+			// Make cluster pairs.
+			List<Cluster[]> clusterPairs = new ArrayList<Cluster[]>();
+			for(Cluster topCluster : topClusters) {
+				for(Cluster botCluster : botClusters) {
+					clusterPairs.add(new Cluster[] { topCluster, botCluster });
+				}
+			}
+			
+			// Populate the all cluster pair plots.
+			for(Cluster[] pair : clusterPairs) {
+				allPlots.addClusterPair(pair);
+			}
+			
 			// Check each of the event-type conditions.
 			boolean isMøller = false;
 			boolean isTrident = false;
@@ -81,6 +176,12 @@
 			// within a certain band of the beam energy.
 			møllerTrackLoop:
 			for(ReconstructedParticle[] pair : pairList) {
+				// If trackless events are to be excluded, then require
+				// that each "track" have a real track.
+				if(excludeNoTrackEvents && (pair[0].getTracks().isEmpty() || pair[1].getTracks().isEmpty())) {
+					continue møllerTrackLoop;
+				}
+				
 				// Both tracks are required to be negatively charged.
 				if(pair[0].getCharge() >= 0 || pair[1].getCharge() >= 0) {
 					continue møllerTrackLoop;
@@ -137,6 +238,7 @@
 				
 				// Populate the Møller plots.
 				energyPlot[MØLLER].fill(sum);
+				møllerPlots.addClusterPair(trackClusters);
 				electronPlot[MØLLER].fill(pair[0].getMomentum().magnitude());
 				electronPlot[MØLLER].fill(pair[1].getMomentum().magnitude());
 				energy2DPlot[MØLLER].fill(pair[0].getMomentum().magnitude(), pair[1].getMomentum().magnitude());
@@ -145,23 +247,64 @@
 			// Check the elastic condition. Elastic events should be
 			// negatively and have an energy approximately equal to
 			// the beam energy.
+			elasticTrackLoop:
 			for(ReconstructedParticle track : trackList) {
+				// If trackless events are to be excluded, then require
+				// that the "track" has a real track.
+				if(excludeNoTrackEvents && track.getTracks().isEmpty()) {
+					continue elasticTrackLoop;
+				}
+				
+				// Check the elastic condition.
 				if(track.getCharge() < 0 && track.getMomentum().magnitude() >= 0.900) {
 					isElastic = true;
 					energyPlot[ELASTIC].fill(track.getMomentum().magnitude());
+					if(!track.getClusters().isEmpty()) {
+						elasticPlots.addCluster(track.getClusters().get(0));
+					}
 				}
 			}
 			
 			// Check the trident condition. Tridents are events that
 			// contain both one positive and one negative track.
+			tridentTrackLoop:
 			for(ReconstructedParticle[] pair : pairList) {
-				if((pair[0].getCharge() < 0 && pair[1].getCharge() > 0) ||
-						pair[0].getCharge() > 0 && pair[1].getCharge() < 0) {
+				// If trackless events are to be excluded, then require
+				// that each "track" have a real track.
+				if(excludeNoTrackEvents && (pair[0].getTracks().isEmpty() || pair[1].getTracks().isEmpty())) {
+					continue tridentTrackLoop;
+				}
+				
+				// Check the trident condition.
+				if((pair[0].getCharge() < 0 && pair[1].getCharge() > 0) || pair[0].getCharge() > 0 && pair[1].getCharge() < 0) {
+					// Both tracks must have clusters associated with them.
+					Cluster[] trackClusters = new Cluster[2];
+					for(int i = 0; i < 2; i++) {
+						// Disallow tracks with no associated clusters.
+						if(pair[i].getClusters().size() == 0) {
+							continue tridentTrackLoop;
+						}
+						
+						// Store the first cluster associated with the track.
+						trackClusters[i] = pair[i].getClusters().get(0);
+					}
+					
+					// Require that the track clusters be within a certain
+					// time window of one another.
+					CalorimeterHit[] seeds = new CalorimeterHit[2];
+					seeds[0] = trackClusters[0].getCalorimeterHits().get(0);
+					seeds[1] = trackClusters[1].getCalorimeterHits().get(0);
+					timeCoincidencePlot.fill(Math.abs(seeds[0].getTime() - seeds[1].getTime()));
+					if(Math.abs(trackClusters[0].getCalorimeterHits().get(0).getTime() - trackClusters[1].getCalorimeterHits().get(0).getTime()) > timeCoincidenceCut) {
+						continue tridentTrackLoop;
+					}
+					
 					// Require that the energy of the electron is below
 					// 900 MeV.
 					if((pair[0].getCharge() < 0 && pair[0].getMomentum().magnitude() < 0.900)
 							|| (pair[1].getCharge() < 0 && pair[1].getMomentum().magnitude() < 0.900)) {
 						isTrident = true;
+						tridentPlots.addClusterPair(trackClusters);
 						if(pair[0].getCharge() > 0) {
 							positronPlot.fill(pair[1].getMomentum().magnitude());
 							electronPlot[TRIDENT].fill(pair[0].getMomentum().magnitude());
@@ -185,22 +328,60 @@
 			// Get the number of charged tracks in the event.
 			int tracks = 0;
 			for(ReconstructedParticle track : trackList) {
-				if(track.getCharge() != 0) { tracks++; }
-			}
-			
-			// Add the result to the appropriate plots.
+				if(track.getCharge() != 0) {
+					if(excludeNoTrackEvents && !track.getTracks().isEmpty()) {
+						tracks++;
+					} else { tracks++; }
+				}
+			}
+			
+			// Get the TI bits.
+			String bitString = null;
+			List<GenericObject> bankList = event.get(GenericObject.class, bankCollectionName);
+			for(GenericObject obj : bankList) {
+				if(AbstractIntData.getTag(obj) == TIData.BANK_TAG) {
+					TIData tiBank = new TIData(obj);
+					bitString = getBitString(tiBank.isPulserTrigger(), tiBank.isSingle0Trigger(),
+							tiBank.isSingle1Trigger(), tiBank.isPair0Trigger(), tiBank.isPair1Trigger());
+				}
+			}
+			if(bitString == null) {
+				System.out.println("No TI data found!!");
+			}
+			
+			// Add the result to the appropriate plots and increment
+			// the appropriate trigger bit combination.
 			if(isMøller) {
+				møllerEvents++;
 				chargedTracksPlot[MØLLER].fill(tracks);
+				
+				Integer val = møllerBitMap.get(bitString);
+				if(val == null) { møllerBitMap.put(bitString, 1); }
+				else { møllerBitMap.put(bitString, val + 1); }
 			} else if(isTrident) {
+				tridentEvents++;
 				chargedTracksPlot[TRIDENT].fill(tracks);
+				
+				Integer val = tridentBitMap.get(bitString);
+				if(val == null) { tridentBitMap.put(bitString, 1); }
+				else { tridentBitMap.put(bitString, val + 1); }
 			} else if(isElastic) {
+				elasticEvents++;
 				chargedTracksPlot[ELASTIC].fill(tracks);
+				
+				Integer val = elasticBitMap.get(bitString);
+				if(val == null) { elasticBitMap.put(bitString, 1); }
+				else { elasticBitMap.put(bitString, val + 1); }
 			}
 		}
 	}
 	
 	public void setTimeCoincidenceCut(double value) {
 		timeCoincidenceCut = value;
+	}
+	
+	public void setExcludeNoTrackEvents(boolean state) {
+		excludeNoTrackEvents = state;
 	}
 	
 	private static final List<ReconstructedParticle[]> getTrackPairs(List<ReconstructedParticle> trackList) {

Added: java/trunk/users/src/main/java/org/hps/users/kmccarty/MTETriggerPlotsFormatter.java
 =============================================================================
--- java/trunk/users/src/main/java/org/hps/users/kmccarty/MTETriggerPlotsFormatter.java	(added)
+++ java/trunk/users/src/main/java/org/hps/users/kmccarty/MTETriggerPlotsFormatter.java	Fri Jul 31 19:36:32 2015
@@ -0,0 +1,177 @@
+package org.hps.users.kmccarty;
+
+import java.io.IOException;
+
+import org.hps.users.kmccarty.plots.FormattedPlot1D;
+import org.hps.users.kmccarty.plots.FormattedPlot2D;
+import org.hps.users.kmccarty.plots.PlotFormatModule;
+import org.hps.users.kmccarty.PlotsFormatter.ColorStyle;
+
+import hep.aida.IAnalysisFactory;
+import hep.aida.IHistogram1D;
+import hep.aida.IHistogram2D;
+import hep.aida.ITree;
+
+
+public class MTETriggerPlotsFormatter {
+	public static void main(String[] args) throws IllegalArgumentException, IOException {
+		// Define the root directory for the plots.
+		String rootDir = "D:\\cygwin64\\home\\Kyle\\";
+		
+		// Define the new name of the file containing the trigger plots.
+		String plotFile = rootDir + "5772-ana.aida";
+		
+		// Get the plots file and open it.
+		IAnalysisFactory af = IAnalysisFactory.create();
+		ITree tree = af.createTreeFactory().create(plotFile);
+		if(tree == null) { throw new IllegalArgumentException("Unable to load plot file."); }
+		
+		// Define the 1D trigger plot names for Møllers and tridents.
+		String[] plotNames1D = { "Cluster Hit Count", "Cluster Seed Energy", "Cluster Total Energy",
+				"Pair Coplanarity", "Pair Energy Difference", "Pair Energy Slope", "Pair Energy Sum" };
+		String[] displayNames1D = { "Cluster Hit Count", "Cluster Seed Energy", "Cluster Total Energy",
+				"Pair Coplanarity", "Pair Energy Difference", "Pair Energy Slope", "Pair Energy Sum" };
+		String[] xAxisNames1D = { "Hit Count", "Seed Energy (GeV)", "Total Energy (GeV)",
+				"Coplanarity (Degrees)", "Energy Difference (GeV)", "Energy Slope (GeV)", "Energy Sum (GeV)" };
+		String yAxisName1D = "Count";
+		
+		// Define the 2D trigger plot names for Møllers and tridents.
+		String[] plotNames2D = { "Cluster Seed", "Pair Energy Sum 2D" };
+		String[] displayNames2D = { "Cluster Seed Distribution", "2D Energy Sum" };
+		String[] xAxisNames2D = { "x-Index", "Second Cluster Energy (GeV)" };
+		String[] yAxisNames2D = { "y-Index", "First Cluster Energy (GeV)" };
+		
+		// Define the 1D trigger plot names for elastics.
+		String[] plotNamesElastic1D = { "Cluster Hit Count", "Cluster Seed Energy", "Cluster Total Energy" };
+		String[] displayNamesElastic1D = { "Cluster Hit Count", "Cluster Seed Energy", "Cluster Total Energy" };
+		String[] xAxisNamesElastic1D = { "Hit Count", "Seed Energy (GeV)", "Total Energy (GeV)" };
+		String yAxisNameElastic1D = "Count";
+		
+		// Define the 2D trigger plot names for elastics.
+		String[] plotNamesElastic2D = { "Cluster Seed" };
+		String[] displayNamesElastic2D = { "Cluster Seed Distribution" };
+		String[] xAxisNamesElastic2D = { "x-Index" };
+		String[] yAxisNamesElastic2D = { "y-Index" };
+		
+		// Define the Møller, trident, and elastic prefixes.
+		String allPrefix = "All Trigger Plots/Pair Plots/";
+		String møllerPrefix = "Møller Trigger Plots/Pair Plots/";
+		String tridentPrefix = "Trident Trigger Plots/Pair Plots/";
+		String elasticPrefix = "Elastic Trigger Plots/Singles Plots/";
+		String allSinglesPrefix = "All Trigger Plots/Singles Plots/";
+		
+		// Define the plot type prefix.
+		String allTypeName = "All Pairs - ";
+		String møllerTypeName = "Møller - ";
+		String tridentTypeName = "Trident - ";
+		String elasticTypeName = "Elastic - ";
+		String allSinglesTypeName = "All Singles - ";
+		
+		// Define the plot type colors.
+		ColorStyle allColor = PlotsFormatter.ColorStyle.GREY;
+		ColorStyle møllerColor = PlotsFormatter.ColorStyle.MS_BLUE;
+		ColorStyle tridentColor = PlotsFormatter.ColorStyle.MS_ORANGE;
+		ColorStyle elasticColor = PlotsFormatter.ColorStyle.MS_GREEN;
+		
+		// Create a plot formatting module.
+		PlotFormatModule module = new PlotFormatModule();
+		
+		// Get the histograms and add them to the module. Start with the
+		// trident and Møller plots.
+		for(int i = 0; i < plotNames1D.length; i++) {
+			// Get the Møller and trident plots.
+			IHistogram1D allPlot = (IHistogram1D) tree.find(allPrefix + plotNames1D[i]);
+			IHistogram1D møllerPlot = (IHistogram1D) tree.find(møllerPrefix + plotNames1D[i]);
+			IHistogram1D tridentPlot = (IHistogram1D) tree.find(tridentPrefix + plotNames1D[i]);
+			
+			// Make a formatted plot for each.
+			FormattedPlot1D allFormattedPlot = new FormattedPlot1D(allPlot, allColor, xAxisNames1D[i], yAxisName1D, allTypeName + displayNames1D[i]);
+			FormattedPlot1D møllerFormattedPlot = new FormattedPlot1D(møllerPlot, møllerColor, xAxisNames1D[i], yAxisName1D, møllerTypeName + displayNames1D[i]);
+			FormattedPlot1D tridentFormattedPlot = new FormattedPlot1D(tridentPlot, tridentColor, xAxisNames1D[i], yAxisName1D, tridentTypeName + displayNames1D[i]);
+			
+			// Add them to the module.
+			module.addPlot1D(allFormattedPlot);
+			module.addPlot1D(møllerFormattedPlot);
+			module.addPlot1D(tridentFormattedPlot);
+		}
+		for(int i = 0; i < plotNames2D.length; i++) {
+			// Get the Møller and trident plots.
+			IHistogram2D allPlot = (IHistogram2D) tree.find(allPrefix + plotNames2D[i]);
+			IHistogram2D møllerPlot = (IHistogram2D) tree.find(møllerPrefix + plotNames2D[i]);
+			IHistogram2D tridentPlot = (IHistogram2D) tree.find(tridentPrefix + plotNames2D[i]);
+			
+			// Make a formatted plot for each.
+			FormattedPlot2D allFormattedPlot = new FormattedPlot2D(allPlot, i == 0 ? true : false, xAxisNames2D[i], yAxisNames2D[i], allTypeName + displayNames2D[i]);
+			FormattedPlot2D møllerFormattedPlot = new FormattedPlot2D(møllerPlot, i == 0 ? true : false, xAxisNames2D[i], yAxisNames2D[i], møllerTypeName + displayNames2D[i]);
+			FormattedPlot2D tridentFormattedPlot = new FormattedPlot2D(tridentPlot, i == 0 ? true : false, xAxisNames2D[i], yAxisNames2D[i], tridentTypeName + displayNames2D[i]);
+			
+			// Add them to the module.
+			module.addPlot2D(allFormattedPlot);
+			module.addPlot2D(møllerFormattedPlot);
+			module.addPlot2D(tridentFormattedPlot);
+		}
+		
+		// Get the histograms for the elastic plots and add them to the module.
+		for(int i = 0; i < plotNamesElastic1D.length; i++) {
+			// Get the Møller and trident plots.
+			IHistogram1D allPlot = (IHistogram1D) tree.find(allSinglesPrefix + plotNames1D[i]);
+			IHistogram1D elasticPlot = (IHistogram1D) tree.find(elasticPrefix + plotNames1D[i]);
+			
+			// Make a formatted plot for each.
+			FormattedPlot1D allFormattedPlot = new FormattedPlot1D(allPlot, allColor, xAxisNamesElastic1D[i], yAxisNameElastic1D,
+					allSinglesTypeName + displayNamesElastic1D[i]);
+			FormattedPlot1D elasticFormattedPlot = new FormattedPlot1D(elasticPlot, elasticColor, xAxisNamesElastic1D[i], yAxisNameElastic1D,
+					elasticTypeName + displayNamesElastic1D[i]);
+			
+			// Add them to the module.
+			module.addPlot1D(allFormattedPlot);
+			module.addPlot1D(elasticFormattedPlot);
+		}
+		for(int i = 0; i < plotNamesElastic2D.length; i++) {
+			// Get the Møller and trident plots.
+			IHistogram2D allPlot = (IHistogram2D) tree.find(allPrefix + plotNamesElastic2D[i]);
+			IHistogram2D elasticPlot = (IHistogram2D) tree.find(møllerPrefix + plotNamesElastic2D[i]);
+			
+			// Make a formatted plot for each.
+			FormattedPlot2D allFormattedPlot = new FormattedPlot2D(allPlot, i == 0 ? true : false, xAxisNamesElastic2D[i], yAxisNamesElastic2D[i],
+					allSinglesTypeName + plotNames2D[i]);
+			FormattedPlot2D elasticFormattedPlot = new FormattedPlot2D(elasticPlot, i == 0 ? true : false, xAxisNamesElastic2D[i], yAxisNamesElastic2D[i],
+					elasticTypeName + displayNamesElastic2D[i]);
+			
+			// Add them to the module.
+			module.addPlot2D(allFormattedPlot);
+			module.addPlot2D(elasticFormattedPlot);
+		}
+		
+		// Add the MTE plots to the module.
+		module.addPlot1D(new FormattedPlot1D((IHistogram1D) tree.find("MTE Analysis/Elastic Energy Distribution"), elasticColor,
+				"Momentum (GeV)", "Count", "Elastic - Momentum"));
+		module.addPlot1D(new FormattedPlot1D((IHistogram1D) tree.find("MTE Analysis/Elastic Event Tracks"), elasticColor,
+				"Tracks", "Count", "Elastic - Tracks in Event"));
+		
+		module.addPlot1D(new FormattedPlot1D((IHistogram1D) tree.find("MTE Analysis/Møller Energy Sum Distribution"), møllerColor,
+				"Momentum Sum (GeV)", "Count", "Møller - Momentum Sum"));
+		module.addPlot1D(new FormattedPlot1D((IHistogram1D) tree.find("MTE Analysis/Møller Electron Energy Distribution"), møllerColor,
+				"Momentum (GeV)", "Count", "Møller - Momentum (Electron)"));
+		module.addPlot1D(new FormattedPlot1D((IHistogram1D) tree.find("MTE Analysis/Møller Time Coincidence Distribution (All Møller Cuts)"), møllerColor,
+				"Time (ns)", "Count", "Møller - Time Coincidence"));
+		module.addPlot1D(new FormattedPlot1D((IHistogram1D) tree.find("MTE Analysis/Møller Event Tracks"), møllerColor,
+				"Tracks", "Count", "Møller - Tracks in Event"));
+		module.addPlot2D(new FormattedPlot2D((IHistogram2D) tree.find("MTE Analysis/Møller 2D Energy Distribution"), false,
+				"First Track Momentum (GeV)", "Second Track Momentum (GeV)", "Møller - 2D Momentum Sum"));
+		
+		module.addPlot1D(new FormattedPlot1D((IHistogram1D) tree.find("MTE Analysis/Trident Energy Sum Distribution"), tridentColor,
+				"Momentum Sum (GeV)", "Count", "Trident - Momentum Sum"));
+		module.addPlot1D(new FormattedPlot1D((IHistogram1D) tree.find("MTE Analysis/Trident Electron Energy Distribution"), tridentColor,
+				"Momentum (GeV)", "Count", "Trident - Momentum (Electron)"));
+		module.addPlot1D(new FormattedPlot1D((IHistogram1D) tree.find("MTE Analysis/Trident Positron Energy Distribution"), tridentColor,
+				"Momentum (GeV)", "Count", "Trident - Momentum (Positron)"));
+		module.addPlot1D(new FormattedPlot1D((IHistogram1D) tree.find("MTE Analysis/Trident Event Tracks"), tridentColor,
+				"Tracks", "Count", "Trident - Tracks in Event"));
+		module.addPlot2D(new FormattedPlot2D((IHistogram2D) tree.find("MTE Analysis/Trident 2D Energy Distribution"), false,
+				"First Track Momentum (GeV)", "Second Track Momentum (GeV)", "Trident - 2D Momentum Sum"));
+		
+		// Display the plots.
+		module.savePlots("C:\\Users\\Kyle\\Desktop\\EnergyShift\\TestPrint\\");
+	}
+}

Modified: java/trunk/users/src/main/java/org/hps/users/kmccarty/TridentTrackDriver.java
 =============================================================================
--- java/trunk/users/src/main/java/org/hps/users/kmccarty/TridentTrackDriver.java	(original)
+++ java/trunk/users/src/main/java/org/hps/users/kmccarty/TridentTrackDriver.java	Fri Jul 31 19:36:32 2015
@@ -8,6 +8,7 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import org.hps.recon.tracking.TrackUtils;
 import org.lcsim.event.EventHeader;
 import org.lcsim.event.ReconstructedParticle;
 import org.lcsim.util.Driver;
@@ -109,6 +110,10 @@
 					tracksFinalStateCluster++;
 				}
 				
+				// Process the track position plots.
+				Hep3Vector trackPosAtEcal = TrackUtils.extrapolateTrack(track.getTracks().get(0), 1394.5);
+				position[ANY_CLUSTER].fill(trackPosAtEcal.x(), trackPosAtEcal.y());
+				
 				// Process the tracks based on charge.
 				if(track.getCharge() > 0) {
 					// Increment the counters and populate the momentum plots.
@@ -124,9 +129,9 @@
 						posMomentum[HAS_CLUSTER].fill(track.getMomentum().magnitude());
 						
 						// Populate the cluster position plot.
-						int ix = track.getClusters().get(0).getCalorimeterHits().get(0).getIdentifierFieldValue("ix");
-						int iy = track.getClusters().get(0).getCalorimeterHits().get(0).getIdentifierFieldValue("iy");
-						position[HAS_CLUSTER].fill(ix, iy);
+						//int ix = track.getClusters().get(0).getCalorimeterHits().get(0).getIdentifierFieldValue("ix");
+						//int iy = track.getClusters().get(0).getCalorimeterHits().get(0).getIdentifierFieldValue("iy");
+						position[HAS_CLUSTER].fill(trackPosAtEcal.x(), trackPosAtEcal.y());
 					}
 				} else if(track.getCharge() < 0) {
 					// Increment the counters and populate the momentum plots.
@@ -142,9 +147,9 @@
 						negMomentum[HAS_CLUSTER].fill(track.getMomentum().magnitude());
 						
 						// Populate the cluster position plot.
-						int ix = track.getClusters().get(0).getCalorimeterHits().get(0).getIdentifierFieldValue("ix");
-						int iy = track.getClusters().get(0).getCalorimeterHits().get(0).getIdentifierFieldValue("iy");
-						position[HAS_CLUSTER].fill(ix, iy);
+						//int ix = track.getClusters().get(0).getCalorimeterHits().get(0).getIdentifierFieldValue("ix");
+						//int iy = track.getClusters().get(0).getCalorimeterHits().get(0).getIdentifierFieldValue("iy");
+						position[HAS_CLUSTER].fill(trackPosAtEcal.x(), trackPosAtEcal.y());
 					}
 				} else {
 					if(track.getClusters().size() > 0) {
@@ -152,9 +157,9 @@
 						allClusterTrackList.add(track);
 						
 						// Populate the cluster position plot.
-						int ix = track.getClusters().get(0).getCalorimeterHits().get(0).getIdentifierFieldValue("ix");
-						int iy = track.getClusters().get(0).getCalorimeterHits().get(0).getIdentifierFieldValue("iy");
-						position[HAS_CLUSTER].fill(ix, iy);
+						//int ix = track.getClusters().get(0).getCalorimeterHits().get(0).getIdentifierFieldValue("ix");
+						//int iy = track.getClusters().get(0).getCalorimeterHits().get(0).getIdentifierFieldValue("iy");
+						position[HAS_CLUSTER].fill(trackPosAtEcal.x(), trackPosAtEcal.y());
 					}
 				}
 			}

Added: java/trunk/users/src/main/java/org/hps/users/kmccarty/plots/FormattedPlot.java
 =============================================================================
--- java/trunk/users/src/main/java/org/hps/users/kmccarty/plots/FormattedPlot.java	(added)
+++ java/trunk/users/src/main/java/org/hps/users/kmccarty/plots/FormattedPlot.java	Fri Jul 31 19:36:32 2015
@@ -0,0 +1,25 @@
+package org.hps.users.kmccarty.plots;
+
+public abstract class FormattedPlot {
+	private final String xAxis;
+	private final String yAxis;
+	private final String plotName;
+	
+	public FormattedPlot(String xAxis, String yAxis, String plotName) {
+		this.xAxis = xAxis;
+		this.yAxis = yAxis;
+		this.plotName = plotName;
+	}
+	
+	public String getPlotName() {
+		return plotName;
+	}
+	
+	public String getXAxisName() {
+		return xAxis;
+	}
+	
+	public String getYAxisName() {
+		return yAxis;
+	}
+}

Added: java/trunk/users/src/main/java/org/hps/users/kmccarty/plots/FormattedPlot1D.java
 =============================================================================
--- java/trunk/users/src/main/java/org/hps/users/kmccarty/plots/FormattedPlot1D.java	(added)
+++ java/trunk/users/src/main/java/org/hps/users/kmccarty/plots/FormattedPlot1D.java	Fri Jul 31 19:36:32 2015
@@ -0,0 +1,24 @@
+package org.hps.users.kmccarty.plots;
+
+import org.hps.users.kmccarty.PlotsFormatter.ColorStyle;
+
+import hep.aida.IHistogram1D;
+
+public class FormattedPlot1D extends FormattedPlot {
+	private final ColorStyle style;
+	private final IHistogram1D plot;
+	
+	public FormattedPlot1D(IHistogram1D plot, ColorStyle style, String xAxis, String yAxis, String plotName) {
+		super(xAxis, yAxis, plotName);
+		this.plot = plot;
+		this.style = style;
+	}
+	
+	public IHistogram1D getPlot() {
+		return plot;
+	}
+	
+	public ColorStyle getColorStyle() {
+		return style;
+	}
+}

Added: java/trunk/users/src/main/java/org/hps/users/kmccarty/plots/FormattedPlot2D.java
 =============================================================================
--- java/trunk/users/src/main/java/org/hps/users/kmccarty/plots/FormattedPlot2D.java	(added)
+++ java/trunk/users/src/main/java/org/hps/users/kmccarty/plots/FormattedPlot2D.java	Fri Jul 31 19:36:32 2015
@@ -0,0 +1,22 @@
+package org.hps.users.kmccarty.plots;
+
+import hep.aida.IHistogram2D;
+
+public class FormattedPlot2D extends FormattedPlot {
+	private final IHistogram2D plot;
+	private final boolean logarithmic;
+	
+	public FormattedPlot2D(IHistogram2D plot, boolean logarithmic, String xAxis, String yAxis, String plotName) {
+		super(xAxis, yAxis, plotName);
+		this.plot = plot;
+		this.logarithmic = logarithmic;
+	}
+	
+	public IHistogram2D getPlot() {
+		return plot;
+	}
+	
+	public boolean isLogarithmic() {
+		return logarithmic;
+	}
+}

Added: java/trunk/users/src/main/java/org/hps/users/kmccarty/plots/PlotFormatModule.java
 =============================================================================
--- java/trunk/users/src/main/java/org/hps/users/kmccarty/plots/PlotFormatModule.java	(added)
+++ java/trunk/users/src/main/java/org/hps/users/kmccarty/plots/PlotFormatModule.java	Fri Jul 31 19:36:32 2015
@@ -0,0 +1,112 @@
+package org.hps.users.kmccarty.plots;
+
+import hep.aida.IAnalysisFactory;
+import hep.aida.IHistogram1D;
+import hep.aida.IHistogram2D;
+import hep.aida.IPlotter;
+import hep.aida.IPlotterFactory;
+import hep.aida.ref.plotter.PlotterRegion;
+
+import org.hps.users.kmccarty.PlotsFormatter;
+import org.hps.users.kmccarty.PlotsFormatter.ColorStyle;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+public class PlotFormatModule {
+	private String width = "2000";
+	private String height = "1200";
+	private List<FormattedPlot1D> formattedPlots1D = new ArrayList<FormattedPlot1D>();
+	private List<FormattedPlot2D> formattedPlots2D = new ArrayList<FormattedPlot2D>();
+	
+	public void addPlot1D(FormattedPlot1D plot) {
+		formattedPlots1D.add(plot);
+	}
+	
+	public void addPlot2D(FormattedPlot2D plot) {
+		formattedPlots2D.add(plot);
+	}
+	
+	public void setDisplayHeight(int height) {
+		this.height = "" + height;
+	}
+	
+	public void setDisplayWidth(int width) {
+		this.width = "" + width;
+	}
+	
+	public void displayPlots() {
+		try { processPlots(null); }
+		catch (IOException e) { e.printStackTrace(); }
+	}
+	
+	public void savePlots(String filePath) throws IOException {
+		processPlots(filePath);
+	}
+	
+	private void processPlots(String filePath) throws IOException {
+		// Create a plotter factory.
+		IAnalysisFactory af = IAnalysisFactory.create();
+		IPlotterFactory plotterFactory = af.createPlotterFactory();
+		
+		// Format and display the 1D plots.
+		for(FormattedPlot1D formattedPlot : formattedPlots1D) {
+			// Get the plot.
+			IHistogram1D plot = formattedPlot.getPlot();
+			
+			// Create a plotter and plotting region for the plot.
+			IPlotter plotter = plotterFactory.create(plot.title());
+			plotter.createRegions(1);
+			plotter.region(0).plot(plot);
+			
+			// Format the axis labels.
+			PlotterRegion region = (PlotterRegion) plotter.region(0);
+			region.getPlot().setTitle(formattedPlot.getPlotName());
+			region.getPlot().getXAxis().setLabel(formattedPlot.getXAxisName());
+			region.getPlot().getYAxis().setLabel(formattedPlot.getYAxisName());
+			
+			// Format the fonts and general plot presentation.
+			PlotsFormatter.setDefault1DStyle(region, new ColorStyle[] { formattedPlot.getColorStyle() });
+			
+			// Set the plotter dimensions.
+			plotter.setParameter("plotterWidth", width);
+			plotter.setParameter("plotterHeight", height);
+			
+			// If the file path is null, display the plots. Otherwise,
+			// save them to the destination folder.
+			if(filePath == null) { plotter.show(); }
+			else { plotter.writeToFile(filePath + formattedPlot.getPlotName() + ".png"); }
+		}
+		
+		// Format and display the 2D plots.
+		for(FormattedPlot2D formattedPlot : formattedPlots2D) {
+			// Get the plot.
+			IHistogram2D plot = formattedPlot.getPlot();
+			
+			// Create a plotter and plotting region for the plot.
+			IPlotter plotter = plotterFactory.create(formattedPlot.getPlotName());
+			plotter.createRegions(1);
+			plotter.region(0).plot(plot);
+			
+			// Format the axis labels.
+			PlotterRegion region = (PlotterRegion) plotter.region(0);
+			region.getPlot().setTitle(formattedPlot.getPlotName());
+			region.getPlot().getXAxis().setLabel(formattedPlot.getXAxisName());
+			region.getPlot().getYAxis().setLabel(formattedPlot.getYAxisName());
+			
+			
+			// Format the fonts and general plot presentation.
+			PlotsFormatter.setDefault2DStyle(region, formattedPlot.isLogarithmic());
+			
+			// Set the plotter dimensions.
+			plotter.setParameter("plotterWidth", width);
+			plotter.setParameter("plotterHeight", height);
+			
+			// If the file path is null, display the plots. Otherwise,
+			// save them to the destination folder.
+			if(filePath == null) { plotter.show(); }
+			else { plotter.writeToFile(filePath + formattedPlot.getPlotName() + ".png"); }
+		}
+	}
+}