Commit in lcsim/src/org/lcsim/contrib/onoprien/vsegment on MAIN
geom/ForwardingSegmenter.java+3-31.1 -> 1.2
    /RegionSegmenter.java+14-261.1 -> 1.2
    /SegmentationManager.java+10-91.2 -> 1.3
    /Segmenter.java+6-51.1 -> 1.2
    /SensorType.java+7-101.1 -> 1.2
geom/segmenter/CylindricalBarrelSegmenter.java+184added 1.1
              /DiskToWedgesSegmenter.java+5-51.1 -> 1.2
              /DiskTrackerToRingsSegmenter.java+71-301.1 -> 1.2
geom/sensortype/Cylinder.java+12-151.4 -> 1.5
               /Hexagon.java+9-111.1 -> 1.2
               /Rectangle.java+39-561.2 -> 1.3
               /Ring.java+15-151.1 -> 1.2
               /WedgeSideParallel.java+10-41.1 -> 1.2
process/ChargeCollectionDriver.java+9-71.3 -> 1.4
transform/IRefFrame.java+2-51.3 -> 1.4
         /RefFrameCylinder.java+56-171.2 -> 1.3
SegmenterSiD01.java+70added 1.1
+522-218
2 added + 15 modified, total 17 files
Sensor overlap support.
Per layer parameter setting in disk/cylinder Segmenters.

lcsim/src/org/lcsim/contrib/onoprien/vsegment/geom
ForwardingSegmenter.java 1.1 -> 1.2
diff -u -r1.1 -r1.2
--- ForwardingSegmenter.java	2 Sep 2008 19:29:43 -0000	1.1
+++ ForwardingSegmenter.java	30 Sep 2008 04:41:51 -0000	1.2
@@ -17,7 +17,7 @@
  * {@link #addDaughterSegmenter(AbstractSegmenter)}.
  *
  * @author D. Onoprienko
- * @version $Id: ForwardingSegmenter.java,v 1.1 2008/09/02 19:29:43 onoprien Exp $
+ * @version $Id: ForwardingSegmenter.java,v 1.2 2008/09/30 04:41:51 onoprien Exp $
  */
 abstract public class ForwardingSegmenter extends AbstractSegmenter {
   
@@ -59,9 +59,9 @@
    * Returns integer <tt>SensorID</tt> uniquely identifying a {@link Sensor} object
    * within the whole detector, given the simulated hit.
    */
-  public int getSensorID(SimTrackerHit hit) {
+  public List<Integer> getSensorID(SimTrackerHit hit) {
     AbstractSegmenter daughter = chooseSegmenter(hit);
-    return (daughter == null) ? null : daughter.getSensorID(hit);
+    return (daughter == null) ? Collections.<Integer>emptyList() : daughter.getSensorID(hit);
   }
   
   /**

lcsim/src/org/lcsim/contrib/onoprien/vsegment/geom
RegionSegmenter.java 1.1 -> 1.2
diff -u -r1.1 -r1.2
--- RegionSegmenter.java	2 Sep 2008 19:29:43 -0000	1.1
+++ RegionSegmenter.java	30 Sep 2008 04:41:51 -0000	1.2
@@ -28,7 +28,7 @@
  * dependent initialization is required.
  *
  * @author D. Onoprienko
- * @version $Id: RegionSegmenter.java,v 1.1 2008/09/02 19:29:43 onoprien Exp $
+ * @version $Id: RegionSegmenter.java,v 1.2 2008/09/30 04:41:51 onoprien Exp $
  */
 abstract public class RegionSegmenter extends AbstractSegmenter {
   
@@ -41,13 +41,10 @@
 // -- To be implemented by subclusses :  ---------------------------------------
   
   /**
-   * Subclasses should implement this method to return <tt>postfix</tt> corresponding 
-   * to the position of the given simulated hit. 
-   * The <tt>postfix</tt> must be non-negative integer, unique within the part of 
-   * the detector handled by this <tt>Segmenter</tt>  object. If the hit is outside
-   * of any sensor, "-1" should be returned.
+   * Subclasses should implement this method to return an array of sensor <tt>postfix</tt> 
+   * values corresponding to the position of the specified simulated hit. 
    */
-  abstract protected int makePostfix(SimTrackerHit hit);
+  abstract protected int[] makePostfix(SimTrackerHit hit);
 
   /**
    * Subclasses should implement this method to create a new {@link Sensor} object given
@@ -92,16 +89,15 @@
    * Returns integer <tt>SensorID</tt> uniquely identifying a {@link Sensor} object
    * within the whole detector, given the simulated hit.
    */
-  public int getSensorID(SimTrackerHit hit) {
-    int postfix = makePostfix(hit);
-//    if (postfix == -1) {
-//      System.out.println(" ");
-//      System.out.println("From RegionSegmenter.getSensorID(hit) :");
-//      System.out.println("Segmenter " + this + " failed to produce Sensor");
-//      System.out.println("for hit in " + hit.getSubdetector().getName() + " layer " + hit.getLayer());
-//      System.out.println(" ");
-//    }
-    return (postfix == -1) ? -1 : postfixToID(postfix);
+  public List<Integer> getSensorID(SimTrackerHit hit) {
+    int[] postfix = makePostfix(hit);
+    if (postfix.length == 0) {
+      return Collections.emptyList();
+    } else {
+      List<Integer> pfList = new ArrayList(postfix.length);
+      for (int pf : postfix) pfList.add(postfixToID(pf));
+      return pfList;
+    }
   }
   
   /**
@@ -113,15 +109,7 @@
   public Sensor getSensor(int sensorID) {
     return makeSensor(idToPostfix(sensorID));
   }
-  
-  /**
-   * Creates a new {@link Sensor} object given simulated hit.
-   */
-  public Sensor getSensor(SimTrackerHit hit) {
-    int postfix = makePostfix(hit);
-    return (postfix == -1) ? null : makeSensor(postfix);
-  }
-  
+
   /** 
    * Called by the framework whenever detector geometry changes.
    * Subclasses can override this method if they need to perform any 

lcsim/src/org/lcsim/contrib/onoprien/vsegment/geom
SegmentationManager.java 1.2 -> 1.3
diff -u -r1.2 -r1.3
--- SegmentationManager.java	15 Sep 2008 15:44:02 -0000	1.2
+++ SegmentationManager.java	30 Sep 2008 04:41:51 -0000	1.3
@@ -45,7 +45,7 @@
  * method in the future.
  *
  * @author D.Onoprienko
- * @version $Id: SegmentationManager.java,v 1.2 2008/09/15 15:44:02 onoprien Exp $
+ * @version $Id: SegmentationManager.java,v 1.3 2008/09/30 04:41:51 onoprien Exp $
  */
 public class SegmentationManager extends Driver implements ConditionsListener {
   
@@ -253,20 +253,21 @@
   }
   
   /** 
-   * Converts cell ID and position obtained from {@link SimTrackerHit} object to 
-   * sensor ID, and returns {@link Sensor} object corresponding to this ID.
+   * Returns a list of sensors the specified simulated hit belongs to.
    */
-  public Sensor getSensor(SimTrackerHit hit) {
-    int id = getSensorID(hit);
-    return (id == -1) ? null : getSensor(id);
+  public List<Sensor> getSensor(SimTrackerHit hit) {
+    List<Integer> idList = getSensorID(hit);
+    ArrayList<Sensor> sensors = new ArrayList<Sensor>(idList.size());
+    for (int id : idList) {
+      sensors.add(getSensor(id));
+    }
+    return sensors;
   }
 
   /** 
    * Converts cell ID and position obtained from {@link SimTrackerHit} object to sensor ID.
-   * FIXME: should be just return _segmenter.getSensorID(hit);
-   * The rest is a workaround for Detector being created twice bug.
    */
-  public int getSensorID(SimTrackerHit hit) {
+  public List<Integer> getSensorID(SimTrackerHit hit) {
     return _segmenter.getSensorID(hit);
   }
 

lcsim/src/org/lcsim/contrib/onoprien/vsegment/geom
Segmenter.java 1.1 -> 1.2
diff -u -r1.1 -r1.2
--- Segmenter.java	2 Sep 2008 19:29:43 -0000	1.1
+++ Segmenter.java	30 Sep 2008 04:41:51 -0000	1.2
@@ -13,7 +13,7 @@
  * {@link AbstractSegmenter} for details.
  *
  * @author D. Onoprienko
- * @version $Id: Segmenter.java,v 1.1 2008/09/02 19:29:43 onoprien Exp $
+ * @version $Id: Segmenter.java,v 1.2 2008/09/30 04:41:51 onoprien Exp $
  */
 public interface Segmenter {
   
@@ -24,11 +24,12 @@
   public List<Integer> getSensorIDs();
   
   /**
-   * Returns integer <tt>SensorID</tt> uniquely identifying a {@link Sensor} object
-   * within the whole detector, given the simulated hit. 
-   * Returns "-1" if the hit is outside of any sensor.
+   * Returns a list of integer <tt>SensorIDs</tt> uniquely identifying each of the 
+   * {@link Sensor} objects the specified simulated hit belongs to.
+   * The hit may belong to more than one sensor to simulate overlaps, double sided
+   * sensors, etc. The hit may belong to no sensors to simulate gaps.
    */
-  public int getSensorID(SimTrackerHit hit);
+  public List<Integer> getSensorID(SimTrackerHit hit);
   
   /**
    * Creates a new {@link Sensor} object given full <tt>SensorID</tt>.

lcsim/src/org/lcsim/contrib/onoprien/vsegment/geom
SensorType.java 1.1 -> 1.2
diff -u -r1.1 -r1.2
--- SensorType.java	2 Sep 2008 19:29:43 -0000	1.1
+++ SensorType.java	30 Sep 2008 04:41:51 -0000	1.2
@@ -8,15 +8,11 @@
 import org.lcsim.contrib.onoprien.vsegment.transform.IRefFrame;
 
 /**
- * Any class that implements this interface defines a particular shape of silicon
- * sensor and its segmentation into strips or pixels.
- * Current design assumes that all strips are parallel to each other, each strip or 
- * pixel has no more than one neighbor in each direction. Reference frame on a sensor: 
- * (U, V, W). U is the measurement direction (in the sensor plane, perpendicular to 
- * strips), V is along the strips, W forms right-nahded system.
+ * Any class that implements this interface defines a particular shape of a sensor 
+ * and its segmentation into channels (strips or pixels in case of silicon sensors).
  *
  * @author D.Onoprienko
- * @version $Id: SensorType.java,v 1.1 2008/09/02 19:29:43 onoprien Exp $
+ * @version $Id: SensorType.java,v 1.2 2008/09/30 04:41:51 onoprien Exp $
  */
 public interface SensorType {
 
@@ -58,10 +54,11 @@
    * concept of a neighbor in the given direction. 
    *
    * @param channelID  ID of the original channel
-   * @param shiftV     move in <tt>V</tt> direction by <tt>shiftV</tt> channels
-   * @param shiftU     move in <tt>U</tt> direction by <tt>shiftU</tt> channels
+   * @param shiftV     move in <tt>U</tt> direction by <tt>shiftU</tt> channels
+   * @param shiftU     move in <tt>V</tt> direction by <tt>shiftV</tt> channels
+   * @param shiftW     move in <tt>W</tt> direction by <tt>shiftW</tt> channels
    */
-  int getNeighbor(int channelID, int shiftU, int shiftV);
+  int getNeighbor(int channelID, int shiftU, int shiftV, int shiftW);
   
   /**
    * Returns a list of IDs of all immediate neighbor channels.

lcsim/src/org/lcsim/contrib/onoprien/vsegment/geom/segmenter
CylindricalBarrelSegmenter.java added at 1.1
diff -N CylindricalBarrelSegmenter.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ CylindricalBarrelSegmenter.java	30 Sep 2008 04:41:51 -0000	1.1
@@ -0,0 +1,184 @@
+package org.lcsim.contrib.onoprien.vsegment.geom.segmenter;
+
+import java.util.*;
+
+import hep.physics.vec.BasicHep3Vector;
+import org.lcsim.event.SimTrackerHit;
+import org.lcsim.geometry.Detector;
+import org.lcsim.geometry.Subdetector;
+import org.lcsim.detector.IDetectorElement;
+import org.lcsim.detector.IGeometryInfo;
+import org.lcsim.detector.ILogicalVolume;
+import org.lcsim.detector.IPhysicalVolume;
+import org.lcsim.detector.solids.Tube;
+import org.lcsim.units.clhep.SystemOfUnits;
+
+import org.lcsim.contrib.onoprien.vsegment.geom.AbstractSegmenter;
+import org.lcsim.contrib.onoprien.vsegment.geom.RegionSegmenter;
+import org.lcsim.contrib.onoprien.vsegment.geom.Sensor;
+import org.lcsim.contrib.onoprien.vsegment.geom.SensorType;
+import org.lcsim.contrib.onoprien.vsegment.geom.sensortype.Cylinder;
+import org.lcsim.contrib.onoprien.vsegment.transform.RefFrameCylinder;
+
+/**
+ * {@link Segmenter} that tiles barrel cylinders with Z-parallel strips or pixels.
+ * <p>
+ * Each barrel layer will correspond to a single {@link Sensor} object, with the
+ * <tt>postfix</tt> equal to layer number.
+ * 
+ * 
+ * @author D.Onoprienko
+ * @version $Id: CylindricalBarrelSegmenter.java,v 1.1 2008/09/30 04:41:51 onoprien Exp $
+ */
+public class CylindricalBarrelSegmenter extends RegionSegmenter {
+  
+// -- Constructors and initialization :  ---------------------------------------
+
+  /**
+   * Creates a new instance of <tt>CylindricalBarrelSegmenter</tt> to be used on the subdetector
+   * specified by the given name. Strip pitch and length are not set.
+   */
+  public CylindricalBarrelSegmenter(String subdetectorName) {
+    _sdName = subdetectorName;
+  }
+
+  /**
+   * Creates a new instance of <tt>CylindricalBarrelSegmenter</tt> to be used on the subdetector
+   * specified by the given name. Strip pitch and length will be the same for all layers.
+   * 
+   * @param  pitch   Strip or pixel width.
+   * @param  length  Strip or pixel length.
+   */
+  public CylindricalBarrelSegmenter(String subdetectorName, double pitch, double length) {
+    _sdName = subdetectorName;
+    setStripWidth(pitch);
+    setStripLength(length);
+  }
+
+  /**
+   * Creates a new instance of <tt>CylindricalBarrelSegmenter</tt> to be used on the subdetector
+   * specified by the given name. Strip pitch and length can be specified for each layer.
+   * The sizes of supplied arrays should be equal to the number of layers in the subdetector.
+   * 
+   * @param  pitch   Strip or pixel width.
+   * @param  length  Strip or pixel length.
+   */
+  public CylindricalBarrelSegmenter(String subdetectorName, double[] pitch, double[] length) {
+    _sdName = subdetectorName;
+    setStripWidth(pitch);
+    setStripLength(length);
+  }
+  
+  /** 
+   * Detector-dependent initialization.
+   */
+  public void detectorChanged(Detector detector) {
+    super.detectorChanged(detector);
+    Subdetector sub = detector.getSubdetector(_sdName);
+    if (sub == null) return;
+    _detElts = AbstractSegmenter.getLeaves(sub.getDetectorElement());
+    for (IDetectorElement de : _detElts) {
+      if (!(de.getGeometry().getLogicalVolume().getSolid() instanceof Tube)) {
+        throw new RuntimeException("You are trying to apply CylindricalBarrelSegmenter to detector whose barrel is not made of Tubes");
+      }
+    }
+    Collections.sort(_detElts, new Comparator<IDetectorElement>() {
+      public int compare(IDetectorElement s1, IDetectorElement s2) {
+        return (int)Math.signum(((Tube)(s1.getGeometry().getLogicalVolume().getSolid())).getInnerRadius()
+                              - ((Tube)(s2.getGeometry().getLogicalVolume().getSolid())).getInnerRadius());
+      }
+    });
+    _nLayers = _detElts.size();
+    if ((_stripWidth == null) || (_stripWidth.length != 1 && _stripWidth.length != _nLayers) ||
+        (_stripLength == null) || (_stripLength.length != 1 && _stripLength.length != _nLayers)) {
+      throw new RuntimeException("Wrong number of layers in "+ _sdName);
+    }
+    _radius = new double[_nLayers];
+    _length = new double[_nLayers];
+    int postfix = 0;
+    for (IDetectorElement del : _detElts) {
+      IGeometryInfo gInfo = del.getGeometry();
+      Tube solid = (Tube) gInfo.getLogicalVolume().getSolid();
+      double rInner = solid.getInnerRadius();
+      double rOuter = solid.getOuterRadius();
+      _radius[postfix] = (rInner + rOuter)/2.;
+      _length[postfix] = solid.getZHalfLength()*2.;
+      postfix++;
+    }
+  }
+  
+// -- Setters :  ---------------------------------------------------------------
+
+  /** Set strip width for all layers. */
+  public void setStripWidth(double pitch) {
+    _stripWidth = new double[]{pitch};
+  }
+
+  /**
+   * Set strip width for each layer.
+   * The size of the supplied array should be equal to the number of layers in the subdetector.
+   */
+  public void setStripWidth(double[] pitch) {
+    _stripWidth = pitch.clone();
+  }
+  
+  /** Set strip length for all layers. */
+  public void setStripLength(double length) {
+    _stripLength = new double[]{length};
+  }
+  
+  /** 
+   * Set strip length for each layer.
+   * The size of the supplied array should be equal to the number of layers in the subdetector.
+   */
+  public void setStripLength(double[] length) {
+    _stripLength = length.clone();
+  }
+  
+// -----------------------------------------------------------------------------
+
+  /**
+   * Returns sensor ID postfix corresponding to the given position. This postfix must 
+   * be positive  integer, unique within the part of the detector handled by this 
+   * <tt>Segmenter</tt>  object. The final Sensor ID will be constructed taking into
+   * account the prefix set through a call to {@link #setPrefix} method.
+   */
+  public int[] makePostfix(SimTrackerHit hit) {
+    return new int[]{hit.getLayer()};
+  }
+  
+  /**
+   * Returns maximum postfix value that can be returned by
+   * {@link #makePostfix(SimTrackerHit)} method of this <tt>Segmenter</tt>.
+   */
+  public int getMaxPostfix() {
+    return _nLayers-1;
+  }
+
+  /** Creates a {@link Sensor} object given the ID. */
+  public Sensor makeSensor(int postfix) {
+    double stripWidth = (postfix >= _stripWidth.length) ? _stripWidth[0] : _stripWidth[postfix];
+    double stripLength = (postfix >= _stripLength.length) ? _stripLength[0] : _stripLength[postfix];
+    SensorType type = new Cylinder(_radius[postfix], _length[postfix], stripWidth, stripLength);
+    return new Sensor(_detElts.get(postfix), postfixToID(postfix), type, new RefFrameCylinder(_radius[postfix]));
+  }
+  
+  /**
+   * Returnes <tt>null</tt> since there is no stereo in cylindrical barel.
+   */
+  public List<Integer> getStereoPartners(int sensorID) {
+    return null;
+  }
+  
+// -- Private parts :  ---------------------------------------------------------
+  
+  String _sdName;
+  
+  List<IDetectorElement> _detElts;
+  
+  private int _nLayers;
+  private double[] _radius;
+  private double[] _length;
+  private double[] _stripLength;
+  private double[] _stripWidth;
+}

lcsim/src/org/lcsim/contrib/onoprien/vsegment/geom/segmenter
DiskToWedgesSegmenter.java 1.1 -> 1.2
diff -u -r1.1 -r1.2
--- DiskToWedgesSegmenter.java	3 Sep 2008 16:02:51 -0000	1.1
+++ DiskToWedgesSegmenter.java	30 Sep 2008 04:41:51 -0000	1.2
@@ -24,7 +24,7 @@
  * Simplistic <tt>Segmenter</tt> that tiles a single disk with wedges.
  * 
  * @author D. Onoprienko
- * @version $Id: DiskToWedgesSegmenter.java,v 1.1 2008/09/03 16:02:51 onoprien Exp $
+ * @version $Id: DiskToWedgesSegmenter.java,v 1.2 2008/09/30 04:41:51 onoprien Exp $
  */
 public class DiskToWedgesSegmenter extends RegionSegmenter {
   
@@ -71,11 +71,11 @@
   /**
    * Returns <tt>postfix</tt> corresponding to the position of the given simulated hit. 
    */
-  protected int makePostfix(SimTrackerHit hit) {
+  protected int[] makePostfix(SimTrackerHit hit) {
     
     double[] pos = hit.getPoint();
     
-    if (pos[2]<_zMin || pos[2]>_zMax) return -1;
+    if (pos[2]<_zMin || pos[2]>_zMax) return new int[0];
     
     double r = Math.hypot(pos[0],pos[1]);
     double phi = Math.atan2(pos[1], pos[0]);
@@ -87,9 +87,9 @@
     
     double rMiddle = r * Math.cos(phi - _deltaPhi*(indexPhi+.5));
     int indexR = (int) Math.floor((rMiddle - _rMiddleMin) / _deltaRMiddle);
-    if ((indexR < 0) || (indexR >= _nRadial)) return -1;
+    if ((indexR < 0) || (indexR >= _nRadial)) return new int[0];
     
-    return (_nRadial * indexPhi) + indexR;
+    return new int[]{(_nRadial * indexPhi) + indexR};
   }
   
   /**

lcsim/src/org/lcsim/contrib/onoprien/vsegment/geom/segmenter
DiskTrackerToRingsSegmenter.java 1.1 -> 1.2
diff -u -r1.1 -r1.2
--- DiskTrackerToRingsSegmenter.java	3 Sep 2008 16:02:51 -0000	1.1
+++ DiskTrackerToRingsSegmenter.java	30 Sep 2008 04:41:51 -0000	1.2
@@ -29,7 +29,7 @@
 
 /**
  * 
- * Simplistic <tt>Segmenter</tt> that tiles endcap disks with strips or pixels.
+ * Simplistic {@link Segmenter} that tiles endcap disks with a grid of strips or pixels.
  * <p>
  * Each disk will correspond to a {@link Sensor} object. Postfixes are assigned in
  * the increasing Z order. Sensors corresponding to layers facing away from the center
@@ -37,29 +37,51 @@
  * {@link #setStereoAngle(double angle)}.
  * 
  * @author D.Onoprienko
- * @version $Id: DiskTrackerToRingsSegmenter.java,v 1.1 2008/09/03 16:02:51 onoprien Exp $
+ * @version $Id: DiskTrackerToRingsSegmenter.java,v 1.2 2008/09/30 04:41:51 onoprien Exp $
  */
 public class DiskTrackerToRingsSegmenter extends RegionSegmenter {
   
 // -- Constructors and initialization :  ---------------------------------------
   
   /**
-   * 
-   * Creates a new instance of DiskTrackerToRingsSegmenter.
-   * Subdetector name supplied to the constructor is used to provide reasonable 
-   * defaults for strip width, length, and stereo angle.
+   * Creates a new instance of <tt>DiskTrackerToRingsSegmenter</tt> to handle the subdetector
+   * specified by the supplied name. Strip sizes are not set. Zero stereo angle.
    */
   public DiskTrackerToRingsSegmenter(String subdetectorName) {
     _sdName = subdetectorName;
-    if (_sdName == "TrackerEndcap") {
-      setStripWidth(25.*SystemOfUnits.micrometer);
-      setStripLength(10.*SystemOfUnits.cm);
-      setStereoAngle(Math.PI / 2.);
-    } else if (_sdName == "VertexEndcap" || _sdName == "TrackerForward") {
-      setStripWidth(25.*SystemOfUnits.micrometer);
-      setStripLength(25.*SystemOfUnits.micrometer);
-      setStereoAngle(0.);
-    }
+    setStereoAngle(0.);
+  }
+  
+  /**
+   * Creates a new instance of <tt>DiskTrackerToRingsSegmenter</tt> to handle the subdetector
+   * specified by the supplied name. Strip pitch and length will be the same for all layers.
+   * 
+   * @param  stripPitch   Strip or pixel width.
+   * @param  stripLength  Strip or pixel length.
+   * @param  stereoAngle  Stereo angle.
+   */
+  public DiskTrackerToRingsSegmenter(String subdetectorName, double stripPitch, double stripLength, double stereoAngle) {
+    _sdName = subdetectorName;
+    setStripWidth(stripPitch);
+    setStripLength(stripLength);
+    setStereoAngle(stereoAngle);
+  }
+  
+  /**
+   * Creates a new instance of <tt>DiskTrackerToRingsSegmenter</tt> to handle the subdetector
+   * specified by the supplied name. Strip pitch and length are set for each layer.
+   * The sizes of supplied arrays should be equal to the number of layers in the subdetector
+   * (disks on the two sides of a support disk are considered to be separate layers).
+   * 
+   * @param  stripPitch   Strip or pixel width.
+   * @param  stripLength  Strip or pixel length.
+   * @param  stereoAngle  Stereo angle.
+   */
+  public DiskTrackerToRingsSegmenter(String subdetectorName, double[] stripPitch, double[] stripLength, double stereoAngle) {
+    _sdName = subdetectorName;
+    setStripWidth(stripPitch);
+    setStripLength(stripLength);
+    setStereoAngle(stereoAngle);
   }
 
   /** 
@@ -77,9 +99,12 @@
     });
     _nDisks = _detElts.size();
     _nLayers = _nDisks/2;
+    if ((_stripWidth == null) || (_stripWidth.length != 1 && _stripWidth.length != _nLayers) ||
+        (_stripLength == null) || (_stripLength.length != 1 && _stripLength.length != _nLayers)) {
+      throw new RuntimeException("Wrong number of layers in "+ _sdName);
+    }
     _radiusInner = new double[_nDisks];
     _radiusOuter = new double[_nDisks];
-    _thickness = new double[_nDisks];
     _z = new double[_nDisks];
     int postfix = 0;
     for (IDetectorElement del : _detElts) {
@@ -87,7 +112,6 @@
       Tube solid = (Tube) gInfo.getLogicalVolume().getSolid();
       _radiusInner[postfix] = solid.getInnerRadius();
       _radiusOuter[postfix] = solid.getOuterRadius();
-      _thickness[postfix] = solid.getZHalfLength()*2.;
       _z[postfix] = gInfo.getPosition().z();
       postfix++;
     }
@@ -96,19 +120,35 @@
 // -- Setters :  ---------------------------------------------------------------
 
   /**
-   * Set strip width.
-   * Default is 25 micron.
+   * Set strip width for all disks.
    */
   public void setStripWidth(double pitch) {
-    _stripWidth = pitch;
+    _stripWidth = new double[]{pitch};
   }
 
   /**
-   * Set strip length. 
-   * Default is 10 cm for "TrackerEndcap", 25 micron for "VertexEndcap" and "TrackerForward".
+   * Set strip width for each disk.
+   * The size of supplied array should be equal to the number of layers in the subdetector
+   * (disks on the two sides of a support disk are considered to be separate layers).
+   */
+  public void setStripWidth(double[] pitch) {
+    _stripWidth = pitch.clone();
+  }
+
+  /**
+   * Set strip length for all disks. 
    */
   public void setStripLength(double length) {
-    _stripLength = length;
+    _stripLength = new double[]{length};
+  }
+
+  /**
+   * Set strip length for each disk. 
+   * The size of supplied array should be equal to the number of layers in the subdetector
+   * (disks on the two sides of a support disk are considered to be separate layers).
+   */
+  public void setStripLength(double[] length) {
+    _stripLength = length.clone();
   }
 
   /**
@@ -126,9 +166,9 @@
   /**
    * Returns sensor ID postfix corresponding to the given position.
    */
-  public int makePostfix(SimTrackerHit hit) {
+  public int[] makePostfix(SimTrackerHit hit) {
     int layer = hit.getLayer();
-    return hit.getPoint()[2] < 0. ? _nLayers - layer - 1  : _nLayers + layer ;
+    return new int[]{hit.getPoint()[2] < 0. ? _nLayers - layer - 1  : _nLayers + layer };
   }
   
   /**
@@ -141,9 +181,11 @@
 
   /** Creates a {@link Sensor} object given the ID. */
   public Sensor makeSensor(int postfix) {
-    SensorType type = new Ring(_radiusInner[postfix], _radiusOuter[postfix], _stripWidth, _stripLength, _thickness[postfix], 0.);
+    int layer = (postfix < _nLayers) ? _nLayers - postfix - 1 : postfix - _nLayers ;
+    double stripWidth = (layer >= _stripWidth.length) ? _stripWidth[0] : _stripWidth[layer];
+    double stripLength = (layer >= _stripLength.length) ? _stripLength[0] : _stripLength[layer];
+    SensorType type = new Ring(_radiusInner[postfix], _radiusOuter[postfix], stripWidth, stripLength);
     Hep3Vector trans = new BasicHep3Vector();
-    int layer = (postfix < _nDisks) ? _nDisks - postfix - 1 : postfix - _nDisks ;
     Translation3D translation = new Translation3D(0.,0.,_z[postfix]);
     IRefFrame rf;
     if (layer % 2 == 0) {
@@ -164,10 +206,9 @@
   private int _nLayers;
   private double[] _radiusInner;
   private double[] _radiusOuter;
-  private double[] _thickness;
   private double[] _z;
-  private double _stripLength;
-  private double _stripWidth;
+  private double[] _stripLength;
+  private double[] _stripWidth;
   
   private IRotation3D _rot1;
   private ConstHep3Vector _u1, _v1;

lcsim/src/org/lcsim/contrib/onoprien/vsegment/geom/sensortype
Cylinder.java 1.4 -> 1.5
diff -u -r1.4 -r1.5
--- Cylinder.java	15 Sep 2008 16:08:12 -0000	1.4
+++ Cylinder.java	30 Sep 2008 04:41:51 -0000	1.5
@@ -10,6 +10,8 @@
 import org.lcsim.contrib.onoprien.vsegment.hit.ITrackerHit;
 import org.lcsim.contrib.onoprien.vsegment.transform.ConstHep3Vector;
 import org.lcsim.contrib.onoprien.vsegment.transform.IRefFrame;
+import org.lcsim.contrib.onoprien.vsegment.transform.RefFrameCylinder;
+import org.lcsim.contrib.onoprien.vsegment.transform.RefFrameLocalOnCylinder;
 
 /**
  * This class represents a cylindrical sensor with pixels or strips parallel to its axis.
@@ -19,7 +21,7 @@
  * 
  * 
  * @author D.Onoprienko
- * @version $Id: Cylinder.java,v 1.4 2008/09/15 16:08:12 onoprien Exp $
+ * @version $Id: Cylinder.java,v 1.5 2008/09/30 04:41:51 onoprien Exp $
  */
 public class Cylinder extends Rectangle {
   
@@ -31,14 +33,11 @@
    *
    * @param length      Length of the cylinder (along strip direction).
    * @param radius      Radius of the cylinder (average between inner and outer redii).
-   * @param thickness   Thickness of the cylinder.
    * @param nLength     Number of divisions along the cylinder length.
    * @param nPhi        Number of divisions in phi.
-   * @param rReference  Radius of the reference surface.
    */
-  public Cylinder(double radius, double length, double thickness, int nPhi, int nLength, double rReference) {
-    super(2.*Math.PI*rReference, length, thickness, nPhi, nLength, new ConstHep3Vector(0., 0., radius-rReference));
-    _hitType = ((length/nLength)/((2.*Math.PI*rReference)/nPhi) < 4.) ? ITrackerHit.Type.PIXEL : ITrackerHit.Type.STRIP;
+  public Cylinder(double radius, double length, int nPhi, int nLength) {
+    super(2.*Math.PI*radius, length, nPhi, nLength);
   }
   
   /**
@@ -48,13 +47,11 @@
    *
    * @param length       Length of the cylinder (along strip direction).
    * @param radius       Radius of the cylinder.
-   * @param thickness    Thickness of the sensor.
    * @param stripPitch   Strip width.
    * @param stripLength  Strip length.
-   * @param center       Controls definition of the local reference frame
    */
-  public Cylinder(double radius, double length, double thickness, double stripPitch, double stripLength, double rReference) {
-    this(radius, length, thickness, (int) Math.round((2.*Math.PI*rReference)/stripPitch), (int) Math.round(length/stripLength), rReference);
+  public Cylinder(double radius, double length, double stripPitch, double stripLength) {
+    this(radius, length, (int) Math.round((2.*Math.PI*radius)/stripPitch), (int) Math.round(length/stripLength));
   }
 
 // -----------------------------------------------------------------------------
@@ -80,10 +77,9 @@
   
   /**
    * Returns local cartesian reference frame at the specified position in local sensor coordinates.
-   * For this type of sensor, the specified sensor reference frame is returned, independent of position.
    */
   public IRefFrame getLocalFrame(IRefFrame sensorFrame, Hep3Vector position) {
-    return sensorFrame;
+    return new RefFrameLocalOnCylinder((RefFrameCylinder)sensorFrame, position);
   }
   
   /**
@@ -91,12 +87,13 @@
    * Returns -1 if the channel defined by shifts does not exist on this sensor.
    *
    * @param channelID  ID of the original channel
-   * @param shiftV     move in <tt>V</tt> direction by <tt>shiftV</tt> channels
    * @param shiftU     move in <tt>U</tt> direction by <tt>shiftU</tt> channels
+   * @param shiftV     move in <tt>V</tt> direction by <tt>shiftV</tt> channels
+   * @param shiftW     move in <tt>W</tt> direction by <tt>shiftW</tt> channels
    */
-  public int getNeighbor(int channelID, int shiftU, int shiftV) {
+  public int getNeighbor(int channelID, int shiftU, int shiftV, int shiftW) {
     int nV = (channelID / _nDivU) + shiftV;
-    if (nV < 0 || nV >= _nDivV) return -1;
+    if (nV < 0 || nV >= _nDivV || shiftW != 0) return -1;
     int nU = (channelID % _nDivU) + shiftU;
     while (nU < 0) nU += _nDivU;
     while (nU >= _nDivU) nU -= _nDivU;

lcsim/src/org/lcsim/contrib/onoprien/vsegment/geom/sensortype
Hexagon.java 1.1 -> 1.2
diff -u -r1.1 -r1.2
--- Hexagon.java	3 Sep 2008 04:28:29 -0000	1.1
+++ Hexagon.java	30 Sep 2008 04:41:51 -0000	1.2
@@ -14,12 +14,12 @@
  * This class represents a hexagonal sensor with strips parallel to its side.
  * The reference frame origin is at the center of the sensor.
  * <p>
- * Note: sensor thickness is ignored in the current implementation - <tt>getCnannel(position)</tt> 
- * method does not check whether the specified position belongs to the sensitive volume. The reference
- * surface is defined by the <tt>W = 0</tt> plane in the sensor local reference frame.
+ * There is no thickness associated with this type of sensor. W coordinate is ignored
+ * when converting position into channel ID. All channel positions have W=0.  All channel
+ * have zero dimension in W direction.
  *
  * @author D.Onoprienko
- * @version $Id: Hexagon.java,v 1.1 2008/09/03 04:28:29 onoprien Exp $
+ * @version $Id: Hexagon.java,v 1.2 2008/09/30 04:41:51 onoprien Exp $
  */
 public class Hexagon implements SensorType {
   
@@ -29,13 +29,11 @@
    * Create <tt>Hexagon</tt> instance.
    *
    * @param sideLength      Length of the hexagon side.
-   * @param thickness       Thickness of the sensor.
    * @param nU              Number of divisions along U (measurement direction, perpendicular to strips).
    */
-  public Hexagon(double sideLength, double thickness, int nU) {
+  public Hexagon(double sideLength, int nU) {
     _side = sideLength;
     _halfWidth = sideLength*COSPI6;
-    _halfThick = thickness/2.;
     _nDivU = nU;
     _pitch = (2.*_halfWidth)/nU;
   }
@@ -105,12 +103,13 @@
    * Returns -1 if the channel defined by shifts does not exist on this sensor.
    *
    * @param channelID  ID of the original channel
-   * @param shiftV     move in <tt>V</tt> direction by <tt>shiftV</tt> channels
    * @param shiftU     move in <tt>U</tt> direction by <tt>shiftU</tt> channels
+   * @param shiftV     move in <tt>V</tt> direction by <tt>shiftV</tt> channels
+   * @param shiftW     move in <tt>W</tt> direction by <tt>shiftW</tt> channels
    */
-  public int getNeighbor(int channelID, int shiftU, int shiftV) {
+  public int getNeighbor(int channelID, int shiftU, int shiftV, int shiftW) {
     int nU = channelID + shiftU;
-    return (nU < 0 || nU >= _nDivU || shiftV != 0) ? -1 : nU ;
+    return (nU < 0 || nU >= _nDivU || shiftV != 0 || shiftW != 0) ? -1 : nU ;
   }
   
   /** Returns array of IDs of all immediate neighbor channels. */
@@ -125,7 +124,6 @@
   
   protected double _side;
   protected double _halfWidth;
-  protected double _halfThick;
   
   protected double _pitch;
   

lcsim/src/org/lcsim/contrib/onoprien/vsegment/geom/sensortype
Rectangle.java 1.2 -> 1.3
diff -u -r1.2 -r1.3
--- Rectangle.java	15 Sep 2008 15:44:06 -0000	1.2
+++ Rectangle.java	30 Sep 2008 04:41:51 -0000	1.3
@@ -11,14 +11,14 @@
 import org.lcsim.contrib.onoprien.vsegment.transform.IRefFrame;
 
 /**
- * This class represents a rectangular sensor with rectangular strips or pixel sparallel to its side.
+ * This class represents a rectangular sensor with rectangular strips or pixel parallel to its side.
  * <p>
- * Note: sensor thickness is ignored in the current implementation - <tt>getCnannel(position)</tt> 
- * method does not check whether the specified position belongs to the sensitive volume. The reference
- * surface is defined by the <tt>W = 0</tt> plane in the sensor local reference frame.
+ * There is no thickness associated with this type of sensor. W coordinate is ignored
+ * when converting position into channel ID. All channel positions have W=0.  All channel
+ * have zero dimension in W direction.
  *
  * @author D.Onoprienko
- * @version $Id: Rectangle.java,v 1.2 2008/09/15 15:44:06 onoprien Exp $
+ * @version $Id: Rectangle.java,v 1.3 2008/09/30 04:41:51 onoprien Exp $
  */
 public class Rectangle implements SensorType {
   
@@ -34,39 +34,33 @@
    *
    * @param width       Width of the sensor.
    * @param length      Length of the sensor (along strip direction).
-   * @param thickness   Thickness of the sensor.
    * @param nWidth      Number of divisions across the sensor width.
    * @param nLength     Number of divisions along the sensor length.
-   * @param center      Position of the sensor volume cuboid center in the local reference frame.
+   * @param centerU     U position of the rectangle center in the local reference frame.
+   * @param centerV     V position of the rectangle center in the local reference frame.
    */
-  public Rectangle(double width, double length, double thickness, 
-                   int nWidth, int nLength, Hep3Vector center) {
+  public Rectangle(double width, double length, int nWidth, int nLength, double centerU, double centerV) {
     if (nLength == 0) nLength = 1;
-    _uLow = center.x() - width/2.;
-    _vLow = center.y() - length/2.;
-    _wCenter = center.z();
+    _uLow = centerU - width/2.;
+    _vLow = centerV - length/2.;
     _pitch = width/nWidth;
     _length = length/nLength;
-    _thick = thickness;
     _hitType = (_length/_pitch < 4.) ? ITrackerHit.Type.PIXEL : ITrackerHit.Type.STRIP;
     _nDivV = nLength;
     _nDivU = nWidth;
-//    System.out.println("Rect w "+width+" len "+length+" thick "+thickness+" nW "+nWidth+" nL "+nLength+" center "+center);
-//    System.out.println(" pitch "+_pitch+" length "+_length+" thick "+_thick+" hitDim "+_hitDim);
   }
   
   /**
    * Create <tt>Rectangle</tt> instance.
-   * Reference frame origin will be in the center of the cuboid defining the sensor volume.
+   * Reference frame origin is at the center of the sensor rectangle.
    *
    * @param width       Width of the sensor.
    * @param length      Length of the sensor (along strip direction).
-   * @param thickness   Thickness of the sensor.
    * @param nWidth      Number of divisions across the sensor width.
    * @param nLength     Number of divisions along the sensor length.
    */
-  public Rectangle(double width, double length, double thickness, int nWidth, int nLength) {
-    this(width, length, thickness, nWidth, nLength, new BasicHep3Vector());
+  public Rectangle(double width, double length, int nWidth, int nLength) {
+    this(width, length, nWidth, nLength, 0.,0.);
   }
   
   /**
@@ -77,30 +71,27 @@
    *
    * @param width       Width of the sensor.
    * @param length      Length of the sensor (along strip direction).
-   * @param thickness   Thickness of the sensor.
    * @param stripPitch  Strip width.
    * @param nLength     Number of divisions along the sensor length.
-   * @param center      Position of the cuboid center in the local reference frame
+   * @param centerU     U position of the rectangle center in the local reference frame.
+   * @param centerV     V position of the rectangle center in the local reference frame.
    */
-  public Rectangle(double width, double length, double thickness, 
-                   double stripPitch, int nLength, Hep3Vector center) {
-    this(width, length, thickness, (int)Math.round(width/stripPitch), nLength, center);
+  public Rectangle(double width, double length, double stripPitch, int nLength, double centerU, double centerV) {
+    this(width, length, (int)Math.round(width/stripPitch), nLength, centerU, centerV);
   }
   
   /**
    * Create <tt>Rectangle</tt> instance.
-   * Reference frame origin will be in the center of the cuboid defining the sensor volume.
+   * Reference frame origin is at the center of the sensor rectangle.
    * Strip width will be rounded to place integral number of strips on the rectangle.
    *
    * @param width       Width of the sensor.
    * @param length      Length of the sensor (along strip direction).
-   * @param thickness   Thickness of the sensor.
    * @param stripPitch  Strip width.
    * @param nLength     Number of divisions along the sensor length.
    */
-  public Rectangle(double width, double length, double thickness, 
-                   double stripPitch, int nLength) {
-    this(width, length, thickness, (int)Math.round(width/stripPitch), nLength, new BasicHep3Vector());
+  public Rectangle(double width, double length, double stripPitch, int nLength) {
+    this(width, length, (int)Math.round(width/stripPitch), nLength, 0.,0.);
   }
   
   /**
@@ -111,30 +102,27 @@
    *
    * @param width         Width of the sensor.
    * @param length        Length of the sensor (along strip direction).
-   * @param thickness     Thickness of the sensor.
    * @param nWidth        Number of divisions across the sensor width.
    * @param stripLength   Strip length.
-   * @param center        Position of the cuboid center in the local reference frame
+   * @param centerU     U position of the rectangle center in the local reference frame.
+   * @param centerV     V position of the rectangle center in the local reference frame.
    */
-  public Rectangle(double width, double length, double thickness, 
-                   int nWidth, double stripLength, Hep3Vector center) {
-    this(width, length, thickness, nWidth, (int)Math.round(length/stripLength), center);
+  public Rectangle(double width, double length, int nWidth, double stripLength, double centerU, double centerV) {
+    this(width, length, nWidth, (int)Math.round(length/stripLength), centerU, centerV);
   }
   
   /**
    * Create <tt>Rectangle</tt> instance.
-   * Reference frame origin will be in the center of the cuboid defining the sensor volume.
+   * Reference frame origin is at the center of the sensor rectangle.
    * Strip length will be rounded to place integral number of strips on the rectangle.
    *
    * @param width         Width of the sensor.
    * @param length        Length of the sensor (along strip direction).
-   * @param thickness     Thickness of the sensor.
    * @param nWidth        Number of divisions across the sensor width.
    * @param stripLength   Strip length.
    */
-  public Rectangle(double width, double length, double thickness, 
-                   int nWidth, double stripLength) {
-    this(width, length, thickness, nWidth, (int)Math.round(length/stripLength), new BasicHep3Vector());
+  public Rectangle(double width, double length, int nWidth, double stripLength) {
+    this(width, length, nWidth, (int)Math.round(length/stripLength), 0.,0.);
   }
   
   /**
@@ -145,30 +133,27 @@
    *
    * @param width         Width of the sensor.
    * @param length        Length of the sensor (along strip direction).
-   * @param thickness     Thickness of the sensor.
    * @param stripPitch    Strip width.
    * @param stripLength   Strip length.
-   * @param center        Position of the cuboid center in the local reference frame
+   * @param centerU     U position of the rectangle center in the local reference frame.
+   * @param centerV     V position of the rectangle center in the local reference frame.
    */
-  public Rectangle(double width, double length, double thickness, 
-                   double stripPitch, double stripLength, Hep3Vector center) {
-    this(width, length, thickness, (int)Math.round(width/stripPitch), (int)Math.round(length/stripLength), center);
+  public Rectangle(double width, double length, double stripPitch, double stripLength, double centerU, double centerV) {
+    this(width, length, (int)Math.round(width/stripPitch), (int)Math.round(length/stripLength), centerU, centerV);
   }
   
   /**
    * Create <tt>Rectangle</tt> instance.
-   * Reference frame origin will be in the center of the cuboid defining the sensor volume.
+   * Reference frame origin is at the center of the sensor rectangle.
    * Strip width and length will be rounded to place integral number of strips on the rectangle.
    *
    * @param width         Width of the sensor.
    * @param length        Length of the sensor (along strip direction).
-   * @param thickness     Thickness of the sensor.
    * @param stripPitch    Strip width.
    * @param stripLength   Strip length.
    */
-  public Rectangle(double width, double length, double thickness, 
-                   double stripPitch, double stripLength) {
-    this(width, length, thickness, (int)Math.round(width/stripPitch), (int)Math.round(length/stripLength), new BasicHep3Vector());
+  public Rectangle(double width, double length, double stripPitch, double stripLength) {
+    this(width, length, (int)Math.round(width/stripPitch), (int)Math.round(length/stripLength), 0.,0.);
   }
 
 // -- Setters :  ---------------------------------------------------------------
@@ -187,8 +172,6 @@
    * Returns -1 if the point is outside of sensor sensitive area.
    */
   public int getChannelID(Hep3Vector point) {
-    
-//    if (Math.abs(point.z()-_wCenter) > _thick/2.) return -1;
 
     double u = point.x();
     double v = point.y();
@@ -225,7 +208,7 @@
    * Returns dimensions of the given channel along U, V, W.
    */
   public Hep3Vector getChannelDimensions(int channelID) {
-    return new BasicHep3Vector(_pitch, _length, _thick);
+    return new BasicHep3Vector(_pitch, _length, 0.);
   }
   
   
@@ -249,10 +232,12 @@
    * Returns -1 if the channel defined by shifts does not exist on this sensor.
    *
    * @param channelID  ID of the original channel
-   * @param shiftV     move in <tt>V</tt> direction by <tt>shiftV</tt> channels
    * @param shiftU     move in <tt>U</tt> direction by <tt>shiftU</tt> channels
+   * @param shiftV     move in <tt>V</tt> direction by <tt>shiftV</tt> channels
+   * @param shiftW     move in <tt>W</tt> direction by <tt>shiftW</tt> channels
    */
-  public int getNeighbor(int channelID, int shiftU, int shiftV) {
+  public int getNeighbor(int channelID, int shiftU, int shiftV, int shiftW) {
+    if (shiftW != 0) return -1;
     int nU = (channelID % _nDivU) + shiftU;
     if ((nU < 0) || (nU >= _nDivU)) return -1;
     int nV = (channelID / _nDivU) + shiftV;
@@ -281,11 +266,9 @@
   
   protected double _uLow;
   protected double _vLow;
-  protected double _wCenter;
   
   protected double _pitch;
   protected double _length;
-  protected double _thick;
   
   protected ITrackerHit.Type _hitType;
   

lcsim/src/org/lcsim/contrib/onoprien/vsegment/geom/sensortype
Ring.java 1.1 -> 1.2
diff -u -r1.1 -r1.2
--- Ring.java	3 Sep 2008 04:28:29 -0000	1.1
+++ Ring.java	30 Sep 2008 04:41:51 -0000	1.2
@@ -7,13 +7,17 @@
 
 /**
  * Class to represent a disk sensor divided into rectangular strips or pixels.
- * Reference frame origin is at the center of the disk in X and Y, Z position can be controlled. 
- *
+ * Reference frame origin is at the center of the disk in X and Y. 
+ * <p>
+ * There is no thickness associated with this type of sensor. W coordinate is ignored
+ * when converting position into channel ID. All channel positions have W=0.  All channel
+ * have zero dimension in W direction.
+ * <p>
  * {@link #getChannelID(Hep3Vector)} method returns <tt>-1</tt> if and only if the 
- * center of the rectangle (strip) to which the point belongs is ouside the ring.
+ * center of the channel (strip or pixel) to which the point belongs is ouside the ring.
  *
  * @author D.Onoprienko
- * @version $Id: Ring.java,v 1.1 2008/09/03 04:28:29 onoprien Exp $
+ * @version $Id: Ring.java,v 1.2 2008/09/30 04:41:51 onoprien Exp $
  */
 public class Ring extends Rectangle {
   
@@ -26,12 +30,9 @@
    * @param radiusMax   Outside radius of the ring.
    * @param pitch       Width of a strip.
    * @param length      Length of a strip.
-   * @param thickness   Thickness of the sensor.
-   * @param wCenter     W coordinate of the disk volume center in the local reference frame.
    */
-  public Ring(double radiusMin, double radiusMax, double pitch, double length, double thickness, double wCenter) {
-    super(pitch*Math.ceil(2.*radiusMax/pitch), length*Math.ceil(2.*radiusMax/length), thickness, pitch, length, 
-            new BasicHep3Vector(0.,0.,wCenter));
+  public Ring(double radiusMin, double radiusMax, double pitch, double length) {
+    super(pitch*Math.ceil(2.*radiusMax/pitch), length*Math.ceil(2.*radiusMax/length), pitch, length);
     _rMin = radiusMin;
     _rMax = radiusMax;
   }
@@ -52,15 +53,16 @@
    * Returns -1 if the channel defined by shifts does not exist on this sensor.
    *
    * @param channelID  ID of the original channel
-   * @param shiftV     move in <tt>V</tt> direction by <tt>shiftV</tt> channels
    * @param shiftU     move in <tt>U</tt> direction by <tt>shiftU</tt> channels
+   * @param shiftV     move in <tt>V</tt> direction by <tt>shiftV</tt> channels
+   * @param shiftW     move in <tt>W</tt> direction by <tt>shiftW</tt> channels
    */
-  public int getNeighbor(int channelID, int shiftU, int shiftV) {
-    int neighbor = super.getNeighbor(channelID, shiftU, shiftV);
+  public int getNeighbor(int channelID, int shiftU, int shiftV, int shiftW) {
+    int neighbor = super.getNeighbor(channelID, shiftU, shiftV, shiftW);
     return isValidChannelID(neighbor) ? neighbor : -1;
   }
   
-  /** Returns array of IDs of all immediate neighbor channels. */
+  /** Returns a list of IDs of all immediate neighbor channels. */
   public List<Integer> getNeighbors(int channelID) {
     List<Integer> raw = super.getNeighbors(channelID);
     List<Integer> out = new ArrayList<Integer>(raw.size());
@@ -69,8 +71,6 @@
     }
     return out;
   }
-  
-// -- Helper methods :  --------------------------------------------------------
 
   /**
    * Returns <tt>true</tt> if the center of the channel is inside the ring.

lcsim/src/org/lcsim/contrib/onoprien/vsegment/geom/sensortype
WedgeSideParallel.java 1.1 -> 1.2
diff -u -r1.1 -r1.2
--- WedgeSideParallel.java	3 Sep 2008 04:28:29 -0000	1.1
+++ WedgeSideParallel.java	30 Sep 2008 04:41:51 -0000	1.2
@@ -10,9 +10,14 @@
 import org.lcsim.contrib.onoprien.vsegment.transform.IRefFrame;
 
 /**
+ * This class represents a wedge-shaped sensor with strips parallel to its side.
+ * <p>
+ * There is no thickness associated with this type of sensor. W coordinate is ignored
+ * when converting position into channel ID. All channel positions have W=0.  All channel
+ * have zero dimension in W direction.
  *
  * @author D.Onoprienko
- * @version $Id: WedgeSideParallel.java,v 1.1 2008/09/03 04:28:29 onoprien Exp $
+ * @version $Id: WedgeSideParallel.java,v 1.2 2008/09/30 04:41:51 onoprien Exp $
  */
 public class WedgeSideParallel implements SensorType {
   
@@ -128,11 +133,12 @@
    * concept of a neighbor in the given direction. 
    *
    * @param channelID  ID of the original channel
-   * @param shiftV     move in <tt>V</tt> direction by <tt>shiftV</tt> channels
    * @param shiftU     move in <tt>U</tt> direction by <tt>shiftU</tt> channels
+   * @param shiftV     move in <tt>V</tt> direction by <tt>shiftV</tt> channels
+   * @param shiftV     move in <tt>W</tt> direction by <tt>shiftW</tt> channels
    */
-  public int getNeighbor(int channelID, int shiftU, int shiftV) {
-    if (shiftV != 0) return -1;
+  public int getNeighbor(int channelID, int shiftU, int shiftV, int shiftW) {
+    if (shiftV != 0 || shiftW != 0) return -1;
     int channel = channelID + shiftU;
     return ((channel < 0) || (channel > _maxID)) ? -1 : channel;
   }

lcsim/src/org/lcsim/contrib/onoprien/vsegment/process
ChargeCollectionDriver.java 1.3 -> 1.4
diff -u -r1.3 -r1.4
--- ChargeCollectionDriver.java	15 Sep 2008 15:44:03 -0000	1.3
+++ ChargeCollectionDriver.java	30 Sep 2008 04:41:51 -0000	1.4
@@ -30,7 +30,7 @@
  * 
  * 
  * @author D.Onoprienko
- * @version $Id: ChargeCollectionDriver.java,v 1.3 2008/09/15 15:44:03 onoprien Exp $
+ * @version $Id: ChargeCollectionDriver.java,v 1.4 2008/09/30 04:41:51 onoprien Exp $
  */
 public class ChargeCollectionDriver extends VSDriver implements VSEventListener {
   
@@ -172,12 +172,14 @@
           hit.setDetectorElement( deHit.get(0) );
         }
         
-        Sensor sensor = _segMan.getSensor(hit);
-        ChargeCollector collector = getChargeCollector(sensor);
-        if (collector == null) {
-          missedHits++;
-        } else {
-          outMap.add(sensor, collector.collectCharge(sensor, hit));
+        List<Sensor> sensors = _segMan.getSensor(hit);
+        for (Sensor sensor : sensors) {
+          ChargeCollector collector = getChargeCollector(sensor);
+          if (collector == null) {
+            missedHits++;
+          } else {
+            outMap.add(sensor, collector.collectCharge(sensor, hit));
+          }
         }
       }
     }

lcsim/src/org/lcsim/contrib/onoprien/vsegment/transform
IRefFrame.java 1.3 -> 1.4
diff -u -r1.3 -r1.4
--- IRefFrame.java	15 Sep 2008 15:44:03 -0000	1.3
+++ IRefFrame.java	30 Sep 2008 04:41:51 -0000	1.4
@@ -8,7 +8,7 @@
  * Interface to represent a reference frame.
  *
  * @author D. Onoprienko
- * @version $Id: IRefFrame.java,v 1.3 2008/09/15 15:44:03 onoprien Exp $
+ * @version $Id: IRefFrame.java,v 1.4 2008/09/30 04:41:51 onoprien Exp $
  */
 public interface IRefFrame {
   
@@ -22,11 +22,8 @@
     /** Cartesian reference frame. */
     XYZ,
     
-    /** Cylindrical reference frame. */
-    CYL,
-    
     /** Cylindrical reference frame with coordinates (Phi*R0, Z, R-R0). */
-    CYL_LZR
+    CYL
   }
   
 // -- Getters :  ---------------------------------------------------------------

lcsim/src/org/lcsim/contrib/onoprien/vsegment/transform
RefFrameCylinder.java 1.2 -> 1.3
diff -u -r1.2 -r1.3
--- RefFrameCylinder.java	15 Sep 2008 15:44:03 -0000	1.2
+++ RefFrameCylinder.java	30 Sep 2008 04:41:51 -0000	1.3
@@ -10,13 +10,13 @@
  * Reference frame on a cylinder of radius R0 and length L.
  * The axis of the cylinder is assumed to coincide with the Z axis of the global reference frame.
  * The coordinates are:<br>
- * <#nbsp;> phi*R0 <#nbsp;> [-2*PI*R0, 2*PI*R0] <br>
- * <#nbsp;> Z <#nbsp;> [-L/2, L/2] <br>
- * <#nbsp;> R-R0 <#nbsp;> [-R0, + infinity] <br>
+ * &nbsp; <b>phi*R0</b> &nbsp; [-2*PI*R0, 2*PI*R0] <br>
+ * &nbsp; <b>Z</b> &nbsp; [-L/2, L/2] <br>
+ * &nbsp; <b>R-R0</b> &nbsp; [-R0, + infinity] <br>
  * 
  * 
  * @author D. Onoprienko
- * @version $Id: RefFrameCylinder.java,v 1.2 2008/09/15 15:44:03 onoprien Exp $
+ * @version $Id: RefFrameCylinder.java,v 1.3 2008/09/30 04:41:51 onoprien Exp $
  */
 public class RefFrameCylinder implements IRefFrame {
   
@@ -27,14 +27,14 @@
     _r = radius;
   }
   
-  public RefFrameCylinder(double originZ, double radius) {
+  public RefFrameCylinder(double radius, double originZ) {
     _z = originZ;
     _r = radius;
   }
 
 // -- IRefFrame getters :  -----------------------------------------------------
   
-  public Type getType() {return Type.CYL_LZR;}
+  public Type getType() {return Type.CYL;}
   
   /** Throws <tt>UnsupportedOperationException</tt> since this frame is not Cartesian. */
   public Hep3Vector u() {throw new UnsupportedOperationException();}
@@ -102,6 +102,7 @@
    * covariance matrix cannot be transformed without knowing the position.
    */
   public SymmetricMatrix transformTo(SymmetricMatrix covMatrix, IRefFrame referenceFrame) {
+    if (referenceFrame == this) return covMatrix;
     throw new UnsupportedOperationException();
   }
   
@@ -118,6 +119,7 @@
    * covariance matrix cannot be transformed without knowing the position.
    */
   public SymmetricMatrix transformFrom(SymmetricMatrix covMatrix, IRefFrame referenceFrame) {
+    if (referenceFrame == this) return covMatrix;
     throw new UnsupportedOperationException();
   }
   
@@ -126,11 +128,33 @@
    * and position in the global reference frame. 
    */
   public SymmetricMatrix transformTo(SymmetricMatrix covMatrix, Hep3Vector vector) {
-    double[] cov = CovarianceMatrixTransformer.xy2rphi(vector.x(), vector.y(),
-                   covMatrix.e(0,0), covMatrix.e(1,1), covMatrix.e(0,1));
-    return new SymmetricMatrix(3, new double[] {cov[0]*_r*_r, 
-                                                          0.,  covMatrix.e(2,2),
-                                                   cov[2]*_r,                0.,  cov[1] }, true);
+    
+    double x = vector.x();
+    double y = vector.y();
+    double r2 = x*x+y*y;
+    double r = Math.sqrt(r2);
+    double LX = - _r*y/r2;
+    double LY = _r*x/r2;
+    double RX = x/r;
+    double RY = y/r;
+    
+    double eXX = covMatrix.e(0,0);
+    double eXY = covMatrix.e(0,1);
+    double eYY = covMatrix.e(1,1);
+    double eXZ = covMatrix.e(0,2);
+    double eYZ = covMatrix.e(1,2);
+    
+    double eUU = LX*LX*eXX + 2.*LX*LY*eXY + LY*LY*eYY;
+    double eUV = LX*eXZ + LY*eYZ;
+    double eUW = RX*LX*eXX + (RY*LX+RX*LY)*eXY + RY*LY*eYY;
+    double eVW = RX*eXZ + RY*eYZ;
+    double eWW = RX*RX*eXX + 2.*RX*RY*eXY + RY*RY*eYY;
+    
+    return new SymmetricMatrix(3, 
+            new double[] {eUU, 
+                          eUV,  covMatrix.e(2,2),
+                          eUW,               eVW,  eWW},
+            true);
   }
   
   /**
@@ -146,13 +170,28 @@
    * covariance matrix and position in the transformed reference frame. 
    */
   public SymmetricMatrix transformFrom(SymmetricMatrix covMatrix, Hep3Vector vector) {
+    
     double phi = vector.x() / _r ;
-    double r = vector.z() + _r;
-    double[] cov = CovarianceMatrixTransformer.rphi2xy(r, phi, 
-            covMatrix.e(2,2), covMatrix.e(0,0)/(_r*_r), covMatrix.e(0,2)/_r);
-    return new SymmetricMatrix(3, new double[] {cov[0],
-                                                cov[2],  cov[1],
-                                                    0.,      0.,  covMatrix.e(1,1)}, true);
+    double a = (vector.z() + _r)/_r;
+    double c = Math.cos(phi);
+    double s = Math.sin(phi);
+    double a2 = a*a;
+    double s2 = s*s;
+    double c2 = c*c;
+    
+    double eUU = covMatrix.e(0,0);
+    double eWW = covMatrix.e(2,2);
+    double eUV = covMatrix.e(0,1);
+    double eUW = covMatrix.e(0,2);
+    double eVW = covMatrix.e(1,2);
+    
+    double b = 2.*a*s*c*eUW;
+    
+    return new SymmetricMatrix(3,
+            new double[] {a2*s2*eUU - b + c2*eWW,
+                          s*c*(eWW - a2*eUU) + a*eUW*(c2-s2),  a2*c2*eUU + b + s2*eWW,
+                          c*eVW - a*s*eUV,                     a*c*eUV + s*eVW,         covMatrix.e(1,1)},
+            true);
   }
 
   /**

lcsim/src/org/lcsim/contrib/onoprien/vsegment
SegmenterSiD01.java added at 1.1
diff -N SegmenterSiD01.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ SegmenterSiD01.java	30 Sep 2008 04:41:51 -0000	1.1
@@ -0,0 +1,70 @@
+package org.lcsim.contrib.onoprien.vsegment;
+
+import org.lcsim.units.clhep.SystemOfUnits;
+
+import org.lcsim.contrib.onoprien.vsegment.geom.segmenter.CylindricalBarrelSegmenter;
+import org.lcsim.contrib.onoprien.vsegment.geom.segmenter.DiskTrackerToWedgesSegmenter;
+import org.lcsim.contrib.onoprien.vsegment.geom.segmenter.DiskTrackerToRingsSegmenter;
+import org.lcsim.contrib.onoprien.vsegment.geom.segmenter.SubdetectorBasedSegmenter;
+
+/**
+ * Reference segmenter intended for use with SID01 detector.
+ * This segmenter describes a virtual segmentation scheme identical to the one described
+ * by <tt>ExampleSegmenter1</tt> in the original version of the toolkit 
+ * (org.lcsim.onoprien.tracking).
+ * 
+ * @author D. Onoprienko
+ * @version $Id: SegmenterSiD01.java,v 1.1 2008/09/30 04:41:51 onoprien Exp $
+ */
+public class SegmenterSiD01 extends SubdetectorBasedSegmenter {
+  
+// -- Constructors :  ----------------------------------------------------------
+  
+  public SegmenterSiD01() {
+    
+    String sdName;
+    
+    // 25 um pixels in VTX Barrel
+    
+    sdName = "VertexBarrel";
+    CylindricalBarrelSegmenter vtxBarrelSegmenter = new CylindricalBarrelSegmenter(sdName);
+    vtxBarrelSegmenter.setStripLength(25.*SystemOfUnits.micrometer);
+    vtxBarrelSegmenter.setStripWidth(25.*SystemOfUnits.micrometer);
+    setSegmenter(sdName, vtxBarrelSegmenter);
+    
+    // 10 cm x 25 um strips in outer Tracker Barrel
+    
+    sdName = "TrackerBarrel";
+    CylindricalBarrelSegmenter trackerBarrelSegmenter = new CylindricalBarrelSegmenter(sdName);
+    trackerBarrelSegmenter.setStripLength(10.*SystemOfUnits.cm);
+    trackerBarrelSegmenter.setStripWidth(25.*SystemOfUnits.micrometer);
+    setSegmenter(sdName, trackerBarrelSegmenter);
+    
+    // 25 um pixels in VTX Endcap
+    
+    sdName = "VertexEndcap";
+    DiskTrackerToRingsSegmenter vtxEndcapSegmenter = new DiskTrackerToRingsSegmenter(sdName);
+    vtxEndcapSegmenter.setStripLength(25.*SystemOfUnits.micrometer);
+    vtxEndcapSegmenter.setStripWidth(25.*SystemOfUnits.micrometer);
+    setSegmenter(sdName, vtxEndcapSegmenter);
+    
+    // 15 degrees stereo wedges in Forward Tracker
+    
+    sdName = "TrackerForward";
+    DiskTrackerToWedgesSegmenter trackerForwardSegmenter = new DiskTrackerToWedgesSegmenter(sdName);
+    trackerForwardSegmenter.setStripLength(10.*SystemOfUnits.cm);
+    trackerForwardSegmenter.setStripWidth(25.*SystemOfUnits.micrometer);
+    trackerForwardSegmenter.setNumberOfPhiSlices(24);
+    setSegmenter(sdName, trackerForwardSegmenter);
+    
+    // 15 degrees stereo wedges in outer Tracker Endcap
+    
+    sdName = "TrackerEndcap";
+    DiskTrackerToWedgesSegmenter trackerEndcapSegmenter = new DiskTrackerToWedgesSegmenter(sdName);
+    trackerEndcapSegmenter.setNumberOfRadialSlices(new int[]{3,5,8,10, 10});
+    trackerEndcapSegmenter.setStripWidth(25.*SystemOfUnits.micrometer);
+    trackerEndcapSegmenter.setNumberOfPhiSlices(24);
+    setSegmenter(sdName, trackerEndcapSegmenter);
+  }
+
+}
CVSspam 0.2.8