Author: [log in to unmask] Date: Mon May 23 15:38:21 2016 New Revision: 4370 Log: one driver to correct them all (ecal time hits) Added: java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/EcalTimeCorrectionDriver.java Added: java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/EcalTimeCorrectionDriver.java ============================================================================= --- java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/EcalTimeCorrectionDriver.java (added) +++ java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/EcalTimeCorrectionDriver.java Mon May 23 15:38:21 2016 @@ -0,0 +1,152 @@ +package org.hps.recon.ecal; + +import java.util.ArrayList; +import java.util.List; + +import org.hps.conditions.database.DatabaseConditionsManager; +import org.hps.conditions.ecal.EcalChannelConstants; +import org.hps.conditions.ecal.EcalConditions; +import org.hps.conditions.ecal.EcalTimeWalk; +import org.hps.conditions.ecal.EcalTimeWalk.EcalTimeWalkCollection; +import org.lcsim.event.CalorimeterHit; +import org.lcsim.event.EventHeader; +import org.lcsim.geometry.Detector; +import org.lcsim.util.Driver; + +/** + * Perform time walk correction on ECal hits and create new collection of hits with corrected time. + * + * @author Jeremy McCormick, SLAC + */ +public class EcalTimeCorrectionDriver extends Driver { + + private String inputHitsCollectionName = "EcalCalHits"; + private String outputHitsCollectionName = "TimeCorrEcalHits"; + + /** + * ecalCollectionName "type" (must match detector-data) + */ + private final String ecalReadoutName = "EcalHits"; + + private boolean mode3 = false; + private boolean useFit = true; + private boolean useTimeWalkCondition = true; + + private EcalConditions ecalConditions = null; + + public void setMode3(boolean mode3) { + this.mode3 = mode3; + } + + public void setUseFit(boolean useFit) { + this.useFit = useFit; + } + + public void setUseTimeWalkCondition(boolean useTimeWalkCondition) { + this.useTimeWalkCondition = useTimeWalkCondition; + } + + /** + * Set the output {@link org.lcsim.event.CalorimeterHit} collection name, + * + * @param ecalCollectionName The <code>CalorimeterHit</code> collection name. + */ + public void setInputHitsCollectionName(String inputHitsCollectionName) { + this.inputHitsCollectionName = inputHitsCollectionName; + } + + // Time walk default parameters for mode 3. Not studied since 2014 run. + // This is basically not used anymore. + private static final double[] DEFAULT_PARAMETERS = {3.64218e+01, -4.60756e+02, 9.18743e+03, 3.73873e+01, + -6.57130e+01, 1.07182e+02}; + + private double[] parameters = DEFAULT_PARAMETERS; + + /* + * Time walk parameters for mode 1. These parameters were dervied from data for both 2015 and 2016 running. + */ + public void detectorChanged(Detector detector) { + System.out.println("detector changed"); + + if (useTimeWalkCondition) { + DatabaseConditionsManager manager = DatabaseConditionsManager.getInstance(); + EcalTimeWalkCollection timeWalks = manager.getCachedConditions(EcalTimeWalkCollection.class, + "ecal_time_walk").getCachedData(); + ecalConditions = manager.getEcalConditions(); + + EcalTimeWalk timeWalk = timeWalks.get(0); + parameters = new double[6]; + parameters[0] = timeWalk.getP0(); + parameters[1] = timeWalk.getP1(); + parameters[2] = timeWalk.getP2(); + parameters[3] = timeWalk.getP3(); + parameters[4] = timeWalk.getP4(); + } + } + + public void process(EventHeader event) { + + List<CalorimeterHit> hits = event.get(CalorimeterHit.class, inputHitsCollectionName); + + List<CalorimeterHit> newHits = new ArrayList<CalorimeterHit>(); + + for (CalorimeterHit hit : hits) { + double time = hit.getTime(); + double energy = hit.getRawEnergy(); + + if (mode3) { + time = correctTimeWalk(time, energy); + + } else if (useFit) { + time = correctTimeWalkPulseFitting(time, energy); + + } + + //Apply overall time offset + time -= findChannel(hit.getCellID()).getTimeShift().getTimeShift(); + + newHits.add(CalorimeterHitUtilities.create(energy, time, hit.getCellID())); + } + + event.put(this.outputHitsCollectionName, newHits, CalorimeterHit.class, event.getMetaData(hits).getFlags(), ecalReadoutName); + + } + + /** + * Perform time walk correction. + * + * @param time FADC Mode-3 Hit time (ns) + * @param energy Pulse energy (GeV) + * @return corrected time (ns) + */ + private final double correctTimeWalk(double time, double energy) { + final double poly1 = parameters[0] + parameters[1] * energy + parameters[2] * energy * energy; + final double poly2 = parameters[3] * energy + parameters[4] * energy * energy + parameters[5] + * Math.pow(energy, 4); + return time - poly1 * Math.exp(-poly2); + } + + /** + * Perform time walk correction for mode 1 hits using pulse fitting. + * + * @param time FADC Mode 1 hit time from pulse fitting (ns) + * @param energy Pulse energy from pulse fitting (GeV) + * @return corrected time (ns) + */ + private final double correctTimeWalkPulseFitting(double time, double energy) { + final double polyA = parameters[0] + parameters[1] * energy; + final double polyB = parameters[2] + parameters[3] * energy + parameters[4] * Math.pow(energy, 2); + return time - (Math.exp(polyA) + polyB); + } + + /** + * Convert physical ID to gain value. + * + * @param cellID (long) + * @return channel constants (EcalChannelConstants) + */ + public EcalChannelConstants findChannel(long cellID) { + return ecalConditions.getChannelConstants(ecalConditions.getChannelCollection().findGeometric(cellID)); + } + +}