Print

Print


Author: [log in to unmask]
Date: Mon Jun  8 19:17:47 2015
New Revision: 3115

Log:
change default pulse width to 9.6 ns

Modified:
    java/trunk/ecal-readout-sim/src/main/java/org/hps/readout/ecal/FADCEcalReadoutDriver.java

Modified: java/trunk/ecal-readout-sim/src/main/java/org/hps/readout/ecal/FADCEcalReadoutDriver.java
 =============================================================================
--- java/trunk/ecal-readout-sim/src/main/java/org/hps/readout/ecal/FADCEcalReadoutDriver.java	(original)
+++ java/trunk/ecal-readout-sim/src/main/java/org/hps/readout/ecal/FADCEcalReadoutDriver.java	Mon Jun  8 19:17:47 2015
@@ -49,41 +49,26 @@
     private Subdetector ecal;
     private EcalConditions ecalConditions = null;
     //buffer for preamp signals (units of volts, no pedestal)
-    private Map<Long, RingBuffer> signalMap = null;
+    private Map<Long, RingBuffer> analogPipelines = null;
     //ADC pipeline for readout (units of ADC counts)
-    private Map<Long, FADCPipeline> pipelineMap = null;
+    private Map<Long, FADCPipeline> digitalPipelines = null;
     //buffer for window sums
-    private Map<Long, Integer> sumMap = null;
+    private Map<Long, Integer> triggerPathHitSums = null;
     //buffer for timestamps
-    private Map<Long, Integer> timeMap = null;
+    private Map<Long, Integer> triggerPathHitTimes = null;
     //queue for hits to be output to clusterer
-    private PriorityQueue<RawCalorimeterHit> outputQueue = null;
-    //length of ring buffer (in readout cycles)
+    private PriorityQueue<RawCalorimeterHit> triggerPathDelayQueue = null;
+    //output buffer for hits
+    private LinkedList<RawCalorimeterHit> triggerPathCoincidenceQueue = new LinkedList<RawCalorimeterHit>();
     private int bufferLength = 100;
-    //length of readout pipeline (in readout cycles)
     private int pipelineLength = 2000;
-    //shaper time constant in ns
-    private double tp = 6.95;
-    //delay (number of readout periods) between start of summing window and output of hit to clusterer
+    private double tp = 9.6;
     private int delay0 = 32;
-    //start of readout window relative to trigger time (in readout cycles)
-    //in FADC documentation, "Programmable Latency" or PL
     private int readoutLatency = 100;
-    //number of ADC samples to read out
-    //in FADC documentation, "Programmable Trigger Window" or PTW
     private int readoutWindow = 100;
-    //number of ADC samples to read out before each rising threshold crossing
-    //in FADC documentation, "number of samples before" or NSB
     private int numSamplesBefore = 5;
-    //number of ADC samples to read out after each rising threshold crossing
-    //in FADC documentation, "number of samples before" or NSA
     private int numSamplesAfter = 30;
-//    private HPSEcalConverter converter = null;
-    //output buffer for hits
-    private LinkedList<RawCalorimeterHit> buffer = new LinkedList<RawCalorimeterHit>();
-    //number of readout periods for which a given hit stays in the buffer
     private int coincidenceWindow = 2;
-    //output collection name for hits read out from trigger
     private String ecalReadoutCollectionName = "EcalReadoutHits";
     private int mode = ECAL_PULSE_INTEGRAL_MODE;
     private int readoutThreshold = 10;
@@ -92,17 +77,8 @@
     private double fixedGain = -1;
     private boolean constantTriggerWindow = true;
     private boolean addNoise = false;
-
-    // 32.8 p.e./MeV = New detector in 2014
-    // 2 p.e./MeV = Test Run detector
-    private double pePerMeV = 32.8; //photoelectrons per MeV, used to calculate noise
-
-    //switch between test run and 2014 definitions of gain constants
-    // true = ONLY simulation studies in 2014
-    // false = Test Run data/simulations and 2014+ Detector's real data 
+    private double pePerMeV = 32.8;
     private boolean use2014Gain = false;
-
-    //switch between three pulse shape functions
     private PulseShape pulseShape = PulseShape.ThreePole;
 
     public enum PulseShape {
@@ -118,14 +94,34 @@
 //        converter = new HPSEcalConverter(null);
     }
 
+    /**
+     * Add noise (photoelectron statistics and readout/preamp noise) to hits
+     * before adding them to the analog pipeline.
+     *
+     * @param addNoise True to add noise, default of false.
+     */
     public void setAddNoise(boolean addNoise) {
         this.addNoise = addNoise;
     }
 
+    /**
+     * Sets the trigger-path hit processing algorithm.
+     *
+     * @param constantTriggerWindow True for 2014+ FADC behavior, false for test
+     * run behavior. True by default.
+     */
     public void setConstantTriggerWindow(boolean constantTriggerWindow) {
         this.constantTriggerWindow = constantTriggerWindow;
     }
 
+    /**
+     * Override the ECal gains set in the conditions system with a single
+     * uniform value.
+     *
+     * @param fixedGain Units of MeV/(ADC counts in pulse integral). Negative
+     * value causes the conditions system to be used for gains. Default is
+     * negative.
+     */
     public void setFixedGain(double fixedGain) {
         this.fixedGain = fixedGain;
     }
@@ -134,78 +130,176 @@
         this.ecalName = ecalName;
     }
 
+    /**
+     * Threshold for readout-path hits. For 2014+ running this should always
+     * equal the trigger threshold.
+     *
+     * @param readoutThreshold Units of ADC counts, default of 10.
+     */
     public void setReadoutThreshold(int readoutThreshold) {
         this.readoutThreshold = readoutThreshold;
     }
 
+    /**
+     * Scale factor for trigger-path hit amplitudes. Only used for test run.
+     *
+     * @param scaleFactor Default of 1.
+     */
     public void setScaleFactor(double scaleFactor) {
         this.scaleFactor = scaleFactor;
     }
 
+    /**
+     * Threshold for trigger-path hits. For 2014+ running this should always
+     * equal the readout threshold.
+     *
+     * @param triggerThreshold Units of ADC counts, default of 10.
+     */
     public void setTriggerThreshold(int triggerThreshold) {
         this.triggerThreshold = triggerThreshold;
     }
 
+    /**
+     * Output collection name for readout-path hits.
+     *
+     * @param ecalReadoutCollectionName
+     */
     public void setEcalReadoutCollectionName(String ecalReadoutCollectionName) {
         this.ecalReadoutCollectionName = ecalReadoutCollectionName;
     }
 
+    /**
+     * Number of ADC samples to process after each rising threshold crossing. In
+     * FADC documentation, "number of samples after" or NSA.
+     *
+     * @param numSamplesAfter Units of 4 ns FADC clock cycles, default of 30.
+     */
     public void setNumSamplesAfter(int numSamplesAfter) {
         this.numSamplesAfter = numSamplesAfter;
     }
 
+    /**
+     * Number of ADC samples to process before each rising threshold crossing.
+     * In FADC documentation, "number of samples before" or NSB.
+     *
+     * @param numSamplesBefore Units of 4 ns FADC clock cycles, default of 5.
+     */
     public void setNumSamplesBefore(int numSamplesBefore) {
         this.numSamplesBefore = numSamplesBefore;
     }
 
+    /**
+     * Start of readout window relative to trigger time (in readout cycles). In
+     * FADC documentation, "Programmable Latency" or PL.
+     *
+     * @param readoutLatency Units of 4 ns FADC clock cycles, default of 100.
+     */
     public void setReadoutLatency(int readoutLatency) {
         this.readoutLatency = readoutLatency;
     }
 
+    /**
+     * Number of ADC samples to read out. In FADC documentation, "Programmable
+     * Trigger Window" or PTW.
+     *
+     * @param readoutWindow Units of 4 ns FADC clock cycles, default of 100.
+     */
     public void setReadoutWindow(int readoutWindow) {
         this.readoutWindow = readoutWindow;
     }
 
+    /**
+     * Number of clock cycles for which the same trigger-path hit is sent to the
+     * clusterer. Only used for old clusterer simulations (CTPClusterDriver).
+     * Otherwise this should be set to 1.
+     *
+     * @param coincidenceWindow Units of 4 ns FADC clock cycles, default of 1.
+     */
     public void setCoincidenceWindow(int coincidenceWindow) {
         this.coincidenceWindow = coincidenceWindow;
     }
 
+    /**
+     * Switch between test run and 2014 definitions of gain constants. True for
+     * MC studies and mock data in 2014. For all real data (test run and 2014+),
+     * test run MC, and 2015+ production MC, this should be false.
+     *
+     *
+     * @param use2014Gain True ONLY for simulation studies in 2014. Default of
+     * false.
+     */
     public void setUse2014Gain(boolean use2014Gain) {
         this.use2014Gain = use2014Gain;
     }
 
+    /**
+     * Model used for the preamp pulse shape.
+     *
+     * @param pulseShape ThreePole, DoubleGaussian, or CRRC. Default is
+     * ThreePole.
+     */
     public void setPulseShape(String pulseShape) {
         this.pulseShape = PulseShape.valueOf(pulseShape);
     }
 
+    /**
+     * Shaper time constant. Definition depends on the pulse shape. For the
+     * three-pole function, this is equal to RC, or half the peaking time.
+     *
+     * @param tp Units of ns, default of 9.6.
+     */
     public void setTp(double tp) {
         this.tp = tp;
     }
 
-//    public void setFallTime(double fallTime) {
-//        this.fallTime = fallTime;
-//    }
+    /**
+     * Photoelectrons per MeV, used to calculate noise due to photoelectron
+     * statistics. Test run detector had a value of 2 photoelectrons/MeV; new
+     * 2014 detector has a value of 32.8 photoelectrons/MeV.
+     *
+     * @param pePerMeV Units of photoelectrons/MeV, default of 32.8.
+     */
     public void setPePerMeV(double pePerMeV) {
         this.pePerMeV = pePerMeV;
     }
 
-//    public void setRiseTime(double riseTime) {
-//        this.riseTime = riseTime;
-//    }
+    /**
+     * Latency between threshold crossing and output of trigger-path hit to
+     * clusterer.
+     *
+     * @param delay0 Units of 4 ns FADC clock cycles, default of 32.
+     */
     public void setDelay0(int delay0) {
         this.delay0 = delay0;
     }
 
+    /**
+     * Length of analog pipeline.
+     *
+     * @param bufferLength Units of 4 ns FADC clock cycles, default of 100.
+     */
     public void setBufferLength(int bufferLength) {
         this.bufferLength = bufferLength;
         resetFADCBuffers();
     }
 
+    /**
+     * Length of digital pipeline. The digital pipeline in the FADC is 2000
+     * cells long.
+     *
+     * @param pipelineLength Units of 4 ns FADC clock cycles, default of 2000.
+     */
     public void setPipelineLength(int pipelineLength) {
         this.pipelineLength = pipelineLength;
         resetFADCBuffers();
     }
 
+    /**
+     * Mode for readout-path hits.
+     *
+     * @param mode 1, 2 or 3. Values correspond to the standard FADC mode
+     * numbers (1=raw, 2=pulse, 3=pulse integral).
+     */
     public void setMode(int mode) {
         this.mode = mode;
         if (mode != ECAL_RAW_MODE && mode != ECAL_PULSE_MODE && mode != ECAL_PULSE_INTEGRAL_MODE) {
@@ -219,7 +313,7 @@
      * @return
      */
     public Map<Long, RingBuffer> getSignalMap() {
-        return signalMap;
+        return analogPipelines;
     }
 
     /**
@@ -228,16 +322,23 @@
      * @return
      */
     public Map<Long, FADCPipeline> getPipelineMap() {
-        return pipelineMap;
-    }
-
+        return digitalPipelines;
+    }
+
+    /**
+     * Digitize values in the analog pipelines and append them to the digital
+     * pipelines. Integrate trigger-path hits and add them to the trigger path
+     * queues. Read out trigger-path hits to the list sent to the clusterer.
+     *
+     * @param hits List to be filled by this method.
+     */
     @Override
     protected void readHits(List<RawCalorimeterHit> hits) {
 
-        for (Long cellID : signalMap.keySet()) {
-            RingBuffer signalBuffer = signalMap.get(cellID);
-
-            FADCPipeline pipeline = pipelineMap.get(cellID);
+        for (Long cellID : analogPipelines.keySet()) {
+            RingBuffer signalBuffer = analogPipelines.get(cellID);
+
+            FADCPipeline pipeline = digitalPipelines.get(cellID);
             pipeline.step();
 
             // Get the channel data.
@@ -250,9 +351,9 @@
             int pedestalSubtractedValue = digitizedValue - pedestal;
             //System.out.println(signalBuffer.currentValue() + "   " + currentValue + "   " + pipeline.currentValue());
 
-            Integer sum = sumMap.get(cellID);
+            Integer sum = triggerPathHitSums.get(cellID);
             if (sum == null && pedestalSubtractedValue > triggerThreshold) {
-                timeMap.put(cellID, readoutCounter);
+                triggerPathHitTimes.put(cellID, readoutCounter);
                 if (constantTriggerWindow) {
                     int sumBefore = 0;
                     for (int i = 0; i < numSamplesBefore; i++) {
@@ -261,57 +362,57 @@
                         }
                         sumBefore += pipeline.getValue(numSamplesBefore - i - 1);
                     }
-                    sumMap.put(cellID, sumBefore);
+                    triggerPathHitSums.put(cellID, sumBefore);
                 } else {
-                    sumMap.put(cellID, pedestalSubtractedValue);
+                    triggerPathHitSums.put(cellID, pedestalSubtractedValue);
                 }
             }
             if (sum != null) {
                 if (constantTriggerWindow) {
-                    if (timeMap.get(cellID) + numSamplesAfter >= readoutCounter) {
+                    if (triggerPathHitTimes.get(cellID) + numSamplesAfter >= readoutCounter) {
                         if (debug) {
-                            System.out.format("trigger %d, %d: %d\n", cellID, readoutCounter - timeMap.get(cellID) + numSamplesBefore - 1, pipeline.getValue(0));
+                            System.out.format("trigger %d, %d: %d\n", cellID, readoutCounter - triggerPathHitTimes.get(cellID) + numSamplesBefore - 1, pipeline.getValue(0));
                         }
-                        sumMap.put(cellID, sum + pipeline.getValue(0));
-                    } else if (timeMap.get(cellID) + delay0 <= readoutCounter) {
+                        triggerPathHitSums.put(cellID, sum + pipeline.getValue(0));
+                    } else if (triggerPathHitTimes.get(cellID) + delay0 <= readoutCounter) {
 //                        System.out.printf("sum = %f\n", sum);
-                        outputQueue.add(new BaseRawCalorimeterHit(cellID,
+                        triggerPathDelayQueue.add(new BaseRawCalorimeterHit(cellID,
                                 (int) Math.round(sum / scaleFactor),
-                                64 * timeMap.get(cellID)));
-                        sumMap.remove(cellID);
+                                64 * triggerPathHitTimes.get(cellID)));
+                        triggerPathHitSums.remove(cellID);
                     }
                 } else {
-                    if (pedestalSubtractedValue < triggerThreshold || timeMap.get(cellID) + delay0 == readoutCounter) {
+                    if (pedestalSubtractedValue < triggerThreshold || triggerPathHitTimes.get(cellID) + delay0 == readoutCounter) {
 //					System.out.printf("sum = %f\n",sum);
-                        outputQueue.add(new BaseRawCalorimeterHit(cellID,
+                        triggerPathDelayQueue.add(new BaseRawCalorimeterHit(cellID,
                                 (int) Math.round((sum + pedestalSubtractedValue) / scaleFactor),
-                                64 * timeMap.get(cellID)));
-                        sumMap.remove(cellID);
+                                64 * triggerPathHitTimes.get(cellID)));
+                        triggerPathHitSums.remove(cellID);
                     } else {
-                        sumMap.put(cellID, sum + pedestalSubtractedValue);
+                        triggerPathHitSums.put(cellID, sum + pedestalSubtractedValue);
                     }
                 }
             }
             signalBuffer.step();
         }
-        while (outputQueue.peek() != null && outputQueue.peek().getTimeStamp() / 64 <= readoutCounter - delay0) {
-            if (outputQueue.peek().getTimeStamp() / 64 < readoutCounter - delay0) {
+        while (triggerPathDelayQueue.peek() != null && triggerPathDelayQueue.peek().getTimeStamp() / 64 <= readoutCounter - delay0) {
+            if (triggerPathDelayQueue.peek().getTimeStamp() / 64 < readoutCounter - delay0) {
                 System.out.println(this.getName() + ": Stale hit in output queue");
-                outputQueue.poll();
+                triggerPathDelayQueue.poll();
             } else {
-                buffer.add(outputQueue.poll());
-            }
-        }
-        while (!buffer.isEmpty() && buffer.peek().getTimeStamp() / 64 <= readoutCounter - delay0 - coincidenceWindow) {
-            buffer.remove();
+                triggerPathCoincidenceQueue.add(triggerPathDelayQueue.poll());
+            }
+        }
+        while (!triggerPathCoincidenceQueue.isEmpty() && triggerPathCoincidenceQueue.peek().getTimeStamp() / 64 <= readoutCounter - delay0 - coincidenceWindow) {
+            triggerPathCoincidenceQueue.remove();
         }
         if (debug) {
-            for (RawCalorimeterHit hit : buffer) {
+            for (RawCalorimeterHit hit : triggerPathCoincidenceQueue) {
                 System.out.format("new hit: energy %d\n", hit.getAmplitude());
             }
         }
 
-        hits.addAll(buffer);
+        hits.addAll(triggerPathCoincidenceQueue);
     }
 
     @Override
@@ -355,7 +456,7 @@
     }
 
     protected short[] getWindow(long cellID) {
-        FADCPipeline pipeline = pipelineMap.get(cellID);
+        FADCPipeline pipeline = digitalPipelines.get(cellID);
         short[] adcValues = new short[readoutWindow];
         for (int i = 0; i < readoutWindow; i++) {
             adcValues[i] = (short) pipeline.getValue(readoutLatency - i - 1);
@@ -369,7 +470,7 @@
     protected List<RawTrackerHit> readWindow() {
 //		System.out.println("Reading FADC data");
         List<RawTrackerHit> hits = new ArrayList<RawTrackerHit>();
-        for (Long cellID : pipelineMap.keySet()) {
+        for (Long cellID : digitalPipelines.keySet()) {
             short[] adcValues = getWindow(cellID);
             EcalChannelConstants channelData = findChannel(cellID);
             boolean isAboveThreshold = false;
@@ -389,7 +490,7 @@
     protected List<RawTrackerHit> readPulses() {
 //		System.out.println("Reading FADC data");
         List<RawTrackerHit> hits = new ArrayList<RawTrackerHit>();
-        for (Long cellID : pipelineMap.keySet()) {
+        for (Long cellID : digitalPipelines.keySet()) {
             short[] window = getWindow(cellID);
             short[] adcValues = null;
             int pointerOffset = 0;
@@ -423,7 +524,7 @@
     protected List<RawCalorimeterHit> readIntegrals() {
 //		System.out.println("Reading FADC data");
         List<RawCalorimeterHit> hits = new ArrayList<RawCalorimeterHit>();
-        for (Long cellID : pipelineMap.keySet()) {
+        for (Long cellID : digitalPipelines.keySet()) {
             short[] window = getWindow(cellID);
             int adcSum = 0;
             int pointerOffset = 0;
@@ -456,11 +557,17 @@
         return hits;
     }
 
+    /**
+     * Fill the analog pipelines with the preamp pulses generated by hits in the
+     * ECal.
+     *
+     * @param hits ECal hits from SLIC/Geant4.
+     */
     @Override
     protected void putHits(List<CalorimeterHit> hits) {
         //fill the readout buffers
         for (CalorimeterHit hit : hits) {
-            RingBuffer eDepBuffer = signalMap.get(hit.getCellID());
+            RingBuffer eDepBuffer = analogPipelines.get(hit.getCellID());
             double energyAmplitude = hit.getRawEnergy();
             // Get the channel data.
             EcalChannelConstants channelData = findChannel(hit.getCellID());
@@ -476,6 +583,9 @@
                 }
                 energyAmplitude += RandomGaussian.getGaussian(0, noise);
             }
+            if ((1) * readoutPeriod + readoutTime() - (ClockSingleton.getTime() + hit.getTime()) >= readoutPeriod) {
+                throw new RuntimeException("trying to add a hit to the analog pipeline, but time seems incorrect");
+            }
             for (int i = 0; i < bufferLength; i++) {
                 eDepBuffer.addToCell(i, energyAmplitude * pulseAmplitude((i + 1) * readoutPeriod + readoutTime() - (ClockSingleton.getTime() + hit.getTime()), hit.getCellID()));
             }
@@ -485,9 +595,9 @@
     @Override
     protected void initReadout() {
         //initialize buffers
-        sumMap = new HashMap<Long, Integer>();
-        timeMap = new HashMap<Long, Integer>();
-        outputQueue = new PriorityQueue(20, new TimeComparator());
+        triggerPathHitSums = new HashMap<Long, Integer>();
+        triggerPathHitTimes = new HashMap<Long, Integer>();
+        triggerPathDelayQueue = new PriorityQueue(20, new TimeComparator());
         resetFADCBuffers();
     }
 
@@ -506,17 +616,26 @@
         if (ecal == null) {
             return false;
         }
-        signalMap = new HashMap<Long, RingBuffer>();
-        pipelineMap = new HashMap<Long, FADCPipeline>();
+        analogPipelines = new HashMap<Long, RingBuffer>();
+        digitalPipelines = new HashMap<Long, FADCPipeline>();
         Set<Long> cells = ((HPSEcal3) ecal).getNeighborMap().keySet();
         for (Long cellID : cells) {
             EcalChannelConstants channelData = findChannel(cellID);
-            signalMap.put(cellID, new RingBuffer(bufferLength));
-            pipelineMap.put(cellID, new FADCPipeline(pipelineLength, (int) Math.round(channelData.getCalibration().getPedestal())));
+            analogPipelines.put(cellID, new RingBuffer(bufferLength));
+            digitalPipelines.put(cellID, new FADCPipeline(pipelineLength, (int) Math.round(channelData.getCalibration().getPedestal())));
         }
         return true;
     }
 
+    /**
+     * Returns pulse amplitude at the given time (relative to hit time). Gain is
+     * applied.
+     *
+     * @param time Units of ns. Relative to hit time (negative=before the start
+     * of the pulse).
+     * @param cellID Crystal ID as returned by hit.getCellID().
+     * @return Amplitude, units of volts/GeV.
+     */
     private double pulseAmplitude(double time, long cellID) {
         // Get the channel data.
         EcalChannelConstants channelData = findChannel(cellID);
@@ -546,10 +665,11 @@
 
     /**
      * Returns pulse amplitude at the given time (relative to hit time).
-     * Amplitude is normalized so the pulse integral is 1.
-     *
-     * @param time
-     * @return
+     *
+     * @param time Units of ns. Relative to hit time (negative=before the start
+     * of the pulse).
+     * @return Amplitude, units of inverse ns. Normalized so the pulse integral
+     * is 1.
      */
     public static double pulseAmplitude(double time, PulseShape shape, double shapingTime) {
         if (time <= 0.0) {