Author: [log in to unmask] Date: Thu Feb 26 17:59:21 2015 New Revision: 2216 Log: Updating EcalRawConverter(Driver) to emulate FADC firmware in converting Mode-1 readout (ECalRawTrackerHit) into Mode-3 readout (CalorimeterHit) for use by clustering algorithms. This new behavior is disabled by default; enabled with flag in steering file. Added: java/trunk/steering-files/src/main/resources/org/hps/steering/users/baltzell/EngineeringRun2014ECalRecon_Pass1_FirmwareEmulator.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/EcalRawConverterDriver.java 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 Thu Feb 26 17:59:21 2015 @@ -23,6 +23,7 @@ * @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 { @@ -32,11 +33,31 @@ 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) + + private EcalConditions ecalConditions = null; public EcalRawConverter() { } + public void setLeadingEdgeThreshold(double thresh) { + leadingEdgeThreshold=thresh; + } + public void setNSA(int nsa) { + NSA=nsa; + } + public void setNSB(int nsb) { + NSB=nsb; + } + public void setGain(double gain) { constantGain = true; this.gain = gain; @@ -103,6 +124,78 @@ } /* + * NAB 2015/02/26 + * + * 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(); + + // find threshold crossing: + int thresholdCrossing = -1; + if (samples[0] > pedestal+leadingEdgeThreshold) { + // 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) + { + // found threshold crossing: + thresholdCrossing = ii; + // one pulse only: + break; + } + } + } + if (thresholdCrossing < 0) return null; + + // pulse time: + double time = thresholdCrossing*nsPerSample; + + // pulse integral: + short sum = 0; + for (int jj=thresholdCrossing-NSB/nsPerSample; jj<thresholdCrossing+NSA/nsPerSample; 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); + + 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). */ 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 Thu Feb 26 17:59:21 2015 @@ -20,6 +20,11 @@ * * @version $Id: HPSEcalRawConverterDriver.java,v 1.2 2012/05/03 00:17:54 * phansson Exp $ + * + * 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. */ public class EcalRawConverterDriver extends Driver { @@ -43,6 +48,8 @@ private boolean useTimestamps = false; private boolean useTruthTime = false; + private boolean emulateFirmware = false; + public EcalRawConverterDriver() { converter = new EcalRawConverter(); } @@ -70,6 +77,19 @@ this.threshold = threshold; } + public void setEmulateFirmware(boolean emulateFirmware) { + this.emulateFirmware = emulateFirmware; + } + public void setLeadingEdgeThreshold(double threshold) { + converter.setLeadingEdgeThreshold(threshold); + } + public void setNsa(int nsa) { + converter.setNSA(nsa); + } + public void setNsb(int nsb) { + converter.setNSB(nsb); + } + public void setGain(double gain) { converter.setGain(gain); } @@ -182,7 +202,15 @@ List<RawTrackerHit> hits = event.get(RawTrackerHit.class, rawCollectionName); for (RawTrackerHit hit : hits) { - CalorimeterHit newHit = converter.HitDtoA(hit); + + CalorimeterHit newHit = null; + if (emulateFirmware) { + newHit = converter.firmwareHitDtoA(hit); + if (newHit==null) continue; + } else { + newHit = converter.HitDtoA(hit); + } + // Get the channel data. EcalChannelConstants channelData = findChannel(newHit.getCellID()); Added: java/trunk/steering-files/src/main/resources/org/hps/steering/users/baltzell/EngineeringRun2014ECalRecon_Pass1_FirmwareEmulator.lcsim ============================================================================= --- java/trunk/steering-files/src/main/resources/org/hps/steering/users/baltzell/EngineeringRun2014ECalRecon_Pass1_FirmwareEmulator.lcsim (added) +++ java/trunk/steering-files/src/main/resources/org/hps/steering/users/baltzell/EngineeringRun2014ECalRecon_Pass1_FirmwareEmulator.lcsim Thu Feb 26 17:59:21 2015 @@ -0,0 +1,70 @@ +<!-- + Offline reconstruction for 2014 engineering run (ECal only) data. + + Changes made by JM: + + -Replaced clustering Drivers with new recon.ecal.cluster classes. + -Commented out the legacy clusterer. + -Configured ReconClusterDriver to not write the rejected hit collection. + -Changed output cluster collection names. + + NAB: (Feb 11, 2015) Added EcalRunningPedestalDriver + + @author Matt Graham <[log in to unmask]> + @author Jeremy McCormick<[log in to unmask]> +--> +<lcsim xmlns:xs="http://www.w3.org/2001/XMLSchema-instance" + xs:noNamespaceSchemaLocation="http://www.lcsim.org/schemas/lcsim/1.0/lcsim.xsd"> + <execute> + <!--<driver name="EventMarkerDriver" />--> + <driver name="EcalRunningPedestal"/> + <driver name="EcalRawConverter" /> + <driver name="ReconClusterer" /> + <driver name="GTPOnlineClusterer" /> + <driver name="LCIOWriter" /> + <driver name="CleanupDriver" /> + </execute> + <drivers> + <driver name="EventMarkerDriver" type="org.lcsim.job.EventMarkerDriver"> + <eventInterval>1</eventInterval> + </driver> + <driver name="EcalRunningPedestal" type="org.hps.recon.ecal.ECalRunningPedestalDriver"> + <minLookbackEvents>10</minLookbackEvents> + <maxLookbackEvents>50</maxLookbackEvents> + </driver> + <driver name="EcalRawConverter" type="org.hps.recon.ecal.EcalRawConverterDriver"> + <ecalCollectionName>EcalCalHits</ecalCollectionName> + <use2014Gain>false</use2014Gain> + <useTimestamps>false</useTimestamps> + <useTruthTime>false</useTruthTime> + <useRunningPedestal>true</useRunningPedestal> + <useTimeWalkCorrection>true</useTimeWalkCorrection> + <emulateFirmware>true</emulateFirmware> + <leadingEdgeThreshold>12</leadingEdgeThreshold> + <nsa>20</nsa> + <nsb>100</nsb> + </driver> + <driver name="ReconClusterer" type="org.hps.recon.ecal.cluster.ReconClusterDriver"> + <logLevel>WARNING</logLevel> + <outputClusterCollectionName>EcalClusters</outputClusterCollectionName> + <hitEnergyThreshold>0.01</hitEnergyThreshold> + <seedEnergyThreshold>0.100</seedEnergyThreshold> + <clusterEnergyThreshold>0.200</clusterEnergyThreshold> + <minTime>0.0</minTime> + <timeWindow>25.0</timeWindow> + <useTimeCut>true</useTimeCut> + <writeRejectedHitCollection>false</writeRejectedHitCollection> + </driver> + <driver name="GTPOnlineClusterer" type="org.hps.recon.ecal.cluster.ClusterDriver"> + <logLevel>WARNING</logLevel> + <clustererName>GTPOnlineClusterer</clustererName> + <outputClusterCollectionName>EcalClustersGTP</outputClusterCollectionName> + <!-- seedMinEnergy --> + <cuts>0.100</cuts> + </driver> + <driver name="LCIOWriter" type="org.lcsim.util.loop.LCIODriver"> + <outputFilePath>${outputFile}.slcio</outputFilePath> + </driver> + <driver name="CleanupDriver" type="org.lcsim.recon.tracking.digitization.sisim.config.ReadoutCleanupDriver" /> + </drivers> +</lcsim>