8 added + 3 removed + 12 modified, total 23 files
lcsim/src/org/lcsim/detector/driver
diff -u -r1.5 -r1.6
--- RawTrackerHitIdentifierReadoutDriver.java 24 Apr 2009 19:56:09 -0000 1.5
+++ RawTrackerHitIdentifierReadoutDriver.java 24 Aug 2009 23:07:38 -0000 1.6
@@ -9,8 +9,8 @@
import org.lcsim.detector.identifier.Identifier;
import org.lcsim.event.EventHeader;
import org.lcsim.event.RawTrackerHit;
-import org.lcsim.recon.tracking.digitization.sisim.CollectionHandler;
-import org.lcsim.recon.tracking.digitization.sisim.ReadoutCleanupDriver;
+import org.lcsim.recon.tracking.digitization.sisim.config.CollectionHandler;
+import org.lcsim.recon.tracking.digitization.sisim.config.ReadoutCleanupDriver;
public class RawTrackerHitIdentifierReadoutDriver
extends CollectionHandler
lcsim/src/org/lcsim/detector/driver
diff -u -r1.6 -r1.7
--- TrackerHitIdentifierReadoutDriver.java 24 Apr 2009 19:56:09 -0000 1.6
+++ TrackerHitIdentifierReadoutDriver.java 24 Aug 2009 23:07:38 -0000 1.7
@@ -5,11 +5,11 @@
import org.lcsim.detector.IReadout;
import org.lcsim.event.EventHeader;
import org.lcsim.event.TrackerHit;
-import org.lcsim.recon.tracking.digitization.sisim.CollectionHandler;
-import org.lcsim.recon.tracking.digitization.sisim.ReadoutCleanupDriver;
import org.lcsim.recon.tracking.digitization.sisim.SiTrackerHitPixel;
import org.lcsim.recon.tracking.digitization.sisim.SiTrackerHitStrip1D;
import org.lcsim.recon.tracking.digitization.sisim.TrackerHitType;
+import org.lcsim.recon.tracking.digitization.sisim.config.CollectionHandler;
+import org.lcsim.recon.tracking.digitization.sisim.config.ReadoutCleanupDriver;
public class TrackerHitIdentifierReadoutDriver
extends CollectionHandler
lcsim/src/org/lcsim/recon/tracking/digitization/sisim
diff -u -r1.3 -r1.4
--- TrackerHitDriver.java 24 Apr 2009 19:49:46 -0000 1.3
+++ TrackerHitDriver.java 24 Aug 2009 23:07:39 -0000 1.4
@@ -21,6 +21,7 @@
import org.lcsim.event.EventHeader;
import org.lcsim.event.RawTrackerHit;
import org.lcsim.geometry.Detector;
+import org.lcsim.recon.tracking.digitization.sisim.config.SimTrackerHitReadoutDriver;
import org.lcsim.util.Driver;
import org.lcsim.util.lcio.LCIOConstants;
lcsim/src/org/lcsim/recon/tracking/digitization/sisim
diff -N CollectionHandler.java
--- CollectionHandler.java 24 Apr 2009 18:24:01 -0000 1.1
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,56 +0,0 @@
-package org.lcsim.recon.tracking.digitization.sisim;
-
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import org.lcsim.util.Driver;
-
-public abstract class CollectionHandler extends Driver
-{
- Set<String> collections = new HashSet<String>();
-
- public CollectionHandler()
- {}
-
- public CollectionHandler(List<String> collectionNames)
- {
- for (String collection : collectionNames)
- {
- this.collections.add(collection);
- }
- }
-
- public CollectionHandler(String[] collectionNames)
- {
- for (String collection : collectionNames)
- {
- this.collections.add(collection);
- }
- }
-
- public void setCollections(String[] collectionNames)
- {
- collections.addAll(Arrays.asList(collectionNames));
- }
-
- public void setCollection(String collection)
- {
- collections.add(collection);
- }
-
- /**
- * Return whether this CollectionHandler can handle the collection called
- * <code>collectionName</code>.
- * @param collectionName
- * @return True if <code>collections</code> is empty or if
- * collections contains </code>collectionName</code>;
- * false if does not contain </code>collectionName</code>.
- */
- public boolean canHandle(String collectionName)
- {
- if (collections.size() == 0) return true;
- return collections.contains(collectionName);
- }
-}
lcsim/src/org/lcsim/recon/tracking/digitization/sisim
diff -N ReadoutCleanupDriver.java
--- ReadoutCleanupDriver.java 24 Apr 2009 19:56:09 -0000 1.1
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,49 +0,0 @@
-package org.lcsim.recon.tracking.digitization.sisim;
-
-import java.util.List;
-
-import org.lcsim.event.EventHeader;
-import org.lcsim.geometry.Detector;
-import org.lcsim.geometry.compact.Subdetector;
-
-/**
- * This Driver clears the DetectorElement Readout
- * associated with a given collection in the event header.
- * It accepts a list of collection names and ignores
- * others.
- *
- * @author jeremym
- * @version $Id: ReadoutCleanupDriver.java,v 1.1 2009/04/24 19:56:09 jeremy Exp $
- */
-public class ReadoutCleanupDriver
-extends CollectionHandler
-{
- public ReadoutCleanupDriver(List<String> collectionNames)
- {
- super(collectionNames);
- }
-
- public ReadoutCleanupDriver(String[] collectionNames)
- {
- super(collectionNames);
- }
-
- protected void process(EventHeader event)
- {
- Detector detector = event.getDetector();
-
- for (Subdetector subdet : detector.getSubdetectors().values())
- {
- if (subdet.getReadout() != null)
- {
- if (canHandle(subdet.getReadout().getName()))
- {
- if (subdet.getDetectorElement() != null)
- {
- subdet.getDetectorElement().clearReadouts();
- }
- }
- }
- }
- }
-}
\ No newline at end of file
lcsim/src/org/lcsim/recon/tracking/digitization/sisim
diff -N SimTrackerHitReadoutDriver.java
--- SimTrackerHitReadoutDriver.java 27 Apr 2009 19:00:15 -0000 1.3
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,78 +0,0 @@
-package org.lcsim.recon.tracking.digitization.sisim;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.lcsim.event.EventHeader;
-import org.lcsim.event.SimTrackerHit;
-
-/**
- * Assigns {@link org.lcsim.event.SimTrackerHit} objects to the readouts of their
- * corresponding {@link org.lcsim.detector.IDetectorElement}.
- * @author jeremym
- */
-public class SimTrackerHitReadoutDriver
-extends CollectionHandler
-{
- boolean needCleanupDriver=true;
- boolean debug=false;
-
- public SimTrackerHitReadoutDriver()
- {}
-
- public SimTrackerHitReadoutDriver(List<String> collectionNames)
- {
- super(collectionNames);
- }
-
- public SimTrackerHitReadoutDriver(String[] collectionNames)
- {
- super(collectionNames);
- }
-
- public void setReadoutCollections(String[] collectionNames)
- {
- super.setCollections(collectionNames);
- }
-
- public void setDebug(boolean debug)
- {
- this.debug = debug;
- }
-
- public void startOfData()
- {
- if (needCleanupDriver)
- {
- add(new ReadoutCleanupDriver(new ArrayList<String>(collections)));
- needCleanupDriver=false;
- }
- }
-
- protected void process(EventHeader header)
- {
- super.process(header);
- List<List<SimTrackerHit>> collections = header.get(SimTrackerHit.class);
- for (List<SimTrackerHit> collection : collections)
- {
- if (canHandle(header.getMetaData(collection).getName()))
- {
- for (SimTrackerHit hit : collection)
- {
- hit.getDetectorElement().getReadout().addHit(hit);
- if (debug)
- {
- System.out.println("driver assigned hit " + hit.getExpandedIdentifier().toString() + " to " + hit.getDetectorElement().getName() + " with id " + hit.getDetectorElement().getExpandedIdentifier().toString() + ".");
- System.out.println(" hit raw: " + hit.getIdentifier().toHexString() + ", DE raw: " + hit.getDetectorElement().getIdentifier().toHexString());
- System.out.println(" hit pos: " + hit.getPositionVec().toString() + ", DE pos: " + hit.getDetectorElement().getGeometry().getPosition().toString());
- System.out.println();
- if (!hit.getDetectorElement().getReadout().getHits(SimTrackerHit.class).contains(hit))
- {
- throw new RuntimeException("Readout of " + hit.getDetectorElement().getName() + " is missing a SimTrackerHit that points to it.");
- }
- }
- }
- }
- }
- }
-}
\ No newline at end of file
lcsim/src/org/lcsim/recon/tracking/digitization/sisim/config
diff -N CollectionHandler.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ CollectionHandler.java 24 Aug 2009 23:07:39 -0000 1.1
@@ -0,0 +1,56 @@
+package org.lcsim.recon.tracking.digitization.sisim.config;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.lcsim.util.Driver;
+
+public abstract class CollectionHandler extends Driver
+{
+ Set<String> collections = new HashSet<String>();
+
+ public CollectionHandler()
+ {}
+
+ public CollectionHandler(List<String> collectionNames)
+ {
+ for (String collection : collectionNames)
+ {
+ this.collections.add(collection);
+ }
+ }
+
+ public CollectionHandler(String[] collectionNames)
+ {
+ for (String collection : collectionNames)
+ {
+ this.collections.add(collection);
+ }
+ }
+
+ public void setCollections(String[] collectionNames)
+ {
+ collections.addAll(Arrays.asList(collectionNames));
+ }
+
+ public void setCollection(String collection)
+ {
+ collections.add(collection);
+ }
+
+ /**
+ * Return whether this CollectionHandler can handle the collection called
+ * <code>collectionName</code>.
+ * @param collectionName
+ * @return True if <code>collections</code> is empty or if
+ * collections contains </code>collectionName</code>;
+ * false if does not contain </code>collectionName</code>.
+ */
+ public boolean canHandle(String collectionName)
+ {
+ if (collections.size() == 0) return true;
+ return collections.contains(collectionName);
+ }
+}
lcsim/src/org/lcsim/recon/tracking/digitization/sisim/config
diff -N DigiDriver.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ DigiDriver.java 24 Aug 2009 23:07:39 -0000 1.1
@@ -0,0 +1,90 @@
+package org.lcsim.recon.tracking.digitization.sisim.config;
+
+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.tracker.silicon.SiSensor;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.RawTrackerHit;
+import org.lcsim.event.TrackerHit;
+import org.lcsim.geometry.Detector;
+import org.lcsim.recon.tracking.digitization.sisim.Clusterer;
+import org.lcsim.recon.tracking.digitization.sisim.SiDigitizer;
+import org.lcsim.recon.tracking.digitization.sisim.SiTrackerHit;
+import org.lcsim.util.Driver;
+import org.lcsim.util.lcio.LCIOConstants;
+
+/**
+ * Driver for running the tracker digitization. This
+ * driver should be setup as a child driver of a parent
+ * which accepts configuration parameters.
+ *
+ * @author jeremym
+ */
+public class DigiDriver extends Driver
+{
+ SiDigitizer digitizer;
+ Clusterer clusterer;
+
+ String rawHitsCollectionName;
+ String trackerHitsCollectionName;
+
+ List<String> subdetectorNames;
+
+ public DigiDriver(
+ SiDigitizer digitizer,
+ Clusterer clusterer,
+ String rawHitsCollectionName,
+ String trackerHitsCollectionName,
+ List<String> subdetectorNames)
+ {
+ this.digitizer = digitizer;
+ this.clusterer = clusterer;
+ this.rawHitsCollectionName = rawHitsCollectionName;
+ this.trackerHitsCollectionName = trackerHitsCollectionName;
+ this.subdetectorNames = subdetectorNames;
+ }
+
+ // List of sensors to process.
+ Set<SiSensor> sensorsToProcess = new HashSet<SiSensor>();
+
+ public void detectorChanged(Detector detector)
+ {
+ super.detectorChanged(detector);
+ setupSensorList(detector);
+ }
+
+ private void setupSensorList(Detector detector)
+ {
+ sensorsToProcess.clear();
+
+ IDetectorElement detectorDe = detector.getDetectorElement();
+
+ for (String subdetectorName : subdetectorNames)
+ {
+ IDetectorElement subdetectorDe = detectorDe.findDetectorElement(subdetectorName);
+ sensorsToProcess.addAll(subdetectorDe.findDescendants(SiSensor.class));
+ }
+ }
+
+ public void process(EventHeader event)
+ {
+ super.process(event);
+
+ List<RawTrackerHit> rawHits = new ArrayList<RawTrackerHit>();
+ List<SiTrackerHit> trackerHits = new ArrayList<SiTrackerHit>();
+
+ for (SiSensor sensor : sensorsToProcess)
+ {
+ rawHits.addAll(digitizer.makeHits(sensor));
+ trackerHits.addAll(clusterer.makeHits(sensor));
+ }
+
+ int flag = (1 << LCIOConstants.RTHBIT_HITS | 1 << LCIOConstants.TRAWBIT_ID1);
+ event.put(rawHitsCollectionName, rawHits, RawTrackerHit.class, flag, toString());
+ event.put(trackerHitsCollectionName, trackerHits, TrackerHit.class, 0, toString());
+ }
+}
lcsim/src/org/lcsim/recon/tracking/digitization/sisim/config
diff -N PixelDigiSetupDriver.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ PixelDigiSetupDriver.java 24 Aug 2009 23:07:39 -0000 1.1
@@ -0,0 +1,237 @@
+package org.lcsim.recon.tracking.digitization.sisim.config;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.lcsim.detector.tracker.silicon.SiSensor;
+import org.lcsim.event.EventHeader;
+import org.lcsim.geometry.Detector;
+import org.lcsim.recon.tracking.digitization.sisim.CDFSiSensorSim;
+import org.lcsim.recon.tracking.digitization.sisim.GenericReadoutChip;
+import org.lcsim.recon.tracking.digitization.sisim.Kpix;
+import org.lcsim.recon.tracking.digitization.sisim.NearestNeighbor;
+import org.lcsim.recon.tracking.digitization.sisim.PixelHitMaker;
+import org.lcsim.recon.tracking.digitization.sisim.RawTrackerHitMaker;
+import org.lcsim.recon.tracking.digitization.sisim.ReadoutChip;
+import org.lcsim.recon.tracking.digitization.sisim.SiDigitizer;
+import org.lcsim.recon.tracking.digitization.sisim.SiSensorSim;
+import org.lcsim.util.Driver;
+
+/**
+ * Driver for configuring and running the tracking digitization for strip detectors.
+ * Accepts a number of parameters related to clustering and readout chip, as well
+ * as a list of subdetectors and the name of the output digit collections.
+ *
+ * @author jeremym
+ */
+public class PixelDigiSetupDriver extends Driver
+{
+ // Output collection names.
+ private String rawHitsCollectionName;
+ private String trackerHitsCollectionName;
+
+ // Subdetector names.
+ private List<String> subdetectorNames = new ArrayList<String>();
+
+ // Readout chip parameters.
+ String readoutChipType = "generic";
+ private double noiseIntercept;
+ private double noiseSlope;
+ private double noiseThreshold;
+ private double readoutNeighborThreshold;
+
+ // NN clustering algorithm parameters.
+ private double seedThreshold;
+ private double neighborThreshold;
+
+ // Clustering parameters.
+ private int maxClusterSize = 10;
+
+ double oneClusterErr = 1 / Math.sqrt(12);
+ double twoClusterErr = 1 / 5;
+ double threeClusterErr = 1 / 3;
+ double fourClusterErr = 1 / 2;
+ double fiveClusterErr = 1;
+
+ // List of sensors to process.
+ Set<SiSensor> sensorsToProcess = new HashSet<SiSensor>();
+
+ // Objects for running the digitization. These are setup in the detectorChanged() method.
+ SiSensorSim sisim = new CDFSiSensorSim();
+ ReadoutChip readout;
+ SiDigitizer digitizer;
+ PixelHitMaker clusterer;
+
+ // Setup flag.
+ private boolean wasSetup = false;
+
+ public PixelDigiSetupDriver()
+ {}
+
+ public void setReadoutChipType(String readoutChipType)
+ {
+ this.readoutChipType = readoutChipType;
+ }
+
+ public void setSubdetectorName(String name)
+ {
+ if (!subdetectorNames.contains(name))
+ subdetectorNames.add(name);
+ }
+
+ public void setSubdetectorNames(String names[])
+ {
+ subdetectorNames.addAll(Arrays.asList(names));
+ }
+
+ public void setNoiseIntercept(double noiseIntercept)
+ {
+ this.noiseIntercept = noiseIntercept;
+ }
+
+ public void setNoiseSlope(double noiseSlope)
+ {
+ this.noiseSlope = noiseSlope;
+ }
+
+ public void setNoiseThreshold(double noiseThreshold)
+ {
+ this.noiseThreshold = noiseThreshold;
+ }
+
+ public void setReadoutNeighborThreshold(double readoutNeighborThreshold)
+ {
+ this.readoutNeighborThreshold = readoutNeighborThreshold;
+ }
+
+ public void setSeedThreshold(double seedThreshold)
+ {
+ this.seedThreshold = seedThreshold;
+ }
+
+ public void setNeighborThreshold(double neighborThreshold)
+ {
+ this.neighborThreshold = neighborThreshold;
+ }
+
+ public void setMaxClusterSize(int maxClusterSize)
+ {
+ this.maxClusterSize = maxClusterSize;
+ }
+
+ 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;
+ }
+
+ public void setRawHitsCollectionName(String rawHitsCollectionName)
+ {
+ this.rawHitsCollectionName = rawHitsCollectionName;
+ }
+
+ public void setTrackerHitsCollectionName(String trackerHitsCollectionName)
+ {
+ this.trackerHitsCollectionName = trackerHitsCollectionName;
+ }
+
+ public String getRawHitsCollectionName()
+ {
+ return rawHitsCollectionName;
+ }
+
+ public String getTrackerHitsCollectionName()
+ {
+ return trackerHitsCollectionName;
+ }
+
+ public void detectorChanged(Detector detector)
+ {
+ //setupReadoutDriver(detector);
+ setupDigi();
+ super.detectorChanged(detector);
+ }
+
+ public void setupDigi()
+ {
+ if (wasSetup)
+ return;
+
+ // Setup Kpix or Generic readout chip.
+ if (readoutChipType.toLowerCase().equals("kpix"))
+ {
+ Kpix chip = new Kpix();
+ chip.setNoiseThreshold(noiseThreshold);
+ chip.setNeighborThreshold(readoutNeighborThreshold);
+ }
+ else if (readoutChipType.toLowerCase().equals("generic"))
+ {
+ GenericReadoutChip chip = new GenericReadoutChip();
+ chip.setNoiseIntercept(noiseIntercept);
+ chip.setNoiseSlope(noiseSlope);
+ chip.setNoiseThreshold(noiseThreshold);
+ chip.setNeighborThreshold(readoutNeighborThreshold);
+ this.readout = chip;
+ }
+ else
+ {
+ throw new RuntimeException(readoutChipType + " is not a valid reaodut chip type.");
+ }
+
+ digitizer = new RawTrackerHitMaker(sisim, readout);
+
+ NearestNeighbor clustering = new NearestNeighbor();
+ clustering.setSeedThreshold(seedThreshold);
+ clustering.setNeighborThreshold(neighborThreshold);
+
+ clusterer = new PixelHitMaker(sisim, readout, clustering);
+ clusterer.setMaxClusterSize(maxClusterSize);
+ clusterer.SetOneClusterErr(oneClusterErr);
+ clusterer.SetTwoClusterErr(twoClusterErr);
+ clusterer.SetThreeClusterErr(threeClusterErr);
+ clusterer.SetFourClusterErr(fourClusterErr);
+ clusterer.SetFiveClusterErr(fiveClusterErr);
+
+ // Add driver to run the digitization.
+ add(new DigiDriver(
+ digitizer,
+ clusterer,
+ getRawHitsCollectionName(),
+ getTrackerHitsCollectionName(),
+ subdetectorNames));
+
+ wasSetup = true;
+ }
+
+ public void startOfData()
+ {
+ super.startOfData();
+ }
+
+ public void process(EventHeader event)
+ {
+ super.process(event);
+ }
+}
\ No newline at end of file
lcsim/src/org/lcsim/recon/tracking/digitization/sisim/config
diff -N ReadoutCleanupDriver.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ReadoutCleanupDriver.java 24 Aug 2009 23:07:39 -0000 1.1
@@ -0,0 +1,49 @@
+package org.lcsim.recon.tracking.digitization.sisim.config;
+
+import java.util.List;
+
+import org.lcsim.event.EventHeader;
+import org.lcsim.geometry.Detector;
+import org.lcsim.geometry.compact.Subdetector;
+
+/**
+ * This Driver clears the DetectorElement Readout
+ * associated with a given collection in the event header.
+ * It accepts a list of collection names and ignores
+ * others.
+ *
+ * @author jeremym
+ * @version $Id: ReadoutCleanupDriver.java,v 1.1 2009/08/24 23:07:39 jeremy Exp $
+ */
+public class ReadoutCleanupDriver
+extends CollectionHandler
+{
+ public ReadoutCleanupDriver(List<String> collectionNames)
+ {
+ super(collectionNames);
+ }
+
+ public ReadoutCleanupDriver(String[] collectionNames)
+ {
+ super(collectionNames);
+ }
+
+ protected void process(EventHeader event)
+ {
+ Detector detector = event.getDetector();
+
+ for (Subdetector subdet : detector.getSubdetectors().values())
+ {
+ if (subdet.getReadout() != null)
+ {
+ if (canHandle(subdet.getReadout().getName()))
+ {
+ if (subdet.getDetectorElement() != null)
+ {
+ subdet.getDetectorElement().clearReadouts();
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
lcsim/src/org/lcsim/recon/tracking/digitization/sisim/config
diff -N SimTrackerHitReadoutDriver.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ SimTrackerHitReadoutDriver.java 24 Aug 2009 23:07:39 -0000 1.1
@@ -0,0 +1,78 @@
+package org.lcsim.recon.tracking.digitization.sisim.config;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.SimTrackerHit;
+
+/**
+ * Assigns {@link org.lcsim.event.SimTrackerHit} objects to the readouts of their
+ * corresponding {@link org.lcsim.detector.IDetectorElement}.
+ * @author jeremym
+ */
+public class SimTrackerHitReadoutDriver
+extends CollectionHandler
+{
+ boolean needCleanupDriver=true;
+ boolean debug=false;
+
+ public SimTrackerHitReadoutDriver()
+ {}
+
+ public SimTrackerHitReadoutDriver(List<String> collectionNames)
+ {
+ super(collectionNames);
+ }
+
+ public SimTrackerHitReadoutDriver(String[] collectionNames)
+ {
+ super(collectionNames);
+ }
+
+ public void setReadoutCollections(String[] collectionNames)
+ {
+ super.setCollections(collectionNames);
+ }
+
+ public void setDebug(boolean debug)
+ {
+ this.debug = debug;
+ }
+
+ public void startOfData()
+ {
+ if (needCleanupDriver)
+ {
+ add(new ReadoutCleanupDriver(new ArrayList<String>(collections)));
+ needCleanupDriver=false;
+ }
+ }
+
+ protected void process(EventHeader header)
+ {
+ super.process(header);
+ List<List<SimTrackerHit>> collections = header.get(SimTrackerHit.class);
+ for (List<SimTrackerHit> collection : collections)
+ {
+ if (canHandle(header.getMetaData(collection).getName()))
+ {
+ for (SimTrackerHit hit : collection)
+ {
+ hit.getDetectorElement().getReadout().addHit(hit);
+ if (debug)
+ {
+ System.out.println("driver assigned hit " + hit.getExpandedIdentifier().toString() + " to " + hit.getDetectorElement().getName() + " with id " + hit.getDetectorElement().getExpandedIdentifier().toString() + ".");
+ System.out.println(" hit raw: " + hit.getIdentifier().toHexString() + ", DE raw: " + hit.getDetectorElement().getIdentifier().toHexString());
+ System.out.println(" hit pos: " + hit.getPositionVec().toString() + ", DE pos: " + hit.getDetectorElement().getGeometry().getPosition().toString());
+ System.out.println();
+ if (!hit.getDetectorElement().getReadout().getHits(SimTrackerHit.class).contains(hit))
+ {
+ throw new RuntimeException("Readout of " + hit.getDetectorElement().getName() + " is missing a SimTrackerHit that points to it.");
+ }
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
lcsim/src/org/lcsim/recon/tracking/digitization/sisim/config
diff -N StripDigiSetupDriver.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ StripDigiSetupDriver.java 24 Aug 2009 23:07:39 -0000 1.1
@@ -0,0 +1,248 @@
+package org.lcsim.recon.tracking.digitization.sisim.config;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.lcsim.detector.tracker.silicon.SiSensor;
+import org.lcsim.event.EventHeader;
+import org.lcsim.geometry.Detector;
+import org.lcsim.recon.tracking.digitization.sisim.CDFSiSensorSim;
+import org.lcsim.recon.tracking.digitization.sisim.GenericReadoutChip;
+import org.lcsim.recon.tracking.digitization.sisim.Kpix;
+import org.lcsim.recon.tracking.digitization.sisim.NearestNeighbor;
+import org.lcsim.recon.tracking.digitization.sisim.RawTrackerHitMaker;
+import org.lcsim.recon.tracking.digitization.sisim.ReadoutChip;
+import org.lcsim.recon.tracking.digitization.sisim.SiDigitizer;
+import org.lcsim.recon.tracking.digitization.sisim.SiSensorSim;
+import org.lcsim.recon.tracking.digitization.sisim.StripHitMaker;
+import org.lcsim.util.Driver;
+
+/**
+ * Driver for configuring and running the tracking digitization for strip detectors.
+ * Accepts a number of parameters related to clustering and readout chip, as well
+ * as a list of subdetectors and the name of the output digit collections.
+ *
+ * @author jeremym
+ */
+public class StripDigiSetupDriver extends Driver
+{
+ // Output collection names.
+ private String rawHitsCollectionName;
+ private String trackerHitsCollectionName;
+
+ // Subdetector names.
+ private List<String> subdetectorNames = new ArrayList<String>();
+
+ // Readout chip parameters.
+ String readoutChipType = "generic";
+ private double noiseIntercept;
+ private double noiseSlope;
+ private double noiseThreshold;
+ private double readoutNeighborThreshold;
+
+ // NN clustering algorithm parameters.
+ private double seedThreshold;
+ private double neighborThreshold;
+
+ // Clustering parameters.
+ private int maxClusterSize;
+ private int centralStripAveragingThreshold;
+ private double oneClusterErr;
+ private double twoClusterErr;
+ private double threeClusterErr;
+ private double fourClusterErr;
+ private double fiveClusterErr;
+
+ // List of sensors to process.
+ Set<SiSensor> sensorsToProcess = new HashSet<SiSensor>();
+
+ // Objects for running the digitization. These are setup in the detectorChanged() method.
+ SiSensorSim sisim = new CDFSiSensorSim();
+ ReadoutChip readout;
+ SiDigitizer digitizer;
+ StripHitMaker clusterer;
+
+ // Setup flag.
+ private boolean wasSetup = false;
+
+ public StripDigiSetupDriver()
+ {}
+
+ public void setReadoutChipType(String readoutChipType)
+ {
+ this.readoutChipType = readoutChipType;
+ }
+
+ public void setSubdetectorName(String name)
+ {
+ if (!subdetectorNames.contains(name))
+ subdetectorNames.add(name);
+ }
+
+ public void setSubdetectorNames(String names[])
+ {
+ subdetectorNames.addAll(Arrays.asList(names));
+ }
+
+ public void setNoiseIntercept(double noiseIntercept)
+ {
+ this.noiseIntercept = noiseIntercept;
+ }
+
+ public void setNoiseSlope(double noiseSlope)
+ {
+ this.noiseSlope = noiseSlope;
+ }
+
+ public void setNoiseThreshold(double noiseThreshold)
+ {
+ this.noiseThreshold = noiseThreshold;
+ }
+
+ public void setReadoutNeighborThreshold(double readoutNeighborThreshold)
+ {
+ this.readoutNeighborThreshold = readoutNeighborThreshold;
+ }
+
+ public void setSeedThreshold(double seedThreshold)
+ {
+ this.seedThreshold = seedThreshold;
+ }
+
+ public void setNeighborThreshold(double neighborThreshold)
+ {
+ this.neighborThreshold = neighborThreshold;
+ }
+
+ public void setMaxClusterSize(int maxClusterSize)
+ {
+ this.maxClusterSize = maxClusterSize;
+ }
+
+ public void setCentralStripAveragingThreshold(int centralStripAveragingThreshold)
+ {
+ this.centralStripAveragingThreshold = centralStripAveragingThreshold;
+ }
+
+ 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;
+ }
+
+ public void setRawHitsCollectionName(String rawHitsCollectionName)
+ {
+ this.rawHitsCollectionName = rawHitsCollectionName;
+ }
+
+ public void setTrackerHitsCollectionName(String trackerHitsCollectionName)
+ {
+ this.trackerHitsCollectionName = trackerHitsCollectionName;
+ }
+
+ public String getRawHitsCollectionName()
+ {
+ return rawHitsCollectionName;
+ }
+
+ public String getTrackerHitsCollectionName()
+ {
+ return trackerHitsCollectionName;
+ }
+
+ public void detectorChanged(Detector detector)
+ {
+ setupReadoutDriver(detector);
+ setupDigi();
+ super.detectorChanged(detector);
+ }
+
+ private void setupReadoutDriver(Detector detector)
+ {
+ List<String> readouts = new ArrayList<String>();
+ for (String subdetectorName : subdetectorNames)
+ {
+ readouts.add(detector.getSubdetector(subdetectorName).getReadout().getName());
+ }
+ add(new SimTrackerHitReadoutDriver(readouts));
+ }
+
+ public void setupDigi()
+ {
+ if (wasSetup)
+ return;
+
+ // Setup Kpix or Generic readout chip.
+ if (readoutChipType.toLowerCase().equals("kpix"))
+ {
+ Kpix chip = new Kpix();
+ chip.setNoiseThreshold(noiseThreshold);
+ chip.setNeighborThreshold(readoutNeighborThreshold);
+ }
+ else if (readoutChipType.toLowerCase().equals("generic"))
+ {
+ GenericReadoutChip chip = new GenericReadoutChip();
+ chip.setNoiseIntercept(noiseIntercept);
+ chip.setNoiseSlope(noiseSlope);
+ chip.setNoiseThreshold(noiseThreshold);
+ chip.setNeighborThreshold(readoutNeighborThreshold);
+ this.readout = chip;
+ }
+ else
+ {
+ throw new RuntimeException(readoutChipType + " is not a valid reaodut chip type.");
+ }
+
+ digitizer = new RawTrackerHitMaker(sisim, readout);
+
+ NearestNeighbor clustering = new NearestNeighbor();
+ clustering.setSeedThreshold(seedThreshold);
+ clustering.setNeighborThreshold(neighborThreshold);
+
+ clusterer = new StripHitMaker(sisim, readout, clustering);
+ clusterer.setMaxClusterSize(maxClusterSize);
+ clusterer.setCentralStripAveragingThreshold(centralStripAveragingThreshold);
+ clusterer.SetOneClusterErr(oneClusterErr);
+ clusterer.SetTwoClusterErr(twoClusterErr);
+ clusterer.SetThreeClusterErr(threeClusterErr);
+ clusterer.SetFourClusterErr(fourClusterErr);
+ clusterer.SetFiveClusterErr(fiveClusterErr);
+
+ // Add driver to run the digitization.
+ add(new DigiDriver(
+ digitizer,
+ clusterer,
+ getRawHitsCollectionName(),
+ getTrackerHitsCollectionName(),
+ subdetectorNames));
+
+ wasSetup = true;
+ }
+
+ public void process(EventHeader event)
+ {
+ super.process(event);
+ }
+}
\ No newline at end of file
lcsim/src/org/lcsim/recon/tracking/digitization/sisim/config
diff -u -r1.1 -r1.2
--- SiTrackerBarrelSensorSetup.java 21 Aug 2009 20:51:03 -0000 1.1
+++ SiTrackerBarrelSensorSetup.java 24 Aug 2009 23:07:39 -0000 1.2
@@ -54,7 +54,7 @@
private void setupSensorDetectorElements(Subdetector subdet)
{
- System.out.println(this.getClass().getCanonicalName() + " - Setting up sensors for " + subdet.getName() + " ...");
+ //System.out.println(this.getClass().getCanonicalName() + " - Setting up sensors for " + subdet.getName() + " ...");
for ( IDetectorElement layer : subdet.getDetectorElement().getChildren() )
{
lcsim/src/org/lcsim/recon/tracking/digitization/sisim/config
diff -u -r1.1 -r1.2
--- SiTrackerEndcap2SensorSetup.java 21 Aug 2009 20:51:03 -0000 1.1
+++ SiTrackerEndcap2SensorSetup.java 24 Aug 2009 23:07:39 -0000 1.2
@@ -54,7 +54,7 @@
private void setupSensorDetectorElements(Subdetector subdet)
{
- System.out.println(this.getClass().getCanonicalName() + " - Setting up sensors for " + subdet.getName() + " ...");
+ //System.out.println(this.getClass().getCanonicalName() + " - Setting up sensors for " + subdet.getName() + " ...");
for ( IDetectorElement endcap : subdet.getDetectorElement().getChildren() )
{
lcsim/src/org/lcsim/recon/tracking/digitization/sisim/config
diff -u -r1.1 -r1.2
--- SiTrackerEndcapSensorSetup.java 21 Aug 2009 20:51:03 -0000 1.1
+++ SiTrackerEndcapSensorSetup.java 24 Aug 2009 23:07:39 -0000 1.2
@@ -54,7 +54,7 @@
private void setupSensorDetectorElements(Subdetector subdet)
{
- System.out.println(this.getClass().getCanonicalName() + " - Setting up sensors for " + subdet.getName() + " ...");
+ //System.out.println(this.getClass().getCanonicalName() + " - Setting up sensors for " + subdet.getName() + " ...");
for ( IDetectorElement endcap : subdet.getDetectorElement().getChildren() )
{
lcsim/src/org/lcsim/recon/tracking/digitization/sisim/config
diff -u -r1.1 -r1.2
--- SiVertexBarrelSensorSetup.java 21 Aug 2009 20:51:03 -0000 1.1
+++ SiVertexBarrelSensorSetup.java 24 Aug 2009 23:07:39 -0000 1.2
@@ -23,6 +23,7 @@
import org.lcsim.geometry.subdetector.SiTrackerBarrel;
import org.lcsim.util.Driver;
+// TODO: Make pixel size a settable parameter.
public class SiVertexBarrelSensorSetup extends Driver
{
String subdetectorName;
@@ -54,7 +55,7 @@
private void setupSensorDetectorElements(Subdetector subdet)
{
- System.out.println(this.getClass().getCanonicalName() + " - Setting up sensors for " + subdet.getName() + " ...");
+ //System.out.println(this.getClass().getCanonicalName() + " - Setting up sensors for " + subdet.getName() + " ...");
for ( IDetectorElement layer : subdet.getDetectorElement().getChildren() )
{
@@ -83,6 +84,7 @@
Transform3D electrodes_transform = new Transform3D(electrodes_position, electrodes_rotation);
// Define the pixel electrodes...collecting holes;
+ // Sets pixel size to x=0.05 and y=0.25 (mm)
SiSensorElectrodes readout_electrodes = new SiPixels(ChargeCarrier.ELECTRON, 0.05, 0.25, sensor, electrodes_transform);
SiSensorElectrodes sense_electrodes = new SiPixels(ChargeCarrier.ELECTRON, 0.05, 0.25, sensor, electrodes_transform);
lcsim/src/org/lcsim/recon/tracking/seedtracker/digiexample
diff -u -r1.4 -r1.5
--- DigiHitReader.java 24 Apr 2009 18:24:01 -0000 1.4
+++ DigiHitReader.java 24 Aug 2009 23:07:39 -0000 1.5
@@ -8,7 +8,7 @@
import java.util.List;
import java.util.ArrayList;
import org.lcsim.recon.tracking.digitization.sisim.SiTrackerHitStrip1D;
-import org.lcsim.recon.tracking.digitization.sisim.SimTrackerHitReadoutDriver;
+import org.lcsim.recon.tracking.digitization.sisim.config.SimTrackerHitReadoutDriver;
import org.lcsim.detector.IDetectorElement;
import org.lcsim.detector.driver.RawTrackerHitIdentifierReadoutDriver;
import org.lcsim.detector.driver.TrackerHitIdentifierReadoutDriver;
lcsim/test/org/lcsim/detector/tracker/readout
diff -u -r1.2 -r1.3
--- SimTrackerHitIdentifierReadoutDriverTest.java 24 Apr 2009 18:24:01 -0000 1.2
+++ SimTrackerHitIdentifierReadoutDriverTest.java 24 Aug 2009 23:07:39 -0000 1.3
@@ -19,14 +19,14 @@
import org.lcsim.event.EventHeader;
import org.lcsim.event.SimTrackerHit;
import org.lcsim.geometry.compact.Subdetector;
-import org.lcsim.recon.tracking.digitization.sisim.CollectionHandler;
-import org.lcsim.recon.tracking.digitization.sisim.SimTrackerHitReadoutDriver;
+import org.lcsim.recon.tracking.digitization.sisim.config.CollectionHandler;
+import org.lcsim.recon.tracking.digitization.sisim.config.SimTrackerHitReadoutDriver;
import org.lcsim.util.Driver;
import org.lcsim.util.cache.FileCache;
import org.lcsim.util.loop.LCSimLoop;
/**
- * Test the {@link org.lcsim.recon.tracking.digitization.sisim.SimTrackerHitReadoutDriver} on the sid01 detector.
+ * Test the {@link org.lcsim.recon.tracking.digitization.sisim.config.SimTrackerHitReadoutDriver} on the sid01 detector.
*/
public class SimTrackerHitIdentifierReadoutDriverTest extends TestCase
{
lcsim/test/org/lcsim/detector/tracker/readout
diff -u -r1.4 -r1.5
--- TrackerBarrelDigitizationDriverTest.java 24 Apr 2009 18:24:01 -0000 1.4
+++ TrackerBarrelDigitizationDriverTest.java 24 Aug 2009 23:07:39 -0000 1.5
@@ -31,7 +31,7 @@
import org.lcsim.recon.tracking.digitization.sisim.ReadoutChip;
import org.lcsim.recon.tracking.digitization.sisim.Kpix;
import org.lcsim.recon.tracking.digitization.sisim.SiElectrodeDataCollection;
-import org.lcsim.recon.tracking.digitization.sisim.SimTrackerHitReadoutDriver;
+import org.lcsim.recon.tracking.digitization.sisim.config.SimTrackerHitReadoutDriver;
/**
* Reads single muon events generated in sid01_polyhedra, which uses
lcsim/test/org/lcsim/detector/tracker/readout
diff -u -r1.4 -r1.5
--- TrackerEndcapDigitizationDriverTest.java 24 Apr 2009 18:24:01 -0000 1.4
+++ TrackerEndcapDigitizationDriverTest.java 24 Aug 2009 23:07:39 -0000 1.5
@@ -31,7 +31,7 @@
import org.lcsim.recon.tracking.digitization.sisim.ReadoutChip;
import org.lcsim.recon.tracking.digitization.sisim.Kpix;
import org.lcsim.recon.tracking.digitization.sisim.SiElectrodeDataCollection;
-import org.lcsim.recon.tracking.digitization.sisim.SimTrackerHitReadoutDriver;
+import org.lcsim.recon.tracking.digitization.sisim.config.SimTrackerHitReadoutDriver;
/**
* Reads single muon events generated in sid01_polyhedra, which uses
lcsim/test/org/lcsim/detector/tracker/readout
diff -u -r1.15 -r1.16
--- TrackerHitDriver_User_Test.java 21 Aug 2009 20:51:27 -0000 1.15
+++ TrackerHitDriver_User_Test.java 24 Aug 2009 23:07:39 -0000 1.16
@@ -12,10 +12,10 @@
import org.lcsim.event.EventHeader;
import org.lcsim.event.RawTrackerHit;
import org.lcsim.event.TrackerHit;
-import org.lcsim.recon.tracking.digitization.sisim.SimTrackerHitReadoutDriver;
import org.lcsim.recon.tracking.digitization.sisim.TrackerHitDriver_User;
import org.lcsim.recon.tracking.digitization.sisim.config.SiTrackerBarrelSensorSetup;
import org.lcsim.recon.tracking.digitization.sisim.config.SiTrackerEndcapSensorSetup;
+import org.lcsim.recon.tracking.digitization.sisim.config.SimTrackerHitReadoutDriver;
import org.lcsim.util.Driver;
import org.lcsim.util.cache.FileCache;
import org.lcsim.util.loop.LCSimLoop;
lcsim/test/org/lcsim/recon/tracking/digitization/sisim/config
diff -N DigiTest.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ DigiTest.java 24 Aug 2009 23:07:39 -0000 1.1
@@ -0,0 +1,15 @@
+package org.lcsim.recon.tracking.digitization.sisim.config;
+
+import junit.framework.TestCase;
+
+import org.lcsim.job.JobControlManager;
+
+public class DigiTest extends TestCase
+{
+ public void testDigi()
+ {
+ JobControlManager mgr = new JobControlManager();
+ mgr.setup("/org/lcsim/recon/tracking/digitization/sisim/config/digiTest.xml");
+ mgr.run();
+ }
+}
lcsim/testResources/org/lcsim/recon/tracking/digitization/sisim/config
diff -N digiTest.xml
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ digiTest.xml 24 Aug 2009 23:07:39 -0000 1.1
@@ -0,0 +1,80 @@
+<lcsim>
+ <inputFiles>
+ <file>./muons100_Theta4-176_1-10GeV_SLIC-v2r6p1_geant4-v9r2p0_LCPhys_sid01_planar_tracker2.slcio</file>
+ </inputFiles>
+ <control>
+ <numberOfEvents>2</numberOfEvents>
+ <verbose>false</verbose>
+ </control>
+ <execute>
+ <driver name="VertexBarrelSetup"/>
+ <driver name="TrackerBarrelSetup"/>
+ <driver name="ReadoutDriver"/>
+ <driver name="TrackerBarrelDigi"/>
+ <driver name="VertexBarrelDigi"/>
+ <driver name="TestTracking" />
+ <driver name="Writer"/>
+ </execute>
+ <drivers>
+ <driver name="ReadoutDriver"
+ type="org.lcsim.recon.tracking.digitization.sisim.config.SimTrackerHitReadoutDriver">
+ <readoutCollections>SiVertexBarrel_RO SiTrackerBarrel_RO</readoutCollections>
+ </driver>
+ <driver name="TrackerBarrelSetup"
+ type="org.lcsim.recon.tracking.digitization.sisim.config.SiTrackerBarrelSensorSetup">
+ <subdetectorName>SiTrackerBarrel</subdetectorName>
+ </driver>
+ <driver name="TrackerBarrelDigi"
+ type="org.lcsim.recon.tracking.digitization.sisim.config.StripDigiSetupDriver">
+ <subdetectorName>SiTrackerBarrel</subdetectorName>
+ <rawHitsCollectionName>SiTrackerBarrel_RawTrackerHits</rawHitsCollectionName>
+ <trackerHitsCollectionName>SiTrackerBarrel_TrackerHits</trackerHitsCollectionName>
+ <maxClusterSize>10</maxClusterSize>
+ <noiseIntercept>300.</noiseIntercept>
+ <noiseSlope>30.</noiseSlope>
+ <noiseThreshold>9000.</noiseThreshold>
+ <readoutNeighborThreshold>9000.</readoutNeighborThreshold>
+ <seedThreshold>9000.</seedThreshold>
+ <neighborThreshold>9000.</neighborThreshold>
+ <centralStripAveragingThreshold>4</centralStripAveragingThreshold>
+ <oneClusterErr>0.288675135</oneClusterErr>
+ <twoClusterErr>0.2</twoClusterErr>
+ <threeClusterErr>0.333333333</threeClusterErr>
+ <fourClusterErr>0.5</fourClusterErr>
+ <fiveClusterErr>1.0</fiveClusterErr>
+ </driver>
+ <driver name="VertexBarrelSetup"
+ type="org.lcsim.recon.tracking.digitization.sisim.config.SiVertexBarrelSensorSetup">
+ <subdetectorName>SiVertexBarrel</subdetectorName>
+ </driver>
+ <driver name="VertexBarrelDigi"
+ type="org.lcsim.recon.tracking.digitization.sisim.config.PixelDigiSetupDriver">
+ <subdetectorName>SiVertexBarrel</subdetectorName>
+ <rawHitsCollectionName>SiVertexBarrel_RawTrackerHits</rawHitsCollectionName>
+ <trackerHitsCollectionName>SiVertexBarrel_TrackerHits</trackerHitsCollectionName>
+ <maxClusterSize>10</maxClusterSize>
+ <noiseIntercept>20.</noiseIntercept>
+ <noiseSlope>2.</noiseSlope>
+ <noiseThreshold>100.</noiseThreshold>
+ <readoutNeighborThreshold>100.</readoutNeighborThreshold>
+ <seedThreshold>100.</seedThreshold>
+ <neighborThreshold>100.</neighborThreshold>
+ <oneClusterErr>0.288675135</oneClusterErr>
+ <twoClusterErr>0.2</twoClusterErr>
+ <threeClusterErr>0.333333333</threeClusterErr>
+ <fourClusterErr>0.5</fourClusterErr>
+ <fiveClusterErr>1.0</fiveClusterErr>
+ </driver>
+ <driver name="Writer"
+ type="org.lcsim.util.loop.LCIODriver">
+ <outputFilePath>./target/test-output/digiTest.slcio</outputFilePath>
+ <writeOnlyCollections>SiTrackerBarrel_RO SiTrackerBarrel_RawTrackerHits SiTrackerBarrel_TrackerHits SiVertexBarrel_RO SiVertexBarrel_RawTrackerHits SiVertexBarrel_TrackerHits HelicalTrackHits</writeOnlyCollections>
+ </driver>
+ <driver name="TestTracking"
+ type="org.lcsim.fit.helicaltrack.HelicalTrackHitDriver">
+ <digiCollectionName>SiVertexBarrel_TrackerHits</digiCollectionName>
+ <digiCollectionName>SiTrackerBarrel_TrackerHits</digiCollectionName>
+ <outputCollectionName>HelicalTrackHits</outputCollectionName>
+ </driver>
+ </drivers>
+</lcsim>
CVSspam 0.2.8