Author: [log in to unmask]
Date: Tue Oct 20 18:57:00 2015
New Revision: 3864
Log:
Added work-in-progress Moller/trident analysis driver.
Added:
java/trunk/users/src/main/java/org/hps/users/kmccarty/TriggerProcessAnalysisDriver.java (with props)
Modified:
java/trunk/users/src/main/java/org/hps/users/kmccarty/plots/formatter/TriggerPlotsFormat.java
Added: java/trunk/users/src/main/java/org/hps/users/kmccarty/TriggerProcessAnalysisDriver.java
=============================================================================
--- java/trunk/users/src/main/java/org/hps/users/kmccarty/TriggerProcessAnalysisDriver.java (added)
+++ java/trunk/users/src/main/java/org/hps/users/kmccarty/TriggerProcessAnalysisDriver.java Tue Oct 20 18:57:00 2015
@@ -0,0 +1,390 @@
+package org.hps.users.kmccarty;
+
+import hep.aida.IHistogram1D;
+import hep.aida.IHistogram2D;
+import hep.physics.vec.VecOp;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.hps.record.triggerbank.TriggerModule;
+import org.lcsim.event.Cluster;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.ReconstructedParticle;
+import org.lcsim.util.Driver;
+import org.lcsim.util.aida.AIDA;
+
+public class TriggerProcessAnalysisDriver extends Driver {
+ private int eventsProcessed = 0;
+ private int møllersProcessed = 0;
+ private int tridentsProcessed = 0;
+ private double timeCoincidence = 2.5;
+ private AIDA aida = AIDA.defaultInstance();
+ private String clusterCollectionName = "EcalClustersCorr";
+ private String particleCollectionName = "FinalStateParticles";
+
+ // Define trident cluster-track matched condition plots.
+ private IHistogram1D trctmInvariantMass = aida.histogram1D("Tridents CTMatched/Invariant Mass", 140, 0.0, 0.070);
+ private IHistogram1D trctmInstancesInEvent = aida.histogram1D("Tridents CTMatched/Instances in Event", 9, 0.5, 9.5);
+ private IHistogram1D trctmEnergySum1D = aida.histogram1D("Tridents CTMatched/Cluster Energy Sum", 150, 0.000, 1.500);
+ private IHistogram1D trctmMomentumSum1D = aida.histogram1D("Tridents CTMatched/Track Momentum Sum", 150, 0.000, 1.500);
+ private IHistogram1D trctmElectronEnergy = aida.histogram1D("Tridents CTMatched/Electron Cluster Energy", 150, 0.000, 1.500);
+ private IHistogram1D trctmElectronMomentum = aida.histogram1D("Tridents CTMatched/Electron Track Momentum", 150, 0.000, 1.500);
+ private IHistogram1D trctmPositronEnergy = aida.histogram1D("Tridents CTMatched/Positron Cluster Energy", 150, 0.000, 1.500);
+ private IHistogram1D trctmPositronMomentum = aida.histogram1D("Tridents CTMatched/Positron Track Momentum", 150, 0.000, 1.500);
+ private IHistogram1D trctmTimeCoincidence = aida.histogram1D("Tridents CTMatched/Time Coincidence", 100, -4, 4);
+ private IHistogram2D trctmClusterPosition = aida.histogram2D("Tridents CTMatched/Cluster Seed Position", 46, -23, 23, 11, -5.5, 5.5);
+ private IHistogram2D trctmEnergySum2D = aida.histogram2D("Tridents CTMatched/Cluster Energy Sum 2D", 300, 0.000, 1.500, 300, 0.000, 1.500);
+ private IHistogram2D trctmMomentumSum2D = aida.histogram2D("Tridents CTMatched/Track Momentum Sum 2D", 300, 0.000, 1.500, 300, 0.000, 1.500);
+
+ // Define the Møller cluster-track matched condition plots.
+ private IHistogram1D møctmInvariantMass = aida.histogram1D("Møller CTMatched/Invariant Mass", 140, 0.0, 0.070);
+ private IHistogram1D møctmInstancesInEvent = aida.histogram1D("Møller CTMatched/Instances in Event", 9, 0.5, 9.5);
+ private IHistogram1D møctmEnergySum1D = aida.histogram1D("Møller CTMatched/Cluster Energy Sum", 150, 0.000, 1.500);
+ private IHistogram1D møctmMomentumSum1D = aida.histogram1D("Møller CTMatched/Track Momentum Sum", 150, 0.000, 1.500);
+ private IHistogram1D møctmElectronEnergy = aida.histogram1D("Møller CTMatched/Electron Cluster Energy", 150, 0.000, 1.500);
+ private IHistogram1D møctmElectronMomentum = aida.histogram1D("Møller CTMatched/Electron Track Momentum", 150, 0.000, 1.500);
+ private IHistogram1D møctmTimeCoincidence = aida.histogram1D("Møller CTMatched/Time Coincidence", 100, -4, 4);
+ private IHistogram2D møctmClusterPosition = aida.histogram2D("Møller CTMatched/Cluster Seed Position", 46, -23, 23, 11, -5.5, 5.5);
+ private IHistogram2D møctmEnergySum2D = aida.histogram2D("Møller CTMatched/Cluster Energy Sum 2D", 300, 0.000, 1.500, 300, 0.000, 1.500);
+ private IHistogram2D møctmMomentumSum2D = aida.histogram2D("Møller CTMatched/Track Momentum Sum 2D", 300, 0.000, 1.500, 300, 0.000, 1.500);
+
+ @Override
+ public void endOfData() {
+ // Calculate the scaling factor for Hertz.
+ double scale = 19000.0 / eventsProcessed;
+
+ System.out.println("Processed " + eventsProcessed + " events.");
+ System.out.println("Processed " + møllersProcessed + " Møller events");
+ System.out.println("\tAcceptance :: " + (100.0 * møllersProcessed / eventsProcessed) + "%");
+ System.out.println("\tRate :: " + (møllersProcessed * scale) + "Hz");
+ System.out.println("Processed " + tridentsProcessed + " trident events");
+ System.out.println("\tAcceptance :: " + (100.0 * tridentsProcessed / eventsProcessed) + "%");
+ System.out.println("\tRate :: " + (tridentsProcessed * scale) + "Hz");
+
+ // Scale the cluster-track matched Møller plots.
+ møctmInvariantMass.scale(scale);
+ møctmInstancesInEvent.scale(scale);
+ møctmEnergySum1D.scale(scale);
+ møctmMomentumSum1D.scale(scale);
+ møctmElectronEnergy.scale(scale);
+ møctmElectronMomentum.scale(scale);
+ møctmTimeCoincidence.scale(scale);
+ møctmClusterPosition.scale(scale);
+ møctmEnergySum2D.scale(scale);
+ møctmMomentumSum2D.scale(scale);
+
+ // Scale the cluster-track matched trident plots.
+ trctmInvariantMass.scale(scale);
+ trctmInstancesInEvent.scale(scale);
+ trctmEnergySum1D.scale(scale);
+ trctmMomentumSum1D.scale(scale);
+ trctmElectronEnergy.scale(scale);
+ trctmElectronMomentum.scale(scale);
+ trctmPositronEnergy.scale(scale);
+ trctmPositronMomentum.scale(scale);
+ trctmTimeCoincidence.scale(scale);
+ trctmClusterPosition.scale(scale);
+ trctmEnergySum2D.scale(scale);
+ trctmMomentumSum2D.scale(scale);
+ }
+
+ @Override
+ public void process(EventHeader event) {
+ // Check whether the SVT was active in this event and, if so,
+ // skip it.
+ final String[] flagNames = { "svt_bias_good", "svt_burstmode_noise_good", "svt_position_good" };
+ boolean svtGood = true;
+ for(int i = 0; i < flagNames.length; i++) {
+ int[] flag = event.getIntegerParameters().get(flagNames[i]);
+ if(flag == null || flag[0] == 0) {
+ svtGood = false;
+ }
+ }
+ if(!svtGood) { return; }
+
+ // Track the number of events with good SVT.
+ eventsProcessed++;
+
+ // Check if the event has a collection of tracks. If it exists,
+ // extract it. Otherwise, skip the event.
+ if(!event.hasCollection(ReconstructedParticle.class, particleCollectionName)) {
+ return;
+ }
+ List<ReconstructedParticle> trackList = event.get(ReconstructedParticle.class, particleCollectionName);
+
+ // Check if the event has a collection of clusters. If it
+ // exists, extract it. Otherwise, skip the event.
+ if(!event.hasCollection(Cluster.class, clusterCollectionName)) {
+ return;
+ }
+ List<Cluster> clusterList = event.get(Cluster.class, clusterCollectionName);
+
+ // Get cluster-track matched top/bottom pairs.
+ List<ReconstructedParticle[]> ctMatchedPairs = getTopBottomTracksCTMatched(trackList);
+
+ // Get the trident and Møller tracks for the matched track
+ // and cluster pair condition sets.
+ List<ReconstructedParticle[]> møllers = getMøllerTracksCTMatched(ctMatchedPairs);
+ List<ReconstructedParticle[]> tridents = getTridentTracksCTMatched(ctMatchedPairs);
+
+ // Track how many events had tridents and Møllers.
+ if(!møllers.isEmpty()) { møllersProcessed++; }
+ if(!tridents.isEmpty()) { tridentsProcessed++; }
+
+ // Produce Møller cluster-track matched plots.
+ møctmInstancesInEvent.fill(møllers.size());
+ for(ReconstructedParticle[] pair : møllers) {
+ // Get the track clusters.
+ Cluster[] trackClusters = { pair[0].getClusters().get(0), pair[1].getClusters().get(0) };
+
+ // Populate the cluster plots.
+ møctmElectronEnergy.fill(trackClusters[0].getEnergy());
+ møctmElectronEnergy.fill(trackClusters[1].getEnergy());
+ møctmEnergySum1D.fill(TriggerModule.getValueEnergySum(trackClusters));
+ møctmEnergySum2D.fill(trackClusters[0].getEnergy(), trackClusters[1].getEnergy());
+ møctmTimeCoincidence.fill(TriggerModule.getClusterTime(trackClusters[0]) - TriggerModule.getClusterTime(trackClusters[1]));
+ møctmClusterPosition.fill(TriggerModule.getClusterXIndex(trackClusters[0]), TriggerModule.getClusterYIndex(trackClusters[0]));
+ møctmClusterPosition.fill(TriggerModule.getClusterXIndex(trackClusters[1]), TriggerModule.getClusterYIndex(trackClusters[1]));
+
+ // Populate the momentum plots.
+ møctmInvariantMass.fill(getInvariantMass(pair));
+ møctmElectronMomentum.fill(pair[0].getMomentum().magnitude());
+ møctmElectronMomentum.fill(pair[1].getMomentum().magnitude());
+ møctmMomentumSum1D.fill(VecOp.add(pair[0].getMomentum(), pair[1].getMomentum()).magnitude());
+ møctmMomentumSum2D.fill(pair[0].getMomentum().magnitude(), pair[1].getMomentum().magnitude());
+ }
+
+ // Produce trident cluster-track matched plots.
+ trctmInstancesInEvent.fill(tridents.size());
+ for(ReconstructedParticle[] pair : tridents) {
+ // Get the electron and positron tracks.
+ ReconstructedParticle electronTrack = pair[pair[0].getCharge() < 0 ? 0 : 1];
+ ReconstructedParticle positronTrack = pair[pair[0].getCharge() > 0 ? 0 : 1];
+
+ // Get the track clusters.
+ Cluster electronCluster = electronTrack.getClusters().get(0);
+ Cluster positronCluster = positronTrack.getClusters().get(0);
+ Cluster[] trackClusters = { pair[0].getClusters().get(0), pair[1].getClusters().get(0) };
+
+ // Populate the cluster plots.
+ trctmElectronEnergy.fill(electronCluster.getEnergy());
+ trctmPositronEnergy.fill(positronCluster.getEnergy());
+ trctmEnergySum1D.fill(TriggerModule.getValueEnergySum(trackClusters));
+ trctmEnergySum2D.fill(pair[0].getEnergy(), pair[1].getEnergy());
+ trctmTimeCoincidence.fill(TriggerModule.getClusterTime(trackClusters[0]) - TriggerModule.getClusterTime(trackClusters[1]));
+ trctmClusterPosition.fill(TriggerModule.getClusterXIndex(trackClusters[0]), TriggerModule.getClusterYIndex(trackClusters[0]));
+ trctmClusterPosition.fill(TriggerModule.getClusterXIndex(trackClusters[1]), TriggerModule.getClusterYIndex(trackClusters[1]));
+
+ // Populate the momentum plots.
+ trctmInvariantMass.fill(getInvariantMass(pair));
+ trctmElectronMomentum.fill(electronTrack.getMomentum().magnitude());
+ trctmPositronMomentum.fill(positronTrack.getMomentum().magnitude());
+ trctmMomentumSum1D.fill(VecOp.add(pair[0].getMomentum(), pair[1].getMomentum()).magnitude());
+ trctmMomentumSum2D.fill(pair[0].getMomentum().magnitude(), pair[1].getMomentum().magnitude());
+ }
+ }
+
+ /**
+ * Produces pairs of tracks. The track pairs are required to be
+ * matched to a cluster and the associated clusters must form a
+ * top/bottom pair. If more than one track points to the same
+ * cluster, only the first track is retained.
+ * @param trackList - A list of all tracks.
+ * @return Returns a list of track pairs meeting the aforementioned
+ * conditions.
+ */
+ private static final List<ReconstructedParticle[]> getTopBottomTracksCTMatched(List<ReconstructedParticle> trackList) {
+ // Track clusters that have already been seen to prevent clusters
+ // that have duplicate tracks from reappearing.
+ Set<Cluster> clusterSet = new HashSet<Cluster>();
+
+ // Separate the tracks into top and bottom tracks based on
+ // the track cluster. Filter out tracks with no clusters.
+ List<ReconstructedParticle> topTracks = new ArrayList<ReconstructedParticle>();
+ List<ReconstructedParticle> botTracks = new ArrayList<ReconstructedParticle>();
+ trackLoop:
+ for(ReconstructedParticle track : trackList) {
+ // Check if the track has a cluster. If not, skip it.
+ if(track.getClusters().isEmpty()) {
+ continue trackLoop;
+ }
+
+ // If the track doesn't have actual tracks, skip it.
+ if(track.getTracks().isEmpty()) {
+ continue trackLoop;
+ }
+
+ // Check if the track cluster has already seen.
+ Cluster trackCluster = track.getClusters().get(0);
+ if(clusterSet.contains(trackCluster)) {
+ continue trackLoop;
+ }
+
+ // If the track has a unique cluster, add it to the proper
+ // list based on the cluster y-index.
+ clusterSet.add(trackCluster);
+ if(TriggerModule.getClusterYIndex(trackCluster) > 0) {
+ topTracks.add(track);
+ } else {
+ botTracks.add(track);
+ }
+ }
+
+ // Form all top/bottom pairs with the unique tracks.
+ List<ReconstructedParticle[]> pairList = new ArrayList<ReconstructedParticle[]>();
+ for(ReconstructedParticle topTrack : topTracks) {
+ for(ReconstructedParticle botTrack : botTracks) {
+ pairList.add(new ReconstructedParticle[] { topTrack, botTrack });
+ }
+ }
+
+ // Return the result.
+ return pairList;
+ }
+
+ /**
+ * Gets a list track pairs that meet the trident condition defined
+ * using tracks with matched calorimeter clusters. A pair meets the
+ * cluster/track matched trident condition is it meets the following:
+ * <ul><li>Both tracks have matched clusters.</li>
+ * <li>Has one positive track.</li>
+ * <li>Has one negative track.</li>
+ * <li>Clusters have a time coincidence of 2.5 ns or less.</li>
+ * <li>The electron momentum is below 900 MeV.</li></ul>
+ * @param pairList - A <code>List</code> collection of parameterized
+ * type <code>ReconstructedParticle[]</code> containing all valid
+ * top/bottom pairs of tracks with matched clusters. These will be
+ * tested to see if they meet the process criteria.
+ * @return Returns a list containing pairs of tracks that meet the
+ * trident condition.
+ */
+ private final List<ReconstructedParticle[]> getTridentTracksCTMatched(List<ReconstructedParticle[]> pairList) {
+ // Store the set of track pairs that meet the trident condition.
+ List<ReconstructedParticle[]> tridentTracks = new ArrayList<ReconstructedParticle[]>();
+
+ // Loop over the filtered pair list and apply the trident
+ // condition test.
+ tridentLoop:
+ for(ReconstructedParticle[] pair : pairList) {
+ // There must be one positive and one negative track.
+ ReconstructedParticle electron = null;
+ ReconstructedParticle positron = null;
+ if(pair[0].getCharge() > 0) { positron = pair[0]; }
+ else if(pair[1].getCharge() > 0) { positron = pair[1]; }
+ if(pair[0].getCharge() < 0) { electron = pair[0]; }
+ else if(pair[1].getCharge() < 0) { electron = pair[1]; }
+ if(electron == null || positron == null) {
+ continue tridentLoop;
+ }
+
+ // Make sure that the clusters are not the same. This should
+ // not actually ever be possible...
+ if(pair[0].getClusters().get(0) == pair[1].getClusters().get(0)) {
+ continue tridentLoop;
+ }
+
+ // The clusters must within a limited time window.
+ Cluster[] trackClusters = { pair[0].getClusters().get(0), pair[1].getClusters().get(0) };
+ if(TriggerModule.getValueTimeCoincidence(trackClusters) > timeCoincidence) {
+ continue tridentLoop;
+ }
+
+ // Require that the electron in the pair have an energy
+ // below 900 MeV to exclude elastic electrons.
+ if(electron.getMomentum().magnitude() >= 0.900) {
+ continue tridentLoop;
+ }
+
+ // If all the above conditions are met, the pair is to be
+ // considered a trident pair. Add it to the list.
+ tridentTracks.add(pair);
+ }
+
+ // Return the list of pairs that passed the condition.
+ return tridentTracks;
+ }
+
+ /**
+ * Gets a list track pairs that meet the Møller condition defined
+ * using tracks with matched calorimeter clusters. A pair meets the
+ * cluster/track matched Møller condition is it meets the following:
+ * <ul><li>Both tracks have matched clusters.</li>
+ * <li>Both tracks are negative.</li>
+ * <li>Clusters have a time coincidence of 2.5 ns or less.</li>
+ * <li>The electron momenta are below 900 MeV.</li>
+ * <li>The momentum sum of the tracks is in the range <code>800 MeV
+ * ⤠p1 + p2 ⤠1500 MeV</li></ul>
+ * @param pairList - A <code>List</code> collection of parameterized
+ * type <code>ReconstructedParticle[]</code> containing all valid
+ * top/bottom pairs of tracks with matched clusters. These will be
+ * tested to see if they meet the process criteria.
+ * @return Returns a list containing pairs of tracks that meet the
+ * Møller condition.
+ */
+ private final List<ReconstructedParticle[]> getMøllerTracksCTMatched(List<ReconstructedParticle[]> pairList) {
+ // Store the set of track pairs that meet the Møller condition.
+ List<ReconstructedParticle[]> møllerTracks = new ArrayList<ReconstructedParticle[]>();
+
+ // Loop over the filtered pair list and apply the Møller
+ // condition test.
+ møllerLoop:
+ for(ReconstructedParticle[] pair : pairList) {
+ // Both tracks must be negatively charged.
+ if(pair[0].getCharge() > 0 || pair[1].getCharge() > 0) {
+ continue møllerLoop;
+ }
+
+ // The clusters must within a limited time window.
+ Cluster[] trackClusters = { pair[0].getClusters().get(0), pair[1].getClusters().get(0) };
+ if(TriggerModule.getValueTimeCoincidence(trackClusters) > timeCoincidence) {
+ continue møllerLoop;
+ }
+
+ // Require that the electrons in the pair have energies
+ // below 900 MeV to exclude elastic electrons.
+ if(pair[0].getMomentum().magnitude() > 0.900 || pair[1].getMomentum().magnitude() > 0.900) {
+ continue møllerLoop;
+ }
+
+ // Require that the energy of the pair be within a range
+ // that is sufficiently "Møller-like."
+ double momentumSum = VecOp.add(pair[0].getMomentum(), pair[1].getMomentum()).magnitude();
+ if(momentumSum < 0.800 || momentumSum > 1.500) {
+ continue møllerLoop;
+ }
+
+ // If all the above conditions are met, the pair is to be
+ // considered a trident pair. Add it to the list.
+ møllerTracks.add(pair);
+ }
+
+ // Return the list of pairs that passed the condition.
+ return møllerTracks;
+ }
+
+ /**
+ * Calculates the approximate invariant mass for a pair of tracks
+ * from their momentum. This assumes that the particles are either
+ * electrons or positrons, and thusly have a sufficiently small
+ * mass term that it can be safely excluded.
+ * @param pair - The track pair for which to calculate the invariant
+ * mass.
+ * @return Returns the approximate invariant mass in units of GeV.
+ */
+ private static final double getInvariantMass(ReconstructedParticle[] pair) {
+ // Get the momentum squared.
+ double p2 = Math.pow(pair[0].getMomentum().magnitude() + pair[1].getMomentum().magnitude(), 2);
+
+ // Get the remaining terms.
+ double xPro = pair[0].getMomentum().x() + pair[1].getMomentum().x();
+ double yPro = pair[0].getMomentum().y() + pair[1].getMomentum().y();
+ double zPro = pair[0].getMomentum().z() + pair[1].getMomentum().z();
+
+ // Calculate the invariant mass.
+ return Math.sqrt(p2 - Math.pow(xPro, 2) - Math.pow(yPro, 2) - Math.pow(zPro, 2));
+ }
+}
+// [log in to unmask]
Modified: java/trunk/users/src/main/java/org/hps/users/kmccarty/plots/formatter/TriggerPlotsFormat.java
=============================================================================
--- java/trunk/users/src/main/java/org/hps/users/kmccarty/plots/formatter/TriggerPlotsFormat.java (original)
+++ java/trunk/users/src/main/java/org/hps/users/kmccarty/plots/formatter/TriggerPlotsFormat.java Tue Oct 20 18:57:00 2015
@@ -57,22 +57,23 @@
*/
public static void main(String[] args) throws IOException {
// Define the root directory for the plots.
- String rootDir = "D:\\cygwin64\\home\\Kyle\\aprime-plots\\";
+ String rootDir = "D:\\cygwin64\\home\\Kyle\\beam-plots\\base\\";
+ //String rootDir = "D:\\cygwin64\\home\\Kyle\\aprime-plots\\base\\readout-plots\\";
// Define the new name of the file containing the trigger plots.
String[] plotFile = {
- //rootDir + "background-ana_triggerPlots.aida"
- rootDir + "15-MeV\\compiled-plots.aida",
- rootDir + "20-MeV\\compiled-plots.aida",
- rootDir + "30-MeV\\compiled-plots.aida",
- rootDir + "40-MeV\\compiled-plots.aida",
- rootDir + "50-MeV\\compiled-plots.aida"
+ rootDir + "compiled-plots.aida"
+ //rootDir + "15-MeV\\compiled-plots.aida",
+ //rootDir + "20-MeV\\compiled-plots.aida",
+ //rootDir + "30-MeV\\compiled-plots.aida",
+ //rootDir + "40-MeV\\compiled-plots.aida",
+ //rootDir + "50-MeV\\compiled-plots.aida"
};
// Define the names of each plot. This will be used for the
// legend in the case of multiple plots.
String[] treeName = {
- //"Background",
+ "Background",
"15 MeV A'",
"20 MeV A'",
"30 MeV A'",
@@ -82,13 +83,13 @@
// Define the color style for the plots.
ColorStyle[] dataColorStyle = {
- //ColorStyle.GREY,
+ ColorStyle.GREY,
ColorStyle.MS_GREEN,
ColorStyle.MS_BLUE,
ColorStyle.MS_ORANGE,
ColorStyle.MS_RED,
+ ColorStyle.TEAL,
ColorStyle.CRIMSON,
- ColorStyle.TEAL,
ColorStyle.FOREST
};
|