Author: [log in to unmask]
Date: Wed Oct 21 12:55:14 2015
New Revision: 3867
Log:
Updated trident and Moller analysis driver to include more selection methods.
Modified:
java/trunk/users/src/main/java/org/hps/users/kmccarty/TriggerProcessAnalysisDriver.java
Modified: java/trunk/users/src/main/java/org/hps/users/kmccarty/TriggerProcessAnalysisDriver.java
=============================================================================
--- java/trunk/users/src/main/java/org/hps/users/kmccarty/TriggerProcessAnalysisDriver.java (original)
+++ java/trunk/users/src/main/java/org/hps/users/kmccarty/TriggerProcessAnalysisDriver.java Wed Oct 21 12:55:14 2015
@@ -9,10 +9,14 @@
import java.util.List;
import java.util.Set;
+import org.hps.recon.tracking.TrackType;
+import org.hps.recon.tracking.TrackUtils;
import org.hps.record.triggerbank.TriggerModule;
import org.lcsim.event.Cluster;
import org.lcsim.event.EventHeader;
import org.lcsim.event.ReconstructedParticle;
+import org.lcsim.event.RelationalTable;
+import org.lcsim.event.Track;
import org.lcsim.util.Driver;
import org.lcsim.util.aida.AIDA;
@@ -20,6 +24,8 @@
private int eventsProcessed = 0;
private int møllersProcessed = 0;
private int tridentsProcessed = 0;
+ private int gblMøllersProcessed = 0;
+ private int gblTridentsProcessed = 0;
private double timeCoincidence = 2.5;
private AIDA aida = AIDA.defaultInstance();
private String clusterCollectionName = "EcalClustersCorr";
@@ -38,6 +44,8 @@
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);
+ private IHistogram2D trctmESumCoplanarity = aida.histogram2D("Tridents CTMatched/Cluster Energy Sum vs. Coplanarity", 300, 0.000, 1.500, 360, 0, 360);
+ private IHistogram2D trctmPSumCoplanarity = aida.histogram2D("Tridents CTMatched/Track Momentum Sum vs. Coplanarity", 300, 0.000, 1.500, 360, 0, 360);
// 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);
@@ -50,6 +58,29 @@
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);
+ private IHistogram2D møctmESumCoplanarity = aida.histogram2D("Møller CTMatched/Cluster Energy Sum vs. Coplanarity", 300, 0.000, 1.500, 360, 0, 360);
+ private IHistogram2D møctmPSumCoplanarity = aida.histogram2D("Møller CTMatched/Track Momentum Sum vs. Coplanarity", 300, 0.000, 1.500, 360, 0, 360);
+
+ // Define the Møller track-only condition plots.
+ private IHistogram1D møgblTimeCoincidence = aida.histogram1D("Møller Track-Only/Time Coincidence", 100, -4, 4);
+ private IHistogram1D møgblInvariantMass = aida.histogram1D("Møller Track-Only/Invariant Mass", 140, 0.0, 0.070);
+ private IHistogram1D møgblInstancesInEvent = aida.histogram1D("Møller Track-Only/Instances in Event", 9, 0.5, 9.5);
+ private IHistogram1D møgblMomentumSum1D = aida.histogram1D("Møller Track-Only/Track Momentum Sum", 150, 0.000, 1.500);
+ private IHistogram1D møgblElectronMomentum = aida.histogram1D("Møller Track-Only/Electron Track Momentum", 150, 0.000, 1.500);
+ private IHistogram2D møgblClusterPosition = aida.histogram2D("Møller Track-Only/Extrapolated Track Position", 138, -23, 23, 33, -5.5, 5.5);
+ private IHistogram2D møgblMomentumSum2D = aida.histogram2D("Møller Track-Only/Track Momentum Sum 2D", 300, 0.000, 1.500, 300, 0.000, 1.500);
+ private IHistogram2D møgblPSumCoplanarity = aida.histogram2D("Møller Track-Only/Track Momentum Sum vs. Coplanarity", 300, 0.000, 1.500, 360, 0, 360);
+
+ // Define the GBL trident condition plots.
+ private IHistogram1D trgblInvariantMass = aida.histogram1D("Tridents Track-Only/Invariant Mass", 140, 0.0, 0.070);
+ private IHistogram1D trgblInstancesInEvent = aida.histogram1D("Tridents Track-Only/Instances in Event", 9, 0.5, 9.5);
+ private IHistogram1D trgblMomentumSum1D = aida.histogram1D("Tridents Track-Only/Track Momentum Sum", 150, 0.000, 1.500);
+ private IHistogram1D trgblElectronMomentum = aida.histogram1D("Tridents Track-Only/Electron Track Momentum", 150, 0.000, 1.500);
+ private IHistogram1D trgblPositronMomentum = aida.histogram1D("Tridents Track-Only/Positron Track Momentum", 150, 0.000, 1.500);
+ private IHistogram1D trgblTimeCoincidence = aida.histogram1D("Tridents Track-Only/Time Coincidence", 100, -4, 4);
+ private IHistogram2D trgblClusterPosition = aida.histogram2D("Tridents Track-Only/Extrapolated Track Position", 46, -23, 23, 11, -5.5, 5.5);
+ private IHistogram2D trgblMomentumSum2D = aida.histogram2D("Tridents Track-Only/Track Momentum Sum 2D", 300, 0.000, 1.500, 300, 0.000, 1.500);
+ private IHistogram2D trgblPSumCoplanarity = aida.histogram2D("Tridents Track-Only/Track Momentum Sum vs. Coplanarity", 300, 0.000, 1.500, 360, 0, 360);
@Override
public void endOfData() {
@@ -59,10 +90,19 @@
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("\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");
+ System.out.println("\tRate :: " + (tridentsProcessed * scale) + " Hz");
+
+ System.out.println("Processed " + gblMøllersProcessed + " track-only Møller events");
+ System.out.println("\tAcceptance :: " + (100.0 * gblMøllersProcessed / eventsProcessed) + "%");
+ System.out.println("\tRate :: " + (gblMøllersProcessed * scale) + " Hz");
+
+ System.out.println("Processed " + gblTridentsProcessed + " Rafo trident events");
+ System.out.println("\tAcceptance :: " + (100.0 * gblTridentsProcessed / eventsProcessed) + "%");
+ System.out.println("\tRate :: " + (gblTridentsProcessed * scale) + " Hz");
// Scale the cluster-track matched Møller plots.
møctmInvariantMass.scale(scale);
@@ -123,16 +163,21 @@
List<Cluster> clusterList = event.get(Cluster.class, clusterCollectionName);
// Get cluster-track matched top/bottom pairs.
- List<ReconstructedParticle[]> ctMatchedPairs = getTopBottomTracksCTMatched(trackList);
+ List<ReconstructedParticle[]> gblMatchedPairs = getTopBottomTracksGBL(trackList);
+ 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);
+ List<ReconstructedParticle[]> møllers = getMøllerTracksCTMatched(ctMatchedPairs);
+ List<ReconstructedParticle[]> møllersGBL = getMøllerTracksGBL(gblMatchedPairs, event);
+ List<ReconstructedParticle[]> tridents = getTridentTracksCTMatched(ctMatchedPairs);
+ List<ReconstructedParticle[]> tridentsGBL = getTridentClustersGBL(gblMatchedPairs, TriggerModule.getTopBottomPairs(clusterList, Cluster.class), event);
// Track how many events had tridents and Møllers.
if(!møllers.isEmpty()) { møllersProcessed++; }
if(!tridents.isEmpty()) { tridentsProcessed++; }
+ if(!møllersGBL.isEmpty()) { gblMøllersProcessed++; }
+ if(!tridentsGBL.isEmpty()) { gblTridentsProcessed++; }
// Produce Møller cluster-track matched plots.
møctmInstancesInEvent.fill(møllers.size());
@@ -145,6 +190,7 @@
møctmElectronEnergy.fill(trackClusters[1].getEnergy());
møctmEnergySum1D.fill(TriggerModule.getValueEnergySum(trackClusters));
møctmEnergySum2D.fill(trackClusters[0].getEnergy(), trackClusters[1].getEnergy());
+ møctmESumCoplanarity.fill(TriggerModule.getValueEnergySum(trackClusters), getCalculatedCoplanarity(trackClusters));
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]));
@@ -155,6 +201,8 @@
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());
+ møctmPSumCoplanarity.fill(VecOp.add(pair[0].getMomentum(), pair[1].getMomentum()).magnitude(),
+ getCalculatedCoplanarity(new Track[] { pair[0].getTracks().get(0), pair[1].getTracks().get(0) }));
}
// Produce trident cluster-track matched plots.
@@ -172,8 +220,9 @@
// Populate the cluster plots.
trctmElectronEnergy.fill(electronCluster.getEnergy());
trctmPositronEnergy.fill(positronCluster.getEnergy());
+ trctmEnergySum2D.fill(pair[0].getEnergy(), pair[1].getEnergy());
trctmEnergySum1D.fill(TriggerModule.getValueEnergySum(trackClusters));
- trctmEnergySum2D.fill(pair[0].getEnergy(), pair[1].getEnergy());
+ trctmESumCoplanarity.fill(TriggerModule.getValueEnergySum(trackClusters), getCalculatedCoplanarity(trackClusters));
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]));
@@ -184,7 +233,104 @@
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());
- }
+ trctmPSumCoplanarity.fill(VecOp.add(pair[0].getMomentum(), pair[1].getMomentum()).magnitude(),
+ getCalculatedCoplanarity(new Track[] { pair[0].getTracks().get(0), pair[1].getTracks().get(0) }));
+ }
+
+ // Produce the Møller track-only plots.
+ møgblInstancesInEvent.fill(møllersGBL.size());
+ RelationalTable<?, ?> hitToStrips = TrackUtils.getHitToStripsTable(event);
+ RelationalTable<?, ?> hitToRotated = TrackUtils.getHitToRotatedTable(event);
+ for(ReconstructedParticle pair[] : møllersGBL) {
+ // Get the tracks and track times.
+ Track[] tracks = { pair[0].getTracks().get(0), pair[1].getTracks().get(0) };
+ double times[] = {
+ TrackUtils.getTrackTime(tracks[0], hitToStrips, hitToRotated),
+ TrackUtils.getTrackTime(tracks[1], hitToStrips, hitToRotated)
+ };
+
+ // Fill the plots.
+ møgblTimeCoincidence.fill(times[0] - times[1]);
+ møgblInvariantMass.fill(getInvariantMass(pair));
+ møgblElectronMomentum.fill(pair[0].getMomentum().magnitude());
+ møgblElectronMomentum.fill(pair[1].getMomentum().magnitude());
+ møgblMomentumSum1D.fill(VecOp.add(pair[0].getMomentum(), pair[1].getMomentum()).magnitude());
+ møgblMomentumSum2D.fill(pair[0].getMomentum().magnitude(), pair[1].getMomentum().magnitude());
+ møgblClusterPosition.fill(TrackUtils.getTrackPositionAtEcal(tracks[0]).x(), TrackUtils.getTrackPositionAtEcal(tracks[0]).y());
+ møgblClusterPosition.fill(TrackUtils.getTrackPositionAtEcal(tracks[1]).x(), TrackUtils.getTrackPositionAtEcal(tracks[1]).y());
+ møgblPSumCoplanarity.fill(VecOp.add(pair[0].getMomentum(), pair[1].getMomentum()).magnitude(),
+ getCalculatedCoplanarity(new Track[] { pair[0].getTracks().get(0), pair[1].getTracks().get(0) }));
+ }
+
+ // Produce track-only trident plots.
+ trgblInstancesInEvent.fill(tridentsGBL.size());
+ for(ReconstructedParticle[] pair : tridentsGBL) {
+ // Get the tracks and track times.
+ Track[] tracks = { pair[0].getTracks().get(0), pair[1].getTracks().get(0) };
+ double times[] = {
+ TrackUtils.getTrackTime(tracks[0], hitToStrips, hitToRotated),
+ TrackUtils.getTrackTime(tracks[1], hitToStrips, hitToRotated)
+ };
+
+ // Fill the plots.
+ trgblTimeCoincidence.fill(times[0] - times[1]);
+ trgblInvariantMass.fill(getInvariantMass(pair));
+ trgblElectronMomentum.fill(pair[0].getMomentum().magnitude());
+ trgblElectronMomentum.fill(pair[1].getMomentum().magnitude());
+ trgblMomentumSum1D.fill(VecOp.add(pair[0].getMomentum(), pair[1].getMomentum()).magnitude());
+ trgblMomentumSum2D.fill(pair[0].getMomentum().magnitude(), pair[1].getMomentum().magnitude());
+ trgblClusterPosition.fill(TrackUtils.getTrackPositionAtEcal(tracks[0]).x(), TrackUtils.getTrackPositionAtEcal(tracks[0]).y());
+ trgblClusterPosition.fill(TrackUtils.getTrackPositionAtEcal(tracks[1]).x(), TrackUtils.getTrackPositionAtEcal(tracks[1]).y());
+ trgblPSumCoplanarity.fill(VecOp.add(pair[0].getMomentum(), pair[1].getMomentum()).magnitude(),
+ getCalculatedCoplanarity(new Track[] { pair[0].getTracks().get(0), pair[1].getTracks().get(0) }));
+ }
+ }
+
+ /**
+ * Gets a list of all possible GBL top/bottom track pairs. These
+ * tracks are not guaranteed to have a matched cluster.
+ * @param trackList - A list of all possible tracks.
+ * @return Returns a list of track pairs.
+ */
+ private static final List<ReconstructedParticle[]> getTopBottomTracksGBL(List<ReconstructedParticle> trackList) {
+ // Separate the tracks into top and bottom tracks based on
+ // the value of tan(Î). Use only GBL tracks to avoid track
+ // duplication.
+ List<ReconstructedParticle> topTracks = new ArrayList<ReconstructedParticle>();
+ List<ReconstructedParticle> botTracks = new ArrayList<ReconstructedParticle>();
+ trackLoop:
+ for(ReconstructedParticle track : trackList) {
+ // Require that the ReconstructedParticle contain an actual
+ // Track object.
+ if(track.getTracks().isEmpty()) {
+ continue trackLoop;
+ }
+
+ // Ignore tracks that are not GBL tracks.
+ if(!TrackType.isGBL(track.getType())) {
+ continue trackLoop;
+ }
+
+ // If the above tests pass, the ReconstructedParticle has
+ // a track and is also a GBL track. Separate it into either
+ // a top or a bottom track based on its tan(Î) value.
+ if(track.getTracks().get(0).getTrackStates().get(0).getTanLambda() > 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;
}
/**
@@ -243,6 +389,81 @@
// Return the result.
return pairList;
+ }
+
+ private final List<ReconstructedParticle[]> getTridentClustersGBL(List<ReconstructedParticle[]> pairList, List<Cluster[]> clusterList, EventHeader event) {
+ // Store the set of track pairs that meet the trident condition.
+ List<ReconstructedParticle[]> tridentTracks = new ArrayList<ReconstructedParticle[]>();
+
+ // Extract track relational tables from the event object.
+ RelationalTable<?, ?> hitToStrips = TrackUtils.getHitToStripsTable(event);
+ RelationalTable<?, ?> hitToRotated = TrackUtils.getHitToRotatedTable(event);
+
+ // Tracks will not be considered for trident analysis unless there
+ // is at least one top/bottom cluster pair within the time window.
+ boolean passesClusterCondition = false;
+ tridentClusterLoop:
+ for(Cluster[] pair : clusterList) {
+ // Ignore clusters that are too far apart temporally.
+ if(TriggerModule.getValueTimeCoincidence(pair) > timeCoincidence) {
+ continue tridentClusterLoop;
+ }
+
+ // Require that the cluster pair be top/bottom.
+ boolean hasTop = TriggerModule.getClusterYIndex(pair[0]) > 0 || TriggerModule.getClusterYIndex(pair[1]) > 0;
+ boolean hasBot = TriggerModule.getClusterYIndex(pair[0]) < 0 || TriggerModule.getClusterYIndex(pair[1]) < 0;
+ if(!hasTop || !hasBot) {
+ continue tridentClusterLoop;
+ }
+
+ // If the cluster passes, mark that it has done so and skip
+ // the rest. Only one pair need pass.
+ passesClusterCondition = true;
+ break tridentClusterLoop;
+ }
+
+ // If no cluster pair passed the cluster condition, no tracks
+ // are allowed to pass either.
+ if(!passesClusterCondition) {
+ return tridentTracks;
+ }
+
+ // Next, check the track pair list. A track pair must have a
+ // positive and a negative track and must also be within the
+ // time coincidence window.
+ tridentTrackLoop:
+ for(ReconstructedParticle[] pair : pairList) {
+ // Check that there is at least one positive and one negative
+ // track in the pair.
+ boolean hasPositive = pair[0].getCharge() > 0 || pair[1].getCharge() > 0;
+ boolean hasNegative = pair[0].getCharge() < 0 || pair[1].getCharge() < 0;
+ if(hasPositive && hasNegative) {
+ break tridentTrackLoop;
+ }
+
+ // Check that the track pair passes the time cut.
+ double times[] = {
+ TrackUtils.getTrackTime(pair[0].getTracks().get(0), hitToStrips, hitToRotated),
+ TrackUtils.getTrackTime(pair[1].getTracks().get(0), hitToStrips, hitToRotated)
+ };
+
+ if(Math.abs(times[0] - times[1]) > timeCoincidence) {
+ continue tridentTrackLoop;
+ }
+
+ // Require that the negative track have less than 900 MeV
+ // momentum to exclude elastic electrons.
+ if(pair[0].getCharge() < 0 && pair[0].getMomentum().magnitude() > 0.900
+ || pair[1].getCharge() < 0 && pair[1].getMomentum().magnitude() > 0.900) {
+ continue tridentTrackLoop;
+ }
+
+ // If the track passes both, it is considered a trident pair.
+ tridentTracks.add(pair);
+ }
+
+ // Return the resultant pairs.
+ return tridentTracks;
}
/**
@@ -305,6 +526,55 @@
// Return the list of pairs that passed the condition.
return tridentTracks;
+ }
+
+ private final List<ReconstructedParticle[]> getMøllerTracksGBL(List<ReconstructedParticle[]> pairList, EventHeader event) {
+ // Store the set of track pairs that meet the Møller condition.
+ List<ReconstructedParticle[]> møllerTracks = new ArrayList<ReconstructedParticle[]>();
+
+ // Extract track relational tables from the event object.
+ RelationalTable<?, ?> hitToStrips = TrackUtils.getHitToStripsTable(event);
+ RelationalTable<?, ?> hitToRotated = TrackUtils.getHitToRotatedTable(event);
+
+ // 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.
+ double times[] = {
+ TrackUtils.getTrackTime(pair[0].getTracks().get(0), hitToStrips, hitToRotated),
+ TrackUtils.getTrackTime(pair[1].getTracks().get(0), hitToStrips, hitToRotated)
+ };
+
+ if(Math.abs(times[0] - times[1]) > 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;
}
/**
@@ -386,5 +656,56 @@
// Calculate the invariant mass.
return Math.sqrt(p2 - Math.pow(xPro, 2) - Math.pow(yPro, 2) - Math.pow(zPro, 2));
}
+
+ /**
+ * Calculates the coplanarity angle between two points, specified
+ * by a double array. The array must be of the format (x, y, z).
+ * @param position - The first position array.
+ * @param otherPosition - The second position array.
+ * @return Returns the coplanarity angle between the points in units
+ * of degrees.
+ */
+ private static final double getCalculatedCoplanarity(double[] position, double[] otherPosition) {
+ // Define the x- and y-coordinates of the clusters as well as
+ // calorimeter center.
+ final double ORIGIN_X = 42.52;
+ double x[] = { position[0], otherPosition[0] };
+ double y[] = { position[1], otherPosition[1] };
+
+ // Get the cluster angles.
+ double[] clusterAngle = new double[2];
+ for(int i = 0; i < 2; i++) {
+ clusterAngle[i] = Math.atan2(y[i], x[i] - ORIGIN_X) * 180 / Math.PI;
+ if(clusterAngle[i] <= 0) { clusterAngle[i] += 360; }
+ }
+
+ // Calculate the coplanarity cut value.
+ double clusterDiff = clusterAngle[0] - clusterAngle[1];
+ return clusterDiff > 0 ? clusterDiff : clusterDiff + 360;
+ }
+
+ /**
+ * Calculates the coplanarity angle of a pair of clusters.
+ * @param pair - The pair of clusters for which to calculate the
+ * coplanarity angle.
+ * @return Returns the coplanarity angle between the two clusters
+ * in degrees.
+ */
+ private static final double getCalculatedCoplanarity(Cluster[] pair) {
+ return getCalculatedCoplanarity(pair[0].getPosition(), pair[1].getPosition());
+ }
+
+ /**
+ * Calculates the coplanarity angle of a pair of tracks. The track
+ * is extrapolated to the calorimeter face and its position there
+ * used for the arguments in the calculation.
+ * @param pair - The pair of tracks for which to calculate the
+ * coplanarity angle.
+ * @return Returns the coplanarity angle between the two tracks
+ * in degrees.
+ */
+ private static final double getCalculatedCoplanarity(Track[] pair) {
+ return getCalculatedCoplanarity(TrackUtils.getTrackPositionAtEcal(pair[0]).v(), TrackUtils.getTrackPositionAtEcal(pair[1]).v());
+ }
}
// [log in to unmask]
|