Print

Print


Commit in hps-java/src/main/java/org/lcsim/hps on MAIN
evio/ECalEvioWriter.java+2-11.2 -> 1.3
    /ECalEvioReader.java+2-11.2 -> 1.3
    /LCSimTestRunEventBuilder.java+3-31.8 -> 1.9
users/meeg/HPSGenericRawTrackerHitPrintDriver.java+64added 1.1
          /HPSEcalAnalogPrintDriver.java+13-101.1 -> 1.2
          /HPSEcalDigitalPrintDriver.java+3-31.3 -> 1.4
          /HPSEcalRawTrackerHitPrintDriver.java+3-31.1 -> 1.2
util/RingBuffer.java+4-41.4 -> 1.5
recon/tracking/apv25/HPSAPV25.java+354-5531.3 -> 1.4
                    /HPSSiSensorReadout.java+451-5201.6 -> 1.7
recon/tracking/HPSDataProcessingModule.java+349-3731.10 -> 1.11
              /HPSMakeSVTCellID.java+8-81.3 -> 1.4
monitoring/MonitoringApplication.java+1-11.10 -> 1.11
+1257-1480
1 added + 12 modified, total 13 files
cleaning up SVT code in preparation for adding pedestal/noise to conditions system

hps-java/src/main/java/org/lcsim/hps/evio
ECalEvioWriter.java 1.2 -> 1.3
diff -u -r1.2 -r1.3
--- ECalEvioWriter.java	7 Apr 2012 00:07:24 -0000	1.2
+++ ECalEvioWriter.java	10 Apr 2012 01:00:13 -0000	1.3
@@ -29,7 +29,7 @@
 /**
  *
  * @author Sho Uemura <[log in to unmask]>
- * @version $Id: ECalEvioWriter.java,v 1.2 2012/04/07 00:07:24 meeg Exp $
+ * @version $Id: ECalEvioWriter.java,v 1.3 2012/04/10 01:00:13 meeg Exp $
  */
 public class ECalEvioWriter implements EvioWriter {
 
@@ -43,6 +43,7 @@
 
 	public void setEcalName(String ecalName) {
 		this.ecalName = ecalName;
+		ecalIDConverter = null;
 	}
 
 	public void setHitCollectionName(String hitCollectionName) {

hps-java/src/main/java/org/lcsim/hps/evio
ECalEvioReader.java 1.2 -> 1.3
diff -u -r1.2 -r1.3
--- ECalEvioReader.java	7 Apr 2012 00:07:24 -0000	1.2
+++ ECalEvioReader.java	10 Apr 2012 01:00:13 -0000	1.3
@@ -21,7 +21,7 @@
 /**
  *
  * @author Sho Uemura <[log in to unmask]>
- * @version $Id: ECalEvioReader.java,v 1.2 2012/04/07 00:07:24 meeg Exp $
+ * @version $Id: ECalEvioReader.java,v 1.3 2012/04/10 01:00:13 meeg Exp $
  */
 public class ECalEvioReader {
 	// Names of subdetectors.
@@ -40,6 +40,7 @@
 
 	public void setEcalName(String ecalName) {
 		this.ecalName = ecalName;
+		ecalIDConverter = null;
 	}
 
 	public void setRawCalorimeterHitCollectionName(String rawCalorimeterHitCollectionName) {

hps-java/src/main/java/org/lcsim/hps/evio
LCSimTestRunEventBuilder.java 1.8 -> 1.9
diff -u -r1.8 -r1.9
--- LCSimTestRunEventBuilder.java	7 Apr 2012 00:07:24 -0000	1.8
+++ LCSimTestRunEventBuilder.java	10 Apr 2012 01:00:13 -0000	1.9
@@ -19,7 +19,7 @@
  * Build LCSim events from EVIO data.
  * @author Sho Uemura <[log in to unmask]>
  * @author Jeremy McCormick <[log in to unmask]>
- * @version $Id: LCSimTestRunEventBuilder.java,v 1.8 2012/04/07 00:07:24 meeg Exp $
+ * @version $Id: LCSimTestRunEventBuilder.java,v 1.9 2012/04/10 01:00:13 meeg Exp $
  */
 public class LCSimTestRunEventBuilder implements LCSimEventBuilder {
 
@@ -115,9 +115,9 @@
 	}
 
 	public EventHeader makeLCSimEvent(EvioEvent evioEvent) {
-//		if (debug) {
+		if (debug) {
 			System.out.println("Read EVIO event number " + evioEvent.getHeader().getNumber());
-//		}
+		}
 		// Create a new LCSimEvent.
 		EventHeader lcsimEvent = new BaseLCSimEvent(0, evioEvent.getHeader().getNumber(), detector.getDetectorName());
 

hps-java/src/main/java/org/lcsim/hps/users/meeg
HPSGenericRawTrackerHitPrintDriver.java added at 1.1
diff -N HPSGenericRawTrackerHitPrintDriver.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ HPSGenericRawTrackerHitPrintDriver.java	10 Apr 2012 01:00:13 -0000	1.1
@@ -0,0 +1,64 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.lcsim.hps.users.meeg;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.List;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.RawTrackerHit;
+import org.lcsim.util.Driver;
+
+/**
+ *
+ * @author Sho Uemura <[log in to unmask]>
+ * @version $Id: HPSGenericRawTrackerHitPrintDriver.java,v 1.1 2012/04/10 01:00:13 meeg Exp $
+ */
+public class HPSGenericRawTrackerHitPrintDriver extends Driver {
+
+	String outputFileName;
+	PrintWriter outputStream = null;
+
+	public HPSGenericRawTrackerHitPrintDriver() {
+	}
+
+	public void setOutputFileName(String outputFileName) {
+		this.outputFileName = outputFileName;
+	}
+
+	public void startOfData() {
+		if (outputFileName != null) {
+			try {
+				outputStream = new PrintWriter(outputFileName);
+			} catch (IOException ex) {
+				throw new RuntimeException("Invalid outputFilePath!");
+			}
+		} else {
+			outputStream = new PrintWriter(System.out, true);
+		}
+	}
+
+	public void process(EventHeader event) {
+		// Get the list of ECal hits.
+		if (event.hasCollection(RawTrackerHit.class)) {
+			//outputStream.println("Reading RawTrackerHits from event " + event.getEventNumber());
+			List<List<RawTrackerHit>> listOfLists = event.get(RawTrackerHit.class);
+			for (List<RawTrackerHit> hits : listOfLists) {
+
+				//FIXME: this check is necessary because hasCollection(type, name) doesn't seem to actually check type!
+				if (!hits.isEmpty() && !RawTrackerHit.class.isInstance(hits.get(0))) {
+					return;
+				}
+					outputStream.printf("List with %d RawTrackerHits:\n", hits.size());
+				for (RawTrackerHit hit : hits) {
+					outputStream.printf("%d\t%d\n", hit.getCellID() , hit.getADCValues().length);
+					for (int i = 0; i < hit.getADCValues().length; i++) {
+						outputStream.printf("%d\n", hit.getADCValues()[i]);
+					}
+				}
+			}
+		}
+	}
+}

hps-java/src/main/java/org/lcsim/hps/users/meeg
HPSEcalAnalogPrintDriver.java 1.1 -> 1.2
diff -u -r1.1 -r1.2
--- HPSEcalAnalogPrintDriver.java	21 Mar 2012 23:26:48 -0000	1.1
+++ HPSEcalAnalogPrintDriver.java	10 Apr 2012 01:00:13 -0000	1.2
@@ -17,7 +17,7 @@
 /**
  *
  * @author Sho Uemura <[log in to unmask]>
- * @version $Id: HPSEcalAnalogPrintDriver.java,v 1.1 2012/03/21 23:26:48 meeg Exp $
+ * @version $Id: HPSEcalAnalogPrintDriver.java,v 1.2 2012/04/10 01:00:13 meeg Exp $
  */
 public class HPSEcalAnalogPrintDriver extends Driver {
 
@@ -61,6 +61,8 @@
 			} catch (IOException ex) {
 				throw new RuntimeException("Invalid outputFilePath!");
 			}
+		} else {
+			outputStream = new PrintWriter(System.out, true);
 		}
 	}
 
@@ -73,16 +75,17 @@
 	@Override
 	public void process(EventHeader event) {
 		// Get the list of ECal hits.
-		List<CalorimeterHit> hits = event.get(CalorimeterHit.class, ecalCollectionName);
-		if (hits == null) {
-			throw new RuntimeException("Event is missing ECal hits collection!");
-		}
-		for (CalorimeterHit hit : hits) {
-			dec.setID(hit.getCellID());
-			if (outputStream != null) {
+		if (event.hasCollection(CalorimeterHit.class, ecalCollectionName)) {
+			//outputStream.println("Reading RawTrackerHits from event " + event.getEventNumber());
+			List<CalorimeterHit> hits = event.get(CalorimeterHit.class, ecalCollectionName);
+
+			//FIXME: this check is necessary because hasCollection(type, name) doesn't seem to actually check type!
+			if (!hits.isEmpty() && !CalorimeterHit.class.isInstance(hits.get(0))) {
+				return;
+			}
+			for (CalorimeterHit hit : hits) {
+				dec.setID(hit.getCellID());
 				outputStream.printf("%d\t%d\t%f\t%f\n", dec.getValue("ix"), dec.getValue("iy"), hit.getTime(), hit.getRawEnergy());
-			} else {
-				System.out.printf("%d\t%d\t%f\t%f\n", dec.getValue("ix"), dec.getValue("iy"), hit.getTime(), hit.getRawEnergy());
 			}
 		}
 	}

hps-java/src/main/java/org/lcsim/hps/users/meeg
HPSEcalDigitalPrintDriver.java 1.3 -> 1.4
diff -u -r1.3 -r1.4
--- HPSEcalDigitalPrintDriver.java	7 Apr 2012 00:07:25 -0000	1.3
+++ HPSEcalDigitalPrintDriver.java	10 Apr 2012 01:00:13 -0000	1.4
@@ -17,7 +17,7 @@
 /**
  *
  * @author Sho Uemura <[log in to unmask]>
- * @version $Id: HPSEcalDigitalPrintDriver.java,v 1.3 2012/04/07 00:07:25 meeg Exp $
+ * @version $Id: HPSEcalDigitalPrintDriver.java,v 1.4 2012/04/10 01:00:13 meeg Exp $
  */
 public class HPSEcalDigitalPrintDriver extends Driver {
 
@@ -66,7 +66,7 @@
 				throw new RuntimeException("Invalid outputFilePath!");
 			}
 		} else {
-			outputStream = new PrintWriter(System.out);
+			outputStream = new PrintWriter(System.out, true);
 		}
 	}
 
@@ -86,7 +86,7 @@
 				return;
 			}
 
-			outputStream.println("Reading RawCalorimeterHit from event " + event.getEventNumber());
+			//outputStream.println("Reading RawCalorimeterHit from event " + event.getEventNumber());
 			for (RawCalorimeterHit hit : hits) {
 				dec.setID(hit.getCellID());
 				outputStream.printf("%d\t%d\t%d\t%d\n", dec.getValue("ix"), dec.getValue("iy"), hit.getTimeStamp() * timeScale, hit.getAmplitude());

hps-java/src/main/java/org/lcsim/hps/users/meeg
HPSEcalRawTrackerHitPrintDriver.java 1.1 -> 1.2
diff -u -r1.1 -r1.2
--- HPSEcalRawTrackerHitPrintDriver.java	7 Apr 2012 00:07:25 -0000	1.1
+++ HPSEcalRawTrackerHitPrintDriver.java	10 Apr 2012 01:00:13 -0000	1.2
@@ -17,7 +17,7 @@
 /**
  *
  * @author Sho Uemura <[log in to unmask]>
- * @version $Id: HPSEcalRawTrackerHitPrintDriver.java,v 1.1 2012/04/07 00:07:25 meeg Exp $
+ * @version $Id: HPSEcalRawTrackerHitPrintDriver.java,v 1.2 2012/04/10 01:00:13 meeg Exp $
  */
 public class HPSEcalRawTrackerHitPrintDriver extends Driver {
 
@@ -61,7 +61,7 @@
 				throw new RuntimeException("Invalid outputFilePath!");
 			}
 		} else {
-			outputStream = new PrintWriter(System.out);
+			outputStream = new PrintWriter(System.out, true);
 		}
 	}
 
@@ -74,7 +74,7 @@
 	public void process(EventHeader event) {
 		// Get the list of ECal hits.
 		if (event.hasCollection(RawTrackerHit.class, ecalCollectionName)) {
-			outputStream.println("Reading RawTrackerHits from event " + event.getEventNumber());
+			//outputStream.println("Reading RawTrackerHits from event " + event.getEventNumber());
 			List<RawTrackerHit> hits = event.get(RawTrackerHit.class, ecalCollectionName);
 
 			//FIXME: this check is necessary because hasCollection(type, name) doesn't seem to actually check type!

hps-java/src/main/java/org/lcsim/hps/util
RingBuffer.java 1.4 -> 1.5
diff -u -r1.4 -r1.5
--- RingBuffer.java	1 Apr 2012 21:20:56 -0000	1.4
+++ RingBuffer.java	10 Apr 2012 01:00:13 -0000	1.5
@@ -4,13 +4,13 @@
  * Ring buffer for storing ECal (and possibly SVT) samples for trigger and readout
  *
  * @author Sho Uemura <[log in to unmask]>
- * @version $Id: RingBuffer.java,v 1.4 2012/04/01 21:20:56 meeg Exp $
+ * @version $Id: RingBuffer.java,v 1.5 2012/04/10 01:00:13 meeg Exp $
  */
 public class RingBuffer {
 
-	private double[] array;
-	private int size;
-	private int ptr;
+	protected double[] array;
+	protected int size;
+	protected int ptr;
 
 	public RingBuffer(int size) {
 		this.size = size;

hps-java/src/main/java/org/lcsim/hps/recon/tracking/apv25
HPSAPV25.java 1.3 -> 1.4
diff -u -r1.3 -r1.4
--- HPSAPV25.java	30 Mar 2012 23:54:47 -0000	1.3
+++ HPSAPV25.java	10 Apr 2012 01:00:13 -0000	1.4
@@ -1,4 +1,3 @@
-
 package org.lcsim.hps.recon.tracking.apv25;
 
 //--- Java ---//
@@ -13,562 +12,364 @@
 
 //--- hps-java ---//
 import org.lcsim.hps.util.ClockSingleton;
+import org.lcsim.hps.util.RingBuffer;
 
 /**
  *
  * @author Omar Moreno <[log in to unmask]>
- * @version $Id: HPSAPV25.java,v 1.3 2012/03/30 23:54:47 omoreno Exp $
+ * @version $Id: HPSAPV25.java,v 1.4 2012/04/10 01:00:13 meeg Exp $
  */
 public class HPSAPV25 {
-    
-    //--- APV25 parameters ---//
-    //------------------------//
-    
-    private static final double APV25_FRONT_END_GAIN = 100.0; // [mV/MIP]
-    private static final double APV25_MULTIPLEXER_GAIN = 1;   // mA/MIP
-    private static final double APV25_NOISE_INTERCEPT_PEAK  =  270; // e- RMS
-    private static final double APV25_NOISE_INTERCEPT_DECON = 396;  //e- RMS
-    private static final double APV25_NOISE_SLOPE_PEAK  = 36;       // e- rms/pF
-    private static final double APV25_NOISE_SLOPE_DECON = 59.4;       // e- rms/pF
-    
-    // Number of electron-hole pairs created by a min. ionizing particle 
-    // in 300 micrometers of Si
-    private static final int MIP = 25000;  // electron-hole pairs
-    
-    // Total number of channels per APV25 chip
-    private static final int APV25_CHANNELS = 128;
-   
-    // APV25 trigger bit
-    public static boolean triggerBit = false;
-    
-    // 
-    private int    apv25ShapingTime  = 35; // [ns] 
-    private int    apv25SamplingTime = 24; // [ns]
-    private double analogDCLevel     = 0;  // [mA] (Pedestal)
-    public  int    apv25ClockCycle   = 0;
-    private String apv25Mode         = "multi-peak";
-
-    // APV25 Channel
-    private APV25Channel channel;
-
-    // Histograms
-    protected AIDA aida = AIDA.defaultInstance();
-    
-    /**
-     * Constructor
-     */
-    public HPSAPV25( )
-    {
-        // Create a single instance of an APV25 channel
-        channel = new APV25Channel();
-        
-    }
-    
-    
-    //--- Methods ---//
-    //---------------//
-    
-    /**
-     * Set the APV25 shaping time
-     * 
-     * @param shapingTime : APV25 shaping time
-     */
-    public void setShapingTime(int shapingTime)
-    {
-        apv25ShapingTime = shapingTime;
-    }
-    
-    /**
-     * Set the operating mode of the APV25 to either "peak", 
-     * "deconvolution", or "multi-peak".
-     * 
-     * @param mode : APV25 operating mode 
-     */
-    public void setAPV25Mode(String mode)
-    {
-        apv25Mode = mode;
-    }
-    
-    /**
-     * Set the time interval at which the shaper output is sampled
-     * 
-     * @param sampleTime : time interval
-     */
-    public void setSamplingTime(int sampleTime)
-    {
-        apv25SamplingTime = sampleTime;
-    }
-    
-    /**
-     * 
-     */
-    public void setAnalogDCLevel(double dcLevel)
-    {
-        analogDCLevel = dcLevel;
-    }
-       
-    /**
-     * Return an instance of an APV25 channel. Currently, there is only a 
-     * single instance of the channel ( instead of 128 that the actual chip
-     * has).  However, the analog buffers of each channels are distinct and 
-     * are stored in a sorted map for later use.
-     *
-     * @return an instance of APV25Channel
-     */
-    public APV25Channel getChannel()
-    {
-        return channel;
-    }
-            
-    /**
-     * Inject charge into a channel and shape the signal.  The resulting 
-     * shaper signal is then sampled into the analog pipeline
-     * 
-     * @param charge   : Total charge being injected
-     * @param pipeline : Analog pipeline associated with a channel
-     */
-    public APV25AnalogPipeline injectCharge( double charge,
-                                             double noiseRMS,
-                                             APV25AnalogPipeline pipeline)
-    {
-        // Shape the injected charge
-        getChannel().shapeSignal(charge);
-        
-        // Sample the resulting shaper signal
-        return getChannel().sampleShaperSignal(pipeline, noiseRMS);
-    
-    }
-    
-    /**
-     * Increment the position of the trigger and writer pointers of all
-     * channels
-     * 
-     * @param analogPipelineMap : 
-     */
-    public void incrementAllPointerPositions( 
-            Map<Integer, APV25AnalogPipeline> analogPipelineMap )
-    {
-        // Loop through all of the channels and increment the position of
-        // all the trigger and writer pointers
-        for(Map.Entry<Integer, APV25AnalogPipeline> entry : analogPipelineMap.entrySet()){
-            entry.getValue().stepWritterPointer();
-            entry.getValue().stepTriggerPointer();
-        }
-        
-    }
-    
-    /**
-     * 
-     */
-    public int getSamplingTime()
-    {
-        return apv25SamplingTime;
-    }
-    
-        
-    /**
-     * Increment the APV25 clock cycle by one
-     */
-    public void stepAPV25Clock(){
-        apv25ClockCycle += 1;
-    }
-    
-    /**
-     * 
-     */
-    public Map<Integer, double[]> APV25Multiplexer(
-       Map<Integer, APV25AnalogPipeline> pipelineMap){
-        
-        Map<Integer /* chip */, double[]> apv25Map = new HashMap<Integer, double[]>();
-        
-        // The address of the APV25.  There is only a single address for all
-        // chips
-        double[] apv25Address = { 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0 };
-        double[] output;
-        
-        // Create the data streams
-        for(int chipIndex = 0; 
-            chipIndex < Math.ceil((double) pipelineMap.size()/APV25_CHANNELS); 
-            chipIndex++){
-
-            apv25Map.put(chipIndex, createOutputArray(apv25Address, -4));
-        } 
-        
-        // Loop over all channels and readout the cells which the
-        // trigger pointer points to
-        for(int channelN = 0; channelN < pipelineMap.size(); channelN++ ){
-            
-            output 
-               = apv25Map.get((int) Math.floor(channelN/APV25_CHANNELS));
-            
-            output[channelN%128 + 12]
-               += (pipelineMap.get(channelN).readOut()/APV25_FRONT_END_GAIN)*APV25_MULTIPLEXER_GAIN + analogDCLevel;
-        
-        }
-        return apv25Map;
-    }
-    
-      /**
-         * 
-         */
-        private double[] createOutputArray( double[] address, double error ){
-            
-           // Create the array which will contain the output format. The array values
-            // will range from -4 microAmps to 4 microAmps.
-           double[] output = new double[141];
-           for( int index = 0; index < output.length; index++ ){
-               output[ index ] = -4.0;  // microAmps
-           }
-           
-           // Header
-           double[] header = { 4.0, 4.0, 4.0 };
-           
-           // Fill the array with the header, address and error bit and tick
-           System.arraycopy( header, 0, output, 0, 3);
-           output[header.length] = error;
-           System.arraycopy( address, 0, output, 4, 8);
-           output[ output.length - 1 ] = 4.0;
-
-           return output;
-        }
-        
-        //------------------------------------------//
-        //               APV25 Channel            //
-        //-----------------------------------------//
-        
-        public class APV25Channel {
-            
-            // Analog pipeline length
-            private static final int ANALOG_PIPELINE_LENGTH = 192;
-            // Analog pipeline
-            private APV25AnalogPipeline analogPipeline;
-            // Shaper signal
-            private APV25ShaperSignal shaperSignal;
-        
-            /**
-             * Constructor 
-             */
-            public APV25Channel(){} 
-
-            /**
-             * Shape the injected charge
-             * 
-             * @param charge 
-             */
-            private void shapeSignal(double charge)
-            {
-                shaperSignal = new APV25ShaperSignal(charge);
-            }
-            
-            /**
-             * Return the noise in electrons for a given strip capacitance
-             * 
-             * @param capacitance : strip capacitance in pF
-             * @return noise in electrons
-             */
-            public double computeNoise( double capacitance )
-            {
-                if( apv25Mode.equals("peak") 
-                    || apv25Mode.equals("multi-peak") ) 
-                    return APV25_NOISE_INTERCEPT_PEAK
-                       + APV25_NOISE_SLOPE_PEAK*capacitance;
-                else 
-                    return APV25_NOISE_INTERCEPT_DECON
-                       + APV25_NOISE_SLOPE_DECON*capacitance;
-            } 
-            
-            /**
-             * Sample the shaper signal and fill the analog pipeline.
-             * 
-             * @param channel : Channel number
-             */
-            private APV25AnalogPipeline sampleShaperSignal( 
-                        APV25AnalogPipeline pipeline, double noiseRMS ){
-                
-                // Set the analog pipeline corresponding to the channel
-                analogPipeline = pipeline;
-            
-                // Obtain the beam time
-                double beam_time = ClockSingleton.getTime();
-                
-                // Fill the analog pipeline starting with the cell to which 
-                // the writer pointer is pointing to.  Signals arriving within 
-                // the same bucket of length apv25SamplingTime will be shifted
-                // in time depending on when they arrive.
-                for(int cell = 0; cell < ANALOG_PIPELINE_LENGTH; cell++) {
-                
-                    // Time at which the shaper signal will be sampled
-                    int sample_time = cell*apv25SamplingTime 
-                        - ((int) beam_time)%apv25SamplingTime;
-                
-                    // Sample the shaper signal
-                    double sample 
-                       = shaperSignal.getAmplitudeAtTime(sample_time);
-                
-                    // Only add the value into the buffer if it is greater than
-                    // the noise threshold. Note that this isn't done within
-                    // the apv25, however, it will clean up the signal a bit
-                    // for simulation purposes
-                    // This should be done by the data processing module
-                    if( sample > 0.0001 /*(1*noiseRMS/MIP)*APV25_FRONT_END_GAIN)*/) {
-                       analogPipeline.addToCell(cell, sample );
-                    }
-                }
-            
-                // Reset the overflow position
-                analogPipeline.resetOverflow();
-
-                return analogPipeline;
-            }
-            
-            //-----------------------------------//
-            //--- APV25 Shaper Signal ---//
-            //-----------------------------------//
-        
-            
-            /**
-             * 
-             */
-            private class APV25ShaperSignal {
-            
-                // Shaper signal maximum amplitude
-                private double maxAmp = 0;
-           
-                /**
-                 * Constructor
-                 * 
-                 * @param charge : input charge into the channel
-                 */
-                APV25ShaperSignal( double charge ){
-                
-                    maxAmp = (charge/MIP)*APV25_FRONT_END_GAIN;  // mV
-                    
-                    //--->
-                    aida.histogram1D("Shaper Signal Max Amplitude", 100, 0, 500).fill(maxAmp);
-                    //--->
-                }
-  
-                /**
-                 * Get the amplitude at a time t
-                 * 
-                 * @param time : time at which the shaper signal is to be
-                 *               sampled
-                 */
-                private double getAmplitudeAtTime( double time ){
-
-                    return maxAmp*(time/apv25ShapingTime)*Math.exp( 
-                       1-(time/apv25ShapingTime));
-                }     
-            }
-            
-        
-            //-------------------------------------//
-            //---    APV25 Analog Pipeline      ---//
-            //-------------------------------------//
-            // Note that the buffer is modeled after a circular buffer
-        
-            public class APV25AnalogPipeline implements Iterable {
-          
-                private double[] pipeline;
-
-                public  int _trigger_pointer = 0;
-                public int _writer_pointer = 0;
-                int _trigger_latency = 220;
-                
-                int overflow_pos = 0;
-           
-            
-                /**
-                 * Constructor
-                 */
-                public APV25AnalogPipeline( ) {  
-                
-                    // Initialize the pipeline to the APV25 pipeline length
-                    pipeline = new double[ ANALOG_PIPELINE_LENGTH ];
-                
-                    // Initialize the position of the writter pointer to a
-                    // random position
-                    _writer_pointer 
-                       = (int)( Math.random()*( ANALOG_PIPELINE_LENGTH + 1 ));
-                
-                    // Set the position of the trigger pointer
-                    _trigger_pointer = _writer_pointer 
-                       - (int) Math.floor(_trigger_latency/apv25SamplingTime );
-                
-                    if( _trigger_pointer < 0 ) 
-                        _trigger_pointer += ANALOG_PIPELINE_LENGTH;
-                }
-            
-                /**
-                 * Set the trigger latency
-                 * 
-                 * @param latency : trigger latency in [ns]
-                 */
-                public void setTriggerLatency( int latency ){
-                    _trigger_latency = latency;
-                }
-            
-                /**
-                 * Reset the overflow position to the beginning of the buffer
-                 */
-                public void resetOverflow( ){
-                    overflow_pos = 0;
-                }
-            
-                /**
-                 * Add a given value to the specified buffer cell
-                 * 
-                 * @param position : position of the buffer cell
-                 * @param element : value to be added at the given position
-                 */
-                private void addToCell( int position, double element ) {
-
-                    // Offset the position by the writter pointer position
-                    position += _writer_pointer;
-                
-                    // If the cell position is at the end begin writing at the 
-                    // beginning of the buffer until the trigger pointer 
-                    // position is reached
-                    if( position >= ANALOG_PIPELINE_LENGTH 
-                        && overflow_pos != _trigger_pointer ) {
-                        position = overflow_pos;
-                        overflow_pos++;
-                    } else if( position >= ANALOG_PIPELINE_LENGTH 
-                       && overflow_pos == _trigger_pointer ) return;
-                
-                    pipeline[ position ] 
-                       = pipeline[ position ] + element;                  
-                }
-            
-                /**
-                 * Clear the specified cell of all its values
-                 */
-                private void clearCell( int position ){ 
-                    pipeline[ position ] = 0;
-                }
-            
-                /**
-                 * Step the trigger pointer to the next position in the analog
-                 * pipeline
-                 */
-                private void stepTriggerPointer( ) {
-                
-                    // First clear the element to which the trigger used to 
-                    // point to of any signal information
-                    pipeline[ _trigger_pointer ] = 0;
-                
-                    // Increment the position of the trigger pointer to the next
-                    // cell in the buffer
-                    _trigger_pointer++;
-                
-                    if( _trigger_pointer >= ANALOG_PIPELINE_LENGTH ) 
-                        _trigger_pointer = 0;
-                }
-            
-                /**
-                 * Step the writer pointer to the next position in the analog
-                 * pipeline
-                 */
-                private void stepWritterPointer( ){
-                
-                    _writer_pointer++;
-                    if( _writer_pointer >= ANALOG_PIPELINE_LENGTH )
-                        _writer_pointer = 0;
-                }
-            
-                /**
-                 * 
-                 */
-                private double readOut( ){
-
-                    double pipelineValue = pipeline[ _trigger_pointer ];
-                    pipeline[ _trigger_pointer ] = 0;
-                    return pipelineValue;
-                }
-                
-                /**
-                 * 
-                 */
-                public void printAnalogPipeline()
-                {
-                    System.out.print("[ ");
-                    for(int index = 0; index < pipeline.length; index++){
-                        if(index == _trigger_pointer){
-                            System.out.print("TP====>");
-                        }
-                        if(index == _writer_pointer){
-                            System.out.print("WP====>");
-                        }
-                        System.out.print(pipeline[index] + ", ");
-                    }
-                    System.out.println("] ");
-                }
-                
-                /**
-                 * 
-                 */
-                public double getTriggerPointerValue()
-                {
-                    return pipeline[_trigger_pointer];
-                }
-                
-                public double getTriggerPointerValuePlusOne()
-                {
-                    if(_trigger_pointer + 1 == 192) return pipeline[0];
-                    return pipeline[_trigger_pointer + 1];
-                }
-                
-            
-                /**
-                 * 
-                 */
-                @Override
-                public Iterator<Double> iterator(){ 
-                    return new APV25AnalogPipelineIterator( );
-                }
-            
-                
-                //--------------------------------------//
-                //--- APV25 Analog Pipeline Iterator ---//
-                //--------------------------------------//
-                
-                /**
-                 * 
-                 */
-                private class APV25AnalogPipelineIterator 
-                implements Iterator<Double> {
-                
-                    private int index = 0;
-                
-                
-                    /**
-                     * Checks to see if the next element in the buffer exist
-                     */
-                    @Override
-                    public boolean hasNext( ) {
-                        return index < ANALOG_PIPELINE_LENGTH;
-                    }
-                
-                
-                    /**
-                     * 
-                     */
-                    @Override
-                    public Double next( ){ 
-                        if( !hasNext() ) throw new NoSuchElementException( );
-                        return pipeline[index++];
-                    }
-                
-                
-                    /**
-                     * 
-                     */
-                   @Override
-                   public void remove( ) { 
-                        throw new UnsupportedOperationException(
-                            "Not Supported!");
-                    } 
-                }
-            }
-        }
+
+	//--- APV25 parameters ---//
+	//------------------------//
+	private static final double APV25_FRONT_END_GAIN = 100.0; // [mV/MIP]
+	private static final double APV25_MULTIPLEXER_GAIN = 1;   // mA/MIP
+	private static final double APV25_NOISE_INTERCEPT_PEAK = 270; // e- RMS
+	private static final double APV25_NOISE_INTERCEPT_DECON = 396;  //e- RMS
+	private static final double APV25_NOISE_SLOPE_PEAK = 36;       // e- rms/pF
+	private static final double APV25_NOISE_SLOPE_DECON = 59.4;       // e- rms/pF
+	// Number of electron-hole pairs created by a min. ionizing particle 
+	// in 300 micrometers of Si
+	private static final int MIP = 25000;  // electron-hole pairs
+	// Total number of channels per APV25 chip
+	private static final int APV25_CHANNELS = 128;
+	// APV25 trigger bit
+	public static boolean triggerBit = false;
+	// 
+	private int apv25ShapingTime = 35; // [ns] 
+	private int apv25SamplingTime = 24; // [ns]
+	private double analogDCLevel = 0;  // [mA] (Pedestal)
+	public int apv25ClockCycle = 0;
+	private String apv25Mode = "multi-peak";
+	// APV25 Channel
+	private APV25Channel channel;
+	// Histograms
+	protected AIDA aida = AIDA.defaultInstance();
+
+	/**
+	 * Constructor
+	 */
+	public HPSAPV25() {
+		// Create a single instance of an APV25 channel
+		channel = new APV25Channel();
+
+	}
+
+	//--- Methods ---//
+	//---------------//
+	/**
+	 * Set the APV25 shaping time
+	 * 
+	 * @param shapingTime : APV25 shaping time
+	 */
+	public void setShapingTime(int shapingTime) {
+		apv25ShapingTime = shapingTime;
+	}
+
+	/**
+	 * Set the operating mode of the APV25 to either "peak", 
+	 * "deconvolution", or "multi-peak".
+	 * 
+	 * @param mode : APV25 operating mode 
+	 */
+	public void setAPV25Mode(String mode) {
+		apv25Mode = mode;
+	}
+
+	/**
+	 * Set the time interval at which the shaper output is sampled
+	 * 
+	 * @param sampleTime : time interval
+	 */
+	public void setSamplingTime(int sampleTime) {
+		apv25SamplingTime = sampleTime;
+	}
+
+	/**
+	 * 
+	 */
+	public void setAnalogDCLevel(double dcLevel) {
+		analogDCLevel = dcLevel;
+	}
+
+	/**
+	 * Return an instance of an APV25 channel. Currently, there is only a 
+	 * single instance of the channel ( instead of 128 that the actual chip
+	 * has).  However, the analog buffers of each channels are distinct and 
+	 * are stored in a sorted map for later use.
+	 *
+	 * @return an instance of APV25Channel
+	 */
+	public APV25Channel getChannel() {
+		return channel;
+	}
+
+	/**
+	 * Inject charge into a channel and shape the signal.  The resulting 
+	 * shaper signal is then sampled into the analog pipeline
+	 * 
+	 * @param charge   : Total charge being injected
+	 * @param pipeline : Analog pipeline associated with a channel
+	 */
+	public void injectCharge(double charge,
+			double noiseRMS,
+			APV25AnalogPipeline pipeline) {
+		// Shape the injected charge
+		getChannel().shapeSignal(charge);
+
+		// Sample the resulting shaper signal
+		getChannel().sampleShaperSignal(pipeline, noiseRMS);
+	}
+
+	/**
+	 * Increment the position of the trigger and writer pointers of all
+	 * channels
+	 * 
+	 * @param analogPipelineMap : 
+	 */
+	public void incrementAllPointerPositions(
+			Map<Integer, APV25AnalogPipeline> analogPipelineMap) {
+		// Loop through all of the channels and increment the position of
+		// all the trigger and writer pointers
+		for (Map.Entry<Integer, APV25AnalogPipeline> entry : analogPipelineMap.entrySet()) {
+			entry.getValue().step();
+		}
+
+	}
+
+	/**
+	 * 
+	 */
+	public int getSamplingTime() {
+		return apv25SamplingTime;
+	}
+
+	/**
+	 * Increment the APV25 clock cycle by one
+	 */
+	public void stepAPV25Clock() {
+		apv25ClockCycle += 1;
+	}
+
+	/**
+	 * 
+	 */
+	public Map<Integer, double[]> APV25Multiplexer(
+			Map<Integer, APV25AnalogPipeline> pipelineMap) {
+
+		Map<Integer /* chip */, double[]> apv25Map = new HashMap<Integer, double[]>();
+
+		// The address of the APV25.  There is only a single address for all
+		// chips
+		double[] apv25Address = {4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0};
+		double[] output;
+
+		// Create the data streams
+		for (int chipIndex = 0;
+				chipIndex < Math.ceil((double) pipelineMap.size() / APV25_CHANNELS);
+				chipIndex++) {
+
+			apv25Map.put(chipIndex, createOutputArray(apv25Address, -4));
+		}
+
+		// Loop over all channels and readout the cells which the
+		// trigger pointer points to
+		for (int channelN = 0; channelN < pipelineMap.size(); channelN++) {
+
+			output = apv25Map.get((int) Math.floor(channelN / APV25_CHANNELS));
+
+			output[channelN % 128 + 12] += (pipelineMap.get(channelN).readOut() / APV25_FRONT_END_GAIN) * APV25_MULTIPLEXER_GAIN + analogDCLevel;
+
+		}
+		return apv25Map;
+	}
+
+	/**
+	 * 
+	 */
+	private double[] createOutputArray(double[] address, double error) {
+
+		// Create the array which will contain the output format. The array values
+		// will range from -4 microAmps to 4 microAmps.
+		double[] output = new double[141];
+		for (int index = 0; index < output.length; index++) {
+			output[ index] = -4.0;  // microAmps
+		}
+
+		// Header
+		double[] header = {4.0, 4.0, 4.0};
+
+		// Fill the array with the header, address and error bit and tick
+		System.arraycopy(header, 0, output, 0, 3);
+		output[header.length] = error;
+		System.arraycopy(address, 0, output, 4, 8);
+		output[ output.length - 1] = 4.0;
+
+		return output;
+	}
+
+	//------------------------------------------//
+	//               APV25 Channel            //
+	//-----------------------------------------//
+	public class APV25Channel {
+
+		// Analog pipeline length
+		private static final int ANALOG_PIPELINE_LENGTH = 192;
+		// Shaper signal
+		private APV25ShaperSignal shaperSignal;
+
+		/**
+		 * Constructor 
+		 */
+		public APV25Channel() {
+		}
+
+		/**
+		 * Shape the injected charge
+		 * 
+		 * @param charge 
+		 */
+		private void shapeSignal(double charge) {
+			shaperSignal = new APV25ShaperSignal(charge);
+		}
+
+		/**
+		 * Return the noise in electrons for a given strip capacitance
+		 * 
+		 * @param capacitance : strip capacitance in pF
+		 * @return noise in electrons
+		 */
+		public double computeNoise(double capacitance) {
+			if (apv25Mode.equals("peak")
+					|| apv25Mode.equals("multi-peak")) {
+				return APV25_NOISE_INTERCEPT_PEAK
+						+ APV25_NOISE_SLOPE_PEAK * capacitance;
+			} else {
+				return APV25_NOISE_INTERCEPT_DECON
+						+ APV25_NOISE_SLOPE_DECON * capacitance;
+			}
+		}
+
+		/**
+		 * Sample the shaper signal and fill the analog pipeline.
+		 * 
+		 * @param channel : Channel number
+		 */
+		private void sampleShaperSignal(
+				APV25AnalogPipeline pipeline, double noiseRMS) {
+
+			// Obtain the beam time
+			double beam_time = ClockSingleton.getTime();
+
+			// Fill the analog pipeline starting with the cell to which 
+			// the writer pointer is pointing to.  Signals arriving within 
+			// the same bucket of length apv25SamplingTime will be shifted
+			// in time depending on when they arrive.
+			for (int cell = 0; cell < ANALOG_PIPELINE_LENGTH; cell++) {
+
+				// Time at which the shaper signal will be sampled
+				int sample_time = cell * apv25SamplingTime
+						- ((int) beam_time) % apv25SamplingTime;
+				// Sample the shaper signal
+				double sample = shaperSignal.getAmplitudeAtTime(sample_time);
+
+				// Only add the value into the buffer if it is greater than
+				// the noise threshold. Note that this isn't done within
+				// the apv25, however, it will clean up the signal a bit
+				// for simulation purposes
+				// This should be done by the data processing module
+				//if( sample > 0.0001 /*(1*noiseRMS/MIP)*APV25_FRONT_END_GAIN)*/) {
+				pipeline.addToCell(cell, sample);
+				//}
+			}
+		}
+
+		//-----------------------------------//
+		//--- APV25 Shaper Signal ---//
+		//-----------------------------------//
+		/**
+		 * 
+		 */
+		private class APV25ShaperSignal {
+
+			// Shaper signal maximum amplitude
+			private double maxAmp = 0;
+
+			/**
+			 * Constructor
+			 * 
+			 * @param charge : input charge into the channel
+			 */
+			APV25ShaperSignal(double charge) {
+
+				maxAmp = (charge / MIP) * APV25_FRONT_END_GAIN;  // mV
+
+				//--->
+				aida.histogram1D("Shaper Signal Max Amplitude", 100, 0, 500).fill(maxAmp);
+				//--->
+			}
+
+			/**
+			 * Get the amplitude at a time t
+			 * 
+			 * @param time : time at which the shaper signal is to be
+			 *               sampled
+			 */
+			private double getAmplitudeAtTime(double time) {
+
+				return maxAmp * (Math.max(0, time) / apv25ShapingTime) * Math.exp(
+						1 - (time / apv25ShapingTime));
+			}
+		}
+
+		//-------------------------------------//
+		//---    APV25 Analog Pipeline      ---//
+		//-------------------------------------//
+		// Note that the buffer is modeled after a circular buffer
+		public class APV25AnalogPipeline extends RingBuffer {
+			private int _trigger_latency = (int) Math.floor(220 / apv25SamplingTime);
+
+			public APV25AnalogPipeline() {
+				super(ANALOG_PIPELINE_LENGTH);
+			}
+
+			/**
+			 * Set the trigger latency
+			 * 
+			 * @param latency : trigger latency in [ns]
+			 */
+			public void setTriggerLatency(int latency) {
+				_trigger_latency = (int) Math.floor(latency / apv25SamplingTime);
+			}
+
+			private double readOut() {
+				double pipelineValue = currentValue();
+				array[0] = 0;
+				return pipelineValue;
+			}
+
+			@Override
+			public void addToCell(int position, double element) {
+				if (position + _trigger_latency > size) {
+					return;
+				}
+				super.addToCell(position + _trigger_latency, element);
+			}
+
+			public void printAnalogPipeline() {
+				System.out.print("[ ");
+				for (int index = 0; index < size; index++) {
+					if (index == ptr) {
+						System.out.print("TP====>");
+					}
+					if (index == ptr + _trigger_latency) {
+						System.out.print("WP====>");
+					}
+					System.out.print(array[index] + ", ");
+				}
+				System.out.println("] ");
+			}
+		}
+	}
 }

hps-java/src/main/java/org/lcsim/hps/recon/tracking/apv25
HPSSiSensorReadout.java 1.6 -> 1.7
diff -u -r1.6 -r1.7
--- HPSSiSensorReadout.java	30 Mar 2012 23:55:45 -0000	1.6
+++ HPSSiSensorReadout.java	10 Apr 2012 01:00:13 -0000	1.7
@@ -1,4 +1,3 @@
-
 package org.lcsim.hps.recon.tracking.apv25;
 
 //--- Java ---//
@@ -27,7 +26,7 @@
 import org.lcsim.detector.tracker.silicon.ChargeCarrier;
 import org.lcsim.detector.tracker.silicon.SiSensor;
 import org.lcsim.detector.tracker.silicon.SiSensorElectrodes;
-import org.lcsim.detector.tracker.silicon.SiTrackerModule; 
+import org.lcsim.detector.tracker.silicon.SiTrackerModule;
 import org.lcsim.event.EventHeader;
 import org.lcsim.event.SimTrackerHit;
 import org.lcsim.geometry.Detector;
@@ -47,529 +46,461 @@
 import org.lcsim.hps.recon.tracking.HPSRTM;
 import org.lcsim.hps.util.ClockSingleton;
 
-
 /**
  *
  * @author Omar Moreno <[log in to unmask]>
- * @version $Id: HPSSiSensorReadout.java,v 1.6 2012/03/30 23:55:45 omoreno Exp $
+ * @version $Id: HPSSiSensorReadout.java,v 1.7 2012/04/10 01:00:13 meeg Exp $
  */
 public class HPSSiSensorReadout extends Driver {
-    
-    //
-    boolean debug = true;
-    
-    // Array to store the trigger time
-    public static final List<Double> triggerTimeStamp 
-       = new ArrayList<Double>();
-    
-    //
-    List<String> processPaths = new ArrayList<String>();
-    List<IDetectorElement> processDetectorElements 
-       = new ArrayList<IDetectorElement>();
-    List<String> readouts = new ArrayList<String>();
-    
-    //
-    Set<SiSensor> processSensors = new HashSet<SiSensor>();
-    Set<SiTrackerModule> processModules = new HashSet<SiTrackerModule>();
-    
-    // FIFO queue to store trigger times
-    public Queue<Integer> triggerQueue;
-    
-    // # of strips per Si sensor
-    private static final int STRIPS_PER_SENSOR = 667;
-    
-    private HPSAPV25 apv25;
-    private SiSensorSim siSimulation;
-    private HPSRTM rtm;
-    private HPSDataProcessingModule dpm;
-    
-    private static Random random = new Random();
-    private static BinomialDistribution binomial 
-       = new BinomialDistributionImpl(1,1); 
-    private static NormalDistribution gaussian
-       = new NormalDistributionImpl(0.0,1.0);
-    
-    
-    private double noiseThreshold = 4;  // e- RMS
-    
-    // A map used to associate a sensor to the channels and analog pipelines 
-    // of the APV25s being used to readout the sensor
-    public Map< Long /* sensor number */, 
-                Map<Integer /* channel */, APV25AnalogPipeline>> sensorToPipelineMap;
-    
-    // A map used to associate an APV25 channel to its analog pipeline
-    public Map<Integer /* channel */, 
-               APV25AnalogPipeline> analogPipelineMap;
-    
-    // A map used to associate a sensor to the output of the APV25s being 
-    // used to readout the sensor
-    public Map<Long, Map<Integer /* chip # */, double[]>> sensorToAnalogDataMap;
-    
-    // A map used to associate a sensor to the digitzed output of the APV25s
-    // being used to readout the sensor
-    public Map<Long, Map<Integer /*chip # */, double[]>> sensorToDigitalDataMap;
-
-    //
-    public Map<Integer, double[]> analogData;
-    public Map<Integer, double[]> digitalData;
-    
-    public Map<Integer, List<SimTrackerHit> > eventToSimTrackerHitMap;
-    
-    //
-    protected AIDA aida = AIDA.defaultInstance();
-    public Profile1D pipe;
-    
-    int n_events = 0;
-    
-    
-    /**
-     * Constructor
-     */
-    public HPSSiSensorReadout()
-    {
-        sensorToPipelineMap = new HashMap<Long, Map<Integer, APV25AnalogPipeline>>();
-        sensorToAnalogDataMap = new HashMap<Long, Map<Integer, double[]>>();
-        sensorToDigitalDataMap = new  HashMap<Long, Map<Integer, double[]>>();
-
-        eventToSimTrackerHitMap = new HashMap<Integer, List<SimTrackerHit> >();
-        
-        //--- Sensor Simulation ---//
-        //-------------------------//
-        siSimulation = new CDFSiSensorSim();
-        
-        //--- APV25 Simulation ---//
-        //------------------------//
-        apv25 = new HPSAPV25();
-        // Set the APV25 Shaping time [ns]
-        apv25.setShapingTime(35);
-        // Set the APV25 operating mode
-        apv25.setAPV25Mode("multi-peak");
-        // Set the APV25 analog pipeline sampling time
-        apv25.setSamplingTime(24);
-        
-        
-        // 
-        rtm = new HPSRTM(14);
-        
-        // Instantiate the DPM
-        dpm = new HPSDataProcessingModule();
-        dpm.setNoise(18);
-        dpm.setNoiseThreshold(3);
-        dpm.setSamplesAboveThresh(3);
-        dpm.setPedestal(1638);
-        dpm.enableThresholdCut();
-        
-        add(dpm);
-        
-        // Instantiate trigger time queue
-        triggerQueue = new LinkedList<Integer>();
-        
-        // Specify the readouts to process
-        readouts.add("TrackerHits");
-        
-        // Specify the detectors to process
-        processPaths.add("Tracker");
-        
-    }
-    
-    /**
-     * 
-     */
-    @Override
-    public void detectorChanged(Detector detector)
-    {
-        super.detectorChanged(detector);
-        
-        // Proces detectors specified by path, otherwise process the entire
-        // detector
-        IDetectorElement detectorElement = detector.getDetectorElement();
-        for(String detectorElementPath : processPaths ){
-            processDetectorElements.add(
-               detectorElement.findDetectorElement(detectorElementPath));
-        }
-        
-        if(processDetectorElements.isEmpty()) 
-            processDetectorElements.add(detectorElement);
-        
-        for(IDetectorElement dElement : processDetectorElements ){
-            processSensors.addAll(dElement.findDescendants(SiSensor.class));
-            processModules.addAll(
-               dElement.findDescendants(SiTrackerModule.class));
-        }
-        
-        // Initialize the sensor maps
-        for(SiSensor sensor: processSensors){
-            
-            sensorToPipelineMap.put(sensor.getIdentifier().getValue(), 
-                            new HashMap<Integer, APV25AnalogPipeline>());
-            for(int channel = 0; channel < STRIPS_PER_SENSOR; channel++){
-                sensorToPipelineMap.get(sensor.getIdentifier().getValue()).put(channel,apv25.getChannel().new APV25AnalogPipeline());
-            }
-            
-            sensorToAnalogDataMap.put(sensor.getIdentifier().getValue(), 
-                                      new HashMap<Integer, double[]>() );
-            
-            sensorToDigitalDataMap.put(sensor.getIdentifier().getValue(), 
-                                      new HashMap<Integer, double[]>() );                
-
-        }
-    }
-    
-    /**
-     * 
-     */
-    @Override
-    public void process(EventHeader event)
-    {
-
-        
-        super.process(event);
-        
-        if((ClockSingleton.getTime() + ClockSingleton.getDt())%24 == 0){
-            for(Map.Entry<Long, Map<Integer, APV25AnalogPipeline>> sensor : sensorToPipelineMap.entrySet()){
-                apv25.incrementAllPointerPositions(sensor.getValue());
-            }
-            apv25.stepAPV25Clock();
-        }                                                                                                
-                
-        // Loop over all sensors
-        for(SiSensor sensor : processSensors){
-            // Readout the sensors
-            readoutSensor(sensor);
-        }
-        
-        // If a trigger is received readout the APV25 and digitize all hits
-        if(HPSAPV25.triggerBit){
-            
-            triggerTimeStamp.add(ClockSingleton.getTime());
-            
-            // Only add the trigger if there isn't another trigger being 
-            // processed
-            if(!triggerQueue.contains(apv25.apv25ClockCycle)){
-            // Add the time at which each of the six samples should be 
-            // collected to the trigger queue
-                for(int sample = 0; sample < 6; sample++){
-                    triggerQueue.offer(apv25.apv25ClockCycle + sample);
-                }
-            }
-            // Reset the APV25 trigger bit
-            HPSAPV25.triggerBit = false;
-        }
-        
-        // Process any triggers in the queue
-        if(triggerQueue.peek() != null){
-            
-            // Remove any samples that might have already been processed
-            if(triggerQueue.peek() < apv25.apv25ClockCycle){
-                for(int sample = 0; sample < 6; sample++){
-                    triggerQueue.remove();
-                }
-            }
-            else if(triggerQueue.peek() == apv25.apv25ClockCycle){
-                readoutAPV25();
-                triggerQueue.remove();
-            }
-        }
-    }
-    
-    /**
-     * 
-     */
-    @Override
-    public void startOfData()
-    {
-        // Set up readouts if they haven't been set
-        if(!readouts.isEmpty()){
-            super.add(new SimTrackerHitReadoutDriver(readouts));
-        }
-        
-        super.startOfData();
-        readouts.clear();
-        
-    }
-    
-    /**
-     * 
-     * @param sensor 
-     */
-    public void makeRawHits(SiSensor sensor)
-    {
-        readoutSensor(sensor);
-    }
-    
-    /**
-     * Readout the electrodes of an HPS Si sensor and inject the charge into 
-     * the APV25 readout chip.
-     * 
-     * @param sensor : HPS Si sensor
-     */
-    public void readoutSensor(SiSensor sensor)
-    {
-        // Set the sensor to be used in the charge deposition simulation
-        siSimulation.setSensor(sensor);
-        
-        // Perform the charge deposition simulation
-        Map<ChargeCarrier, SiElectrodeDataCollection> electrodeDataMap
-           = siSimulation.computeElectrodeData();
-        
-        // Loop over each charge carrier (electron or hole)
-        for(ChargeCarrier carrier : ChargeCarrier.values()){
-            
-            // If the sensor is capable of collecting the given charge carrier
-            // then obtain the electrode data for the sensor
-            if(sensor.hasElectrodesOnSide(carrier))
-            {   
-                SiElectrodeDataCollection electrodeDataCol 
-                   = electrodeDataMap.get(carrier);
-                
-                // If there is no electrode data available create a new 
-                // instance of electode data
-                if(electrodeDataCol == null){
-                    electrodeDataCol = new SiElectrodeDataCollection();
-                }
-                
-                // Get the readout electrodes
-                SiSensorElectrodes readoutElectrodes
-                   = sensor.getReadoutElectrodes(carrier);
-                
-                // Add noise to the electrodes
-                addNoise(electrodeDataCol, readoutElectrodes);
-                
-                // Get the analog pipeline map associated with this sensor
-                analogPipelineMap 
-                   = sensorToPipelineMap.get(sensor.getIdentifier().getValue());
-                
-                // Loop over all channels
-                for(Integer channel : electrodeDataCol.keySet()){
-                   
-                    // Get the electrode data for this channel
-                    SiElectrodeData electrodeData 
-                       = electrodeDataCol.get(channel);
-                    
-                    // Get the charge in units of electrons
-                    double charge = electrodeData.getCharge();
-                    
-                    //====> Charge deposition on electrode 
-                    aida.histogram1D("Charge", 100,0 ,200000).fill(charge);
-                    //====>
-                    
-                    // Get the RMS noise for this channel
-                    double noise 
-                       = apv25.getChannel().computeNoise(
-                            readoutElectrodes.getCapacitance(channel));
-
-                    //===>
-                    aida.histogram1D(this.getClass().getName() + " - RMS Noise - All Channels", 1000, 3500, 4500).fill(noise);
-                    //===>
-                    
-                    // Check to see if an analog pipeline for this channel
-                    // exist.  If it doesn't, create one.
-                    if(!analogPipelineMap.containsKey(channel)){
-
-                        
-                        analogPipelineMap.put(channel, 
-                           apv25.getChannel().new APV25AnalogPipeline());
-                    }
-
-                    // Get the analog pipeline associated with this channel
-                    APV25AnalogPipeline pipeline 
-                       = analogPipelineMap.get(channel);
-                    
-                    // Inject the charge into the APV25 amplifier chain
-                    pipeline = apv25.injectCharge(charge, noise, pipeline);
-                    // Store the analog pipeline for later use
-                    analogPipelineMap.put(channel, pipeline);
-                   
-                }
-            }   
-        }
-        
-        // Place the analog pipeline back into the sensor map
-        sensorToPipelineMap.put(sensor.getIdentifier().getValue(), analogPipelineMap);
-        
-        // Clear the sensors of all deposited charge
-        siSimulation.clearReadout();
-    }
-    
-    /**
-     * 
-     */
-    public void readoutAPV25()
-    {
-        // Readout all apv25s
-        for(Map.Entry<Long, Map<Integer, APV25AnalogPipeline>> sensor : sensorToPipelineMap.entrySet()){
-            sensorToAnalogDataMap.put(sensor.getKey(), apv25.APV25Multiplexer(sensor.getValue()));
-        }        
- 
-        // Digitize all signals
-        for(Map.Entry<Long, Map<Integer, double[]>> sensor : sensorToAnalogDataMap.entrySet()){
-            sensorToDigitalDataMap.put(sensor.getKey(), rtm.digitize(sensor.getValue()));
-        }
-        
-        // Buffer the samples for further processing
-        dpm.addSample(sensorToDigitalDataMap);
-
-    }
-    
-    
-    /**
-     * 
-     * @param electrodeDataCol
-     * @param electrodes 
-     */
-    public void addNoise(SiElectrodeDataCollection electrodeDataCol, 
-                         SiSensorElectrodes electrodes)
-    {
-        // First add readout noise to the strips in the 
-        // SiElectrodeDataCollection.
-        
-        // Loop over the entries in the SiElectrodeDataCollection
-        for(Entry electrodeDatum : electrodeDataCol.entrySet()){
-            
-            // Get the channel number and electrode data for this entry
-            int channel = (Integer) electrodeDatum.getKey();
-            SiElectrodeData electrodeData 
-               = (SiElectrodeData) electrodeDatum.getValue();
-            
-            // Get the RMS noise for this channel in units of electrons
-            double noise 
-               = apv25.getChannel().computeNoise(
-                    electrodes.getCapacitance(channel));
-           
-            // Add readout noise to the deposited charge
-            int noiseCharge = (int) Math.round( random.nextGaussian()*noise);
-            electrodeData.addCharge(noiseCharge);
-        }
-        
-        // Find the number of strips that are not currently hit
-        int nElectrodes = electrodes.getNCells();
-        int nElectrodesEmpty = nElectrodes - electrodeDataCol.size();
-        
-        // Get the noise threshold in units of the noise charge
-
-        // Calculate how many channels should get noise hits
-        double integral = Erf.phic(noiseThreshold);
-        int nChannelsThrow = drawBinomial(nElectrodesEmpty, integral);
-        
-        // Now throw Gaussian randoms above the seed threshold and put signals
-        // on unoccupied channels
-        for(int ithrow = 0; ithrow < nChannelsThrow; ithrow++)
-        {
-            // Throw to get a channel number
-            int channel = random.nextInt(nElectrodes);
-            while(electrodeDataCol.keySet().contains(channel)){
-                channel = random.nextInt(nElectrodes);
-            }
-        
-            // Calculate the noise for this channel in units of electrons
-            double noise 
-               = apv25.getChannel().computeNoise(
-                    electrodes.getCapacitance(channel));
-        
-            // Throw Gaussian above threshold
-            int charge 
-               = (int) Math.round(drawGaussianAboveThreshold(integral)*noise);
-            
-            // Add the noise hit to the electrode data collection
-            electrodeDataCol.add(channel, new SiElectrodeData(charge));
-        }
-        
-        // Now throw to lower threshold on channels that neighbor hits until
-        // we are exhausted
-        
-        nChannelsThrow = 1;
-        while(nChannelsThrow > 0){
-            
-            // Get neighbor channels
-            Set<Integer> neighbors = new HashSet<Integer>();
-            for(int channel : electrodeDataCol.keySet())
-            {
-                neighbors.addAll(electrodes.getNearestNeighborCells(channel));
-            }
-            neighbors.removeAll(electrodeDataCol.keySet());
-            
-            nElectrodesEmpty = neighbors.size();
-            
-            integral = Erf.phic(noiseThreshold);
-            nChannelsThrow = drawBinomial(nElectrodesEmpty, integral);
-            
-            // Now throw Gaussian randoms above a threshold and put signals on
-            // unoccopied channels
-            for(int ithrow = 0; ithrow < nChannelsThrow; ithrow++)
-            {
-            
-                // Throw to get a channel number
-                List<Integer> neighborList = new ArrayList<Integer>(neighbors);
-
-                int channel 
-                   = neighborList.get(random.nextInt(nElectrodesEmpty));
-            
-                while(electrodeDataCol.keySet().contains(channel)){
-                    channel 
-                       = neighborList.get(random.nextInt(nElectrodesEmpty));
-            
-                }
-                
-                // Calculate the noise for this channel in units of electrons
-                double noise 
-                   = apv25.getChannel().computeNoise(
-                        electrodes.getCapacitance(channel));
-        
-                // Throw Gaussian above threshold
-                int charge 
-                   = (int) 
-                        Math.round(drawGaussianAboveThreshold(integral)*noise);
-            
-                // Add the noise hit to the electrode data collection
-                electrodeDataCol.add(channel, new SiElectrodeData(charge));
-            }
-        }
-    }
-    
-    /**
-     * 
-     */
-      public static int drawBinomial(int ntrials, double probability)
-    {
-        binomial.setNumberOfTrials(ntrials);
-        binomial.setProbabilityOfSuccess(probability);
-
-        int nsuccess = 0;
-        try
-        {
-            nsuccess = binomial.inverseCumulativeProbability(random.nextDouble());
-        } catch (MathException exception)
-        {
-            throw new RuntimeException("APV25 failed to calculate inverse cumulative probability of binomial!");
-        }
-        return nsuccess;
-    }
-      
-      
-      /**
-       * Return a random variable following normal distribution, but beyond
-       * threshold provided during initialization.
-       */
-    public static double drawGaussianAboveThreshold(double prob_above_threshold)
-    {
-        double draw, cumulative_probability;
-
-        draw = prob_above_threshold * random.nextDouble();
-        cumulative_probability = 1.0 - prob_above_threshold + draw;
-
-        assert cumulative_probability < 1.0 : "cumulProb=" + cumulative_probability + ", draw=" + draw + ", probAboveThreshold=" + prob_above_threshold;
-        assert cumulative_probability >= 0.0 : "cumulProb=" + cumulative_probability + ", draw=" + draw + ", probAboveThreshold=" + prob_above_threshold;
-
-        double gaussian_random = 0;
-        try
-        {
-            gaussian_random = gaussian.inverseCumulativeProbability(cumulative_probability);
-        } catch (MathException e)
-        {
-            System.out.println("MathException caught: " + e);
-        }
 
-        return gaussian_random;
-    }
+	//
+	boolean debug = true;
+	// Array to store the trigger time
+	public static final List<Double> triggerTimeStamp = new ArrayList<Double>();
+	//
+	List<String> processPaths = new ArrayList<String>();
+	List<IDetectorElement> processDetectorElements = new ArrayList<IDetectorElement>();
+	List<String> readouts = new ArrayList<String>();
+	//
+	Set<SiSensor> processSensors = new HashSet<SiSensor>();
+	Set<SiTrackerModule> processModules = new HashSet<SiTrackerModule>();
+	// FIFO queue to store trigger times
+	public Queue<Integer> triggerQueue;
+	// # of strips per Si sensor
+	private static final int STRIPS_PER_SENSOR = 667;
+	private HPSAPV25 apv25;
+	private SiSensorSim siSimulation;
+	private HPSRTM rtm;
+	private HPSDataProcessingModule dpm;
+	private static Random random = new Random();
+	private static BinomialDistribution binomial = new BinomialDistributionImpl(1, 1);
+	private static NormalDistribution gaussian = new NormalDistributionImpl(0.0, 1.0);
+	private double noiseThreshold = 4;  // e- RMS
+	// A map used to associate a sensor to the channels and analog pipelines 
+	// of the APV25s being used to readout the sensor
+	public Map< Long /* sensor number */, Map<Integer /* channel */, APV25AnalogPipeline>> sensorToPipelineMap;
+	// A map used to associate an APV25 channel to its analog pipeline
+	public Map<Integer /* channel */, APV25AnalogPipeline> analogPipelineMap;
+	// A map used to associate a sensor to the output of the APV25s being 
+	// used to readout the sensor
+	public Map<Long, Map<Integer /* chip # */, double[]>> sensorToAnalogDataMap;
+	// A map used to associate a sensor to the digitzed output of the APV25s
+	// being used to readout the sensor
+	public Map<Long, Map<Integer /*chip # */, double[]>> sensorToDigitalDataMap;
+	//
+	public Map<Integer, double[]> analogData;
+	public Map<Integer, double[]> digitalData;
+	public Map<Integer, List<SimTrackerHit>> eventToSimTrackerHitMap;
+	//
+	protected AIDA aida = AIDA.defaultInstance();
+	public Profile1D pipe;
+	int n_events = 0;
+
+	/**
+	 * Constructor
+	 */
+	public HPSSiSensorReadout() {
+		sensorToPipelineMap = new HashMap<Long, Map<Integer, APV25AnalogPipeline>>();
+		sensorToAnalogDataMap = new HashMap<Long, Map<Integer, double[]>>();
+		sensorToDigitalDataMap = new HashMap<Long, Map<Integer, double[]>>();
+
+		eventToSimTrackerHitMap = new HashMap<Integer, List<SimTrackerHit>>();
+
+		//--- Sensor Simulation ---//
+		//-------------------------//
+		siSimulation = new CDFSiSensorSim();
+
+		//--- APV25 Simulation ---//
+		//------------------------//
+		apv25 = new HPSAPV25();
+		// Set the APV25 Shaping time [ns]
+		apv25.setShapingTime(35);
+		// Set the APV25 operating mode
+		apv25.setAPV25Mode("multi-peak");
+		// Set the APV25 analog pipeline sampling time
+		apv25.setSamplingTime(24);
+
+
+		// 
+		rtm = new HPSRTM(14);
+
+		// Instantiate the DPM
+		dpm = new HPSDataProcessingModule();
+		dpm.setNoise(18);
+		dpm.setNoiseThreshold(3);
+		dpm.setSamplesAboveThresh(3);
+		dpm.setPedestal(1638);
+		dpm.enableThresholdCut();
+
+		add(dpm);
+
+		// Instantiate trigger time queue
+		triggerQueue = new LinkedList<Integer>();
+
+		// Specify the readouts to process
+		readouts.add("TrackerHits");
+
+		// Specify the detectors to process
+		processPaths.add("Tracker");
+
+	}
+
+	/**
+	 * 
+	 */
+	@Override
+	public void detectorChanged(Detector detector) {
+		super.detectorChanged(detector);
+
+		// Proces detectors specified by path, otherwise process the entire
+		// detector
+		IDetectorElement detectorElement = detector.getDetectorElement();
+		for (String detectorElementPath : processPaths) {
+			processDetectorElements.add(
+					detectorElement.findDetectorElement(detectorElementPath));
+		}
+
+		if (processDetectorElements.isEmpty()) {
+			processDetectorElements.add(detectorElement);
+		}
+
+		for (IDetectorElement dElement : processDetectorElements) {
+			processSensors.addAll(dElement.findDescendants(SiSensor.class));
+			processModules.addAll(
+					dElement.findDescendants(SiTrackerModule.class));
+		}
+
+		// Initialize the sensor maps
+		for (SiSensor sensor : processSensors) {
+
+			sensorToPipelineMap.put(sensor.getIdentifier().getValue(),
+					new HashMap<Integer, APV25AnalogPipeline>());
+			for (int channel = 0; channel < STRIPS_PER_SENSOR; channel++) {
+				sensorToPipelineMap.get(sensor.getIdentifier().getValue()).put(channel, apv25.getChannel().new APV25AnalogPipeline());
+			}
+
+			sensorToAnalogDataMap.put(sensor.getIdentifier().getValue(),
+					new HashMap<Integer, double[]>());
+
+			sensorToDigitalDataMap.put(sensor.getIdentifier().getValue(),
+					new HashMap<Integer, double[]>());
+
+		}
+	}
+
+	/**
+	 * 
+	 */
+	@Override
+	public void process(EventHeader event) {
+
+
+		super.process(event);
+
+		if ((ClockSingleton.getTime() + ClockSingleton.getDt()) % 24 == 0) {
+			for (Map.Entry<Long, Map<Integer, APV25AnalogPipeline>> sensor : sensorToPipelineMap.entrySet()) {
+				apv25.incrementAllPointerPositions(sensor.getValue());
+			}
+			apv25.stepAPV25Clock();
+		}
+
+		// Loop over all sensors
+		for (SiSensor sensor : processSensors) {
+			// Readout the sensors
+			readoutSensor(sensor);
+		}
+
+		// If a trigger is received readout the APV25 and digitize all hits
+		if (HPSAPV25.triggerBit) {
+
+			triggerTimeStamp.add(ClockSingleton.getTime());
+
+			// Only add the trigger if there isn't another trigger being 
+			// processed
+			if (!triggerQueue.contains(apv25.apv25ClockCycle)) {
+				// Add the time at which each of the six samples should be 
+				// collected to the trigger queue
+				for (int sample = 0; sample < 6; sample++) {
+					triggerQueue.offer(apv25.apv25ClockCycle + sample);
+				}
+			}
+			// Reset the APV25 trigger bit
+			HPSAPV25.triggerBit = false;
+		}
+
+		// Process any triggers in the queue
+		if (triggerQueue.peek() != null) {
+
+			// Remove any samples that might have already been processed
+			if (triggerQueue.peek() < apv25.apv25ClockCycle) {
+				for (int sample = 0; sample < 6; sample++) {
+					triggerQueue.remove();
+				}
+			} else if (triggerQueue.peek() == apv25.apv25ClockCycle) {
+				readoutAPV25();
+				triggerQueue.remove();
+			}
+		}
+	}
+
+	/**
+	 * 
+	 */
+	@Override
+	public void startOfData() {
+		// Set up readouts if they haven't been set
+		if (!readouts.isEmpty()) {
+			super.add(new SimTrackerHitReadoutDriver(readouts));
+		}
+
+		super.startOfData();
+		readouts.clear();
+
+	}
+
+	/**
+	 * 
+	 * @param sensor 
+	 */
+	public void makeRawHits(SiSensor sensor) {
+		readoutSensor(sensor);
+	}
+
+	/**
+	 * Readout the electrodes of an HPS Si sensor and inject the charge into 
+	 * the APV25 readout chip.
+	 * 
+	 * @param sensor : HPS Si sensor
+	 */
+	public void readoutSensor(SiSensor sensor) {
+		// Set the sensor to be used in the charge deposition simulation
+		siSimulation.setSensor(sensor);
+
+		// Perform the charge deposition simulation
+		Map<ChargeCarrier, SiElectrodeDataCollection> electrodeDataMap = siSimulation.computeElectrodeData();
+
+		// Loop over each charge carrier (electron or hole)
+		for (ChargeCarrier carrier : ChargeCarrier.values()) {
+
+			// If the sensor is capable of collecting the given charge carrier
+			// then obtain the electrode data for the sensor
+			if (sensor.hasElectrodesOnSide(carrier)) {
+				SiElectrodeDataCollection electrodeDataCol = electrodeDataMap.get(carrier);
+
+				// If there is no electrode data available create a new 
+				// instance of electode data
+				if (electrodeDataCol == null) {
+					electrodeDataCol = new SiElectrodeDataCollection();
+				}
+
+				// Get the readout electrodes
+				SiSensorElectrodes readoutElectrodes = sensor.getReadoutElectrodes(carrier);
+
+				// Add noise to the electrodes
+				addNoise(electrodeDataCol, readoutElectrodes);
+
+				// Get the analog pipeline map associated with this sensor
+				analogPipelineMap = sensorToPipelineMap.get(sensor.getIdentifier().getValue());
+
+				// Loop over all channels
+				for (Integer channel : electrodeDataCol.keySet()) {
+
+					// Get the electrode data for this channel
+					SiElectrodeData electrodeData = electrodeDataCol.get(channel);
+
+					// Get the charge in units of electrons
+					double charge = electrodeData.getCharge();
+
+					//====> Charge deposition on electrode 
+					aida.histogram1D("Charge", 100, 0, 200000).fill(charge);
+					//====>
+
+					// Get the RMS noise for this channel
+					double noise = apv25.getChannel().computeNoise(
+							readoutElectrodes.getCapacitance(channel));
+
+					//===>
+					aida.histogram1D(this.getClass().getName() + " - RMS Noise - All Channels", 1000, 3500, 4500).fill(noise);
+					//===>
+
+					// Check to see if an analog pipeline for this channel
+					// exist.  If it doesn't, create one.
+					if (!analogPipelineMap.containsKey(channel)) {
+						analogPipelineMap.put(channel,
+								apv25.getChannel().new APV25AnalogPipeline());
+					}
+
+					// Get the analog pipeline associated with this channel
+					APV25AnalogPipeline pipeline = analogPipelineMap.get(channel);
+
+					// Inject the charge into the APV25 amplifier chain
+					apv25.injectCharge(charge, noise, pipeline);
+				}
+			}
+		}
+
+		// Place the analog pipeline back into the sensor map
+		sensorToPipelineMap.put(sensor.getIdentifier().getValue(), analogPipelineMap);
+
+		// Clear the sensors of all deposited charge
+		siSimulation.clearReadout();
+	}
+
+	/**
+	 * 
+	 */
+	public void readoutAPV25() {
+		// Readout all apv25s
+		for (Map.Entry<Long, Map<Integer, APV25AnalogPipeline>> sensor : sensorToPipelineMap.entrySet()) {
+			sensorToAnalogDataMap.put(sensor.getKey(), apv25.APV25Multiplexer(sensor.getValue()));
+		}
+
+		// Digitize all signals
+		for (Map.Entry<Long, Map<Integer, double[]>> sensor : sensorToAnalogDataMap.entrySet()) {
+			sensorToDigitalDataMap.put(sensor.getKey(), rtm.digitize(sensor.getValue()));
+		}
+
+		// Buffer the samples for further processing
+		dpm.addSample(sensorToDigitalDataMap);
+
+	}
+
+	/**
+	 * 
+	 * @param electrodeDataCol
+	 * @param electrodes 
+	 */
+	public void addNoise(SiElectrodeDataCollection electrodeDataCol,
+			SiSensorElectrodes electrodes) {
+		// First add readout noise to the strips in the 
+		// SiElectrodeDataCollection.
+
+		// Loop over the entries in the SiElectrodeDataCollection
+		for (Entry electrodeDatum : electrodeDataCol.entrySet()) {
+
+			// Get the channel number and electrode data for this entry
+			int channel = (Integer) electrodeDatum.getKey();
+			SiElectrodeData electrodeData = (SiElectrodeData) electrodeDatum.getValue();
+
+			// Get the RMS noise for this channel in units of electrons
+			double noise = apv25.getChannel().computeNoise(
+					electrodes.getCapacitance(channel));
+
+			// Add readout noise to the deposited charge
+			int noiseCharge = (int) Math.round(random.nextGaussian() * noise);
+			electrodeData.addCharge(noiseCharge);
+		}
+
+		// Find the number of strips that are not currently hit
+		int nElectrodes = electrodes.getNCells();
+		int nElectrodesEmpty = nElectrodes - electrodeDataCol.size();
+
+		// Get the noise threshold in units of the noise charge
+
+		// Calculate how many channels should get noise hits
+		double integral = Erf.phic(noiseThreshold);
+		int nChannelsThrow = drawBinomial(nElectrodesEmpty, integral);
+
+		// Now throw Gaussian randoms above the seed threshold and put signals
+		// on unoccupied channels
+		for (int ithrow = 0; ithrow < nChannelsThrow; ithrow++) {
+			// Throw to get a channel number
+			int channel = random.nextInt(nElectrodes);
+			while (electrodeDataCol.keySet().contains(channel)) {
+				channel = random.nextInt(nElectrodes);
+			}
+
+			// Calculate the noise for this channel in units of electrons
+			double noise = apv25.getChannel().computeNoise(
+					electrodes.getCapacitance(channel));
+
+			// Throw Gaussian above threshold
+			int charge = (int) Math.round(drawGaussianAboveThreshold(integral) * noise);
+
+			// Add the noise hit to the electrode data collection
+			electrodeDataCol.add(channel, new SiElectrodeData(charge));
+		}
+
+		// Now throw to lower threshold on channels that neighbor hits until
+		// we are exhausted
+
+		nChannelsThrow = 1;
+		while (nChannelsThrow > 0) {
+
+			// Get neighbor channels
+			Set<Integer> neighbors = new HashSet<Integer>();
+			for (int channel : electrodeDataCol.keySet()) {
+				neighbors.addAll(electrodes.getNearestNeighborCells(channel));
+			}
+			neighbors.removeAll(electrodeDataCol.keySet());
+
+			nElectrodesEmpty = neighbors.size();
+
+			integral = Erf.phic(noiseThreshold);
+			nChannelsThrow = drawBinomial(nElectrodesEmpty, integral);
+
+			// Now throw Gaussian randoms above a threshold and put signals on
+			// unoccopied channels
+			for (int ithrow = 0; ithrow < nChannelsThrow; ithrow++) {
+
+				// Throw to get a channel number
+				List<Integer> neighborList = new ArrayList<Integer>(neighbors);
+
+				int channel = neighborList.get(random.nextInt(nElectrodesEmpty));
+
+				while (electrodeDataCol.keySet().contains(channel)) {
+					channel = neighborList.get(random.nextInt(nElectrodesEmpty));
+
+				}
+
+				// Calculate the noise for this channel in units of electrons
+				double noise = apv25.getChannel().computeNoise(
+						electrodes.getCapacitance(channel));
+
+				// Throw Gaussian above threshold
+				int charge = (int) Math.round(drawGaussianAboveThreshold(integral) * noise);
+
+				// Add the noise hit to the electrode data collection
+				electrodeDataCol.add(channel, new SiElectrodeData(charge));
+			}
+		}
+	}
+
+	/**
+	 * 
+	 */
+	public static int drawBinomial(int ntrials, double probability) {
+		binomial.setNumberOfTrials(ntrials);
+		binomial.setProbabilityOfSuccess(probability);
+
+		int nsuccess = 0;
+		try {
+			nsuccess = binomial.inverseCumulativeProbability(random.nextDouble());
+		} catch (MathException exception) {
+			throw new RuntimeException("APV25 failed to calculate inverse cumulative probability of binomial!");
+		}
+		return nsuccess;
+	}
+
+	/**
+	 * Return a random variable following normal distribution, but beyond
+	 * threshold provided during initialization.
+	 */
+	public static double drawGaussianAboveThreshold(double prob_above_threshold) {
+		double cumulative_probability;
+
+		cumulative_probability = 1.0 + prob_above_threshold * (random.nextDouble() - 1.0);
+
+		assert cumulative_probability < 1.0 : "cumulProb=" + cumulative_probability + ", probAboveThreshold=" + prob_above_threshold;
+		assert cumulative_probability >= 0.0 : "cumulProb=" + cumulative_probability + ", probAboveThreshold=" + prob_above_threshold;
+
+		double gaussian_random = 0;
+		try {
+			gaussian_random = gaussian.inverseCumulativeProbability(cumulative_probability);
+		} catch (MathException e) {
+			System.out.println("MathException caught: " + e);
+		}
 
+		return gaussian_random;
+	}
 }

hps-java/src/main/java/org/lcsim/hps/recon/tracking
HPSDataProcessingModule.java 1.10 -> 1.11
diff -u -r1.10 -r1.11
--- HPSDataProcessingModule.java	5 Apr 2012 23:57:26 -0000	1.10
+++ HPSDataProcessingModule.java	10 Apr 2012 01:00:13 -0000	1.11
@@ -23,380 +23,356 @@
 /**
  *
  * @author Omar Moreno <[log in to unmask]>
- * @version $Id: HPSDataProcessingModule.java,v 1.10 2012/04/05 23:57:26 jeremy Exp $
+ * @version $Id: HPSDataProcessingModule.java,v 1.11 2012/04/10 01:00:13 meeg Exp $
  */
 public class HPSDataProcessingModule extends Driver {
-    
-    Map<Long, Map<Integer, List<Double>>> sensorToBlocksMap;
-    
-    // Relate a channel to its six samples
-    Map<Integer, List<Double>> channelToBlock;
-    
-    // Relate a sensor Identifier to the actual sensor
-    Map<Long, SiSensor> sensorMap = new HashMap<Long, SiSensor>();
-    
-    // Collection of all sensors
-    Set<SiSensor> sensorSet = new HashSet<SiSensor>();
-    
-    // Collections of RawTrackerHits
-    List<RawTrackerHit> rawHits;        // No cuts are applied
-    List<RawTrackerHit> rawHitsNoCuts;     // Cuts are applied to samples
-    
-    // Collection of all SVT data
-    List<HPSSVTData> svtData;
-    List<HPSSVTData> svtFpgaData;
-    
-    // 1-5 rms noise [ADC Counts] <--- This is going to change
+
+	Map<Long, Map<Integer, List<Double>>> sensorToBlocksMap;
+	// Relate a channel to its six samples
+	Map<Integer, List<Double>> channelToBlock;
+	// Relate a sensor Identifier to the actual sensor
+	Map<Long, SiSensor> sensorMap = new HashMap<Long, SiSensor>();
+	// Collection of all sensors
+	Set<SiSensor> sensorSet = new HashSet<SiSensor>();
+	// Collections of RawTrackerHits
+	List<RawTrackerHit> rawHits;        // Cuts are applied
+	List<RawTrackerHit> rawHitsNoCuts;     // No cuts are applied to samples
+	// Collection of all SVT data
+	List<HPSSVTData> svtData;
+	List<HPSSVTData> svtFpgaData;
+	// 1-5 rms noise [ADC Counts] <--- This is going to change
 //    int[] noiseThreshold = {1657, 1675, 1692, 1709, 1728}; 
-    
-    int numberOfSamples = 0;        // Total number of APV25 samples
-    int nSamplesAboveThresh = 3;    // Number of samples above noise threshold
-    int pedestal = 1638;            // [ADC counts] For now, all channels have the same pedestal
-    int flags = 0;                  //
-    int noise = 18;                 // [ADC Counts] RMS noise 
-    int noiseThreshold = 3;         // Units of RMS noise
-    
-    boolean thresholdCut = false;       // Apply threshold cut?
-    boolean tailCut = false;            // Apply tail cut?
-    boolean noiseSuppression = false;   // Apply noise supression?
-    
-    double[] apv25DataStream;
-    
-    List<Double> samples;
-    
-    String RawTrackerHitsCollectionName = "RawTrackerHits";
-    String RawTrackerHitsNoCutsCollectionName = "RawTrackerHitsNoCuts";
-    String svtCollectionName = "SVTData";
-    
-    /**
-     * Default Constructor
-     */
-    public HPSDataProcessingModule()
-    {
-        channelToBlock  = new HashMap<Integer, List<Double>>();
-        sensorToBlocksMap = new HashMap<Long, Map<Integer, List<Double>>>();
-        rawHits = new ArrayList<RawTrackerHit>();
-        rawHitsNoCuts = new ArrayList<RawTrackerHit>();
-        svtData = new ArrayList<HPSSVTData>();
-        svtFpgaData = new ArrayList<HPSSVTData>();
-    }
-    
-    /**
-     * 
-     */
-    @Override
-    public void detectorChanged(Detector detector){
-        
-        // Get the tracker
-        IDetectorElement tracker 
-           = detector.getDetectorElement().findDetectorElement("Tracker");
-        
-        // Fill the collection of sensors
-        sensorSet.addAll(tracker.findDescendants(SiSensor.class));
-        
-        for(SiSensor sensor : sensorSet){
-        
-            // Map a sensor to its identifier
-            sensorMap.put(sensor.getIdentifier().getValue(), sensor);
-            
-            // Map a sensor to its corresponding samples
-            sensorToBlocksMap.put(sensor.getIdentifier().getValue(), 
-                                    new HashMap<Integer, List<Double>>());
-        }
-    }
-    
-    /**
-     * Set the SVT collection name
-     */
-    public void setSvtCollectionName(String svtCollectionName)
-    {
-    	this.svtCollectionName = svtCollectionName;
-    }
-    
-    /**
-     * Set the number of samples above threshold a signal must have
-     */
-    public void setSamplesAboveThresh(int nSamplesAboveThresh)
-    {
-        this.nSamplesAboveThresh = nSamplesAboveThresh;
-    }
-    
-    /**
-     * Set the noise RMS [ADC Counts]
-     */
-    public void setNoise(int noise)
-    {
-        this.noise = noise;
-    }
-    
-    /**
-     * Set the noise threshold in units of RMS noise
-     */
-    public void setNoiseThreshold(int noiseThreshold)
-    {
-        this.noiseThreshold = noiseThreshold;
-    }
-    
-    /**
-     * Set the pedestal value for all channels
-     */
-    public void setPedestal(int pedestal)
-    {
-        this.pedestal = pedestal;
-    }
-    
-    /**
-     * Enable the threshold cut.  The threshold cut requires a certain number
-     * of samples per hit to be above a noise threshold.
-     */
-    public void enableThresholdCut()
-    {
-        this.noiseSuppression = true;
-    }
-    
-    /**
-     * Enable the tail cut.  The tail cut requires sample 1 to be greater than
-     * sample 0 or sample 2 to be greater than sample 1. This eliminates 
-     * hits that may arise due to shaper signal tails.
-     */
-    public void enableTailCut()
-    {
-        this.tailCut = true;
-    }
-    
-    /**
-     * Enable noise suppression cut.  Requires samples 2 or 3 to be above a
-     * threshold noiseThreshold + noise. 
-     */
-    public void enableNoiseSuppressionCut()
-    {
-        this.noiseSuppression = true;
-    }
-    
-    /**
-     * Buffer a sample that has been readout from a sensor.
-     * 
-     * @param sensorToDigitalMap
-     *      A map relating a sensor to the digital samples readout from the 
-     *      sensor
-     */
-    public void addSample(Map<Long, Map<Integer, double[]>> sensorToDigitalMap)
-    {
-     
-        /*
-         * Long:     Sensor Identifier
-         * Integer:  Chip Number
-         * double[]: APV25 Data Stream 
-         */
-        
-        int channelN = 0;
-        
-        // Loop through the list of all sensors
-        for(Map.Entry<Long, Map<Integer, double[]>> sensor : sensorToDigitalMap.entrySet()){
-            
-            // Loop through all APV25s
-            for(Map.Entry<Integer, double[]> sample : sensor.getValue().entrySet()){
-                
-                // Copy the sample to avoid concurrent modification
-                apv25DataStream = sample.getValue();
-                
-                // Strip the APV25 data stream of all header information
-                // This needs to change so that the real chip address can be 
-                // extracted ...
-                apv25DataStream 
-                   = Arrays.copyOfRange(apv25DataStream, 12, apv25DataStream.length-1);
-                
-                // Loop through all channels
-                for(int channel = 0; channel < apv25DataStream.length; channel++){
-                    
-                    channelN = channel + sample.getKey()*128;
-
-                    // Check if a block has been created for this channel. If
-                    // not create it
-                    if(!sensorToBlocksMap.get(sensor.getKey()).containsKey(channelN)){
-                        sensorToBlocksMap.get(sensor.getKey()).put(channelN, new ArrayList<Double>(6));
-                    }
-                    
-                    sensorToBlocksMap.get(sensor.getKey()).get(channelN).add(apv25DataStream[channel]);
-                    
-                }
-            }
-        }
-        numberOfSamples++;
-    }
-    
-    /**
-     *  Finds hits that satisfied all required cuts and creates both
-     *  RawTrackerHits and SVTData
-     */
-    public void findHits()
-    {
-
-        short[] adc = new short[6];
-        int fpgaAddress = 0;
-        int hybridNumber = 0;
-        int apvNumber = 0;
-
-        // Clear the list of raw tracker hits
-        rawHits.clear();
-        rawHitsNoCuts.clear();
-        svtData.clear();
-        
-        // Loop through all sensors and the corresponding blocks
-        for(Map.Entry<Long, Map<Integer, List<Double>>> sensor : sensorToBlocksMap.entrySet()){
-        	
-            // Get the FPGA address
-            fpgaAddress = HPSSVTDAQMaps.sensorToDAQPair.get(sensorMap.get(sensor.getKey())).getSecondElement();
-            
-            for(Map.Entry<Integer, List<Double>> block : sensor.getValue().entrySet()){
-            
-                // Convert ADC value to a short
-                for(int index = 0; index < adc.length; index++){
-                    adc[index] = block.getValue().get(index).shortValue();                
-                }
-                
-                // Create RawTrackerHits from all hits before applying cuts
-                rawHitsNoCuts.add(makeRawTrackerHit(block.getKey(), sensorMap.get(sensor.getKey()), adc));
-                
-                // Check if a block has the appropriate number of blocks above
-                // threshold
-                if(!(samplesAboveThreshold(adc) >= nSamplesAboveThresh) && thresholdCut) {
-                    block.getValue().clear();
-                    continue;
-                }
-                
-                // Apply the tail cut
-                if(!tailCut(adc) && tailCut){
-                    block.getValue().clear();
-                    continue;
-                }
-                       
-                // Apply noise suppression cut
-                if(!noiseSuppresionCut(adc) && noiseSuppression){
-                    block.getValue().clear();
-                    continue;
-                }     
-                
-                // If all cuts are satisfied, create a RawTrackerHit
-                rawHits.add(makeRawTrackerHit(block.getKey(), sensorMap.get(sensor.getKey()), adc));
-                
-
-                // Get the hybrid number
-                hybridNumber = HPSSVTDAQMaps.sensorToDAQPair.get(sensorMap.get(sensor.getKey())).getFirstElement();
-
-                // Find the APV number
-                apvNumber = (int) Math.floor(block.getKey()/128);
-                
-                // Create an svtData packet
-                svtData.add(new HPSSVTData(hybridNumber, apvNumber, block.getKey()%128, fpgaAddress, adc ));
-                svtFpgaData.add(new HPSSVTData(hybridNumber, apvNumber, block.getKey()%128, fpgaAddress, adc ));
-
-                block.getValue().clear();
-            }
-            
-            HPSSVTDataBuffer.addToBuffer(svtFpgaData, fpgaAddress);
-            
-            // Clear data buffer.
-            svtFpgaData.clear();
-        }
-        
-        System.out.println(this.getClass().getName() + ": Total RawTrackerHits before cuts: " + rawHitsNoCuts.size());
-        System.out.println(this.getClass().getName() + ": Total RawTrackerHits: " + rawHits.size());
-        System.out.println(this.getClass().getName() + ": Total SVTData: " + svtData.size());
-    }
-    
-    /**
-     * Creates a rawTrackerHit
-     * 
-     * @param channelNumber
-     *      Si Strip from which the hit originates from
-     * @param sensor
-     *      Sensor from which the hit originates from
-     * @param adcValues
-     *      Shaper signal samples
-     * @return RawTrackerHit
-     */
-    private RawTrackerHit makeRawTrackerHit( Integer channelNumber, SiSensor sensor, short[] adcValues)
-    {
-        IReadout ro = sensor.getReadout();
-        
-        // No time yet
-        int time = 0;
-        long cell_id = sensor.makeStripId(channelNumber, 1).getValue();
-        
-        RawTrackerHit rawHit = new BaseRawTrackerHit(time, cell_id, adcValues, new ArrayList<SimTrackerHit>(), sensor);
-
-        ro.addHit(rawHit);
-        
-        return rawHit;
-    }
-
-    /**
-     * Finds how many samples are above a given threshold
-     * 
-     * @param adc
-     *      Shaper signal samples
-     * @return Number of samples above threshold
-     */
-    private int samplesAboveThreshold(short[] adc)
-    {
-        // Number of samples above threshold
-        int nSamplesAboveThreshold = 0;
-        
-        for(int sample = 0; sample < adc.length; sample++){
-            if(adc[sample] >= pedestal + noiseThreshold*noise) nSamplesAboveThreshold++;
-        }
-        return nSamplesAboveThreshold;
-    }
-    
-    /**
-     * Applies tail cut
-     * 
-     * @param adc
-     *      Shaper signal samples
-     * @return true if the cut is satisfied, false otherwise
-     */
-    private boolean tailCut(short[] adc)
-    {
-        if(adc[3] > adc[2] || adc[4] > adc[3]) return true;
-        return false;
-    }
-    
-    /**
-     * Applies noise suppression cut
-     * 
-     * @param adc 
-     *      Shaper signal samples
-     * @return true if the cut is satisfied, false otherwise
-     */
-    private boolean noiseSuppresionCut(short[] adc)
-    {
-        if(adc[3] > pedestal + noiseThreshold*noise || adc[4] > pedestal + noiseThreshold*noise) return true;
-        return false;
-    }
-    
-    /**
-     * 
-     */
-    @Override
-    public void process(EventHeader event)
-    {
-        super.process(event);
-
-        // If six samples have been collected process the data
-        if(numberOfSamples == 6){
-
-            // Find hits
-            findHits();
-            
-            // Add RawTrackerHits to the event
-            event.put(RawTrackerHitsCollectionName, rawHits, RawTrackerHit.class, flags);
-            
-            // Add SVTData to event
-            event.put(this.svtCollectionName, this.svtData, HPSSVTData.class, 0);
-            
-            //
-            numberOfSamples = 0;
-        }
-    }
+	int numberOfSamples = 0;        // Total number of APV25 samples
+	int nSamplesAboveThresh = 3;    // Number of samples above noise threshold
+	int pedestal = 1638;            // [ADC counts] For now, all channels have the same pedestal
+	int flags = 0;                  //
+	int noise = 18;                 // [ADC Counts] RMS noise 
+	int noiseThreshold = 3;         // Units of RMS noise
+	private boolean thresholdCut = false;       // Apply threshold cut?
+	private boolean tailCut = false;            // Apply tail cut?
+	private boolean noiseSuppression = false;   // Apply noise supression?
+	double[] apv25DataStream;
+	List<Double> samples;
+	String RawTrackerHitsCollectionName = "RawTrackerHits";
+	String RawTrackerHitsNoCutsCollectionName = "RawTrackerHitsNoCuts";
+	String svtCollectionName = "SVTData";
+
+	/**
+	 * Default Constructor
+	 */
+	public HPSDataProcessingModule() {
+		channelToBlock = new HashMap<Integer, List<Double>>();
+		sensorToBlocksMap = new HashMap<Long, Map<Integer, List<Double>>>();
+		rawHits = new ArrayList<RawTrackerHit>();
+		rawHitsNoCuts = new ArrayList<RawTrackerHit>();
+		svtData = new ArrayList<HPSSVTData>();
+		svtFpgaData = new ArrayList<HPSSVTData>();
+	}
+
+	/**
+	 * 
+	 */
+	@Override
+	public void detectorChanged(Detector detector) {
+
+		// Get the tracker
+		IDetectorElement tracker = detector.getDetectorElement().findDetectorElement("Tracker");
+
+		// Fill the collection of sensors
+		sensorSet.addAll(tracker.findDescendants(SiSensor.class));
+
+		for (SiSensor sensor : sensorSet) {
+
+			// Map a sensor to its identifier
+			sensorMap.put(sensor.getIdentifier().getValue(), sensor);
+
+			// Map a sensor to its corresponding samples
+			sensorToBlocksMap.put(sensor.getIdentifier().getValue(),
+					new HashMap<Integer, List<Double>>());
+		}
+	}
+
+	/**
+	 * Set the SVT collection name
+	 */
+	public void setSvtCollectionName(String svtCollectionName) {
+		this.svtCollectionName = svtCollectionName;
+	}
+
+	/**
+	 * Set the number of samples above threshold a signal must have
+	 */
+	public void setSamplesAboveThresh(int nSamplesAboveThresh) {
+		this.nSamplesAboveThresh = nSamplesAboveThresh;
+	}
+
+	/**
+	 * Set the noise RMS [ADC Counts]
+	 */
+	public void setNoise(int noise) {
+		this.noise = noise;
+	}
+
+	/**
+	 * Set the noise threshold in units of RMS noise
+	 */
+	public void setNoiseThreshold(int noiseThreshold) {
+		this.noiseThreshold = noiseThreshold;
+	}
+
+	/**
+	 * Set the pedestal value for all channels
+	 */
+	public void setPedestal(int pedestal) {
+		this.pedestal = pedestal;
+	}
+
+	/**
+	 * Enable the threshold cut.  The threshold cut requires a certain number
+	 * of samples per hit to be above a noise threshold.
+	 */
+	public void enableThresholdCut() {
+		this.thresholdCut = true;
+	}
+
+	/**
+	 * Enable the tail cut.  The tail cut requires sample 1 to be greater than
+	 * sample 0 or sample 2 to be greater than sample 1. This eliminates 
+	 * hits that may arise due to shaper signal tails.
+	 */
+	public void enableTailCut() {
+		this.tailCut = true;
+	}
+
+	/**
+	 * Enable noise suppression cut.  Requires samples 2 or 3 to be above a
+	 * threshold noiseThreshold + noise. 
+	 */
+	public void enableNoiseSuppressionCut() {
+		this.noiseSuppression = true;
+	}
+
+	/**
+	 * Buffer a sample that has been readout from a sensor.
+	 * 
+	 * @param sensorToDigitalMap
+	 *      A map relating a sensor to the digital samples readout from the 
+	 *      sensor
+	 */
+	public void addSample(Map<Long, Map<Integer, double[]>> sensorToDigitalMap) {
+
+		/*
+		 * Long:     Sensor Identifier
+		 * Integer:  Chip Number
+		 * double[]: APV25 Data Stream 
+		 */
+
+		int channelN = 0;
+
+		// Loop through the list of all sensors
+		for (Map.Entry<Long, Map<Integer, double[]>> sensor : sensorToDigitalMap.entrySet()) {
+
+			// Loop through all APV25s
+			for (Map.Entry<Integer, double[]> sample : sensor.getValue().entrySet()) {
+
+				// Copy the sample to avoid concurrent modification
+				apv25DataStream = sample.getValue();
+
+				// Strip the APV25 data stream of all header information
+				// This needs to change so that the real chip address can be 
+				// extracted ...
+				apv25DataStream = Arrays.copyOfRange(apv25DataStream, 12, apv25DataStream.length - 1);
+
+				// Loop through all channels
+				for (int channel = 0; channel < apv25DataStream.length; channel++) {
+
+					channelN = channel + sample.getKey() * 128;
+
+					// Check if a block has been created for this channel. If
+					// not create it
+					if (!sensorToBlocksMap.get(sensor.getKey()).containsKey(channelN)) {
+						sensorToBlocksMap.get(sensor.getKey()).put(channelN, new ArrayList<Double>(6));
+					}
+
+					sensorToBlocksMap.get(sensor.getKey()).get(channelN).add(apv25DataStream[channel]);
+
+				}
+			}
+		}
+		numberOfSamples++;
+	}
+
+	/**
+	 *  Finds hits that satisfied all required cuts and creates both
+	 *  RawTrackerHits and SVTData
+	 */
+	public void findHits() {
+
+		int fpgaAddress = 0;
+		int hybridNumber = 0;
+		int apvNumber = 0;
+
+		// Clear the list of raw tracker hits
+		rawHits.clear();
+		rawHitsNoCuts.clear();
+		svtData.clear();
+
+		// Loop through all sensors and the corresponding blocks
+		for (Map.Entry<Long, Map<Integer, List<Double>>> sensor : sensorToBlocksMap.entrySet()) {
+
+			// Get the FPGA address
+			fpgaAddress = HPSSVTDAQMaps.sensorToDAQPair.get(sensorMap.get(sensor.getKey())).getSecondElement();
+
+			for (Map.Entry<Integer, List<Double>> block : sensor.getValue().entrySet()) {
+				short[] adc = new short[6];
+
+				// Convert ADC value to a short
+				for (int index = 0; index < adc.length; index++) {
+					adc[index] = block.getValue().get(index).shortValue();
+				}
+
+				// Create RawTrackerHits from all hits before applying cuts
+				RawTrackerHit newHit = makeRawTrackerHit(block.getKey(), sensorMap.get(sensor.getKey()), adc);
+				rawHitsNoCuts.add(newHit);
+
+				// Check if a block has the appropriate number of blocks above
+				// threshold
+				if (thresholdCut && !(samplesAboveThreshold(adc) >= nSamplesAboveThresh)) {
+					block.getValue().clear();
+					continue;
+				}
+
+				// Apply the tail cut
+				if (tailCut && !tailCut(adc)) {
+					block.getValue().clear();
+					continue;
+				}
+
+				// Apply noise suppression cut
+				if (noiseSuppression && !noiseSuppressionCut(adc)) {
+					block.getValue().clear();
+					continue;
+				}
+
+				// If all cuts are satisfied, add the hit to the list of hits to be saved
+				rawHits.add(newHit);
+
+				// Get the hybrid number
+				hybridNumber = HPSSVTDAQMaps.sensorToDAQPair.get(sensorMap.get(sensor.getKey())).getFirstElement();
+
+				// Find the APV number
+				apvNumber = (int) Math.floor(block.getKey() / 128);
+
+				// Create an svtData packet
+				svtData.add(new HPSSVTData(hybridNumber, apvNumber, block.getKey() % 128, fpgaAddress, adc));
+				svtFpgaData.add(new HPSSVTData(hybridNumber, apvNumber, block.getKey() % 128, fpgaAddress, adc));
+
+				block.getValue().clear();
+			}
+
+			HPSSVTDataBuffer.addToBuffer(svtFpgaData, fpgaAddress);
+
+			// Clear data buffer.
+			svtFpgaData.clear();
+		}
+		System.out.println(this.getClass().getName() + ": Total RawTrackerHits before cuts: " + rawHitsNoCuts.size());
+		System.out.println(this.getClass().getName() + ": Total RawTrackerHits: " + rawHits.size());
+		System.out.println(this.getClass().getName() + ": Total SVTData: " + svtData.size());
+	}
+
+	/**
+	 * Creates a rawTrackerHit
+	 * 
+	 * @param channelNumber
+	 *      Si Strip from which the hit originates from
+	 * @param sensor
+	 *      Sensor from which the hit originates from
+	 * @param adcValues
+	 *      Shaper signal samples
+	 * @return RawTrackerHit
+	 */
+	private RawTrackerHit makeRawTrackerHit(Integer channelNumber, SiSensor sensor, short[] adcValues) {
+		IReadout ro = sensor.getReadout();
+
+		// No time yet
+		int time = 0;
+		long cell_id = sensor.makeStripId(channelNumber, 1).getValue();
+
+		RawTrackerHit rawHit = new BaseRawTrackerHit(time, cell_id, adcValues, new ArrayList<SimTrackerHit>(), sensor);
+
+		ro.addHit(rawHit);
+
+		return rawHit;
+	}
+
+	/**
+	 * Finds how many samples are above a given threshold
+	 * 
+	 * @param adc
+	 *      Shaper signal samples
+	 * @return Number of samples above threshold
+	 */
+	private int samplesAboveThreshold(short[] adc) {
+		// Number of samples above threshold
+		int nSamplesAboveThreshold = 0;
+
+		for (int sample = 0; sample < adc.length; sample++) {
+			if (adc[sample] >= pedestal + noiseThreshold * noise) {
+				nSamplesAboveThreshold++;
+			}
+		}
+		return nSamplesAboveThreshold;
+	}
+
+	/**
+	 * Applies tail cut
+	 * 
+	 * @param adc
+	 *      Shaper signal samples
+	 * @return true if the cut is satisfied, false otherwise
+	 */
+	private boolean tailCut(short[] adc) {
+		if (adc[3] > adc[2] || adc[4] > adc[3]) {
+			return true;
+		}
+		return false;
+	}
+
+	/**
+	 * Applies noise suppression cut
+	 * 
+	 * @param adc 
+	 *      Shaper signal samples
+	 * @return true if the cut is satisfied, false otherwise
+	 */
+	private boolean noiseSuppressionCut(short[] adc) {
+		if (adc[3] > pedestal + noiseThreshold * noise || adc[4] > pedestal + noiseThreshold * noise) {
+			return true;
+		}
+		return false;
+	}
+
+	/**
+	 * 
+	 */
+	@Override
+	public void process(EventHeader event) {
+		super.process(event);
+
+		// If six samples have been collected process the data
+		if (numberOfSamples == 6) {
+
+			// Find hits
+			findHits();
+
+			// Add RawTrackerHits to the event
+			event.put(RawTrackerHitsCollectionName, rawHits, RawTrackerHit.class, flags);
+
+			// Add SVTData to event
+			event.put(this.svtCollectionName, this.svtData, HPSSVTData.class, 0);
+
+			//
+			numberOfSamples = 0;
+		}
+	}
 }

hps-java/src/main/java/org/lcsim/hps/recon/tracking
HPSMakeSVTCellID.java 1.3 -> 1.4
diff -u -r1.3 -r1.4
--- HPSMakeSVTCellID.java	28 Mar 2012 18:59:09 -0000	1.3
+++ HPSMakeSVTCellID.java	10 Apr 2012 01:00:13 -0000	1.4
@@ -15,7 +15,7 @@
  */
 public class HPSMakeSVTCellID {
     
-    public long HPSMakeSVTCellID(int hybrid, int fpgaAddress, int apv, int channel) {
+    public static long HPSMakeSVTCellID(int hybrid, int fpgaAddress, int apv, int channel) {
 // Information from Jeremy about how the CellID is coded
 //                Here's the ID scheme for the SVT in that detector...
 //    <readout name="TrackerHits">
@@ -32,8 +32,8 @@
                 IIdentifier sensorIdent = sensor.getIdentifier();
                 SiTrackerIdentifierHelper sensorHelper = (SiTrackerIdentifierHelper) sensor.getIdentifierHelper();
 
-                int layer = 0;
-                int module = sensorHelper.getModuleValue(sensorIdent);
+                long layer = 0;
+                long module = sensorHelper.getModuleValue(sensorIdent);
                 if (module == 0) { //Layers 1-10 (Top SVT Volume)
                     layer = sensorHelper.getLayerValue(sensorIdent);
                 } //Layers 11-20 (Bottom SVT Volume)
@@ -41,15 +41,15 @@
                     layer = sensorHelper.getLayerValue(sensorIdent) + 10;
                 }
 
-                int sensornum = sensorHelper.getSensorValue(sensorIdent);
+                long sensornum = sensorHelper.getSensorValue(sensorIdent);
 
-                int system = 0;
+                long system = 0;
 
-                int barrel = 0;
+                long barrel = 0;
 
-                int side = sensor.getSensorID(); // according to Omar
+                long side = sensor.getSensorID(); // according to Omar
 
-                int strip = channel;
+                long strip = channel;
 
                 long CellID_ = system + (barrel << 6) + (layer << 9) + (module << 13) + (sensornum << 25)
                         + (side << 32) + (strip << 34);

hps-java/src/main/java/org/lcsim/hps/monitoring
MonitoringApplication.java 1.10 -> 1.11
diff -u -r1.10 -r1.11
--- MonitoringApplication.java	9 Apr 2012 00:04:04 -0000	1.10
+++ MonitoringApplication.java	10 Apr 2012 01:00:13 -0000	1.11
@@ -762,7 +762,7 @@
         //final String defaultEventBuilder = MCEventBuilder.class.getCanonicalName();
 
         // These are for Test Run data.
-        final String defaultSteering = "/org/lcsim/hps/defaultSteering/TestRunMonitoring.lcsim";   
+        final String defaultSteering = "/org/lcsim/hps/steering/TestRunMonitoring.lcsim";   
         final String defaultEventBuilder = LCSimTestRunEventBuilder.class.getCanonicalName();
         
         // Push default settings to JobPanel.
CVSspam 0.2.12


Use REPLY-ALL to reply to list

To unsubscribe from the LCD-CVS list, click the following link:
https://listserv.slac.stanford.edu/cgi-bin/wa?SUBED1=LCD-CVS&A=1