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>