Commit in hps-java/src/main/java/org/lcsim/hps/users/meeg on MAIN | |||
SimpleTrackerDigiDriver.java | +317 | added 1.1 | |
NoiselessReadoutChip.java | +314 | added 1.1 | |
+631 |
lobotomized version of TrackerDigiDriver, for testing
diff -N SimpleTrackerDigiDriver.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ SimpleTrackerDigiDriver.java 29 Aug 2012 21:01:36 -0000 1.1 @@ -0,0 +1,317 @@
+package org.lcsim.hps.users.meeg; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.lcsim.detector.IDetectorElement; +import org.lcsim.detector.identifier.IIdentifier; +import org.lcsim.detector.tracker.silicon.SiSensor; +import org.lcsim.detector.tracker.silicon.SiTrackerIdentifierHelper; +import org.lcsim.detector.tracker.silicon.SiTrackerModule; +import org.lcsim.event.EventHeader; +import org.lcsim.event.RawTrackerHit; +import org.lcsim.event.SimTrackerHit; +import org.lcsim.geometry.Detector; +import org.lcsim.hps.recon.tracking.SvtUtils; +import org.lcsim.recon.tracking.digitization.sisim.CDFSiSensorSim; +import org.lcsim.recon.tracking.digitization.sisim.NearestNeighborRMS; +import org.lcsim.recon.tracking.digitization.sisim.RawTrackerHitMaker; +import org.lcsim.recon.tracking.digitization.sisim.SiDigitizer; +import org.lcsim.recon.tracking.digitization.sisim.SiTrackerHit; +import org.lcsim.recon.tracking.digitization.sisim.SiTrackerHitStrip1D; +import org.lcsim.recon.tracking.digitization.sisim.StripHitMaker; +import org.lcsim.recon.tracking.digitization.sisim.config.SimTrackerHitReadoutDriver; +import org.lcsim.util.Driver; +import org.lcsim.util.lcio.LCIOUtil; + +/** + * This Driver runs the tracker digitization to create raw hits and strip hits + * from simulated data. The output can be used by a track reconstruction + * algorithm like Seed Tracker. + * + * @author jeremym + * @version $Id: SimpleTrackerDigiDriver.java,v 1.1 2012/08/29 21:01:36 meeg Exp $ + */ +public class SimpleTrackerDigiDriver extends Driver { + // Debug switch for development. + + private boolean debug = false; + // Collection name. + private String readoutCollectionName = "TrackerHits"; + // Subdetector name. + private String subdetectorName = "Tracker"; + // Name of RawTrackerHit output collection. + private String rawTrackerHitOutputCollectionName = "RawTrackerHitMaker_RawTrackerHits"; + // Name of StripHit1D output collection. + private String stripHitOutputCollectionName = "StripClusterer_SiTrackerHitStrip1D"; + // Readout parameters. + private boolean dropBadChannels = true; + private double readoutNoiseIntercept = 270.0; + private double readoutNoiseSlope = 36.0; + private int readoutNBits = 10; + private int readoutDynamicRange = 40; + // Clustering parameters. + private double clusterSeedThreshold = 4.0; + private double clusterNeighborThreshold = 3.0; + private double clusterThreshold = 4.0; + private int clusterMaxSize = 10; + private int clusterCentralStripAveragingThreshold = 4; + // Clustering errors by number of TrackerHits. + private static final double clusterErrorMultiplier = 1.0; + private double oneClusterErr = clusterErrorMultiplier / Math.sqrt(12.); + private double twoClusterErr = clusterErrorMultiplier / 5.0; + private double threeClusterErr = clusterErrorMultiplier / 3.0; + private double fourClusterErr = clusterErrorMultiplier / 2.0; + private double fiveClusterErr = clusterErrorMultiplier / 1.0; + // Various data lists required by digitization. + private List<String> readouts = new ArrayList<String>(); + private List<String> processPaths = new ArrayList<String>(); + private List<IDetectorElement> processDEs = new ArrayList<IDetectorElement>(); + private Set<SiSensor> processSensors = new HashSet<SiSensor>(); + private Set<SiTrackerModule> processModules = new HashSet<SiTrackerModule>(); + // Digi class objects. + private SiDigitizer stripDigitizer; + private StripHitMaker stripClusterer; + int[][] counts = new int[2][10]; + + public void setDebug(boolean debug) { + this.debug = debug; + } + + public void setReadoutCollectionName(String readoutCollectionName) { + this.readoutCollectionName = readoutCollectionName; + } + + public void setSubdetectorName(String subdetectorName) { + this.subdetectorName = subdetectorName; + } + + public void setRawTrackerHitOutputCollectionName(String rawTrackerHitOutputCollectionName) { + this.rawTrackerHitOutputCollectionName = rawTrackerHitOutputCollectionName; + } + + public void setStripHitOutputCollectionName(String stripHitOutputCollectionName) { + this.stripHitOutputCollectionName = stripHitOutputCollectionName; + } + + public void setDropBadChannels(boolean dropBadChannels) { + this.dropBadChannels = dropBadChannels; + } + + public void setReadoutNoiseIntercept(double readoutNoiseIntercept) { + this.readoutNoiseIntercept = readoutNoiseIntercept; + } + + public void setReadoutNoiseSlope(double readoutNoiseSlope) { + this.readoutNoiseSlope = readoutNoiseSlope; + } + + public void setReadoutNBits(int readoutNBits) { + this.readoutNBits = readoutNBits; + } + + public void setReadoutDynamicRange(int readoutDynamicRange) { + this.readoutDynamicRange = readoutDynamicRange; + } + + public void setClusterSeedThreshold(double clusterSeedThreshold) { + this.clusterSeedThreshold = clusterSeedThreshold; + } + + public void setClusterNeighborThreshold(double clusterNeighborThreshold) { + this.clusterNeighborThreshold = clusterNeighborThreshold; + } + + public void setClusterThreshold(double clusterThreshold) { + this.clusterThreshold = clusterThreshold; + } + + public void setClusterMaxSize(int clusterMaxSize) { + this.clusterMaxSize = clusterMaxSize; + } + + public void setClusterCentralStripAveragingThreshold(int clusterCentralStripAveragingThreshold) { + this.clusterCentralStripAveragingThreshold = clusterCentralStripAveragingThreshold; + } + + public void setOneClusterErr(double oneClusterErr) { + this.oneClusterErr = oneClusterErr; + } + + public void setTwoClusterErr(double twoClusterErr) { + this.twoClusterErr = twoClusterErr; + } + + public void setThreeClusterErr(double threeClusterErr) { + this.threeClusterErr = threeClusterErr; + } + + public void setFourClusterErr(double fourClusterErr) { + this.fourClusterErr = fourClusterErr; + } + + public void setFiveClusterErr(double fiveClusterErr) { + this.fiveClusterErr = fiveClusterErr; + } + + /** + * Creates a new instance of TrackerHitDriver. + */ + public SimpleTrackerDigiDriver() { + } + + /** + * Initializes this Driver's objects with the job parameters. + */ + private void initialize() { + + // Create the sensor simulation. + CDFSiSensorSim stripSim = new CDFSiSensorSim(); + + // Create the readout chips and set the noise parameters. + NoiselessReadoutChip stripReadout = new NoiselessReadoutChip(); + stripReadout.setDropBadChannels(dropBadChannels); + stripReadout.setNoiseIntercept(readoutNoiseIntercept); + stripReadout.setNoiseSlope(readoutNoiseSlope); + stripReadout.setNbits(readoutNBits); + stripReadout.setDynamicRange(readoutDynamicRange); + + // Create the digitizer that produces the raw hits + stripDigitizer = new RawTrackerHitMaker(stripSim, stripReadout); + + // Create Strip clustering algorithm. + NearestNeighborRMS stripClusteringAlgo = new NearestNeighborRMS(); + stripClusteringAlgo.setSeedThreshold(clusterSeedThreshold); + stripClusteringAlgo.setNeighborThreshold(clusterNeighborThreshold); + stripClusteringAlgo.setClusterThreshold(clusterThreshold); + + // Create the clusterers and set hit-making parameters. + stripClusterer = new StripHitMaker(stripSim, stripReadout, stripClusteringAlgo); + stripClusterer.setMaxClusterSize(clusterMaxSize); + stripClusterer.setCentralStripAveragingThreshold(clusterCentralStripAveragingThreshold); + + // Set the cluster errors. + stripClusterer.SetOneClusterErr(oneClusterErr); + stripClusterer.SetTwoClusterErr(twoClusterErr); + stripClusterer.SetThreeClusterErr(threeClusterErr); + stripClusterer.SetFourClusterErr(fourClusterErr); + stripClusterer.SetFiveClusterErr(fiveClusterErr); + + // Set the readout to process. + readouts.add(readoutCollectionName); + + // Set the detector to process. + processPaths.add(subdetectorName); + } + + /** + * This is executed before detectorChanged and initialization of + * digitization objects is done here. + */ + @Override + public void startOfData() { + + // At start of job, setup digitization objects needed by this Driver. + initialize(); + + // If readouts not already set, set them up. + if (!readouts.isEmpty()) { + System.out.println("Adding SimTrackerHitIdentifierReadoutDriver with readouts: " + readouts); + super.add(new SimTrackerHitReadoutDriver(readouts)); + } + super.startOfData(); + readouts.clear(); // FIXME Is this needed? + } + + /** + * Do initialization once we get a Detector. + */ + @Override + public void detectorChanged(Detector detector) { + + // Call sub-Driver's detectorChanged methods. + super.detectorChanged(detector); + + // Process detectors specified by path, otherwise process entire + // detector + IDetectorElement deDetector = detector.getDetectorElement(); + + for (String path : processPaths) { + processDEs.add(deDetector.findDetectorElement(path)); + } + + if (processDEs.isEmpty()) { + processDEs.add(deDetector); + } + + for (IDetectorElement detectorElement : processDEs) { + processSensors.addAll(detectorElement.findDescendants(SiSensor.class)); + //if (debug) + // System.out.println("added " + processSensors.size() + " sensors"); + processModules.addAll(detectorElement.findDescendants(SiTrackerModule.class)); + //if (debug) + // System.out.println("added " + processModules.size() + " modules"); + } + } + + /** + * Perform the digitization. + */ + @Override + public void process(EventHeader event) { + // Call sub-Driver processing. + super.process(event); + + // Make new lists for output. + List<RawTrackerHit> rawHits = new ArrayList<RawTrackerHit>(); + List<SiTrackerHit> stripHits1D = new ArrayList<SiTrackerHit>(); + + if (event.hasCollection(SimTrackerHit.class, this.readoutCollectionName)) { + // Make raw hits. + for (SiSensor sensor : processSensors) { + rawHits.addAll(stripDigitizer.makeHits(sensor)); + } + + // Make strip hits. + for (SiSensor sensor : processSensors) { + stripHits1D.addAll(stripClusterer.makeHits(sensor)); + } + + // Debug prints. + if (debug) { + if (event.hasCollection(SimTrackerHit.class, this.readoutCollectionName)) { + List<SimTrackerHit> simHits = event.get(SimTrackerHit.class, this.readoutCollectionName); + System.out.println("SimTrackerHit collection " + this.readoutCollectionName + " has " + simHits.size() + " hits."); + System.out.println("RawTrackerHit collection " + this.rawTrackerHitOutputCollectionName + " has " + rawHits.size() + " hits."); + System.out.println("TrackerHit collection " + this.stripHitOutputCollectionName + " has " + stripHits1D.size() + " hits."); + } else { + System.out.println("SimTrackerHit collection " + this.readoutCollectionName + " not found."); + } + } + } + + if (debug) { + for (int mod = 0; mod < 2; mod++) { + for (int layer = 0; layer < 10; layer++) { + counts[mod][layer] += SvtUtils.getInstance().getSensor(mod, layer).getReadout().getHits(RawTrackerHit.class).size(); + } + } + } + // Put output hits into collection. + int flag = LCIOUtil.bitSet(0, 31, true); // Turn on 64-bit cell ID. + event.put(this.rawTrackerHitOutputCollectionName, rawHits, RawTrackerHit.class, flag, toString()); + event.put(this.stripHitOutputCollectionName, stripHits1D, SiTrackerHitStrip1D.class, 0, toString()); + } + + public void endOfData() { + if (debug) { + for (int mod = 0; mod < 2; mod++) { + for (int layer = 0; layer < 10; layer++) { + System.out.format("mod %d, layer %d, count %d, ID %d\n", mod, layer, counts[mod][layer], SvtUtils.getInstance().getSensor(mod, layer).getIdentifier().getValue()); + } + } + } + } +}
\ No newline at end of file
diff -N NoiselessReadoutChip.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ NoiselessReadoutChip.java 29 Aug 2012 21:01:36 -0000 1.1 @@ -0,0 +1,314 @@
+/* + * Class BasicReadoutChip + */ +package org.lcsim.hps.users.meeg; + +import java.util.ArrayList; +import java.util.List; +import java.util.SortedMap; +import java.util.TreeMap; +import org.lcsim.detector.tracker.silicon.SiSensor; +import org.lcsim.detector.tracker.silicon.SiSensorElectrodes; +import org.lcsim.event.RawTrackerHit; +import org.lcsim.hps.recon.tracking.HPSSVTCalibrationConstants; +import org.lcsim.recon.tracking.digitization.sisim.ReadoutChip; +import org.lcsim.recon.tracking.digitization.sisim.ReadoutChip.ReadoutChannel; +import org.lcsim.recon.tracking.digitization.sisim.SiElectrodeData; +import org.lcsim.recon.tracking.digitization.sisim.SiElectrodeDataCollection; + +/** + * Basic readout chip class. This class supports the minimal functions expected of + * a readout chip. The charge on a strip/pixel is digitized as an integer number + * with a simple ADC with programmable resolution and dynamic range. A chip with + * 1-bit ADC resolution (binary readout) is treated as a special case. + * + * Noise is added to strips with charge and random noise hits are generated as well. + * Methods are provided to decode the charge and time (although the current + * implementation always returns a time of 0). + * + * This implementation has thresholds that are settable in units of RMS noise of + * each channel to enable simluation of highly optimized readout chains. If + * absolute thresholds are desired, GenericReadoutChip should be used instead. + * + * @author Tim Nelson + */ +public class NoiselessReadoutChip implements ReadoutChip { + + private BasicChannel _channel = new BasicChannel(); + private ADC _adc = new ADC(); + private boolean dropBadChannels = false; + + /** Creates a new instance of BasicReadoutChip */ + public NoiselessReadoutChip() { + } + + public void setDropBadChannels(boolean dropBadChannels) { + this.dropBadChannels = dropBadChannels; + } + + /** + * Set the noise intercept (i.e., the noise for 0 strip/pixel capacitance). + * Units are electrons of noise. + * + * @param noise_intercept noise for 0 capacitance + */ + public void setNoiseIntercept(double noise_intercept) { + _channel.setNoiseIntercept(noise_intercept); + } + + /** + * Set the noise slope (i.e., the proportionality between noise and capacitance). + * Units are electrons of noise per fF of capacitance. + * + * @param noise_slope noise slope per unit capacitance + */ + public void setNoiseSlope(double noise_slope) { + _channel.setNoiseSlope(noise_slope); + } + + /** + * Set the number of bits of ADC resolution + * + * @param nbits + */ + public void setNbits(int nbits) { + getADC().setNbits(nbits); + } + + /** + * Set the dynamic range of the ADC + * + * @param dynamic_range in fC + */ + public void setDynamicRange(double dynamic_range) { + getADC().setDynamicRange(dynamic_range); + } + + /** + * Return the BasicChannel associated with a given channel number. + * For the basic readout, there is a single instance of BasicChannel + * and thus the channel number is ignored. + * + * @param channel_number channel number + * @return associated BasicReadoutChannel + */ + public BasicChannel getChannel(int channel_number) { + return _channel; + } + + private ADC getADC() { + return _adc; + } + + /** + * Given a collection of electrode data (i.e., charge on strips/pixels), + * return a map associating the channel and it's list of raw data. + * + * @param data electrode data from the charge distribution + * @param electrodes strip or pixel electrodes + * @return map containing the ADC counts for this sensor + */ + public SortedMap<Integer, List<Integer>> readout(SiElectrodeDataCollection data, SiSensorElectrodes electrodes) { + + // If there is no electrode data for this readout chip, create an empty + // electrode data collection + if (data == null) { + data = new SiElectrodeDataCollection(); + } + + // Add noise hits to the electrode data collection +// addNoise(data, electrodes); + + // return the digitized charge data as a map that associates a hit + // channel with a list of raw data for the channel + return digitize(data, electrodes); + } + + /** + * Decode the hit charge stored in the RawTrackerHit + * + * @param hit raw hit + * @return hit charge in units of electrons + */ + public double decodeCharge(RawTrackerHit hit) { + return getADC().decodeCharge(hit.getADCValues()[0]); + } + + /** + * Decode the hit time. Currently, the basic readout chip ignores the + * hit time and returns 0. + * + * @param hit raw hit data + * @return hit time + */ + public int decodeTime(RawTrackerHit hit) { + return 0; + } + + /** + * Digitizes the hit channels in a SiElectrodeDataCollection. + * + * The SiElectrodeDataCollection is a map that associates a given channel with + * it's SiElectrodeData. The SiElectrodeData encapsulates the deposited charge + * on an strip/pixel and any associated SimTrackerHits. + * + * The output of this class is a map that associates a channel number with + * a list of raw data + * + * @param data electrode data collection + * @return map associating channels with a list of raw data + */ + private SortedMap<Integer, List<Integer>> digitize(SiElectrodeDataCollection data, + SiSensorElectrodes electrodes) { + // Create the map that associates a given sensor channel with it's list of raw data + SortedMap<Integer, List<Integer>> chip_data = new TreeMap<Integer, List<Integer>>(); + + // Loop over the channels contained in the SiElectrodeDataCollection + for (Integer channel : data.keySet()) { + if (dropBadChannels && HPSSVTCalibrationConstants.isBadChannel((SiSensor) electrodes.getDetectorElement(), channel)) { +// System.out.format("%d bad\n", channel); + continue; + } +// System.out.format("%d OK\n", channel); + // Fetch the electrode data for this channel + SiElectrodeData eldata = data.get(channel); + + // Get the charge in units of electrons + double charge = eldata.getCharge(); + + // Calculate the ADC value for this channel and make sure it is positive + int adc = getADC().convert(charge); + if (adc <= 0) { + continue; + } + + // Create a list containing the adc value - for the basic readout + // there is only 1 word of raw data + List<Integer> channel_data = new ArrayList<Integer>(); + channel_data.add(adc); + + // Save the list of raw data in the chip_data map + chip_data.put(channel, channel_data); + } + + return chip_data; + } + + /** + * BasicChannel class representing a single channel's behavior + * + * Note that binary readout is a special case. Anything positive value + * passed to a binary ADC for digitization is assumed to have crossed t + * hreshold and is assigned a value of 1. Decoding binary readout results + * in either 0 or dynamic_range. + */ + private class BasicChannel implements ReadoutChannel { + + private double _noise_intercept = 0.; + private double _noise_slope = 0.; + + /** + * Set the noise (in electrons) for 0 capacitance + * + * @param noise_intercept noise intercept + */ + private void setNoiseIntercept(double noise_intercept) { + _noise_intercept = noise_intercept; + } + + /** + * Set the capacitative noise slope (in electrons / pF) + * + * @param noise_slope noise slope + */ + private void setNoiseSlope(double noise_slope) { + _noise_slope = noise_slope; + } + + /** + * Return the noise in electrons for a given strip/pixel capacitance + * + * @param capacitance capacitance in pF + * @return noise in electrons + */ + public double computeNoise(double capacitance) { + return _noise_intercept + _noise_slope * capacitance; + } + } + + /** + * ADC class representing analog to digital converter. + */ + private class ADC { + + private int _nbits = 8; + private double _dynamic_range = 20.; + + /** + * Set the ADC resolution in number of bits. + * + * @param nbits number of bits + */ + private void setNbits(int nbits) { + _nbits = nbits; + } + + /** + * Set the dynamic range in fC + * + * @param dynamic range + */ + private void setDynamicRange(double dynamic_range) { + _dynamic_range = dynamic_range; + } + + /** + * Compute the maximum ADC value + * + * @return largest possible ADC value according to # of bits + */ + private int maxADCValue() { + return (int) Math.pow(2, _nbits) - 1; + } + + /** + * Compute the conversion constant in ADC/fC + * + * @return conversion constant for ADC + */ + private double conversionConstant() { + return maxADCValue() / _dynamic_range; + } + + /** + * Perform analog to digital conversion + * + * @return digital ADC output between 0 and maxADCValue + */ + public int convert(double charge) { + if (_nbits != 1) { + return Math.max(0, Math.min(maxADCValue(), (int) Math.floor(charge * 1.602e-4 * conversionConstant()))); + } else { + if (charge <= 0.0) { + return 0; + } else { + return 1; + } + } + } + + /** + * Decode charge from ADC value + * + * @return charge specified by a given ADC value + */ + public double decodeCharge(int adc_value) { + if (_nbits != 1) { + return (adc_value + 0.5) / (1.602e-4 * conversionConstant()); + } else { + return adc_value * _dynamic_range; + } + + } + } +}
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