Author: [log in to unmask] Date: Sat Jan 31 17:18:52 2015 New Revision: 2019 Log: 1st running pedestal Added: java/trunk/users/src/main/java/org/hps/users/baltzell/ java/trunk/users/src/main/java/org/hps/users/baltzell/ECalRunningPedestalDriver.java java/trunk/users/src/main/java/org/hps/users/baltzell/EcalRawConverterDriver_RunPed.java java/trunk/users/src/main/java/org/hps/users/baltzell/EcalRawConverter_RunPed.java Added: java/trunk/users/src/main/java/org/hps/users/baltzell/ECalRunningPedestalDriver.java ============================================================================= --- java/trunk/users/src/main/java/org/hps/users/baltzell/ECalRunningPedestalDriver.java (added) +++ java/trunk/users/src/main/java/org/hps/users/baltzell/ECalRunningPedestalDriver.java Sat Jan 31 17:18:52 2015 @@ -0,0 +1,213 @@ +package org.hps.users.baltzell; + +import java.util.ArrayList; +import java.util.List; + +import org.hps.conditions.database.TableConstants; +import org.hps.conditions.ecal.EcalChannel; +import org.hps.conditions.ecal.EcalChannelConstants; +import org.hps.conditions.ecal.EcalConditions; +import org.hps.recon.ecal.HitExtraData; +import org.lcsim.conditions.ConditionsManager; +import org.lcsim.event.EventHeader; +import org.lcsim.event.GenericObject; +import org.lcsim.event.LCRelation; +import org.lcsim.event.RawCalorimeterHit; +import org.lcsim.geometry.Detector; +import org.lcsim.util.Driver; + +/** + * Calculate a running pedestal average for every channel from Mode7 FADCs. + * @version $Id: ECalRunningPedestalDriver.java,v 0.0 2015/01/31 00:00:00 + * @author <[log in to unmask]> + */ +public class ECalRunningPedestalDriver extends Driver { + + // limit array lengths: + private final int limitLookbackEvents = 1000; + + // minimum number of readouts for running averages: + // (if not satisfied, use pedestals from database) + private int minLookbackEvents = 10; + + // maximum number of readouts for running averages: + // (if too many, discard the oldest ones) + private int maxLookbackEvents = 100; + + // oldest allowed time for running averages: + // (discard older readouts ; negative = no time limit) + private long maxLookbackTime = -1; // units = ms + + private static final String rawCollectionName = "EcalReadoutHits"; + private static final String extraDataRelationsName = "EcalReadoutExtraDataRelations"; + private static final String runningPedestalsName = "EcalRunningPedestals"; + + // FIXME: + private final int nChannels = 442; + + // running pedestal averages, one for each channel: + private List<Double> runningPedestals = new ArrayList<Double>(nChannels); + + // FIXME: + // recent event-by-event pedestals and timestamps: + private List<Integer>[] eventPedestals = (ArrayList<Integer>[]) new ArrayList[nChannels]; + private List<Long>[] eventTimestamps = (ArrayList<Long>[]) new ArrayList[nChannels]; + + private EcalConditions ecalConditions = null; + + + + public ECalRunningPedestalDriver() { + for (int ii = 0; ii < nChannels; ii++) { + eventPedestals[ii] = new ArrayList<>(); + eventTimestamps[ii] = new ArrayList<>(); + runningPedestals.add(-1.); // would like to initialize with DB pedestals, but they're not available yet + } + } + @Override + protected void startOfData() { + } + + @Override + public void detectorChanged(Detector detector) { + ecalConditions = ConditionsManager.defaultInstance() + .getCachedConditions(EcalConditions.class,TableConstants.ECAL_CONDITIONS) + .getCachedData(); + } + public void setMinLookbackEvents(int nev) { + minLookbackEvents = nev; + } + public void setMaxLookbackEvents(int nev) { + maxLookbackEvents = nev; + } + public void setMaxLookbackTime(int time) { + maxLookbackTime = time; + } + + + public double getPedestal(int channel_id) { + final int nped = eventPedestals[channel_id - 1].size(); + if (nped < minLookbackEvents) return getStaticPedestal(channel_id); + else return runningPedestals.get(channel_id - 1); + } + + public void printPedestals() { + for (int ii = 0; ii < nChannels; ii++) { + System.out.printf("(%d,%.2f,%.2f) ",ii,runningPedestals.get(ii),getStaticPedestal(ii + 1)); + } + System.out.printf("\n"); + } + + @Override + protected void process(EventHeader event) { + if (!event.hasCollection(RawCalorimeterHit.class,rawCollectionName)) + return; + if (!event.hasCollection(LCRelation.class,extraDataRelationsName)) + return; + for (LCRelation rel : event.get(LCRelation.class,extraDataRelationsName)) { + RawCalorimeterHit hit = (RawCalorimeterHit) rel.getFrom(); + GenericObject extraData = (GenericObject) rel.getTo(); + updatePedestal(event,hit,extraData); + } + + // quick fix until I know how to read from DB before 'process': + List<Double> peds = new ArrayList<Double>(nChannels); + for (int ii=0; ii<nChannels; ii++){ + peds.add(ii,getPedestal(ii+1)); + } + + // + // don't care right now whether this persists in output slcio, + // just that it is accessible during reconstruction (and it is) + // + // Another option would be to put hits' running pedestals into HitExtraData.Mode7Data + // Or create another LCRelation + // Either would also remove the need for indexing later. + // + event.put(runningPedestalsName,peds,Double.class,1,"dog"); +// event.put(runningPedestalsName,runningPedestals,Double.class,1,"dog"); + +// printPedestals(); + } + + public void updatePedestal(EventHeader event, RawCalorimeterHit hit, GenericObject mode7data) { + final int ii = getChannelID(hit) - 1; + if (ii < 0 || ii >= nChannels) { + System.err.println(String.format("Event #%d, Invalid id: %d/%d ", + event.getEventNumber(),ii + 1,+hit.getCellID())); + } + + final long timestamp = event.getTimeStamp(); + final int min = ((HitExtraData.Mode7Data) mode7data).getAmplLow(); + final int max = ((HitExtraData.Mode7Data) mode7data).getAmplHigh(); + + // ignore if pulse at beginning of window: + if (max <= 0) return; + + // If new timestamp is older than previous one, restart pedestals. + // This should never happen unless firmware counter cycles back to zero, + // in which case it could be dealt with if max timestamp is known. + if (eventTimestamps[ii].size() > 0 && eventTimestamps[ii].get(0) > timestamp) { + System.err.println(String.format("Event #%d, Old Timestamp: %d < %d", + event.getEventNumber(),timestamp,eventTimestamps[ii].get(0))); + eventPedestals[ii].clear(); + eventTimestamps[ii].clear(); + } + + // add pedestal to the list: + eventPedestals[ii].add(min); + eventTimestamps[ii].add(timestamp); + + if (eventPedestals[ii].size() > 1) { + + // remove oldest pedestal if we surpassed limit on #events: + if (eventPedestals[ii].size() > limitLookbackEvents + || (maxLookbackEvents > 0 && eventPedestals[ii].size() > maxLookbackEvents)) { + eventPedestals[ii].remove(0); + eventTimestamps[ii].remove(0); + } + + // remove old pedestals surpassing limit on lookback time: + if (maxLookbackTime > 0) { + while (eventTimestamps[ii].size() > 0) { + if (eventTimestamps[ii].get(0) < timestamp - maxLookbackTime*1e6) { + eventTimestamps[ii].remove(0); + eventPedestals[ii].remove(0); + } else { + break; + } + } + } + } + + // Update running pedestal average: + if (eventPedestals[ii].size() > 0) { + double avg = 0; + for (int jj = 0; jj < eventPedestals[ii].size(); jj++) { + avg += eventPedestals[ii].get(jj); + } + runningPedestals.set(ii,avg / eventPedestals[ii].size()); + } else { + runningPedestals.set(ii,getStaticPedestal(ii+1)); + } + } + + public double getPedestal(RawCalorimeterHit hit) { + return getPedestal(getChannelID(hit)); + } + private double getStaticPedestal(int channel_id) { + EcalChannel cc = ecalConditions.getChannelCollection().findChannel(channel_id); + return ecalConditions.getChannelConstants(cc).getCalibration().getPedestal(); + } + private double getStaticPedestal(RawCalorimeterHit hit) { + return getStaticPedestal(getChannelID(hit)); + } + public int getChannelID(RawCalorimeterHit hit) { + return findChannel(hit.getCellID()).getCalibration().getChannelId(); + } + public EcalChannelConstants findChannel(long cellID) { + return ecalConditions.getChannelConstants(ecalConditions.getChannelCollection() + .findGeometric(cellID)); + } + +} Added: java/trunk/users/src/main/java/org/hps/users/baltzell/EcalRawConverterDriver_RunPed.java ============================================================================= --- java/trunk/users/src/main/java/org/hps/users/baltzell/EcalRawConverterDriver_RunPed.java (added) +++ java/trunk/users/src/main/java/org/hps/users/baltzell/EcalRawConverterDriver_RunPed.java Sat Jan 31 17:18:52 2015 @@ -0,0 +1,301 @@ +package org.hps.users.baltzell; + +import java.util.ArrayList; +import java.util.List; +import org.hps.conditions.database.TableConstants; +import org.hps.conditions.ecal.EcalChannelConstants; +import org.hps.conditions.ecal.EcalConditions; +import org.lcsim.conditions.ConditionsManager; +import org.lcsim.event.CalorimeterHit; +import org.lcsim.event.EventHeader; +import org.lcsim.event.GenericObject; +import org.lcsim.event.LCRelation; +import org.lcsim.event.RawCalorimeterHit; +import org.lcsim.event.RawTrackerHit; +import org.lcsim.geometry.Detector; +import org.lcsim.lcio.LCIOConstants; +import org.lcsim.util.Driver; + +/** + * + * @version $Id: HPSEcalRawConverterDriver.java,v 1.2 2012/05/03 00:17:54 + * phansson Exp $ + */ +public class EcalRawConverterDriver_RunPed extends Driver { + + // To import database conditions + private EcalConditions ecalConditions = null; + + private EcalRawConverter_RunPed converter = null; + private String rawCollectionName = "EcalReadoutHits"; + private final String ecalReadoutName = "EcalHits"; + private String ecalCollectionName = "EcalCalHits"; + + 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; + private boolean dropBadFADC = false; + private boolean runBackwards = false; + private boolean useTimestamps = false; + private boolean useTruthTime = false; + + public EcalRawConverterDriver_RunPed() { + converter = new EcalRawConverter_RunPed(); + } + + public void setUse2014Gain(boolean use2014Gain) { + converter.setUse2014Gain(use2014Gain); + } + + public void setUseRunningPedestal(boolean useRunningPedestal) { + converter.setUseRunningPedestal(useRunningPedestal); + } + public void setRunBackwards(boolean runBackwards) { + this.runBackwards = runBackwards; + } + + public void setDropBadFADC(boolean dropBadFADC) { + this.dropBadFADC = dropBadFADC; + } + + public void setThreshold(double threshold) { + this.threshold = threshold; + } + + public void setGain(double gain) { + converter.setGain(gain); + } + + public void setIntegralWindow(int integralWindow) { + this.integralWindow = integralWindow; + } + + public void setEcalCollectionName(String ecalCollectionName) { + this.ecalCollectionName = ecalCollectionName; + } + + public void setRawCollectionName(String rawCollectionName) { + this.rawCollectionName = rawCollectionName; + } + + public void setApplyBadCrystalMap(boolean apply) { + this.applyBadCrystalMap = apply; + } + + public void setDebug(boolean debug) { + this.debug = debug; + } + + public void setUseTimestamps(boolean useTimestamps) { + this.useTimestamps = useTimestamps; + } + + public void setUseTruthTime(boolean useTruthTime) { + this.useTruthTime = useTruthTime; + } + + @Override + public void startOfData() { + if (ecalCollectionName == null) { + throw new RuntimeException("The parameter ecalCollectionName was not set!"); + } + } + + @Override + public void detectorChanged(Detector detector) { + + // set the detector for the converter + // FIXME: This method doesn't even need the detector object and does not use it. + converter.setDetector(detector); + + // ECAL combined conditions object. + ecalConditions = ConditionsManager.defaultInstance() + .getCachedConditions(EcalConditions.class, TableConstants.ECAL_CONDITIONS).getCachedData(); + } + + /** + * @return false if the channel is a good one, true if it is a bad one + * @param CalorimeterHit + */ + public boolean isBadCrystal(CalorimeterHit hit) { + // Get the channel data. + EcalChannelConstants channelData = findChannel(hit.getCellID()); + + return channelData.isBadChannel(); + } + + /** + * @return false if the ADC is a good one, true if it is a bad one + * @param CalorimeterHit + */ + public boolean isBadFADC(CalorimeterHit hit) { + return (getCrate(hit.getCellID()) == 1 && getSlot(hit.getCellID()) == 3); + } + + private static double getTimestamp(int system, EventHeader event) { //FIXME: copied from org.hps.readout.ecal.ReadoutTimestamp + if (event.hasCollection(GenericObject.class, "ReadoutTimestamps")) { + List<GenericObject> timestamps = event.get(GenericObject.class, "ReadoutTimestamps"); + for (GenericObject timestamp : timestamps) { + if (timestamp.getIntVal(0) == system) { + return timestamp.getDoubleVal(0); + } + } + return 0; + } else { + return 0; + } + } + + @Override + public void process(EventHeader event) { + final int SYSTEM_TRIGGER = 0; + final int SYSTEM_TRACKER = 1; + final int SYSTEM_ECAL = 2; + + double timeOffset = 0.0; + if (useTimestamps) { + double t0ECal = getTimestamp(SYSTEM_ECAL, event); + double t0Trig = getTimestamp(SYSTEM_TRIGGER, event); + timeOffset += (t0ECal - t0Trig) + 200.0; + } + if (useTruthTime) { + double t0ECal = getTimestamp(SYSTEM_ECAL, event); + timeOffset += ((t0ECal + 250.0) % 500.0) - 250.0; + } + + int flags = 0; + flags += 1 << LCIOConstants.RCHBIT_TIME; //store hit time + flags += 1 << LCIOConstants.RCHBIT_LONG; //store hit position; this flag has no effect for RawCalorimeterHits + + if (!runBackwards) { + ArrayList<CalorimeterHit> newHits = new ArrayList<CalorimeterHit>(); + + // Get the list of ECal hits. + if (event.hasCollection(RawTrackerHit.class, rawCollectionName)) { + List<RawTrackerHit> hits = event.get(RawTrackerHit.class, rawCollectionName); + + for (RawTrackerHit hit : hits) { + CalorimeterHit newHit = converter.HitDtoA(hit); + + // Get the channel data. + EcalChannelConstants channelData = findChannel(newHit.getCellID()); + + if (applyBadCrystalMap && channelData.isBadChannel()) { + continue; + } + if (dropBadFADC && isBadFADC(newHit)) { + continue; + } + if (newHit.getRawEnergy() > threshold) { + newHits.add(newHit); + } + } + event.put(ecalCollectionName, newHits, CalorimeterHit.class, flags, ecalReadoutName); + } + if (event.hasCollection(RawCalorimeterHit.class, rawCollectionName)) { //A.C. this is the case of the RAW pulse hits + if (event.hasCollection(LCRelation.class, extraDataRelationsName)) { // extra information available from mode 7 readout + List<LCRelation> extraDataRelations = event.get(LCRelation.class, extraDataRelationsName); + for (LCRelation rel : extraDataRelations) { + RawCalorimeterHit hit = (RawCalorimeterHit) rel.getFrom(); + if (debug) { + System.out.format("old hit energy %d\n", hit.getAmplitude()); + } + GenericObject extraData = (GenericObject) rel.getTo(); + CalorimeterHit newHit; + newHit = converter.HitDtoA(event, hit, extraData, integralWindow, timeOffset); + if (newHit.getRawEnergy() > threshold) { + if (applyBadCrystalMap && isBadCrystal(newHit)) { + continue; + } + if (dropBadFADC && isBadFADC(newHit)) { + continue; + } + if (debug) { + System.out.format("new hit energy %f\n", newHit.getRawEnergy()); + } + newHits.add(newHit); + } + + } + } else { + List<RawCalorimeterHit> hits = event.get(RawCalorimeterHit.class, rawCollectionName); + for (RawCalorimeterHit hit : hits) { + if (debug) { + System.out.format("old hit energy %d\n", hit.getAmplitude()); + } + CalorimeterHit newHit; + newHit = converter.HitDtoA(hit, integralWindow, timeOffset); + if (newHit.getRawEnergy() > threshold) { + if (applyBadCrystalMap && isBadCrystal(newHit)) { + continue; + } + if (dropBadFADC && isBadFADC(newHit)) { + continue; + } + if (debug) { + System.out.format("new hit energy %f\n", newHit.getRawEnergy()); + } + newHits.add(newHit); + } + } + } + event.put(ecalCollectionName, newHits, CalorimeterHit.class, flags, ecalReadoutName); + } + } else { + ArrayList<RawCalorimeterHit> newHits = new ArrayList<RawCalorimeterHit>(); + if (event.hasCollection(CalorimeterHit.class, ecalCollectionName)) { + List<CalorimeterHit> hits = event.get(CalorimeterHit.class, ecalCollectionName); + + for (CalorimeterHit hit : hits) { + if (debug) { + System.out.format("old hit energy %f\n", hit.getRawEnergy()); + } + RawCalorimeterHit newHit = converter.HitAtoD(hit, integralWindow); + if (newHit.getAmplitude() > 0) { + if (debug) { + System.out.format("new hit energy %d\n", newHit.getAmplitude()); + } + newHits.add(newHit); + } + } + event.put(rawCollectionName, newHits, RawCalorimeterHit.class, flags, ecalReadoutName); + } + } + } + + /** + * Convert physical ID to gain value. + * + * @param cellID (long) + * @return channel constants (EcalChannelConstants) + */ + private EcalChannelConstants findChannel(long cellID) { + return ecalConditions.getChannelConstants(ecalConditions.getChannelCollection().findGeometric(cellID)); + } + + /** + * Return crate number from cellID + * + * @param cellID (long) + * @return Crate number (int) + */ + private int getCrate(long cellID) { + // Find the ECAL channel and return the crate number. + return ecalConditions.getChannelCollection().findGeometric(cellID).getCrate(); + } + + /** + * Return slot number from cellID + * + * @param cellID (long) + * @return Slot number (int) + */ + private int getSlot(long cellID) { + // Find the ECAL channel and return the slot number. + return ecalConditions.getChannelCollection().findGeometric(cellID).getSlot(); + } +} Added: java/trunk/users/src/main/java/org/hps/users/baltzell/EcalRawConverter_RunPed.java ============================================================================= --- java/trunk/users/src/main/java/org/hps/users/baltzell/EcalRawConverter_RunPed.java (added) +++ java/trunk/users/src/main/java/org/hps/users/baltzell/EcalRawConverter_RunPed.java Sat Jan 31 17:18:52 2015 @@ -0,0 +1,184 @@ +package org.hps.users.baltzell; + +import java.util.List; + +import org.hps.conditions.database.TableConstants; +import org.hps.conditions.ecal.EcalCalibration; +import org.hps.conditions.ecal.EcalChannelConstants; +import org.hps.conditions.ecal.EcalConditions; +import org.hps.recon.ecal.CalorimeterHitUtilities; +import org.hps.recon.ecal.ECalUtils; +import org.lcsim.conditions.ConditionsManager; +import org.lcsim.event.CalorimeterHit; +import org.lcsim.event.EventHeader; +import org.lcsim.event.GenericObject; +import org.lcsim.event.RawCalorimeterHit; +import org.lcsim.event.RawTrackerHit; +import org.lcsim.event.base.BaseRawCalorimeterHit; +import org.lcsim.geometry.Detector; + +/** + * This class is used to convert {@link org.lcsim.event.RawCalorimeterHit} + * objects to {@link org.lcsim.event.CalorimeterHit} objects with energy + * information. It has methods to convert pedestal subtracted ADC counts to + * energy. + * + * Temporary: NAB January 31, 2015, just for testing running pedestal + * + * @author Sho Uemura <[log in to unmask]> + * @author Jeremy McCormick <[log in to unmask]> + * @author Andrea Celentano <[log in to unmask]> + */ +public class EcalRawConverter_RunPed { + + private boolean useRunningPedestal = false; + private boolean constantGain = false; + private double gain; + private boolean use2014Gain = true; + + private EcalConditions ecalConditions = null; + + public EcalRawConverter_RunPed() { + } + + public void setGain(double gain) { + constantGain = true; + this.gain = gain; + } + + public void setUse2014Gain(boolean use2014Gain) { + this.use2014Gain = use2014Gain; + } + + public void setUseRunningPedestal(boolean useRunningPedestal) { + this.useRunningPedestal=useRunningPedestal; + } + + // NAB January 2015 + // Choose whether to use static pedestal from database or running pedestal: + public double getPedestal(EventHeader event, long cellID) { + EcalCalibration calib = findChannel(cellID).getCalibration(); + if (useRunningPedestal) { + // works, but remove indexing by using LCRelation or adding to Mode7Data + if (event.hasCollection(Double.class,"EcalRunningPedestals")) { + List<Double> peds = event.get(Double.class,"EcalRunningPedestals"); + final int cid = calib.getChannelId()-1; + if (cid < 0 || cid>=peds.size()) { + // logger, or throw exception, ... + System.err.println("EcalRawConverter::getPedestal Bad Channel_id: "+cid); + } else { + // System.out.println(String.format("%d - %.2f",channel_id-1,peds.get(cid))); + return peds.get(cid); + } + } + } + // pedestal from database: + return calib.getPedestal(); + } + + public short sumADC(RawTrackerHit hit) { + EcalChannelConstants channelData = findChannel(hit.getCellID()); + double pedestal = channelData.getCalibration().getPedestal(); + short sum = 0; + short samples[] = hit.getADCValues(); + for (int isample = 0; isample < samples.length; ++isample) { + sum += (samples[isample] - pedestal); + } + return sum; + } + + public CalorimeterHit HitDtoA(RawTrackerHit hit) { + double time = hit.getTime(); + long id = hit.getCellID(); + double rawEnergy = adcToEnergy(sumADC(hit), id); + return CalorimeterHitUtilities.create(rawEnergy, time, id); + } + + public CalorimeterHit HitDtoA(RawCalorimeterHit hit, int window, double timeOffset) { + if (hit.getTimeStamp() % 64 != 0) { + System.out.println("unexpected timestamp " + hit.getTimeStamp()); + } + double time = hit.getTimeStamp() / 16.0; + long id = hit.getCellID(); + // Get the channel data. + EcalChannelConstants channelData = findChannel(id); + double adcSum = hit.getAmplitude() - window * channelData.getCalibration().getPedestal(); + double rawEnergy = adcToEnergy(adcSum, id); + return CalorimeterHitUtilities.create(rawEnergy, time + timeOffset, id); + //return h2; + } + + // NAB Januray 2015, mod for running pedestal + public CalorimeterHit HitDtoA(EventHeader event,RawCalorimeterHit hit, GenericObject mode7Data, int window, double timeOffset) { + double time = hit.getTimeStamp() / 16.0; //timestamps use the full 62.5 ps resolution + long id = hit.getCellID(); +// // Get the channel data. + EcalChannelConstants channelData = findChannel(id); +// double adcSum = hit.getAmplitude() - window * channelData.getCalibration().getPedestal(); +// double adcSum = hit.getAmplitude() - window * Mode7Data.getAmplLow(mode7Data); //A.C. is this the proper way to pedestal subtract in mode 7? + double adcSum = hit.getAmplitude() - window * getPedestal(event,id); + double rawEnergy = adcToEnergy(adcSum, id); + return CalorimeterHitUtilities.create(rawEnergy, time + timeOffset, id); + + //return h2; + } + + public RawCalorimeterHit HitAtoD(CalorimeterHit hit, int window) { + 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; + if (constantGain) { + amplitude = (int) Math.round((hit.getRawEnergy() / ECalUtils.MeV) / gain + window * channelData.getCalibration().getPedestal()); + } else { + amplitude = (int) Math.round((hit.getRawEnergy() / ECalUtils.MeV) / channelData.getGain().getGain() + window * channelData.getCalibration().getPedestal()); + } + RawCalorimeterHit h = new BaseRawCalorimeterHit(id, amplitude, time); + return h; + } + + /* + * return energy (units of GeV) corresponding to the ADC sum and crystal ID + */ + private double adcToEnergy(double adcSum, long cellID) { + + // Get the channel data. + EcalChannelConstants channelData = findChannel(cellID); + + if (use2014Gain) { + if (constantGain) { + return adcSum * ECalUtils.gainFactor * ECalUtils.ecalReadoutPeriod; + } else { + return channelData.getGain().getGain() * adcSum * ECalUtils.gainFactor * ECalUtils.ecalReadoutPeriod; // should not be used for the moment (2014/02) + } + } else { + if (constantGain) { + return gain * adcSum * ECalUtils.MeV; + } else { + return channelData.getGain().getGain() * adcSum * ECalUtils.MeV; //gain is defined as MeV/integrated ADC + } + } + } + + /** + * Must be set when an object EcalRawConverter is created. + * + * @param detector (long) + */ + public void setDetector(Detector detector) { + // ECAL combined conditions object. + ecalConditions = ConditionsManager.defaultInstance() + .getCachedConditions(EcalConditions.class, TableConstants.ECAL_CONDITIONS).getCachedData(); + } + + /** + * 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)); + } +}