Commit in lcsim/src/org/lcsim/contrib/onoprien/tracking on MAIN
geom/Navigator.java+79added 1.1
    /SegmentationManager.java+13-11.10 -> 1.11
geom/sensortypes/WedgeSideParallel.java+22-11.3 -> 1.4
hitmaking/TrackerHitConverter.java+68-601.1 -> 1.2
mctruth/MCTruth.java+18-11.3 -> 1.4
tests/HitConverterTest.java+116-1191.2 -> 1.3
+316-182
1 added + 5 modified, total 6 files
hit converter testing code

lcsim/src/org/lcsim/contrib/onoprien/tracking/geom
Navigator.java added at 1.1
diff -N Navigator.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Navigator.java	30 Oct 2007 02:25:42 -0000	1.1
@@ -0,0 +1,79 @@
+package org.lcsim.contrib.onoprien.tracking.geom;
+
+import org.lcsim.detector.IDetectorElement;
+import org.lcsim.detector.converter.compact.DeSubdetector;
+import org.lcsim.detector.identifier.IIdentifierDictionary;
+import org.lcsim.geometry.Detector;
+import org.lcsim.geometry.Subdetector;
+
+/**
+ * Utility class that contains helper methods for geometry navigation.
+ *
+ * @author D. Onoprienko
+ * @version $Id: Navigator.java,v 1.1 2007/10/30 02:25:42 onoprien Exp $
+ */
+public final class Navigator {
+  
+// -- Constructors :  ----------------------------------------------------------
+  
+  public Navigator(Detector detector) {
+    _vtxBarrel = detector.getSubdetector("VertexBarrel");
+    _vtxEndcap = detector.getSubdetector("VertexEndcap");
+    _trkBarrel = detector.getSubdetector("TrackerBarrel");
+    _trkEndcap = detector.getSubdetector("TrackerEndcap");
+    try {
+      _trkForward = detector.getSubdetector("TrackerForward");
+    } catch (Exception x) {}
+  }
+  
+// -- Subdetectors :  ----------------------------------------------------------
+  
+  public Subdetector VERTEX_BARREL() {return _vtxBarrel;}
+  public Subdetector VERTEX_ENDCAP() {return _vtxEndcap;}
+  public Subdetector TRACKER_FORWARD() {return _trkForward;}
+  public Subdetector TRACKER_BARREL() {return _trkBarrel;}
+  public Subdetector TRACKER_ENDCAP() {return _trkEndcap;}
+  
+// -- Sensor location in the detector hierarchy :  -----------------------------
+  
+  public int getLayer(Sensor sensor) {
+    IDetectorElement de = sensor.getDetectorElement();
+    try {
+      return de.getIdentifierHelper().getValue(de.getIdentifier(), "layer");
+    } catch (IIdentifierDictionary.FieldNotFoundException x) {throw new RuntimeException(x);}
+  }
+  
+  public int getSuperLayer(Sensor sensor) {
+    Subdetector sd = getSubdetector(sensor);
+    int layer = getLayer(sensor);
+    if ((sd == _vtxBarrel) || (sd == _vtxEndcap) || (sd == _trkBarrel)) {
+      return layer;
+    } else {
+      return layer/2;
+    }
+  }
+  
+  public Subdetector getSubdetector(Sensor sensor) {
+    return sensor.getDetectorElement().findAncestors(DeSubdetector.class).get(0).getSubdetector();
+  }
+  
+  public int getSignZ(Sensor sensor) {
+    double z = sensor.getDetectorElement().getGeometry().getPosition().z();
+    if (z > Double.MIN_VALUE) {
+      return 1;
+    } else if (z < - Double.MIN_VALUE) {
+      return -1;
+    } else {
+      return 0;
+    }
+  }
+  
+// -- Private parts :  ---------------------------------------------------------
+  
+  private Subdetector _vtxBarrel;
+  private Subdetector _vtxEndcap;
+  private Subdetector _trkForward;
+  private Subdetector _trkBarrel;
+  private Subdetector _trkEndcap;
+  
+}

lcsim/src/org/lcsim/contrib/onoprien/tracking/geom
SegmentationManager.java 1.10 -> 1.11
diff -u -r1.10 -r1.11
--- SegmentationManager.java	12 Oct 2007 21:52:07 -0000	1.10
+++ SegmentationManager.java	30 Oct 2007 02:25:42 -0000	1.11
@@ -38,7 +38,7 @@
  * method in the future.
  *
  * @author D.Onoprienko
- * @version $Id: SegmentationManager.java,v 1.10 2007/10/12 21:52:07 onoprien Exp $
+ * @version $Id: SegmentationManager.java,v 1.11 2007/10/30 02:25:42 onoprien Exp $
  */
 public class SegmentationManager extends Driver implements ConditionsListener {
   
@@ -91,6 +91,7 @@
           _sensorMap.put(sensorID, _segmenter.getSensor(sensorID));
         };
       }
+      _navigator = new Navigator(detector);
     } else {
       throw new RuntimeException("SegmentationManager cannot initialize, no Detector");      
     }
@@ -127,6 +128,16 @@
     }
   }
   
+// -- Getters :  ---------------------------------------------------------------
+  
+  /** 
+   * Returns <tt>Navigator</tt> that provides various convenience methods for use
+   * with <tt>Sensors</tt> created by this <tt>SegmentationManager</tt>.
+   */
+  public Navigator getNavigator() {
+    return _navigator;
+  }
+  
 // -- Event processing :  ------------------------------------------------------
 
   /** Called by framework to process event. */
@@ -264,6 +275,7 @@
   private HashMap<Integer, Sensor> _sensorMap;
   
   private Segmenter _segmenter;
+  private Navigator _navigator;
   
   private boolean _createSensorsOnDetectorChange;
 

lcsim/src/org/lcsim/contrib/onoprien/tracking/geom/sensortypes
WedgeSideParallel.java 1.3 -> 1.4
diff -u -r1.3 -r1.4
--- WedgeSideParallel.java	12 Oct 2007 21:52:07 -0000	1.3
+++ WedgeSideParallel.java	30 Oct 2007 02:25:42 -0000	1.4
@@ -10,7 +10,7 @@
 /**
  *
  * @author D.Onoprienko
- * @version $Id: WedgeSideParallel.java,v 1.3 2007/10/12 21:52:07 onoprien Exp $
+ * @version $Id: WedgeSideParallel.java,v 1.4 2007/10/30 02:25:42 onoprien Exp $
  */
 public class WedgeSideParallel implements SensorType {
   
@@ -141,6 +141,27 @@
     return out;
   }
   
+  /**
+   * Returns an array of (U,V) coordinates of corners of the sensor.
+   * Useful for event display. The dimensions of the returned array are [4][2].
+   */
+  public double[][] getCorners() {
+    double[][] out = new double[4][2];
+    out[0] = new double[]{0.,0.};
+    if (_left) {
+      out[1] = new double[]{0.,_side};
+      double u = (_side - _vConst) * Math.sin(2.*Math.atan(_tan));
+      out[2] = new double[]{u, _side - u * _tan};
+      out[3] = new double[]{_uCorner, - _uCorner * _tan};
+    } else {
+      double u = - _side * Math.sin(2.*Math.atan(_tan));
+      out[1] = new double[]{u, - u * _cotan2};
+      out[2] = new double[]{_uCorner, _side + _uCorner * _tan};
+      out[3] = new double[]{_uCorner, _uCorner * _tan};
+    }
+    return out;
+  }
+  
 // -- Private parts :  ---------------------------------------------------------
   
   private boolean _left;

lcsim/src/org/lcsim/contrib/onoprien/tracking/hitmaking
TrackerHitConverter.java 1.1 -> 1.2
diff -u -r1.1 -r1.2
--- TrackerHitConverter.java	9 Oct 2007 18:08:46 -0000	1.1
+++ TrackerHitConverter.java	30 Oct 2007 02:25:43 -0000	1.2
@@ -1,5 +1,3 @@
-//FIXME setters for seg.manager and hit maker
-
 package org.lcsim.contrib.onoprien.tracking.hitmaking;
 
 import java.util.*;
@@ -16,6 +14,7 @@
 import org.lcsim.spacegeom.SpacePointVector;
 import org.lcsim.util.Driver;
 
+import org.lcsim.contrib.onoprien.tracking.geom.RegionSegmenter;
 import org.lcsim.contrib.onoprien.tracking.geom.SegmentationManager;
 import org.lcsim.contrib.onoprien.tracking.geom.Sensor;
 import org.lcsim.contrib.onoprien.tracking.geom.SensorType;
@@ -24,26 +23,42 @@
 import org.lcsim.contrib.onoprien.tracking.hitmaking.hitmakers.TrackerHitMakerBasic;
 
 /**
- *
+ * Driver that converts a collection of {@link TrackerCluster} or {@link TrackerHit}
+ * objects into a collection of org.lcsim.event.{@link TrackerHit} objects.
+ * <p>
+ * See the description of {@link #set} method for details on how to specify input and
+ * output collections. If this Driver is run on <tt>TrackerClusters</tt>, it first generates
+ * <tt>TrackerHits</tt> internally, using the {@link TrackerHitMaker} set through a call to 
+ * <tt>set("HIT_MAKER", hitMaker)</tt>, and then converts them into <tt>OldTrackerHits</tt>.
+ * <p>
+ * Creation of <tt>OldTrackerHit</tt> objects is done either by {@link #convert(TrackerHit hit)}
+ * (for pixels and sensors for which <tt>getStereoPartners(Sensor)</tt> method of the 
+ * corresponding <tt>Segmenter</tt> returns <tt>null</tt>) or by
+ * {@link #cross(TrackerHit hit1, TrackerHit hit2)} method. A user can override either of these
+ * methods to control what position and covariance matrix are assigned to newly created
+ * <tt>OldTrackerHits</tt>.
+ * <p>
+ * If <tt>getStereoPartners(Sensor)</tt> method returns an empty list (default behavior
+ * of {@link RegionSegmenter}) for a given <tt>Sensor</tt> object, and that Sensor contains
+ * strips, no <tt>OldTrackerHits</tt> will be produced from clusters on that sensor.
  *
  * @author D. Onoprienko
- * @version $Id: TrackerHitConverter.java,v 1.1 2007/10/09 18:08:46 onoprien Exp $
+ * @version $Id: TrackerHitConverter.java,v 1.2 2007/10/30 02:25:43 onoprien Exp $
  */
 public class TrackerHitConverter extends Driver {
   
 // -- Constructors :  ----------------------------------------------------------
   
   public TrackerHitConverter() {
-//    _aida = AIDA.defaultInstance();
     _notInit = true;
     _hitMapName = null;
     _clusterMapName = "TrackerClusters";
     _outListName = "StandardTrackerHits";
   }
   
-  private void init() {
+  private void init(EventHeader event) {
     _notInit = false;
-    if (_segMan == null) _segMan = SegmentationManager.defaultInstance();
+    if (_segMan == null) _segMan = (SegmentationManager) event.get("SegmentationManager");
     if (_clusterMapName != null) {
       List<Driver> drivers = drivers();
       ListIterator<Driver> it = drivers.listIterator();
@@ -76,7 +91,10 @@
    *             <br>Default: "TrackerClusters".</dd>
    * <dt>"OUTPUT_HIT_LIST_NAME"</dt> <dd>Name of output collection of tracker hits
    *             (type <tt>List&lt;org.lcsim.event.TrackerHit&gt;</tt>). 
-   *             <br>Default: "StandardTrackerHits".</dd></dl>
+   *             <br>Default: "StandardTrackerHits".</dd>
+   * <dt>"HIT_MAKER"</dt> <dd>{@link TrackerHitMaker} object to be used by this converter. 
+   *             <br>Default: New instance of {@link TrackerHitMakerBasic} will be used
+   *             if the hit maker is not set explicitly.</dd></dl>
    * 
    * @param name   Name of parameter to be set. Case is ignored.
    * @param value  Value to be assigned to the parameter.
@@ -84,15 +102,21 @@
    *         Subclasses may catch this exception after a call to <tt>super.set()</tt>
    *         and set their own parameters.
    */
-  public void set(String name, String value) {
-    if (name.equalsIgnoreCase("INPUT_HIT_MAP_NAME")) {
-      _hitMapName = value;
-    } else if (name.equalsIgnoreCase("INPUT_CLUSTER_MAP_NAME")) {
-      _clusterMapName = value;
-    } else if (name.equalsIgnoreCase("OUTPUT_HIT_LIST_NAME")) {
-      _outListName = value;
-    } else {
-      throw new NoSuchParameterException(name, this.getClass());
+  public void set(String name, Object value) {
+    try {
+      if (name.equalsIgnoreCase("INPUT_HIT_MAP_NAME")) {
+        _hitMapName = (String) value;
+      } else if (name.equalsIgnoreCase("INPUT_CLUSTER_MAP_NAME")) {
+        _clusterMapName = (String) value;
+      } else if (name.equalsIgnoreCase("OUTPUT_HIT_LIST_NAME")) {
+        _outListName = (String) value;
+      } else if (name.equalsIgnoreCase("HIT_MAKER")) {
+        _hitMaker = (TrackerHitMaker) value;
+      } else {
+        throw new NoSuchParameterException(name, this.getClass());
+      }
+    } catch (ClassCastException x) {
+      throw new IllegalArgumentException("Value of incompatible type", x);
     }
   }
   
@@ -100,18 +124,12 @@
   
   public void process(EventHeader event) {
     
-    if (_notInit) init();
+    if (_notInit) init(event);
     
 //    System.out.println(" ");
 //    System.out.println("Starting conversion of TrackerHits into TrackerHits");
     
     super.process(event);
-    
-//    int nCross = 0;
-//    nCrossTry = 0;
-//    int nPixel = 0;
-//    int nSingle = 0;
-//    int nStereo = 0;
 
     String hitMapName = (_hitMapName == null) ? "_temporary_" : _hitMapName;
     HashMap<Sensor, ArrayList<TrackerHit>> hitMap = (HashMap<Sensor, ArrayList<TrackerHit>>) event.get(hitMapName);
@@ -127,36 +145,19 @@
         List<Sensor> partners = _segMan.getStereoPartners(sensor);
         if (partners == null) {
           for (TrackerHit hit : hitsOnSensor) {
-            out.add(convert(hit));
-//            nSingle++;
+            OldTrackerHit oHit = convert(hit);
+            if (oHit != null) out.add(oHit);
           }
         } else {
-//          _aida.cloud1D("Partner multiplicity").fill(partners.size());
           for (Sensor partner : partners) {
             Hep3Vector shift = VecOp.sub(sensor.getTranslation(), partner.getTranslation());
-//            _aida.cloud1D("Partner shift X").fill(shift.x());
-//            _aida.cloud1D("Partner shift Y").fill(shift.y());
-//            _aida.cloud1D("Partner shift Z").fill(shift.z());
             if (! processedSensors.contains(partner)) {
               List<TrackerHit>  hitsOnPartner = hitMap.get(partner);
               if (hitsOnPartner != null) {
                 for (TrackerHit hitOnSensor : hitsOnSensor) {
                   for (TrackerHit hitOnPartner : hitsOnPartner) {
-//                    nCrossTry++;
-//                    Hep3Vector start = hitOnSensor.getSegment().getStartPoint();
-//                    Hep3Vector end = hitOnSensor.getSegment().getEndPoint();
-//                    _aida.cloud2D(nCrossTry+"OnSensor").fill(start.x(), start.y());
-//                    _aida.cloud2D(nCrossTry+"OnSensor").fill(end.x(), end.y());
-//                    start = hitOnPartner.getSegment().getStartPoint();
-//                    end = hitOnPartner.getSegment().getEndPoint();
-//                    _aida.cloud2D(nCrossTry+"OnPartner").fill(start.x(), start.y());
-//                    _aida.cloud2D(nCrossTry+"OnPartner").fill(end.x(), end.y());
                     OldTrackerHit hit = cross(hitOnSensor, hitOnPartner);
-                    if (hit != null) {
-//                      System.out.println("Success "+nCrossTry);
-                      out.add(hit);
-//                      nCross++;
-                    }
+                    if (hit != null) out.add(hit);
                   }
                 }
               }
@@ -166,8 +167,8 @@
         }
       } else if (hitDimension == 2) { // Pixels
         for (TrackerHit hit : hitsOnSensor) {
-          out.add(convert(hit));
-//          nPixel++;
+          OldTrackerHit oHit = convert(hit);
+          if (oHit != null) out.add(oHit);
         }
       } else {
         throw new RuntimeException("Unknown hit dimension " + hitDimension);
@@ -177,9 +178,20 @@
     out.trimToSize();
     if (_hitMapName == null) event.remove("_temporary_");
     event.put(_outListName, out);
-//    System.out.println("Crosses tried "+nCrossTry+" Crosses done "+nCross+" Single "+nSingle+" Pixel "+nPixel);
   }
   
+  /**
+   * Creates a new <tt>OldTrackerHit</tt> from a pair of <tt>TrackerHits</tt> in stereo layers.
+   * <p>
+   * The implementation assumes that hits provided as arguments are both segment-like, and 
+   * belong to parallel <tt>Sensors</tt> (local reference frame W axes parallel) 
+   * with non-parallel strips (U axes are not parallel). If any of these assumptions is
+   * not true, <tt>null</tt> will be returned and error message printed. Otherwise, the
+   * method will try to find an intersection in U,V plane (ignoring W difference between 
+   * the sensors). If successful, the returned <tt>OldTrackerHit</tt> will have U and V
+   * coordinates corresponding to that intersection, and W coordinate will be half way
+   * between sensor planes. If hits do not cross, the method returns <tt>null</tt>.
+   */
   protected OldTrackerHit cross(TrackerHit hit1, TrackerHit hit2) {
     
     Sensor sensor1 = hit1.getSensor();
@@ -192,11 +204,6 @@
     Hep3Vector locStart1 = locSegment1.getStartPoint();
     Hep3Vector locEnd1 = locSegment1.getEndPoint();
     
-//                    _aida.cloud2D(nCrossTry+"OnSensorLoc").fill(locStart1.x(), locStart1.y());
-//                    _aida.cloud2D(nCrossTry+"OnSensorLoc").fill(locEnd1.x(), locEnd1.y());
-//                    _aida.cloud2D(nCrossTry+"OnPartnerLoc").fill(locStart2.x(), locStart2.y());
-//                    _aida.cloud2D(nCrossTry+"OnPartnerLoc").fill(locEnd2.x(), locEnd2.y());
-    
     double du = locEnd2.x() - locStart2.x();
     double dw = Math.abs(locEnd2.z() - locStart2.z());
     if (Math.abs(du) < tolerance) {
@@ -209,11 +216,9 @@
     double u = locStart1.x();
     double v = locStart2.y() - ((locStart2.x()-u) * (locEnd2.y()-locStart2.y())) / du;
     
-    //_aida.cloud2D(nCrossTry+"Cross").fill(u, v);    
-    
     if (((v - locStart1.y()) * (v - locEnd1.y())) > 0.) return null;  // not intersecting
    
-    Hep3Vector locPos = new BasicHep3Vector(u, v, (locEnd2.z() + locStart2.z())/2.);
+    Hep3Vector locPos = new BasicHep3Vector(u, v, (locEnd2.z() + locEnd1.z())/2.);
     
     Hep3Vector locUnitU2 = sensor1.globalToLocal(hit2.getSensor().localToGlobal(unitU));
     double a = locUnitU2.x();
@@ -232,6 +237,13 @@
     return new OldTrackerHit(sensor1.localToGlobal(locPos), new SymmetricMatrix(3,cov,true), signal, time, 0, parents);
   }
   
+  /**
+   * Creates a new <tt>OldTrackerHit</tt> given <tt>TrackerHit</tt>.
+   * Position and covariance matrix of the created <tt>OldTrackerHit</tt> are
+   * global position and covariance matrix of the <tt>TrackerHit</tt> (if the 
+   * supplied <tt>TrackerHit</tt> is segment-like, that places the newly created
+   * <tt>TrackerHit</tt> at the center of the segment. 
+   */
   protected OldTrackerHit convert(TrackerHit hit) {
     ArrayList<TrackerCluster> parents = new ArrayList<TrackerCluster>(1);
     parents.add(hit.getCluster());
@@ -252,9 +264,5 @@
   private double _stereoTolerance = 0.01;
   
   private double _errFlat = 1./Math.sqrt(12.);
-  private Hep3Vector unitU = new BasicHep3Vector(1., 0., 0.);
-
-//  protected AIDA _aida;  
-//  int nCrossTry;
-  
+  private Hep3Vector unitU = new BasicHep3Vector(1., 0., 0.);  
 }

lcsim/src/org/lcsim/contrib/onoprien/tracking/mctruth
MCTruth.java 1.3 -> 1.4
diff -u -r1.3 -r1.4
--- MCTruth.java	19 Oct 2007 19:27:13 -0000	1.3
+++ MCTruth.java	30 Oct 2007 02:25:43 -0000	1.4
@@ -18,7 +18,7 @@
  * be added to the processing chain (usually as the first driver).
  *
  * @author D. Onoprienko
- * @version $Id: MCTruth.java,v 1.3 2007/10/19 19:27:13 onoprien Exp $
+ * @version $Id: MCTruth.java,v 1.4 2007/10/30 02:25:43 onoprien Exp $
  */
 public class MCTruth {
   
@@ -233,6 +233,23 @@
     return out;
   }
   
+// -- Stereo :  ----------------------------------------------------------------
+  
+  /**
+   * Returns <tt>true</tt> if the hit supplied as an argument is a cross between hits
+   * in stereo layer, and no MCParticle contributed to both of its parent clusters.
+   */
+  public boolean isGhost(OldTrackerHit hit) {
+    if (! hit.isStereo()) return false;
+    List<TrackerCluster> clusters = hit.getClusters();
+    List<MCParticle> mcList1 = getMCParticles(clusters.get(0));
+    List<MCParticle> mcList2 = getMCParticles(clusters.get(1));
+    for (MCParticle mc : mcList1) {
+      if (mcList2.contains(mc)) return false;
+    }
+    return true;
+  }
+
 // -- Modifiers :  -------------------------------------------------------------
   
   /**

lcsim/src/org/lcsim/contrib/onoprien/tracking/tests
HitConverterTest.java 1.2 -> 1.3
diff -u -r1.2 -r1.3
--- HitConverterTest.java	12 Oct 2007 21:52:07 -0000	1.2
+++ HitConverterTest.java	30 Oct 2007 02:25:43 -0000	1.3
@@ -3,6 +3,8 @@
 import java.util.*;
 
 import hep.aida.*;
+import org.lcsim.detector.IDetectorElement;
+import org.lcsim.detector.converter.compact.DeSubdetector;
 import org.lcsim.event.EventHeader;
 import org.lcsim.event.SimTrackerHit;
 import org.lcsim.recon.cat.util.NoSuchParameterException;
@@ -19,10 +21,13 @@
 import org.lcsim.contrib.onoprien.tracking.digitization.SimToDigiDriver;
 import org.lcsim.contrib.onoprien.tracking.digitization.SimToDigiConverter;
 import org.lcsim.contrib.onoprien.tracking.digitization.algorithms.ConverterSimple;
+import org.lcsim.contrib.onoprien.tracking.geom.Navigator;
 import org.lcsim.contrib.onoprien.tracking.geom.SegmentationManager;
 import org.lcsim.contrib.onoprien.tracking.geom.Segmenter;
 import org.lcsim.contrib.onoprien.tracking.geom.Sensor;
 import org.lcsim.contrib.onoprien.tracking.geom.SensorType;
+import org.lcsim.contrib.onoprien.tracking.geom.sensortypes.Cylinder;
+import org.lcsim.contrib.onoprien.tracking.geom.sensortypes.WedgeSideParallel;
 import org.lcsim.contrib.onoprien.tracking.hit.DigiTrackerHit;
 import org.lcsim.contrib.onoprien.tracking.hit.TrackerCluster;
 import org.lcsim.contrib.onoprien.tracking.hit.TrackerHit;
@@ -39,17 +44,18 @@
  *
  *
  * @author D. Onoprienko
- * @version $Id: HitConverterTest.java,v 1.2 2007/10/12 21:52:07 onoprien Exp $
+ * @version $Id: HitConverterTest.java,v 1.3 2007/10/30 02:25:43 onoprien Exp $
  */
 public class HitConverterTest extends Driver {
   
 // -- Constructors :  ----------------------------------------------------------
   
   public HitConverterTest() {
-    
+
     _aida = AIDA.defaultInstance();
     _hFactory = _aida.histogramFactory();
-    _eventHistList = new LinkedList<IBaseHistogram>();
+    _dFactory = _aida.analysisFactory().createDataPointSetFactory(_aida.tree());
+    _eventDPSMap = new HashMap<String, IDataPointSet>();
 
     add(new MCTruthDriver());
     
@@ -92,8 +98,9 @@
 
     super.process(event);
     
-    while (! _eventHistList.isEmpty()) {
-      _hFactory.destroy(_eventHistList.poll());
+    // Clear "per event" AIDA objects
+    for (IDataPointSet dps : _eventDPSMap.values()) {
+      dps.clear();
     }
     
     MCTruth mcTruth = (MCTruth) event.get("MCTruth");
@@ -121,150 +128,140 @@
     List<OldTrackerHit> oldHitList = (List<OldTrackerHit>) event.get("StandardTrackerHits");
     System.out.println("Created "+ oldHitList.size() + " old style TrackerHits");
     
-    // -- Histograms :
+    // -- Draw Sensors for disks divided into wedges :
+
+    SegmentationManager segMan = (SegmentationManager) event.get("SegmentationManager");
+    Navigator gNav = segMan.getNavigator();
+    for (Sensor sensor : segMan.getSensors()) {
+      if (sensor.getType() instanceof WedgeSideParallel) {
+        
+        String title = "Sensors " + gNav.getSubdetector(sensor).getName() +
+                " SuperLayer " + gNav.getSuperLayer(sensor) +
+                " Z " + ((gNav.getSignZ(sensor) > 0) ? "Plus" : "Minus");
+        IDataPointSet dpGeom = getDataPointSet(title,2);
+        
+        WedgeSideParallel sType = (WedgeSideParallel) sensor.getType();
+        double[][] corners = sType.getCorners();
+        
+        for (double[] corner : corners) {
+          Hep3Vector p = sensor.localToGlobal(new BasicHep3Vector(corner[0], corner[1], 0.));
+          IDataPoint dp = dpGeom.addPoint();
+          dp.coordinate(0).setValue(p.x());
+          dp.coordinate(1).setValue(p.y());
+        }
+        IDataPoint dp = dpGeom.addPoint();
+        Hep3Vector p = sensor.localToGlobal(new BasicHep3Vector(corners[0][0], corners[0][1], 0.));
+        dp.coordinate(0).setValue(p.x());
+        dp.coordinate(1).setValue(p.y());
+        dp = dpGeom.addPoint();
+        dp.coordinate(0).setValue(Double.NaN);
+        dp.coordinate(1).setValue(Double.NaN);
+        
+      }
+    }
+    
+    // -- Loop over all Sensors with hits :
     
-    for (Sensor sensor : clusterMap.keySet()) {
+    for (Sensor sensor : hitMap.keySet()) {
+      
       boolean isPixels = (sensor.getType().getHitDimension() == 2);
       int sensorID = sensor.getID();
       SensorType sensorType = sensor.getType();
-      
-      System.out.println("Sensor "+sensorID+" Type "+sensorType.getClass().getName());
 
-      ICloud1D uCloud = _hFactory.createCloud1D("Sensor "+sensorID+" DigiTrackerHits - U");
-      ICloud1D vCloud = null;
-      ICloud2D uvCloud = _hFactory.createCloud2D("Sensor "+sensorID+" DigiTrackerHits - UV");
-      if (isPixels) {
-        vCloud = _hFactory.createCloud1D("Sensor "+sensorID+" DigiTrackerHits - V");
-        _eventHistList.add(vCloud);
-      }
-      _eventHistList.add(uCloud);
-      _eventHistList.add(uvCloud);
-      for (DigiTrackerHit dHit : digiMap.get(sensor)) {
-        Hep3Vector dPos = sensorType.getChannelPosition(dHit.getChannel());
-        uCloud.fill(dPos.x(), dHit.getSignal());
-        if (isPixels) vCloud.fill(dPos.y(), dHit.getSignal());
-        uvCloud.fill(dPos.x(), dPos.y(), dHit.getSignal());
+      String title = gNav.getSubdetector(sensor).getName()+" SuperLayer "+gNav.getSuperLayer(sensor);
+      if (gNav.getSignZ(sensor) != 0) {
+        title += " Z " + ((gNav.getSignZ(sensor) > 0) ? "Plus" : "Minus");
       }
       
-      ICloud1D uCloudC = _hFactory.createCloud1D("Sensor "+sensorID+" Clusters - U");
-      ICloud1D vCloudC = null;
-      ICloud2D uvCloudC = _hFactory.createCloud2D("Sensor "+sensorID+" Clusters - UV");
-      if (isPixels) {
-        vCloudC = _hFactory.createCloud1D("Sensor "+sensorID+" Clusters - V");
-        _eventHistList.add(vCloudC);
-      }
-      _eventHistList.add(uCloudC);
-      _eventHistList.add(uvCloudC);
-      for (TrackerCluster cluster : clusterMap.get(sensor)) {
-        for (DigiTrackerHit dHit : cluster.getDigiHits()) {
-          Hep3Vector dPos = sensorType.getChannelPosition(dHit.getChannel());
-          uCloudC.fill(dPos.x(), dHit.getSignal());
-          if (isPixels) vCloudC.fill(dPos.y(), dHit.getSignal());
-          uvCloudC.fill(dPos.x(), dPos.y(), dHit.getSignal());
-        }
-      }
+      // Draw TrackerHits and SimTrackerHits :
       
-      ICloud1D uCloudS = _hFactory.createCloud1D("Sensor "+sensorID+" SimTrackerHits - U");
-      ICloud1D vCloudS = null;
-      ICloud2D uvCloudS = _hFactory.createCloud2D("Sensor "+sensorID+" SimTrackerHits - UV");
-      if (isPixels) {
-        vCloudS = _hFactory.createCloud1D("Sensor "+sensorID+" SimTrackerHits - V");
-        _eventHistList.add(vCloudS);
-      }
-      _eventHistList.add(uCloudS);
-      _eventHistList.add(uvCloudS);
-      for (TrackerCluster cluster : clusterMap.get(sensor)) {
-        for (SimGroup simGroup : mcTruth.getSimGroups(cluster)) {
+      IDataPointSet dpHits = getDataPointSet("Hits "+title, 2);
+      IDataPointSet dpSimHits = getDataPointSet("SimHits "+title, 2);
+      
+      for (TrackerHit tHit : hitMap.get(sensor)) {
+        for (SimGroup simGroup : mcTruth.getSimGroups(tHit)) {
           for (SimTrackerHit sHit : simGroup.getSimTrackerHits()) {
-            Hep3Vector globPos = new BasicHep3Vector(sHit.getPoint());
-            Hep3Vector locPos = sensor.globalToLocal(globPos);
-            uCloudS.fill(locPos.x(), sHit.getdEdx());
-            if (isPixels) vCloudS.fill(locPos.y(), sHit.getdEdx());
-            uvCloudS.fill(locPos.x(), locPos.y(), sHit.getdEdx());
+            Hep3Vector p = new BasicHep3Vector(sHit.getPoint());
+            IDataPoint dp = dpSimHits.addPoint();
+            if (sensorType instanceof Cylinder) p = sensor.globalToLocal(p);
+            dp.coordinate(0).setValue(p.x());
+            dp.coordinate(1).setValue(p.y());
+            dp = dpSimHits.addPoint();
+            dp.coordinate(0).setValue(Double.NaN);
+            dp.coordinate(1).setValue(Double.NaN);
           }
         }
+        Hep3Vector p = tHit.getSegment().getStartPoint();
+        if (sensorType instanceof Cylinder) p = sensor.globalToLocal(p);
+        IDataPoint dp = dpHits.addPoint();
+        dp.coordinate(0).setValue(p.x());
+        dp.coordinate(1).setValue(p.y());
+        p = tHit.getSegment().getEndPoint();
+        if (sensorType instanceof Cylinder) p = sensor.globalToLocal(p);
+        dp = dpHits.addPoint();
+        dp.coordinate(0).setValue(p.x());
+        dp.coordinate(1).setValue(p.y());
+        dp = dpHits.addPoint();
+        dp.coordinate(0).setValue(Double.NaN);
+        dp.coordinate(1).setValue(Double.NaN);
       }
       
-      ICloud1D uCloudH = _hFactory.createCloud1D("Sensor "+sensorID+" TrackerHits - U");
-      ICloud1D vCloudH = null;
-      ICloud2D uvCloudH = _hFactory.createCloud2D("Sensor "+sensorID+" TrackerHits - UV");
-      if (isPixels) {
-        vCloudH = _hFactory.createCloud1D("Sensor "+sensorID+" TrackerHits - V");
-        _eventHistList.add(vCloudH);
+      // Draw old style TrackerHits :
+      
+      IDataPointSet dpStereoHits = getDataPointSet("True 3D hits "+title, 2);
+      IDataPointSet dpGhostHits = getDataPointSet("Ghost 3D hits "+title, 2);
+      for (OldTrackerHit oHit : oldHitList) {
+        if (sensor == oHit.getClusters().get(0).getSensor()) {
+          IDataPoint dp = mcTruth.isGhost(oHit) ? dpGhostHits.addPoint() : dpStereoHits.addPoint();
+          Hep3Vector p = new BasicHep3Vector(oHit.getPosition());
+          if (sensorType instanceof Cylinder) p = sensor.globalToLocal(p);
+          dp.coordinate(0).setValue(p.x());
+          dp.coordinate(1).setValue(p.y());
+          dp = mcTruth.isGhost(oHit) ? dpGhostHits.addPoint() : dpStereoHits.addPoint();
+          dp.coordinate(0).setValue(Double.NaN);
+          dp.coordinate(1).setValue(Double.NaN);
+        }
       }
-      _eventHistList.add(uCloudH);
-      _eventHistList.add(uvCloudH);
+
+    } // end of loop over all Sensors with TrackerHits
+
+    // Fill histograms for distance from SimTrackerHit to non-ghost OldTrackerHit
       
-      for (TrackerHit tHit : hitMap.get(sensor)) {
-        
-        Hep3Vector tPos = tHit.getLocalPosition();
-        uCloudH.fill(tPos.x(), tHit.getSignal());
-        if (isPixels) vCloudH.fill(tPos.y(), tHit.getSignal());
-        uvCloudH.fill(tPos.x(), tPos.y(), tHit.getSignal());
-        
-        List<SimGroup> simGroupList = mcTruth.getSimGroups(tHit);
+    for (OldTrackerHit oHit : oldHitList) {
+      if (!mcTruth.isGhost(oHit)) {
+        List<SimGroup> simGroupList = mcTruth.getSimGroups(oHit);
         String subDetName = simGroupList.get(0).getSimTrackerHits().get(0).getSubdetector().getName();
-        Hep3Vector position = new BasicHep3Vector();
+        Hep3Vector simPos = new BasicHep3Vector();
         double signal = 0.;
         for (SimGroup simGroup : simGroupList) {
           double s = simGroup.getSignal();
           signal += s;
-          position = VecOp.add(position, VecOp.mult(s, simGroup.getPosition()));
+          simPos = VecOp.add(simPos, VecOp.mult(s, simGroup.getPosition()));
           double[] point = simGroup.getSimTrackerHits().get(0).getPoint();
         }
-        position = VecOp.mult(1./signal, position);
+        simPos = VecOp.mult(1./signal, simPos);
         _aida.cloud1D("SimTrackerHit to TrackerHit Distance, " + subDetName)
-              .fill(VecOp.sub(position, sensor.localToGlobal(tPos)).magnitude());
-        _aida.cloud1D("SimTrackerHit, TrackerHit signal difference, " + subDetName).fill(tHit.getSignal()-signal);
-        
+              .fill(VecOp.sub(simPos, (new BasicHep3Vector(oHit.getPosition()))).magnitude());
       }
-
     }
-    
-    for (OldTrackerHit tHit : oldHitList) {
-      
-      Sensor sensor = tHit.getClusters().get(0).getSensor();
-      int sensorID = sensor.getID();
-      boolean isPixels = (sensor.getType().getHitDimension() == 2);
-      
-      ICloud1D uCloudO = _hFactory.createCloud1D("Sensor "+sensorID+" OldHits - U");
-      ICloud1D vCloudO = null;
-      ICloud2D uvCloudO = _hFactory.createCloud2D("Sensor "+sensorID+" OldHits - UV");
-      if (isPixels) {
-        vCloudO = _hFactory.createCloud1D("Sensor "+sensorID+" OldHits - V");
-        _eventHistList.add(vCloudO);
-      }
-      _eventHistList.add(uCloudO);
-      _eventHistList.add(uvCloudO);
-      
-      Hep3Vector tPos = sensor.globalToLocal(new BasicHep3Vector(tHit.getPosition()));
-      uCloudO.fill(tPos.x(), tHit.getdEdx());
-      if (isPixels) vCloudO.fill(tPos.y(), tHit.getdEdx());
-      uvCloudO.fill(tPos.x(), tPos.y(), tHit.getdEdx());
-      
-      List<SimGroup> simGroupList = mcTruth.getSimGroups(tHit);
-      String subDetName = simGroupList.get(0).getSimTrackerHits().get(0).getSubdetector().getName();
-      Hep3Vector position = new BasicHep3Vector();
-      double signal = 0.;
-      for (SimGroup simGroup : simGroupList) {
-        double s = simGroup.getSignal();
-        signal += s;
-        position = VecOp.add(position, VecOp.mult(s, simGroup.getPosition()));
-        double[] point = simGroup.getSimTrackerHits().get(0).getPoint();
-      }
-      position = VecOp.mult(1./signal, position);
-      _aida.cloud1D("SimTrackerHit to OldTrackerHit Distance, " + subDetName)
-      .fill(VecOp.sub(position, sensor.localToGlobal(tPos)).magnitude());
-      _aida.cloud1D("SimTrackerHit, OldTrackerHit signal difference, " + subDetName).fill(tHit.getdEdx()-signal);
-      
+
+  }
+  
+// -- Helpers :  ---------------------------------------------------------------
+  
+  private IDataPointSet getDataPointSet(String title, int dimension) {
+    IDataPointSet set = _eventDPSMap.get(title);
+    if (set == null) {
+      set = _dFactory.create(title, title, dimension);
+      _eventDPSMap.put(title, set);
     }
-    
+    return set;
   }
   
 // -- Private parts :  ---------------------------------------------------------
   
   protected AIDA _aida;  
   protected IHistogramFactory _hFactory;
-  protected LinkedList<IBaseHistogram> _eventHistList;
-  
+  protected IDataPointSetFactory _dFactory;
+  protected HashMap<String, IDataPointSet> _eventDPSMap;
 }
CVSspam 0.2.8