Author: [log in to unmask] Date: Fri Jan 30 11:14:13 2015 New Revision: 2007 Log: Added SSP trigger bank classes to allow for easier access and reading of the SSPData object. These have not yet been put into use; this is pending additional inforamation about some of the SSPData functions so that their behavior will not be broken by the switch. Added: java/trunk/ecal-readout-sim/src/main/java/org/hps/readout/ecal/triggerbank/SSPCluster.java java/trunk/ecal-readout-sim/src/main/java/org/hps/readout/ecal/triggerbank/SSPCosmicTrigger.java java/trunk/ecal-readout-sim/src/main/java/org/hps/readout/ecal/triggerbank/SSPPairTrigger.java java/trunk/ecal-readout-sim/src/main/java/org/hps/readout/ecal/triggerbank/SSPSinglesTrigger.java java/trunk/ecal-readout-sim/src/main/java/org/hps/readout/ecal/triggerbank/SSPTrigger.java java/trunk/ecal-readout-sim/src/main/java/org/hps/readout/ecal/triggerbank/SSPTriggerFactory.java Added: java/trunk/ecal-readout-sim/src/main/java/org/hps/readout/ecal/triggerbank/SSPCluster.java ============================================================================= --- java/trunk/ecal-readout-sim/src/main/java/org/hps/readout/ecal/triggerbank/SSPCluster.java (added) +++ java/trunk/ecal-readout-sim/src/main/java/org/hps/readout/ecal/triggerbank/SSPCluster.java Fri Jan 30 11:14:13 2015 @@ -0,0 +1,90 @@ +package org.hps.readout.ecal.triggerbank; + +import java.util.logging.Logger; + +import org.hps.recon.ecal.cluster.ClusterDriver; +import org.lcsim.util.log.BasicFormatter; +import org.lcsim.util.log.LogUtil; + +/** + * Class <code>SSPCluster</code> stores all of the information on + * clusters that is reported by the SSP. + * + * @author Kyle McCarty <[log in to unmask]> + */ +public final class SSPCluster { + // Cluster definition variables. + private final int ix; + private final int iy; + private final int n; + private final int t; + private final double e; + + // Output potential errors or messages. + private static Logger logger = LogUtil.create(ClusterDriver.class, new BasicFormatter(SSPCluster.class.getSimpleName())); + + /** + * Creates a new <code>SSPCluster</code> object. + * @param ix - The x-index of the cluster. + * @param iy - The y-index of the cluster. + * @param energy - The cluster energy in MeV. + * @param hits - The cluster hit count. + * @param time - The time at which the cluster occurred in 4 ns + * clock-cycles. + */ + public SSPCluster(int ix, int iy, int energy, int hits, int time) { + // Make sure that the input values are valid. + if(ix == 0 || ix < -23 || ix > 23) { + logger.warning(String.format("Received out-of-bounds ix value of %d.", ix)); + } if(iy == 0 || iy < -5 || iy > 5) { + logger.warning(String.format("Received out-of-bounds iy value of %d.", iy)); + } if(energy < 0) { + logger.warning("Received negative energy for cluster."); + } if(hits <= 0) { + logger.warning("Received cluster with zero or fewer hits."); + } if(time < 0) { + logger.warning("Received cluster with negative time."); + } + + // Define the cluster parameters. + this.ix = ix; + this.iy = iy; + this.e = energy / 1000.0; + this.t = 4 * time; + this.n = hits; + + // Indicate that the cluster was made. + logger.fine(String.format("Instance instantiated at (%3d, %3d) at time %3d ns with energy %4d MeV and %d hits.", + ix, iy, time, energy, hits)); + } + + /** + * Gets the x-index of the cluster. + * @return Returns the cluster x-index as an <code>int</code>. + */ + public int getXIndex() { return ix; } + + /** + * Gets the y-index of the cluster. + * @return Returns the cluster y-index as an <code>int</code>. + */ + public int getYIndex() { return iy; } + + /** + * Gets the number of hits in the cluster. + * @return Returns the cluster hit count as an <code>int</code>. + */ + public int getHitCount() { return n; } + + /** + * Gets the cluster time in nanoseconds. + * @return Returns the cluster time as an <code>int</code>. + */ + public int getTime() { return t; } + + /** + * Gets the energy of the cluster in GeV. + * @return Returns the cluster energy as a <code>double</code>. + */ + public double getEnergy() { return e; } +} Added: java/trunk/ecal-readout-sim/src/main/java/org/hps/readout/ecal/triggerbank/SSPCosmicTrigger.java ============================================================================= --- java/trunk/ecal-readout-sim/src/main/java/org/hps/readout/ecal/triggerbank/SSPCosmicTrigger.java (added) +++ java/trunk/ecal-readout-sim/src/main/java/org/hps/readout/ecal/triggerbank/SSPCosmicTrigger.java Fri Jan 30 11:14:13 2015 @@ -0,0 +1,27 @@ +package org.hps.readout.ecal.triggerbank; + + +/** + * Class <code>SSPCosmicTrigger</code> represents an SSP trigger for + * the either the top or bottom cosmic trigger. + * + * @author Kyle McCarty <[log in to unmask]> + */ +public class SSPCosmicTrigger extends SSPTrigger { + /** + * Instantiates a new <code>SSPCosmicTrigger</code>. + * @param isTop - Indicates whether this trigger was caused by the + * top crate in the SSP or not. + * @param time - The time at which the trigger occurred. + */ + public SSPCosmicTrigger(boolean isTop, int time) { + // Instantiate the superclass object. + super(isTop ? SSPData.TRIG_TYPE_COSMIC_TOP : SSPData.TRIG_TYPE_COSMIC_BOT, time, 0); + } + + @Override + public boolean isBottom() { return type == SSPData.TRIG_TYPE_COSMIC_BOT; } + + @Override + public boolean isTop() { return type == SSPData.TRIG_TYPE_COSMIC_TOP; } +} Added: java/trunk/ecal-readout-sim/src/main/java/org/hps/readout/ecal/triggerbank/SSPPairTrigger.java ============================================================================= --- java/trunk/ecal-readout-sim/src/main/java/org/hps/readout/ecal/triggerbank/SSPPairTrigger.java (added) +++ java/trunk/ecal-readout-sim/src/main/java/org/hps/readout/ecal/triggerbank/SSPPairTrigger.java Fri Jan 30 11:14:13 2015 @@ -0,0 +1,67 @@ +package org.hps.readout.ecal.triggerbank; + + +/** + * Class <code>SSPPairTrigger</code> represents a pair trigger reported + * by the SSP and also handles parsing the trigger bits. + * + * @author Kyle McCarty <[log in to unmask]> + */ +public class SSPPairTrigger extends SSPTrigger { + /** + * Instantiates a new <code>SSPPairTrigger</code>. + * @param isFirstTrigger - Indicates whether the first or second + * trigger produced this trigger. + * @param time - The time at which the trigger occurred. + * @param data - The trigger data associated with the trigger. + */ + public SSPPairTrigger(boolean isFirstTrigger, int time, int data) { + super(isFirstTrigger ? SSPData.TRIG_TYPE_PAIR0 : SSPData.TRIG_TYPE_PAIR1, time, data); + } + + @Override + public boolean isBottom() { return true; } + + @Override + public boolean isTop() { return true; } + + /** + * Indicates whether the trigger passed the pair energy sum cut + * or not. + * @return Returns <code>true</code> if the cut passed and + * <code>false</code> otherwise. + */ + public boolean passCutEnergySum() { + return (data & 1) == 1; + } + + /** + * Indicates whether the trigger passed the pair energy difference + * cut or not. + * @return Returns <code>true</code> if the cut passed and + * <code>false</code> otherwise. + */ + public boolean passCutEnergyDifference() { + return ((data & 2) >> 1) == 1; + } + + /** + * Indicates whether the trigger passed the pair energy slope cut + * or not. + * @return Returns <code>true</code> if the cut passed and + * <code>false</code> otherwise. + */ + public boolean passCutEnergySlope() { + return ((data & 4) >> 2) == 1; + } + + /** + * Indicates whether the trigger passed the pair coplanarity cut + * or not. + * @return Returns <code>true</code> if the cut passed and + * <code>false</code> otherwise. + */ + public boolean passCutCoplanarity() { + return ((data & 8) >> 3) == 1; + } +} Added: java/trunk/ecal-readout-sim/src/main/java/org/hps/readout/ecal/triggerbank/SSPSinglesTrigger.java ============================================================================= --- java/trunk/ecal-readout-sim/src/main/java/org/hps/readout/ecal/triggerbank/SSPSinglesTrigger.java (added) +++ java/trunk/ecal-readout-sim/src/main/java/org/hps/readout/ecal/triggerbank/SSPSinglesTrigger.java Fri Jan 30 11:14:13 2015 @@ -0,0 +1,67 @@ +package org.hps.readout.ecal.triggerbank; + + +/** + * Class <code>SSPSinglesTrigger</code> represents a singles trigger + * reported by the SSP and also handles the parsing of the trigger data. + * + * @author Kyle McCarty <[log in to unmask]> + */ +public class SSPSinglesTrigger extends SSPTrigger { + /** + * Instantiates a new <code>SSPSinglesTrigger</code> object. + * @param isTrigger0 - Indicates whether this is the first or second + * of the singles triggers. + * @param isTop - Indicates whether this trigger was thrown by the + * top or the bottom SSP crate. + * @param time - Indicates at what time the trigger occurred in ns. + * @param data - The raw trigger data associated with this trigger. + */ + public SSPSinglesTrigger(boolean isTrigger0, boolean isTop, int time, int data) { + // Initialize the superclass object. + super(isTop ? + (isTrigger0 ? SSPData.TRIG_TYPE_SINGLES0_TOP : SSPData.TRIG_TYPE_SINGLES1_TOP) : + (isTrigger0 ? SSPData.TRIG_TYPE_SINGLES0_BOT : SSPData.TRIG_TYPE_SINGLES1_BOT), + time, data); + } + + @Override + public boolean isBottom() { + return (type == SSPData.TRIG_TYPE_SINGLES0_BOT || type == SSPData.TRIG_TYPE_SINGLES1_BOT); + } + + @Override + public boolean isTop() { + return (type == SSPData.TRIG_TYPE_SINGLES0_TOP || type == SSPData.TRIG_TYPE_SINGLES1_TOP); + } + + /** + * Indicates whether the trigger passed the cluster total energy + * lower bound cut or not. + * @return Returns <code>true</code> if the cut passed and + * <code>false</code> otherwise. + */ + public boolean passCutEnergyMin() { + return (data & 1) == 1; + } + + /** + * Indicates whether the trigger passed the cluster total energy + * upper bound cut or not. + * @return Returns <code>true</code> if the cut passed and + * <code>false</code> otherwise. + */ + public boolean passCutEnergyMax() { + return ((data & 2) >> 1) == 1; + } + + /** + * Indicates whether the trigger passed the cluster hit count cut + * or not. + * @return Returns <code>true</code> if the cut passed and + * <code>false</code> otherwise. + */ + public boolean passCutHitCount() { + return ((data & 4) >> 2) == 1; + } +} Added: java/trunk/ecal-readout-sim/src/main/java/org/hps/readout/ecal/triggerbank/SSPTrigger.java ============================================================================= --- java/trunk/ecal-readout-sim/src/main/java/org/hps/readout/ecal/triggerbank/SSPTrigger.java (added) +++ java/trunk/ecal-readout-sim/src/main/java/org/hps/readout/ecal/triggerbank/SSPTrigger.java Fri Jan 30 11:14:13 2015 @@ -0,0 +1,88 @@ +package org.hps.readout.ecal.triggerbank; + +import java.util.logging.Logger; + +import org.hps.recon.ecal.cluster.ClusterDriver; +import org.lcsim.util.log.BasicFormatter; +import org.lcsim.util.log.LogUtil; + +/** + * Abstract class <code>SSPTrigger</code> represents the data output + * by the SSP for a trigger. Individual implementing classes are expected + * to handle parsing the trigger bit data as appropriate for their type. + * + * @author Kyle McCarty <[log in to unmask]> + */ +public class SSPTrigger { + // Trigger data. + protected final int type; + protected final int time; + protected final int data; + + // Logger to output status messages. + protected static Logger logger = LogUtil.create(ClusterDriver.class, new BasicFormatter(SSPCluster.class.getSimpleName())); + + /** + * Instantiates a new <code>SSPTrigger</code> with the indicated + * trigger data. + * @param type - The type of trigger. + * @param time - The time at which the trigger occurred in 4 ns + * clock-cycles. + * @param data - The trigger bit data. + */ + public SSPTrigger(int type, int time, int data) { + // Log any issues with processing the trigger. + if(!SSPTriggerFactory.isKnownTriggerType(type)) { + logger.warning(String.format("Trigger type %d is not recognized.", type)); + } + + // Store the trigger data. + this.type = type; + this.time = 4 * time; + this.data = data; + + // Note that a trigger was made. + logger.fine(String.format("A trigger of type %d occurred at time %3d with data %d.", + type, time, data)); + } + + /** + * Indicates whether the trigger was reported by the bottom SSP + * crate or not. + * @return Returns <code>true</code> if the trigger was reported + * by the bottom crate and <code>false</code> if it was reported + * by the top crate. + */ + public boolean isBottom() { + return false; + } + + /** + * Indicates whether the trigger was reported by the top SSP + * crate or not. + * @return Returns <code>true</code> if the trigger was reported + * by the top crate and <code>false</code> if it was reported by + * the bottom crate. + */ + public boolean isTop() { + return false; + } + + /** + * Gets the raw, unparsed trigger data bank for this trigger. + * @return Returns the trigger data bank as an <code>int</code>. + */ + public int getData() { return data; } + + /** + * Gets the type code for the trigger. + * @return Returns the trigger type as an <code>int</code>. + */ + public int getType() { return type; } + + /** + * Gets the time at which the trigger occurred. + * @return Returns the trigger time as an <code>int</code>. + */ + public int getTime() { return time; } +} Added: java/trunk/ecal-readout-sim/src/main/java/org/hps/readout/ecal/triggerbank/SSPTriggerFactory.java ============================================================================= --- java/trunk/ecal-readout-sim/src/main/java/org/hps/readout/ecal/triggerbank/SSPTriggerFactory.java (added) +++ java/trunk/ecal-readout-sim/src/main/java/org/hps/readout/ecal/triggerbank/SSPTriggerFactory.java Fri Jan 30 11:14:13 2015 @@ -0,0 +1,196 @@ +package org.hps.readout.ecal.triggerbank; + +/** + * Class <code>SSPTriggerFactory</code> builds <code>SSPTrigger<code> + * objects from basic trigger information. These objects will vary in + * subclass depending on the trigger type and provide trigger data + * parsing options. Unknown trigger types will always be of object type + * <code>SSPTrigger</code>, which does not provide trigger data parsing. + * + * @author Kyle McCarty <[log in to unmask]> + */ +public class SSPTriggerFactory { + /** + * Creates an <code>SSPTrigger</code> object representing the given + * trigger information. If the trigger type is unknown, this creates + * a <code>SSPTrigger</code> object. Otherwise, an object for the + * appropriate type of trigger is generated which will provide trigger + * data parsing options. + * @param type - The type of trigger. + * @param time - The time at which the trigger occurred in ns. + * @param data - The trigger data. + * @return Returns an <code>SSPTrigger</code> object. This may be + * a subclass appropriate to the trigger type. + */ + public static final SSPTrigger makeTrigger(int type, int time, int data) { + // Check for cosmic triggers. + if(isCosmicTrigger(type)) { + return new SSPCosmicTrigger(isTopTrigger(type), time); + } + + // Check for singles triggers. + else if(isSinglesTrigger(type)) { + return new SSPSinglesTrigger(isFirstTrigger(type), isTopTrigger(type), time, data); + } + + // Check for pair triggers. + else if(isPairTrigger(type)) { + return new SSPPairTrigger(isFirstTrigger(type), time, data); + } + + // Otherwise, this is an unknown trigger type. + else { + return new SSPTrigger(type, time, data); + } + } + + /** + * Indicates whether the trigger type is a cosmic trigger. + * @param type - The trigger type. + * @return Returns <code>true</code> if the trigger is a cosmic + * trigger and <code>false</code> otherwise. + */ + public static final boolean isCosmicTrigger(int type) { + return (type == SSPData.TRIG_TYPE_COSMIC_BOT) || (type == SSPData.TRIG_TYPE_COSMIC_TOP); + } + + /** + * Indicates whether the trigger type is a singles trigger. + * @param type - The trigger type. + * @return Returns <code>true</code> if the trigger is a singles + * trigger and <code>false</code> otherwise. + */ + public static final boolean isSinglesTrigger(int type) { + return (type == SSPData.TRIG_TYPE_SINGLES0_BOT) || (type == SSPData.TRIG_TYPE_SINGLES0_TOP) || + (type == SSPData.TRIG_TYPE_SINGLES1_BOT) || (type == SSPData.TRIG_TYPE_SINGLES1_TOP); + } + + /** + * Indicates whether the trigger type is a pair trigger. + * @param type - The trigger type. + * @return Returns <code>true</code> if the trigger is a pair + * trigger and <code>false</code> otherwise. + */ + public static final boolean isPairTrigger(int type) { + return (type == SSPData.TRIG_TYPE_PAIR0) || (type == SSPData.TRIG_TYPE_PAIR1); + } + + /** + * Indicates whether this is the first trigger of a set of two + * triggers of the same type. This always returns <code>true</code> + * for cosmic triggers, since there is only one. It always returns + * <code>false</code> for unknown trigger types. + * @param type - The trigger type. + * @return Returns <code>true</code> if this is the first trigger + * in a set of two and <code>false</code> otherwise. + */ + public static final boolean isFirstTrigger(int type) { + // There is only one cosmic trigger, so all cosmic triggers + // are the first trigger. + if(isCosmicTrigger(type)) { return true; } + + // Otherwise, singles trigger 0 (either top or bottom) and + // pair trigger 0 are first triggers. + else if((type == SSPData.TRIG_TYPE_SINGLES0_BOT) || (type == SSPData.TRIG_TYPE_SINGLES0_TOP) || + (type == SSPData.TRIG_TYPE_PAIR0)) { + return true; + } + + // Anything else is not a first trigger. + else { + return false; + } + } + + /** + * Indicates whether this is the second trigger of a set of two + * triggers of the same type. This always returns <code>false</code> + * for cosmic triggers, since there is only one. It also always + * returns <code>false</code> for unknown trigger types. + * @param type - The trigger type. + * @return Returns <code>true</code> if this is the second trigger + * in a set of two and <code>false</code> otherwise. + */ + public static final boolean isSecondTrigger(int type) { + // There is only one cosmic trigger, so no cosmic triggers + // are the second trigger. + if(isCosmicTrigger(type)) { return false; } + + // Otherwise, singles trigger 1 (either top or bottom) and + // pair trigger 1 are second triggers. + else if((type == SSPData.TRIG_TYPE_SINGLES1_BOT) || (type == SSPData.TRIG_TYPE_SINGLES1_TOP) || + (type == SSPData.TRIG_TYPE_PAIR1)) { + return true; + } + + // Anything else is not a second trigger. + else { return false; } + } + + /** + * Indicates whether this trigger originated in the top SPP crate. + * This always returns <code>true</code> for pair triggers, as they + * require both crates, and always returns false for unknown trigger + * types. + * @param type - The trigger type. + * @return Returns <code>true</code> if this trigger originated + * in the top crate and <code>false</code> otherwise. + */ + public static final boolean isTopTrigger(int type) { + // Pair triggers require both crates, so this is always true + // for all triggers of that type. + if(isPairTrigger(type)) { return true; } + + // For singles and cosmic triggers, check the type. + else if((type == SSPData.TRIG_TYPE_COSMIC_TOP) || (type == SSPData.TRIG_TYPE_SINGLES0_TOP) || + (type == SSPData.TRIG_TYPE_SINGLES1_TOP)) { + return true; + } + + // Otherwise, this is not a (known) top trigger. + else { return false; } + } + + /** + * Indicates whether this trigger originated in the bottom SPP crate. + * This always returns <code>true</code> for pair triggers, as they + * require both crates, and always returns false for unknown trigger + * types. + * @param type - The trigger type. + * @return Returns <code>true</code> if this trigger originated + * in the bottom crate and <code>false</code> otherwise. + */ + public static final boolean isBottomTrigger(int type) { + // Pair triggers require both crates, so this is always true + // for all triggers of that type. + if(isPairTrigger(type)) { return true; } + + // For singles and cosmic triggers, check the type. + else if((type == SSPData.TRIG_TYPE_COSMIC_BOT) || (type == SSPData.TRIG_TYPE_SINGLES0_BOT) || + (type == SSPData.TRIG_TYPE_SINGLES1_BOT)) { + return true; + } + + // Otherwise, this is not a (known) bottom trigger. + else { return false; } + } + + /** + * Checks whether the trigger type is from a recognized trigger. + * @param type - The type code. + * @return Returns <code>true</code> if the trigger type is of a + * recognized type and returns <code>false</code> if it is not. + */ + public static final boolean isKnownTriggerType(int type) { + // Check against all known trigger types. + if(type == SSPData.TRIG_TYPE_COSMIC_BOT || type == SSPData.TRIG_TYPE_COSMIC_TOP || + type == SSPData.TRIG_TYPE_PAIR0 || type == SSPData.TRIG_TYPE_PAIR1 || + type == SSPData.TRIG_TYPE_SINGLES0_BOT || type == SSPData.TRIG_TYPE_SINGLES0_TOP || + type == SSPData.TRIG_TYPE_SINGLES1_BOT || type == SSPData.TRIG_TYPE_SINGLES1_TOP) { + return true; + } + + // If it does not match, it is unknown, + else { return false; } + } +}