Author: [log in to unmask]
Date: Thu Oct 8 18:09:02 2015
New Revision: 3817
Log:
Added Calorimeter-only cuts so we can study tracking
Modified:
java/trunk/recon/src/main/java/org/hps/recon/filtering/MollerCandidateFilter.java
java/trunk/steering-files/src/main/resources/org/hps/steering/production/MollerCandidateFilter.lcsim
Modified: java/trunk/recon/src/main/java/org/hps/recon/filtering/MollerCandidateFilter.java
=============================================================================
--- java/trunk/recon/src/main/java/org/hps/recon/filtering/MollerCandidateFilter.java (original)
+++ java/trunk/recon/src/main/java/org/hps/recon/filtering/MollerCandidateFilter.java Thu Oct 8 18:09:02 2015
@@ -1,18 +1,30 @@
package org.hps.recon.filtering;
import static java.lang.Math.abs;
+import java.util.ArrayList;
import java.util.List;
+import org.hps.conditions.database.DatabaseConditionsManager;
import org.hps.record.epics.EpicsData;
+import org.lcsim.event.CalorimeterHit;
+import org.lcsim.event.Cluster;
import org.lcsim.event.EventHeader;
import org.lcsim.event.ReconstructedParticle;
+import org.lcsim.geometry.Detector;
+import org.lcsim.geometry.subdetector.HPSEcal3;
+import org.lcsim.geometry.subdetector.HPSEcal3.NeighborMap;
/**
- * Class to strip off Moller candidates. Currently defined as: e- e- events with
- * tracks matched to clusters. Neither electron can be a full-energy candidate
- * (momentum less than _fullEnergyCut [0.85GeV]) but the momentum sum must be
- * consistent with the beam energy (greater than _mollerMomentumSumMin and less
- * than _mollerMomentumSumMax). The Ecal cluster times must be within _timingCut
+ * Class to strip off Moller candidates.
+ *
+ * Currently the tight selection is defined as: e- e- events with tracks matched
+ * to each cluster. Neither electron can be a full-energy candidate (momentum
+ * less than _fullEnergyCut [0.85GeV]) but the momentum sum must be consistent
+ * with the beam energy (greater than _mollerMomentumSumMin and less than
+ * _mollerMomentumSumMax). The Ecal cluster times must be within _timingCut
* [2.5ns] of each other.
+ *
+ * One can also set calorimeter-only cuts if one is interested in understanding
+ * tracking issues.
*
* @author Norman A Graf
*
@@ -21,14 +33,41 @@
public class MollerCandidateFilter extends EventReconFilter
{
+ private boolean _keepEpicsDataEvents = false;
+
+ // the following are for the tight cuts
+ private boolean _tight = false;
private String _mollerCandidateCollectionName = "TargetConstrainedMollerCandidates";
private double _mollerMomentumSumMin = 0.85;
private double _mollerMomentumSumMax = 1.3;
private double _fullEnergyCut = 0.85;
- private double _clusterTimingCut = 2.5;
-
- private boolean _tight = false;
- private boolean _keepEpicsDataEvents = false;
+ //the following are for the calorimeter cluster cuts
+ private String _mollerCandidateClusterCollectionName = "EcalClustersCorr";
+ //first, single cluster cuts
+ private double _clusterTimeLo = 40;
+ private double _clusterTimeHi = 48;
+ private double _clusterMaxX = 0.;
+ // pair cuts
+ private double _clusterXSumLo = -175.;
+ private double _clusterXSumHi = -145.;
+ private double _clusterXDiffLo = -80.;
+ private double _clusterXDiffHi = 80.;
+ private double _clusterESumLo = 0.85;
+ private double _clusterESumHi = 1.1;
+ private double _clusterEDiffLo = -0.3;
+ private double _clusterEDiffHi = 0.3;
+
+ private HPSEcal3 ecal;
+ private NeighborMap neighborMap;
+
+ private double _clusterDeltaTimeCut = 2.5;
+
+ @Override
+ protected void detectorChanged(Detector detector)
+ {
+ ecal = (HPSEcal3) DatabaseConditionsManager.getInstance().getDetectorObject().getSubdetector("Ecal");
+ neighborMap = ecal.getNeighborMap();
+ }
@Override
protected void process(EventHeader event)
@@ -42,64 +81,129 @@
return;
}
}
- if (!event.hasCollection(ReconstructedParticle.class, _mollerCandidateCollectionName)) {
- skipEvent();
- }
- List<ReconstructedParticle> mollerCandidates = event.get(ReconstructedParticle.class, _mollerCandidateCollectionName);
- if (mollerCandidates.size() == 0) {
- skipEvent();
- }
-
- // tight requires ONLY ONE real vertex fit
+ // tight requires two electron final state particles with a vertex fit
if (_tight) {
- if (mollerCandidates.size() != 2) {
+ if (!event.hasCollection(ReconstructedParticle.class, _mollerCandidateCollectionName)) {
skipEvent();
}
- }
-
- for (ReconstructedParticle rp : mollerCandidates) {
-
- ReconstructedParticle e1 = null;
- ReconstructedParticle e2 = null;
-
- List<ReconstructedParticle> electrons = rp.getParticles();
- if (electrons.size() != 2) {
+ List<ReconstructedParticle> mollerCandidates = event.get(ReconstructedParticle.class, _mollerCandidateCollectionName);
+ if (mollerCandidates.size() == 0) {
skipEvent();
}
- // require both electrons to be associated with an ECal cluster
- e1 = electrons.get(0);
- if (e1.getClusters().size() == 0) {
+ for (ReconstructedParticle rp : mollerCandidates) {
+ ReconstructedParticle e1 = null;
+ ReconstructedParticle e2 = null;
+ List<ReconstructedParticle> electrons = rp.getParticles();
+ if (electrons.size() != 2) {
+ skipEvent();
+ }
+ // require both electrons to be associated with an ECal cluster
+ e1 = electrons.get(0);
+ if (e1.getClusters().size() == 0) {
+ skipEvent();
+ }
+ e2 = electrons.get(1);
+ if (e2.getClusters().size() == 0) {
+ skipEvent();
+ }
+ // remove full energy electrons
+ double p1 = e1.getMomentum().magnitude();
+ if (p1 > _fullEnergyCut) {
+ skipEvent();
+ }
+ double p2 = e2.getMomentum().magnitude();
+ if (p2 > _fullEnergyCut) {
+ skipEvent();
+ }
+ // require momentum sum to be approximately the beam energy
+ double pSum = p1 + p2;
+ if (pSum < _mollerMomentumSumMin || pSum > _mollerMomentumSumMax) {
+ skipEvent();
+ }
+ // calorimeter cluster timing cut
+ // first CalorimeterHit in the list is the seed crystal
+ double t1 = e1.getClusters().get(0).getCalorimeterHits().get(0).getTime();
+ double t2 = e2.getClusters().get(0).getCalorimeterHits().get(0).getTime();
+ if (abs(t1 - t2) > _clusterDeltaTimeCut) {
+ skipEvent();
+ }
+ }
+ } // end of tight selection cuts
+ else // apply only calorimeter-based cuts
+ {
+ if (!event.hasCollection(Cluster.class, _mollerCandidateClusterCollectionName)) {
skipEvent();
}
- e2 = electrons.get(1);
- if (e2.getClusters().size() == 0) {
+ List<Cluster> clusters = event.get(Cluster.class, _mollerCandidateClusterCollectionName);
+ List<Cluster> goodClusters = new ArrayList<Cluster>();
+ for (Cluster c : clusters) {
+ // check that cluster is on electron side
+ if (c.getPosition()[0] > _clusterMaxX) {
+ continue;
+ }
+ // check that cluster is in time window
+ CalorimeterHit seedHit = c.getCalorimeterHits().get(0);
+ double t = seedHit.getTime();
+ if (t < _clusterTimeLo || t > _clusterTimeHi) {
+ continue;
+ }
+ // remove edge clusters
+ int nNeighbors = neighborMap.get(seedHit.getCellID()).size();
+ if (nNeighbors < 8) {
+ continue;
+ }
+ } // end of loop looking for good clusters
+ if (goodClusters.size() < 2) {
skipEvent();
}
- // remove full energy electrons
- double p1 = e1.getMomentum().magnitude();
- if (p1 > _fullEnergyCut) {
+ // should now have at least two good clusters, start looking at pairs
+ boolean goodPair = false;
+ out:
+ for (int i = 0; i < goodClusters.size() - 1; ++i) {
+ for (int j = i + 1; j < goodClusters.size(); ++j) {
+ Cluster c1 = goodClusters.get(i);
+ Cluster c2 = goodClusters.get(j);
+ double[] pos1 = c1.getPosition();
+ double[] pos2 = c2.getPosition();
+ // require clusters to be on opposite sides of y=0 (top/bottom)
+ if (pos1[1] * pos2[1] > 0) {
+ continue;
+ }
+ // cut on x position sum
+ if (pos1[0] + pos2[0] < _clusterXSumLo || pos1[0] + pos2[0] > _clusterXSumHi) {
+ continue;
+ }
+ // cut on x position diff
+ // TODO resolve this source of bias (should be abs)
+ if (pos1[0] - pos2[0] < _clusterXDiffLo || pos1[0] - pos2[0] > _clusterXDiffHi) {
+ continue;
+ }
+ // require energy sum to be close to beam energy
+ double e1 = c1.getEnergy();
+ double e2 = c2.getEnergy();
+ if (e1 + e2 < _clusterESumLo || e1 + e2 > _clusterESumHi) {
+ continue;
+ }
+ // require energy difference to be small
+ // TODO resolve this source of bias (should be abs)
+ if (e1 - e2 < _clusterEDiffLo || e1 - e2 > _clusterEDiffHi) {
+ continue;
+ }
+ // require both cluster times to be the same
+ double t1 = c1.getCalorimeterHits().get(0).getTime();
+ double t2 = c2.getCalorimeterHits().get(0).getTime();
+ if (abs(t1 - t2) > _clusterDeltaTimeCut) {
+ continue;
+ }
+ // if we got here we have a good pair
+ goodPair = true;
+ break out;
+ } // end of j loop
+ } // end of i loop
+ if (!goodPair) {
skipEvent();
}
- double p2 = e2.getMomentum().magnitude();
- if (p2 > _fullEnergyCut) {
- skipEvent();
- }
-
- // require momentum sum to be approximately the beam energy
- double pSum = p1 + p2;
- if (pSum < _mollerMomentumSumMin || pSum > _mollerMomentumSumMax) {
- skipEvent();
- }
-
- // calorimeter cluster timing cut
- // first CalorimeterHit in the list is the seed crystal
- double t1 = e1.getClusters().get(0).getCalorimeterHits().get(0).getTime();
- double t2 = e2.getClusters().get(0).getCalorimeterHits().get(0).getTime();
-
- if (abs(t1 - t2) > _clusterTimingCut) {
- skipEvent();
- }
- }
+ }// end of calorimeter-only selection block
incrementEventPassed();
}
@@ -108,9 +212,9 @@
*
* @param d
*/
- public void setClusterTimingCut(double d)
- {
- _clusterTimingCut = d;
+ public void setClusterDeltaTimeCut(double d)
+ {
+ _clusterDeltaTimeCut = d;
}
/**
@@ -164,7 +268,7 @@
{
_tight = b;
}
-
+
/**
* Setting this true keeps ALL events containing EPICS data
*
@@ -174,4 +278,131 @@
{
_keepEpicsDataEvents = b;
}
+
+ // Calorimeter-only selection cuts
+ /**
+ * Name of Moller Candidate Calorimeter Cluster Collection Name
+ *
+ * @param s
+ */
+ public void setMollerCandidateClusterCollectionName(String s)
+ {
+ _mollerCandidateClusterCollectionName = s;
+ }
+
+ // Individual Cluster selection cuts
+ /**
+ * Minimum value for the Cluster time [ns]
+ *
+ * @param d
+ */
+ public void setClusterTimeLo(double d)
+ {
+ _clusterTimeLo = d;
+ }
+
+ /**
+ * Maximum value for the Cluster time [ns]
+ *
+ * @param d
+ */
+ public void setClusterTimeHi(double d)
+ {
+ _clusterTimeHi = d;
+ }
+
+ // position
+ /**
+ * Maximum value for the Cluster x position [mm]
+ *
+ * @param d
+ */
+ public void setClusterMaxX(double d)
+ {
+ _clusterMaxX = d;
+ }
+
+ // Cluster Pair selection cuts
+ //position
+ /**
+ * Minimum value for the Cluster x position sum [mm]
+ *
+ * @param d
+ */
+ public void setClusterXSumLo(double d)
+ {
+ _clusterXSumLo = d;
+ }
+
+ /**
+ * Maximum value for the Cluster x position sum [mm]
+ *
+ * @param d
+ */
+ public void setClusterXSumHi(double d)
+ {
+ _clusterXSumHi = d;
+ }
+
+ /**
+ * Minimum value for the Cluster x position difference [mm]
+ *
+ * @param d
+ */
+ public void setClusterXDiffLo(double d)
+ {
+ _clusterXDiffLo = d;
+ }
+
+ /**
+ * Maximum value for the Cluster x position difference [mm]
+ *
+ * @param d
+ */
+ public void setClusterXDiffHi(double d)
+ {
+ _clusterXDiffHi = d;
+ }
+
+ // energy
+ /**
+ * Minimum value for the Cluster Energy sum [mm]
+ *
+ * @param d
+ */
+ public void setClusterESumLo(double d)
+ {
+ _clusterESumLo = d;
+ }
+
+ /**
+ * Maximum value for the Cluster Energy sum [mm]
+ *
+ * @param d
+ */
+ public void setClusterESumHi(double d)
+ {
+ _clusterESumHi = d;
+ }
+
+ /**
+ * Minimum value for the Cluster Energy difference [mm]
+ *
+ * @param d
+ */
+ public void setClusterEDiffLo(double d)
+ {
+ _clusterEDiffLo = d;
+ }
+
+ /**
+ * Maximum value for the Cluster Energy difference [mm]
+ *
+ * @param d
+ */
+ public void setClusterEDiffHi(double d)
+ {
+ _clusterEDiffHi = d;
+ }
+
}
Modified: java/trunk/steering-files/src/main/resources/org/hps/steering/production/MollerCandidateFilter.lcsim
=============================================================================
--- java/trunk/steering-files/src/main/resources/org/hps/steering/production/MollerCandidateFilter.lcsim (original)
+++ java/trunk/steering-files/src/main/resources/org/hps/steering/production/MollerCandidateFilter.lcsim Thu Oct 8 18:09:02 2015
@@ -24,6 +24,8 @@
<!-- Driver to strip events -->
<driver name="StripEvent"
type="org.hps.recon.filtering.MollerCandidateFilter">
+ <!-- Setting the tight constraint requires two electrons (track+cluster) -->
+ <tightConstraint>true</tightConstraint>
<!-- Name of the Moller Candidate Collection of ReconstriuctedParticles -->
<mollerCandidateCollectionName>TargetConstrainedMollerCandidates</mollerCandidateCollectionName>
<!-- Maximum momentum of each electron, used to remove full energy electrons -->
@@ -32,8 +34,35 @@
<mollerMomentumSumMin>0.85</mollerMomentumSumMin>
<!-- Sum of the two electron momenta should equal the beam energy, this is the high cut -->
<mollerMomentumSumMax>1.3</mollerMomentumSumMax>
+ <!-- Following is for the calorimeter-only cuts -->
+ <!-- Name of Moller Candidate Calorimeter Cluster Collection Name-->
+ <mollerCandidateClusterCollectionName > "EcalClustersCorr" </mollerCandidateClusterCollectionName>
+ <!-- Minimum value for the Cluster time [ns]-->
+ <clusterTimeLo >40. </clusterTimeLo>
+ <!-- Maximum value for the Cluster time [ns]-->
+ <clusterTimeHi > 48. </clusterTimeHi>
+ <!-- Maximum value for the Cluster x position [mm]-->
+ <clusterMaxX > 0. </clusterMaxX>
+ <!-- Cluster Pair cuts -->
+ <!-- Minimum value for the Cluster x position sum [mm]-->
+ <clusterXSumLo > -175. </clusterXSumLo>
+ <!-- Maximum value for the Cluster x position sum [mm]-->
+ <clusterXSumHi > -145. </clusterXSumHi>
+ <!-- Minimum value for the Cluster x position difference [mm]-->
+ <clusterXDiffLo > -80. </clusterXDiffLo>
+ <!-- Maximum value for the Cluster x position difference [mm]-->
+ <clusterXDiffHi > 80. </clusterXDiffHi>
+ <!-- Minimum value for the Cluster Energy sum [mm]-->
+ <clusterESumLo > 0.85 </clusterESumLo>
+ <!-- Maximum value for the Cluster Energy sum [mm]-->
+ <clusterESumHi > 1.1 </clusterESumHi>
+ <!-- Minimum value for the Cluster Energy difference [mm]-->
+ <clusterEDiffLo > -0.3 </clusterEDiffLo>
+ <!-- Maximum value for the Cluster Energy difference [mm]-->
+ <clusterEDiffHi > 0.3 </clusterEDiffHi>
+
<!-- Maximum difference in the ECal cluster times -->
- <clusterTimingCut>2.5</clusterTimingCut>
+ <clusterDeltaTimeCut>2.5</clusterDeltaTimeCut>
<!-- Setting this true keeps ALL events containing EPICS data -->
<keepEpicsDataEvents>true</keepEpicsDataEvents>
</driver>
|