Print

Print


Author: [log in to unmask]
Date: Wed Mar  4 08:05:05 2015
New Revision: 2239

Log:
Updating EcalRawConverter(Driver) to use NSA/NSB instead of integralWindow in order to unify conversion of all FADC Modes.  Updated a couple old steering files accordingly.  TODO:  Implmement mode-1->mode-7 conversion, implmement more correct pedestal correction for clipped pulses.

Modified:
    java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/EcalRawConverter.java
    java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/EcalRawConverterDriver.java
    java/trunk/steering-files/src/main/resources/org/hps/steering/monitoring/ECalTriggerMonitoring.lcsim
    java/trunk/steering-files/src/main/resources/org/hps/steering/monitoring/ECalTriggerWindowMonitoring.lcsim

Modified: java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/EcalRawConverter.java
 =============================================================================
--- java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/EcalRawConverter.java	(original)
+++ java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/EcalRawConverter.java	Wed Mar  4 08:05:05 2015
@@ -20,10 +20,14 @@
  * information. It has methods to convert pedestal subtracted ADC counts to
  * energy.
  *
+ * TODO: Switch all mode's HitDtoAs to use a clipped pedestal for clipped pulses.
+ *       This requires another parameter, the window size.
+ *
  * @author Sho Uemura <[log in to unmask]>
  * @author Jeremy McCormick <[log in to unmask]>
  * @author Andrea Celentano <[log in to unmask]>
  * @author <[log in to unmask]>
+ * 
  */
 public class EcalRawConverter {
 
@@ -33,15 +37,28 @@
     private double gain;
     private boolean use2014Gain = true;
 
-    
-    // Parameters for replicating the conversion of FADC Mode-1 readout into what
-    // the firmware would have reported for Mode-3 pulse.  Using the same conventions
-    // for these parameters used by the firmware configuration files.  This means
-    // NSA and NSB are in units nanoseconds and must be multiples of 4 ns.
-    private double leadingEdgeThreshold=-1; // above pedestal (units=ADC)
-    private int NSA=-1; // integration range after threshold crossing (units=ns)
-    private int NSB=-1; // integration range before threshold crossing (units=ns)
-    
+    /*
+     * The time for one FADC sample (units = ns).
+     */
+    private static final int nsPerSample = 4;
+    
+    /*
+     * The leading-edge threshold, relative to pedestal, for readout and pulse time
+     * determination.  Units = ADC.  This is used to convert mode-1 readout into
+     * mode-3/7 for clustering.
+     * 
+     * The default value of 12 is what we used for most of the 2014 run.
+     */
+    private double leadingEdgeThreshold=12;
+    
+    /*
+     * Integration range after (NSA) and before (NSB) threshold crossing.  (units = ns)
+     * These must be multiples of 4 ns.
+     * 
+     * The default values of 20/100 are what we had during the entire 2014 run.
+     */
+    private int NSB=20;
+    private int NSA=100;
     
     private EcalConditions ecalConditions = null;
 
@@ -52,9 +69,15 @@
         leadingEdgeThreshold=thresh;
     }
     public void setNSA(int nsa) {
+        if (NSA%nsPerSample !=0 || NSA<0) {
+            throw new RuntimeException("NSA must be multiples of 4ns and non-negative.");
+        }
         NSA=nsa;
     }
     public void setNSB(int nsb) {
+        if (NSB%nsPerSample !=0 || NSB<0) {
+            throw new RuntimeException("NSB must be multiples of 4ns and non-negative.");
+        }
         NSB=nsb;
     }
     
@@ -89,7 +112,6 @@
                         event.get("EcalRunningPedestals");
                 EcalChannel chan = ecalConditions.getChannelCollection().
                         findGeometric(hit.getCellID());
-                //System.err.println(" %%%%%%%%%%%%%%%%% "+chan.getChannelId()+" "+runningPedMap.get(chan));
                 if (!runningPedMap.containsKey(chan)){
                     System.err.println("************** Missing Pedestal");
                 } else {
@@ -105,6 +127,7 @@
         }
         return findChannel(hit.getCellID()).getCalibration().getPedestal();
     }
+    
     public short sumADC(RawTrackerHit hit) {
         EcalChannelConstants channelData = findChannel(hit.getCellID());
         double pedestal = channelData.getCalibration().getPedestal();
@@ -116,6 +139,10 @@
         return sum;
     }
 
+    /*
+     * This should this be replaced by firmwareHitDtoA, as that has the
+     * same functionality if NSA+NSB > window size. Left for now.
+     */
     public CalorimeterHit HitDtoA(RawTrackerHit hit) {
         double time = hit.getTime();
         long id = hit.getCellID();
@@ -125,42 +152,28 @@
 
     /*
      * NAB 2015/02/26
+     * This HitDtoA is for emulating the conversion of Mode-1 readout (RawTrackerHit)
+     * into what EcalRawConverter would have created from a Mode-3 readout.
      * 
-     * This HitDtoA is for emulating the conversion of Mode-1 readout (RawTrackerHit)
-     * into a Mode-3 readout.  This currently only supports finding 1 pulse in the window.
-     * (NOTE: Looks like ADCs have already been converted to doubles.)
-     * 
-     * TODO: Special case when NSA+NSB is greater than the window size is not dealt
-     * with properly, yet.
      */
     public CalorimeterHit firmwareHitDtoA(RawTrackerHit hit) {
      
-        final int nsPerSample=4; // TODO: Get this from somewhere else.
-        
-        if (NSA<0 || NSB<0 || leadingEdgeThreshold<0.0) {
-            throw new RuntimeException("You have to set NSA, NSB, and leadingEdgeThreshold to positive values if you want to emulate firmware.");
-        }
-        
-        // using convention for NSA and NSB in the DAQ config file:
-        if (NSA%nsPerSample !=0 || NSB%nsPerSample !=0) {
-            throw new RuntimeException("NSA/NSB must be multiples of 4ns.");
-        }
-        
         long id = hit.getCellID();
         short samples[] = hit.getADCValues();
         if (samples.length==0) return null;
         EcalChannelConstants channelData = findChannel(hit.getCellID());
         double pedestal = channelData.getCalibration().getPedestal();
-
+        double absoluteThreshold = pedestal+leadingEdgeThreshold;
+        
         // find threshold crossing:
         int thresholdCrossing = -1;
-        if (samples[0] > pedestal+leadingEdgeThreshold) {
+        if (samples[0] > absoluteThreshold) {
             // special case, first sample above threshold:
             thresholdCrossing=0;
         } else {
             for (int ii = 1; ii < samples.length; ++ii) {
-                if ( samples[ii]   >pedestal+leadingEdgeThreshold &&
-                     samples[ii-1]<=pedestal+leadingEdgeThreshold)
+                if ( samples[ii]   >absoluteThreshold &&
+                     samples[ii-1]<=absoluteThreshold)
                 {
                     // found threshold crossing:
                     thresholdCrossing = ii;
@@ -171,41 +184,52 @@
         }
         if (thresholdCrossing < 0) return null;
 
-        // pulse time:
-        double time = thresholdCrossing*nsPerSample;
-       
+        // choose integration range:
+        int firstSample,lastSample;
+        if ((NSA+NSB)/nsPerSample >= samples.length) {
+            // firmware treats this case specially:
+            firstSample = 0;
+            lastSample = samples.length-1;
+        } else {
+            firstSample = thresholdCrossing - NSB/nsPerSample;
+            lastSample  = thresholdCrossing + NSA/nsPerSample - 1;
+        }
+         
         // pulse integral:
         short sum = 0;
-        for (int jj=thresholdCrossing-NSB/nsPerSample; jj<thresholdCrossing+NSA/nsPerSample; jj++) {
+        for (int jj=firstSample; jj<=lastSample; jj++) {
             if (jj<0) continue;
             if (jj>=samples.length) break;
             sum += samples[jj];
         }
 
-        //System.err.println("000000000000000000000000      "+thresholdCrossing+"   "+sum+"  "+pedestal+"  "+NSA+NSB);
-
         // pedestal subtraction:
         sum -= pedestal*(NSA+NSB)/nsPerSample;
       
-        //System.err.println("1111111111111111111      "+thresholdCrossing+"   "+sum);
-        
         // conversion of ADC to energy:
         double rawEnergy = adcToEnergy(sum, id);
         
+        // pulse time:
+        double time = thresholdCrossing*nsPerSample;
+        if (useTimeWalkCorrection) {
+           time = EcalTimeWalk.correctTimeWalk(time,rawEnergy);
+        }
+
         return CalorimeterHitUtilities.create(rawEnergy, time, id);
     }
 
     /*
-     * This HitDtoA is for Mode-3 data at least, but definitely not Mode-7.
-     * A time-walk correction can be applied.  (NAB 2015/02/11).
-     */
-    public CalorimeterHit HitDtoA(RawCalorimeterHit hit, int window, double timeOffset) {
+     * This HitDtoA is for Mode-3 data.
+     * A time-walk correction can be applied.
+     */
+    public CalorimeterHit HitDtoA(RawCalorimeterHit hit, double timeOffset) {
         if (hit.getTimeStamp() % 64 != 0) {
             System.out.println("unexpected timestamp " + hit.getTimeStamp());
         }
         double time = hit.getTimeStamp() / 16.0;
         long id = hit.getCellID();
         EcalChannelConstants channelData = findChannel(id);
+        int window = (NSA+NSB)/nsPerSample;
         double adcSum = hit.getAmplitude() - window * channelData.getCalibration().getPedestal();
         double rawEnergy = adcToEnergy(adcSum, id);
         if (useTimeWalkCorrection) {
@@ -220,20 +244,26 @@
      * format of the input EVIO data.  EventHeader is also passed in order to allow access
      * to running pedestals, which is only applicable to Mode-7 data.  (NAB, 2015/02/11)
      */
-    public CalorimeterHit HitDtoA(EventHeader event,RawCalorimeterHit hit, GenericObject mode7Data, int window, double timeOffset) {
+    public CalorimeterHit HitDtoA(EventHeader event,RawCalorimeterHit hit, GenericObject mode7Data, double timeOffset) {
         double time = hit.getTimeStamp() / 16.0; //timestamps use the full 62.5 ps resolution
         long id = hit.getCellID();
+        int window = (NSA+NSB)/nsPerSample;
         double adcSum = hit.getAmplitude() - window * getMode7Pedestal(event,hit);
         double rawEnergy = adcToEnergy(adcSum, id);        
         return CalorimeterHitUtilities.create(rawEnergy, time + timeOffset, id);
     }
 
-    public RawCalorimeterHit HitAtoD(CalorimeterHit hit, int window) {
+    /*
+     * This converts a corrected pulse integral (pedestal-subtracted and gain-scaled)
+     * back into raw pulse integral with units ADC.
+     */
+    public RawCalorimeterHit HitAtoD(CalorimeterHit hit) {
         int time = (int) (Math.round(hit.getTime() / 4.0) * 64.0);
         long id = hit.getCellID();
         // Get the channel data.
         EcalChannelConstants channelData = findChannel(id);
         int amplitude;
+        int window = (NSA+NSB)/nsPerSample;
         if (constantGain) {
             amplitude = (int) Math.round((hit.getRawEnergy() / ECalUtils.MeV) / gain + window * channelData.getCalibration().getPedestal());
         } else {

Modified: java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/EcalRawConverterDriver.java
 =============================================================================
--- java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/EcalRawConverterDriver.java	(original)
+++ java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/EcalRawConverterDriver.java	Wed Mar  4 08:05:05 2015
@@ -21,10 +21,14 @@
  * @version $Id: HPSEcalRawConverterDriver.java,v 1.2 2012/05/03 00:17:54
  * phansson Exp $
  *
- * baltzell Feb 26, 2015:
+ * baltzell: Feb 26, 2015:
  * added firmware emulation for converting from Mode-1 readout (RawTrackerHit)
  * to Mode-3 pulse (CalorimeterHit).  Turn it on with "emulateFirmware", else
- * defaults to previous behavior.
+ * defaults to previous behavior.  Removed integralWindow in favor of NSA and
+ * NSB in EcalRawConverter, so that all conversions can use the same window.
+ * March 3, 2015:  Removed integralWindow in favor of NSA/NSB in order to treat
+ * all modes uniformly.
+ * 
  */
 public class EcalRawConverterDriver extends Driver {
 
@@ -39,7 +43,6 @@
     private static final String extraDataRelationsName = "EcalReadoutExtraDataRelations";
 //    private static final String extraDataCollectionName = "EcalReadoutExtraData";
 
-    private int integralWindow = 30; //A.C. on 12/14/2014 8:44 after discussion with Nathan.
     private boolean debug = false;
     private double threshold = Double.NEGATIVE_INFINITY;
     private boolean applyBadCrystalMap = true;
@@ -92,10 +95,6 @@
     
     public void setGain(double gain) {
         converter.setGain(gain);
-    }
-
-    public void setIntegralWindow(int integralWindow) {
-        this.integralWindow = integralWindow;
     }
 
     public void setEcalCollectionName(String ecalCollectionName) {
@@ -237,7 +236,7 @@
                         }
                         GenericObject extraData = (GenericObject) rel.getTo();
                         CalorimeterHit newHit;
-                        newHit = converter.HitDtoA(event,hit, extraData, integralWindow, timeOffset);
+                        newHit = converter.HitDtoA(event,hit, extraData, timeOffset);
                         if (newHit.getRawEnergy() > threshold) {
                             if (applyBadCrystalMap && isBadCrystal(newHit)) {
                                 continue;
@@ -259,7 +258,7 @@
                             System.out.format("old hit energy %d\n", hit.getAmplitude());
                         }
                         CalorimeterHit newHit;
-                        newHit = converter.HitDtoA(hit, integralWindow, timeOffset);
+                        newHit = converter.HitDtoA(hit, timeOffset);
                         if (newHit.getRawEnergy() > threshold) {
                             if (applyBadCrystalMap && isBadCrystal(newHit)) {
                                 continue;
@@ -285,7 +284,7 @@
                     if (debug) {
                         System.out.format("old hit energy %f\n", hit.getRawEnergy());
                     }
-                    RawCalorimeterHit newHit = converter.HitAtoD(hit, integralWindow);
+                    RawCalorimeterHit newHit = converter.HitAtoD(hit);
                     if (newHit.getAmplitude() > 0) {
                         if (debug) {
                             System.out.format("new hit energy %d\n", newHit.getAmplitude());

Modified: java/trunk/steering-files/src/main/resources/org/hps/steering/monitoring/ECalTriggerMonitoring.lcsim
 =============================================================================
--- java/trunk/steering-files/src/main/resources/org/hps/steering/monitoring/ECalTriggerMonitoring.lcsim	(original)
+++ java/trunk/steering-files/src/main/resources/org/hps/steering/monitoring/ECalTriggerMonitoring.lcsim	Wed Mar  4 08:05:05 2015
@@ -23,7 +23,9 @@
     <drivers>
         <driver name="EcalRawConverter" type="org.hps.recon.ecal.EcalReadoutToTriggerConverterDriver">
             <rawCollectionName>EcalReadoutHits</rawCollectionName>
-            <integralWindow>35</integralWindow>
+            <!--<integralWindow>35</integralWindow> Deprecated, now use the equivalent in NSA/NSB-->
+            <nsa>120</nsa>
+            <nsb>20</nsb>
             <applyBadCrystalMap>false</applyBadCrystalMap>
             <dropBadFADC>true</dropBadFADC>
             <tp>14.0</tp>

Modified: java/trunk/steering-files/src/main/resources/org/hps/steering/monitoring/ECalTriggerWindowMonitoring.lcsim
 =============================================================================
--- java/trunk/steering-files/src/main/resources/org/hps/steering/monitoring/ECalTriggerWindowMonitoring.lcsim	(original)
+++ java/trunk/steering-files/src/main/resources/org/hps/steering/monitoring/ECalTriggerWindowMonitoring.lcsim	Wed Mar  4 08:05:05 2015
@@ -26,7 +26,9 @@
         </driver>
         <driver name="EcalRawConverter" type="org.hps.recon.ecal.EcalRawConverterDriver">
             <rawCollectionName>EcalIntegralHits</rawCollectionName>
-            <integralWindow>35</integralWindow>
+            <!--<integralWindow>35</integralWindow> Deprecated, now use the equivalent in NSA/NSB-->
+            <nsa>120</nsa>
+            <nsb>20</nsb>
             <gain>1.0</gain>
             <use2014Gain>false</use2014Gain>
         </driver>