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));
+ }
+
+}
|