hps-java/src/main/java/org/lcsim/hps/recon/ecal
diff -N HPSEcalFlashTrigger.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ HPSEcalFlashTrigger.java 7 Oct 2011 20:56:41 -0000 1.1
@@ -0,0 +1,412 @@
+package org.lcsim.hps.recon.ecal;
+
+//--- Java ---//
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+//--- org.lcsim ---//
+import org.lcsim.event.Cluster;
+import org.lcsim.event.EventHeader;
+import org.lcsim.util.Driver;
+
+
+//--- hps-java ---//
+import org.lcsim.hps.users.omoreno.HPSTrigger;
+
+/**
+ * Heavy Photon Search ECal Flash Trigger
+ *
+ * @author Omar Moreno <[log in to unmask]>
+ * @version $Id: HPSEcalFlashTrigger.java,v 1.1 2011/10/07 20:56:41 omoreno Exp $
+ */
+public class HPSEcalFlashTrigger extends Driver
+{
+ // The HPS ECal Clusterer
+ HPSEcal3Clusterer ecalClusterer;
+
+ String ecalRawHitsCollectionName = "EcalHits";
+ String ecalClusterCollectionName = "EcalClusters";
+
+ // A list to contain all cluster pairs in an event
+ List<Cluster[]> clusterPairs;
+
+ int nTriggers;
+ int totalEvents;
+
+ private double clusterEnergyHigh = 1.85; // GeV
+ private double clusterEnergyLow = .1; // GeV
+ private double energySumThreshold = 2; // GeV
+ private double energyDifferenceThreshold = 1.5; // GeV
+ private double maxCoplanarityAngle = 35; // degrees
+
+
+ /**
+ * Constructor
+ */
+ public HPSEcalFlashTrigger( )
+ {
+ // Instantiate the HPS Clusterer
+ ecalClusterer = new HPSEcal3Clusterer();
+ ecalClusterer.setClusterCollectionName( ecalClusterCollectionName );
+ ecalClusterer.setEcalCollectionName( ecalRawHitsCollectionName );
+ ecalClusterer.setEcalName( "Ecal" );
+ add( ecalClusterer );
+
+ clusterPairs = new ArrayList<Cluster[]>();
+ }
+
+ @Override
+ public void process(EventHeader event)
+ {
+
+ super.process(event);
+ totalEvents +=1;
+
+ // Get a list of all clusters found by the clusterer in the event
+ List< Cluster > ecalClusters
+ = event.get(Cluster.class, ecalClusterCollectionName);
+
+ //--- Apply Trigger Cuts ---//
+
+ // Require that the event have at least two clusters in opposite
+ // quadrants
+ if ( !getClusterPairs( ecalClusters ) ) return;
+
+ // Iterate through all cluster pairs present in the event. If at least
+ // one of the cluster pairs satisfies all of the trigger conditions,
+ // a trigger signal is sent to all other detectors.
+ for( Iterator it = clusterPairs.iterator(); it.hasNext(); ){
+
+ Cluster[] clusterPair = (Cluster[]) it.next();
+
+ // Require the componets of a cluster pair to have an energy in
+ // the range of 100 MeV to 1.85 GeV
+ if( !clusterECut( clusterPair ) ) continue;
+
+ // Require the sum of the energies of the components of the
+ // cluster pair to be less than the
+ // (Beam Energy)*(Sampling Fraction) ( 2 GeV for the Test Run )
+ if( !energySum( clusterPair ) ) continue;
+
+ // Require the difference in energy of the components of the
+ // cluster pair to be less than 1.5 GeV
+ if( !energyDifference( clusterPair ) ) continue;
+
+ // Apply a low energy cluster vs. distance cut of the form
+ // E_low + .0032 GeV/mm < .8 GeV
+ if( !energyDistanceCut( clusterPair ) ) continue;
+
+ // Require that the two clusters are coplanar with the beam within
+ // 35 degrees
+ if( !coplanarityCut( clusterPair ) ) continue;
+
+ // If all cuts are pased, send a trigger signal
+// sendTrigger( );
+
+ // Increment number of triggers
+ nTriggers +=1;
+
+ // Only require that at least one cluster pair passes all the
+ // trigger cuts
+ break;
+ }
+ }
+
+ /**
+ * Run before any processes are called
+ */
+ @Override
+ public void startOfData()
+ {
+ nTriggers = 0;
+ totalEvents = 0;
+ }
+
+ /**
+ * Run after all data has been processed
+ */
+ @Override
+ public void endOfData( ) {
+
+ System.out.println( "Total Number of Triggers: " + nTriggers );
+ System.out.println( "The Trigger Rate: "
+ + ( double ) nTriggers/totalEvents + "%" );
+ }
+
+ /**
+ * Get a list of all unique cluster pairs in the event
+ *
+ * @param ecalClusters : List of ECal clusters
+ * @return true if there are any cluster pairs
+ */
+ public boolean getClusterPairs(List<Cluster> ecalClusters)
+ {
+
+ // Check to see if there are at least two clusters
+ if (ecalClusters.size() < 2) return false;
+
+ // Create a list which will hold all neighboring cluster to the cluster
+ // of interest
+ List< Cluster> ecalClusterNeighbors = new ArrayList< Cluster >();
+ for (Cluster ecalCluster : ecalClusters) {
+ ecalClusterNeighbors.add(ecalCluster);
+ }
+
+ // Clear the list of cluster pairs
+ clusterPairs.clear();
+
+ for ( Cluster ecalCluster : ecalClusters ) {
+
+ // Get the quadrant which contains the ECal cluster of interest
+ int ecalClusterQuad = getECalQuadrant(ecalCluster);
+
+ // Create a list of neighbors to the cluster of interest
+ ecalClusterNeighbors.remove(ecalCluster);
+
+ // Loop over all neigboring clusters and check to see if there is
+ // any which lie in opposing quadrants to the cluster of interest.
+ // If so, add them to the list of cluster pairs
+ for (Cluster ecalClusterNeighbor : ecalClusterNeighbors ){
+
+ switch (ecalClusterQuad) {
+ case 1:
+ if ( getECalQuadrant( ecalClusterNeighbor ) == 3 ){
+ Cluster[] clusterPair
+ = { ecalCluster, ecalClusterNeighbor };
+ clusterPairs.add( clusterPair );
+ }
+ break;
+ case 2:
+ if ( getECalQuadrant( ecalClusterNeighbor ) == 4 ){
+ Cluster[] clusterPair
+ = { ecalCluster, ecalClusterNeighbor };
+ clusterPairs.add( clusterPair );
+ }
+ break;
+ case 3:
+ if ( getECalQuadrant( ecalClusterNeighbor ) == 1 ) {
+ Cluster[] clusterPair
+ = { ecalCluster, ecalClusterNeighbor };
+ clusterPairs.add(clusterPair);
+ }
+ break;
+ case 4:
+ if ( getECalQuadrant( ecalClusterNeighbor ) == 2 ) {
+ Cluster[] clusterPair
+ = { ecalCluster, ecalClusterNeighbor };
+ clusterPairs.add(clusterPair);
+ }
+ break;
+ }
+ }
+ }
+
+ return !clusterPairs.isEmpty();
+ }
+
+ /**
+ * Checks if the ECal clusters making up a cluster pair lie above the low
+ * energy threshold and below the high energy threshold
+ *
+ * @param clusterPair : pair of clusters
+ * @return true if a pair is found, false otherwise
+ */
+ public boolean clusterECut( Cluster[] clusterPair )
+ {
+
+ if( clusterPair[ 0 ].getEnergy( ) < clusterEnergyHigh
+ && clusterPair[ 1 ].getEnergy( ) < clusterEnergyHigh
+ && clusterPair[ 0 ].getEnergy( ) > clusterEnergyLow
+ && clusterPair[ 1 ].getEnergy( ) > clusterEnergyLow )
+ return true;
+
+ return false;
+ }
+
+ /**
+ * Returns the quadrant which contains the ECal cluster
+ *
+ * @param ecalCluster : ECal cluster
+ * @return Quadrant number
+ */
+ public int getECalQuadrant(Cluster ecalCluster)
+ {
+ double[] clusterPosition = ecalCluster.getPosition();
+
+ // Quadrant 1
+ if(( clusterPosition[0] > 0.0 ) && ( clusterPosition[1] > 0.0 ))
+ return 1;
+ //Quadrant 2
+ if(( clusterPosition[0] < 0.0 ) && ( clusterPosition[1] > 0.0 ))
+ return 2;
+ // Quadrant 3
+ if(( clusterPosition[0] < 0.0 ) && ( clusterPosition[1] < 0.0 ))
+ return 3;
+ // Quadrant 4
+ return 4;
+ }
+
+ /**
+ * Checks if the sum of the energies of ECal clusters making up a cluster
+ * pair is below an energy sum threshold
+ *
+ * @param clusterPair : pair of clusters
+ * @return true if a pair is found, false otherwise
+ */
+ public boolean energySum( Cluster[] clusterPair )
+ {
+ double clusterESum = clusterPair[ 0 ].getEnergy()
+ + clusterPair[ 1 ].getEnergy();
+ if( clusterESum < energySumThreshold ) return true;
+
+ return false;
+ }
+
+ /**
+ * Checks if the energy difference between the ECal clusters making up
+ * a cluster pair is below an energy difference threshold
+ *
+ * @param clusterPair : pair of clusters
+ * @return true if pair is found, false otherwise
+ */
+ public boolean energyDifference( Cluster[] clusterPair )
+ {
+ double clusterEDifference
+ = Math.abs( clusterPair[ 0 ].getEnergy( )
+ - clusterPair[ 1 ].getEnergy() );
+
+ if( clusterEDifference < energyDifferenceThreshold )
+ return true;
+
+ return false;
+
+ }
+
+ /**
+ * Require that the distance from the beam of the lowest energy cluster
+ * in a cluster pair satisfies the following
+ * E_low + d_b*.0032 GeV/mm < .8 GeV
+ *
+ * @param clusterPiar : pair of clusters
+ * @return true if pair is found, false otherwise
+ */
+ public boolean energyDistanceCut( Cluster[] clusterPair )
+ {
+ Cluster lowEnergyCluster;
+
+ // Obtain the lowest energy cluster
+ if( clusterPair[0].getEnergy() < clusterPair[1].getEnergy() )
+ lowEnergyCluster = clusterPair[0];
+ else lowEnergyCluster = clusterPair[1];
+
+ // Calculate its position
+ double lowEClusterPosition
+ = Math.sqrt( Math.pow( lowEnergyCluster.getPosition()[0], 2)
+ + Math.pow( lowEnergyCluster.getPosition()[1], 2) );
+
+ double clusterDistvsE
+ = lowEnergyCluster.getEnergy() + lowEClusterPosition*(0.0032);
+
+ if( clusterDistvsE > .8 /* GeV */ ) return true;
+
+ return false;
+ }
+
+ /**
+ * Checks if a cluster pair is coplanar to the beam within a given
+ * angle
+ *
+ * @param clusterPair : pair of clusters
+ * @return true if pair is found, false otherwise
+ */
+ public boolean coplanarityCut( Cluster[] clusterPair )
+ {
+ // Find the distance of both clusters from the origin
+ double cluster1Dist
+ = Math.sqrt( Math.pow( clusterPair[0].getPosition()[0],2 )
+ + Math.pow( clusterPair[0].getPosition()[1],2) );
+ double cluster2Dist
+ = Math.sqrt( Math.pow( clusterPair[1].getPosition()[0],2 )
+ + Math.pow( clusterPair[1].getPosition()[1],2) );
+
+ // Calculate the dot product between the distance vectors of
+ // each cluster in the cluster pair
+ double clusterDot
+ = clusterPair[0].getPosition()[0]*clusterPair[1].getPosition()[0]
+ +clusterPair[0].getPosition()[1]*clusterPair[1].getPosition()[1];
+
+ // Find the angle between clusters in the pair
+ double cosphi = clusterDot/( cluster1Dist*cluster2Dist );
+ double phi = Math.toDegrees( Math.acos( cosphi ) );
+
+ if( (180 - phi ) < maxCoplanarityAngle ) return true;
+
+ return false;
+
+ }
+
+ /**
+ * Sends an ECal trigger signal
+ */
+ public void sendTrigger()
+ {
+ HPSTrigger.addTrigger();
+ }
+
+ /**
+ * Set the upper energy cluster threshold
+ *
+ * @param highThreshold : Threshold in GeV
+ */
+ public void setUpperETheshold( double highThreshold )
+ {
+
+ clusterEnergyHigh = highThreshold;
+ }
+
+ /**
+ * Set the lower energy cluster threshold
+ *
+ * @param lowThrehold : Threshold in GeV
+ */
+ public void setLowerEThreshold( double lowThreshold )
+ {
+
+ clusterEnergyLow = lowThreshold;
+ }
+
+ /**
+ * Set the threshold on the sum of the two cluster energies
+ *
+ * @param sumThreshold : Threshold in GeV
+ */
+ public void setESumThreshold( double sumThreshold )
+ {
+
+ energySumThreshold = sumThreshold;
+ }
+
+ /**
+ * Set the threshold on the energy difference between two cluster energies
+ *
+ * @param diffThreshold : Threshold in GeV
+ */
+ public void setEDiffThrehold( double diffThreshold )
+ {
+
+ energyDifferenceThreshold = diffThreshold;
+ }
+
+ /**
+ * Set the maximum angle required to achieve coplanarity between the
+ * clusters and the beam
+ *
+ * @param maxCoplanarity : Maximum angle in degrees
+ */
+ public void setMaxCoplanarityAngle( double maxCoplanarity )
+ {
+ maxCoplanarityAngle = maxCoplanarity;
+ }
+
+}