LISTSERV mailing list manager LISTSERV 16.5

Help for HPS-SVN Archives


HPS-SVN Archives

HPS-SVN Archives


HPS-SVN@LISTSERV.SLAC.STANFORD.EDU


View:

Message:

[

First

|

Previous

|

Next

|

Last

]

By Topic:

[

First

|

Previous

|

Next

|

Last

]

By Author:

[

First

|

Previous

|

Next

|

Last

]

Font:

Proportional Font

LISTSERV Archives

LISTSERV Archives

HPS-SVN Home

HPS-SVN Home

HPS-SVN  June 2015

HPS-SVN June 2015

Subject:

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

From:

[log in to unmask]

Reply-To:

Notification of commits to the hps svn repository <[log in to unmask]>

Date:

Tue, 9 Jun 2015 02:17:58 -0000

Content-Type:

text/plain

Parts/Attachments:

Parts/Attachments

text/plain (561 lines)

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) {

Top of Message | Previous Page | Permalink

Advanced Options


Options

Log In

Log In

Get Password

Get Password


Search Archives

Search Archives


Subscribe or Unsubscribe

Subscribe or Unsubscribe


Archives

November 2017
August 2017
July 2017
January 2017
December 2016
November 2016
October 2016
September 2016
August 2016
July 2016
June 2016
May 2016
April 2016
March 2016
February 2016
January 2016
December 2015
November 2015
October 2015
September 2015
August 2015
July 2015
June 2015
May 2015
April 2015
March 2015
February 2015
January 2015
December 2014
November 2014
October 2014
September 2014
August 2014
July 2014
June 2014
May 2014
April 2014
March 2014
February 2014
January 2014
December 2013
November 2013

ATOM RSS1 RSS2



LISTSERV.SLAC.STANFORD.EDU

Secured by F-Secure Anti-Virus CataList Email List Search Powered by the LISTSERV Email List Manager

Privacy Notice, Security Notice and Terms of Use