Print

Print


Commit in lcsim-contrib/src/main/java/org/lcsim/contrib/onoprien/geom/tracker/lib on MAIN
SegmenterSiD01.java+69added 1.1
SegmenterSiD02_01.java+68added 1.1
package-info.java+15added 1.1
segmenter/CylindricalBarrelSegmenter.java+181added 1.1
         /DiskToWedgesSegmenter.java+142added 1.1
         /DiskTrackerSegmenter.java+104added 1.1
         /DiskTrackerToRingsSegmenter.java+219added 1.1
         /DiskTrackerToWedgesSegmenter.java+155added 1.1
         /SubdetectorBasedSegmenter.java+80added 1.1
         /package-info.java+4added 1.1
sensortype/Cylinder.java+125added 1.1
          /Hexagon.java+149added 1.1
          /Rectangle.java+290added 1.1
          /Ring.java+101added 1.1
          /WedgeSideParallel.java+191added 1.1
          /package-info.java+9added 1.1
+1902
16 added files
New MC Truth access package to support CAT analysis.
Cleanup and refactoring (in progress). 
Streamlined/flexible geometry access.
Skeleton CAT drivers (testing).
Miscelaneous additions/fixes.

lcsim-contrib/src/main/java/org/lcsim/contrib/onoprien/geom/tracker/lib
SegmenterSiD01.java added at 1.1
diff -N SegmenterSiD01.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ SegmenterSiD01.java	8 Jul 2009 15:59:41 -0000	1.1
@@ -0,0 +1,69 @@
+package org.lcsim.contrib.onoprien.geom.tracker.lib;
+
+import org.lcsim.contrib.onoprien.geom.tracker.lib.segmenter.CylindricalBarrelSegmenter;
+import org.lcsim.contrib.onoprien.geom.tracker.lib.segmenter.DiskTrackerToWedgesSegmenter;
+import org.lcsim.contrib.onoprien.geom.tracker.lib.segmenter.DiskTrackerToRingsSegmenter;
+import org.lcsim.contrib.onoprien.geom.tracker.lib.segmenter.SubdetectorBasedSegmenter;
+import org.lcsim.contrib.onoprien.util.constants.Units;
+
+/**
+ * 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 2009/07/08 15:59:41 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.*Units.micrometer);
+    vtxBarrelSegmenter.setStripWidth(25.*Units.micrometer);
+    setSegmenter(sdName, vtxBarrelSegmenter);
+    
+    // 10 cm x 25 um strips in outer Tracker Barrel
+    
+    sdName = "TrackerBarrel";
+    CylindricalBarrelSegmenter trackerBarrelSegmenter = new CylindricalBarrelSegmenter(sdName);
+    trackerBarrelSegmenter.setStripLength(10.*Units.cm);
+    trackerBarrelSegmenter.setStripWidth(25.*Units.micrometer);
+    setSegmenter(sdName, trackerBarrelSegmenter);
+    
+    // 25 um pixels in VTX Endcap
+    
+    sdName = "VertexEndcap";
+    DiskTrackerToRingsSegmenter vtxEndcapSegmenter = new DiskTrackerToRingsSegmenter(sdName);
+    vtxEndcapSegmenter.setStripLength(25.*Units.micrometer);
+    vtxEndcapSegmenter.setStripWidth(25.*Units.micrometer);
+    setSegmenter(sdName, vtxEndcapSegmenter);
+    
+    // 15 degrees stereo wedges in Forward Tracker
+    
+    sdName = "TrackerForward";
+    DiskTrackerToWedgesSegmenter trackerForwardSegmenter = new DiskTrackerToWedgesSegmenter(sdName);
+    trackerForwardSegmenter.setStripLength(10.*Units.cm);
+    trackerForwardSegmenter.setStripWidth(25.*Units.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.*Units.micrometer);
+    trackerEndcapSegmenter.setNumberOfPhiSlices(24);
+    setSegmenter(sdName, trackerEndcapSegmenter);
+  }
+
+}

lcsim-contrib/src/main/java/org/lcsim/contrib/onoprien/geom/tracker/lib
SegmenterSiD02_01.java added at 1.1
diff -N SegmenterSiD02_01.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ SegmenterSiD02_01.java	8 Jul 2009 15:59:41 -0000	1.1
@@ -0,0 +1,68 @@
+package org.lcsim.contrib.onoprien.geom.tracker.lib;
+
+import org.lcsim.contrib.onoprien.geom.tracker.lib.segmenter.CylindricalBarrelSegmenter;
+import org.lcsim.contrib.onoprien.geom.tracker.lib.segmenter.DiskTrackerToWedgesSegmenter;
+import org.lcsim.contrib.onoprien.geom.tracker.lib.segmenter.DiskTrackerToRingsSegmenter;
+import org.lcsim.contrib.onoprien.geom.tracker.lib.segmenter.SubdetectorBasedSegmenter;
+import org.lcsim.contrib.onoprien.util.constants.Units;
+
+/**
+ * Simplistic reference segmenter intended for use with SID02 detector.
+ * <p>
+ * Parameters match those used by Rich in<br>
+ * org.lcsim.recon.tracking.seedtracker.ReconTracking.SiD02ReconSegmenter v 1.1 2008/10/16 21:41:18.
+ * 
+ * @author D. Onoprienko
+ * @version $Id: SegmenterSiD02_01.java,v 1.1 2009/07/08 15:59:41 onoprien Exp $
+ */
+public class SegmenterSiD02_01 extends SubdetectorBasedSegmenter {
+  
+// -- Constructors :  ----------------------------------------------------------
+  
+  public SegmenterSiD02_01() {
+    
+    String sdName;
+    
+    // 20 um pixels in VTX Barrel
+    
+    sdName = "VertexBarrel";
+    CylindricalBarrelSegmenter vtxBarrelSegmenter = new CylindricalBarrelSegmenter(sdName);
+    vtxBarrelSegmenter.setStripLength(20.*Units.micrometer);
+    vtxBarrelSegmenter.setStripWidth(20.*Units.micrometer);
+    setSegmenter(sdName, vtxBarrelSegmenter);
+    
+    // 10 cm x 25 um strips in outer Tracker Barrel
+    
+    sdName = "TrackerBarrel";
+    CylindricalBarrelSegmenter trackerBarrelSegmenter = new CylindricalBarrelSegmenter(sdName);
+    trackerBarrelSegmenter.setStripLength(9.15*Units.cm);
+    trackerBarrelSegmenter.setStripWidth(25.*Units.micrometer);
+    setSegmenter(sdName, trackerBarrelSegmenter);
+    
+    // 20 um pixels in VTX Endcap
+    
+    sdName = "VertexEndcap";
+    DiskTrackerToRingsSegmenter vtxEndcapSegmenter = new DiskTrackerToRingsSegmenter(sdName);
+    vtxEndcapSegmenter.setStripLength(20.*Units.micrometer);
+    vtxEndcapSegmenter.setStripWidth(20.*Units.micrometer);
+    setSegmenter(sdName, vtxEndcapSegmenter);
+    
+    // 20 um pixels in  Forward Tracker
+    
+    sdName = "TrackerForward";
+    DiskTrackerToRingsSegmenter trackerForwardSegmenter = new DiskTrackerToRingsSegmenter(sdName);
+    trackerForwardSegmenter.setStripLength(20.*Units.micrometer);
+    trackerForwardSegmenter.setStripWidth(20.*Units.micrometer);
+    setSegmenter(sdName, trackerForwardSegmenter);
+    
+    // 12 degrees stereo wedges in outer Tracker Endcap
+    
+    sdName = "TrackerEndcap";
+    DiskTrackerToWedgesSegmenter trackerEndcapSegmenter = new DiskTrackerToWedgesSegmenter(sdName);
+    trackerEndcapSegmenter.setNumberOfRadialSlices(new int[]{3,6,9,12});
+    trackerEndcapSegmenter.setStripWidth(25.*Units.micrometer);
+    trackerEndcapSegmenter.setNumberOfPhiSlices(30);
+    setSegmenter(sdName, trackerEndcapSegmenter);
+  }
+
+}

lcsim-contrib/src/main/java/org/lcsim/contrib/onoprien/geom/tracker/lib
package-info.java added at 1.1
diff -N package-info.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ package-info.java	8 Jul 2009 15:59:41 -0000	1.1
@@ -0,0 +1,15 @@
+/**
+ * Library of top level {@link org.lcsim.contrib.onoprien.geom.tracker.Segmenter}s describing particular virtual segmentation
+ * schemes for specific detector versions.
+ * <p>
+ * If your scheme or detector is not here, use one of these as an example, and mix-and-match
+ * {@link org.lcsim.contrib.onoprien.geom.tracker.Segmenter}s and
+ * {@link org.lcsim.contrib.onoprien.geom.tracker.SensorType}s from
+ * {@link org.lcsim.contrib.onoprien.geom.tracker.lib.segmenter} and
+ * {@link org.lcsim.contrib.onoprien.geom.tracker.lib.sensortype} packages to describe
+ * the desired virtual segmentation.
+ *
+ * @author D. Onoprienko
+ */
+package org.lcsim.contrib.onoprien.geom.tracker.lib;
+

lcsim-contrib/src/main/java/org/lcsim/contrib/onoprien/geom/tracker/lib/segmenter
CylindricalBarrelSegmenter.java added at 1.1
diff -N CylindricalBarrelSegmenter.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ CylindricalBarrelSegmenter.java	8 Jul 2009 15:59:41 -0000	1.1
@@ -0,0 +1,181 @@
+package org.lcsim.contrib.onoprien.geom.tracker.lib.segmenter;
+
+import java.util.*;
+
+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.solids.Tube;
+
+import org.lcsim.contrib.onoprien.geom.tracker.AbstractSegmenter;
+import org.lcsim.contrib.onoprien.geom.tracker.RegionSegmenter;
+import org.lcsim.contrib.onoprien.geom.tracker.Sensor;
+import org.lcsim.contrib.onoprien.geom.tracker.SensorType;
+import org.lcsim.contrib.onoprien.geom.tracker.lib.sensortype.Cylinder;
+import org.lcsim.contrib.onoprien.util.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 2009/07/08 15:59:41 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);
+    _sd = detector.getSubdetector(_sdName);
+    if (_sd == null) return;
+    _detElts = AbstractSegmenter.getLeaves(_sd.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(_sd, _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;
+  Subdetector _sd;
+  
+  List<IDetectorElement> _detElts;
+  
+  private int _nLayers;
+  private double[] _radius;
+  private double[] _length;
+  private double[] _stripLength;
+  private double[] _stripWidth;
+}

lcsim-contrib/src/main/java/org/lcsim/contrib/onoprien/geom/tracker/lib/segmenter
DiskToWedgesSegmenter.java added at 1.1
diff -N DiskToWedgesSegmenter.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ DiskToWedgesSegmenter.java	8 Jul 2009 15:59:41 -0000	1.1
@@ -0,0 +1,142 @@
+package org.lcsim.contrib.onoprien.geom.tracker.lib.segmenter;
+
+import hep.physics.vec.BasicHep3Vector;
+import hep.physics.vec.Hep3Vector;
+import org.lcsim.detector.IDetectorElement;
+import org.lcsim.detector.IGeometryInfo;
+import org.lcsim.detector.ILogicalVolume;
+import org.lcsim.detector.IPhysicalVolume;
+import org.lcsim.detector.IRotation3D;
+import org.lcsim.detector.Transform3D;
+import org.lcsim.detector.Translation3D;
+import org.lcsim.detector.Rotation3D;
+import org.lcsim.detector.solids.Tube;
+import org.lcsim.event.SimTrackerHit;
+import org.lcsim.geometry.Subdetector;
+
+import org.lcsim.contrib.onoprien.geom.tracker.RegionSegmenter;
+import org.lcsim.contrib.onoprien.geom.tracker.Sensor;
+import org.lcsim.contrib.onoprien.geom.tracker.SensorType;
+import org.lcsim.contrib.onoprien.geom.tracker.lib.sensortype.WedgeSideParallel;
+import org.lcsim.contrib.onoprien.util.vector.ConstHep3Vector;
+import org.lcsim.contrib.onoprien.util.transform.RefFrameCartesian;
+
+/**
+ * Simplistic <tt>Segmenter</tt> that tiles a single disk with wedges.
+ * 
+ * @author D. Onoprienko
+ * @version $Id: DiskToWedgesSegmenter.java,v 1.1 2009/07/08 15:59:41 onoprien Exp $
+ */
+public class DiskToWedgesSegmenter extends RegionSegmenter {
+  
+// -- Constructors :  ----------------------------------------------------------
+  
+  public DiskToWedgesSegmenter(Subdetector subDetector, IDetectorElement disk, int nRadialSlices, int nPhiSlices, double pitch, boolean left) {
+    
+    _sd = subDetector;
+    _de = disk;
+    _left = left;
+    _pitch = pitch;
+    _nPhi = nPhiSlices;
+    _nRadial = nRadialSlices;
+    
+    IGeometryInfo gInfo = _de.getGeometry();
+    Tube solid = (Tube) gInfo.getLogicalVolume().getSolid();
+    _rMiddleMin = solid.getInnerRadius();
+    double rMax = solid.getOuterRadius();
+
+    _z = gInfo.getPosition().z();
+    
+    _deltaPhi = (2.*Math.PI)/nPhiSlices;
+    _rMin = _rMiddleMin/Math.cos(_deltaPhi/2.);
+    _deltaR = (rMax - _rMin) / nRadialSlices;
+    _deltaRMiddle = _deltaR * Math.cos(_deltaPhi/2.);
+    
+    _sType = new SensorType[_nRadial];
+    for (int indexR=0; indexR < _nRadial; indexR++) {
+      _sType[indexR] = new WedgeSideParallel(_rMin+_deltaR*indexR, _deltaR, _deltaPhi, _pitch, _left);
+    }
+
+    _rotation = new Rotation3D[_nPhi];
+    _u = new ConstHep3Vector[_nPhi];
+    _v = new ConstHep3Vector[_nPhi];
+    for (int indexPhi=0; indexPhi < _nPhi; indexPhi++ ) {
+      double angle = (left) ? _deltaPhi * (indexPhi + 1) - Math.PI/2. : _deltaPhi * indexPhi - Math.PI/2.;
+      _rotation[indexPhi] = Rotation3D.passiveZRotation(-angle);
+      _u[indexPhi] = new ConstHep3Vector(_rotation[indexPhi].rotated(ConstHep3Vector.V100));
+      _v[indexPhi] = new ConstHep3Vector(_rotation[indexPhi].rotated(ConstHep3Vector.V010));
+    }
+  }
+
+
+// -- Implementing RegionSegmenter :  ------------------------------------------
+
+  /**
+   * Returns <tt>postfix</tt> corresponding to the position of the given simulated hit. 
+   */
+  protected int[] makePostfix(SimTrackerHit hit) {
+    
+    double[] pos = hit.getPoint();
+    
+    double r = Math.hypot(pos[0],pos[1]);
+    double phi = Math.atan2(pos[1], pos[0]);
+    phi = (phi > 0.) ? phi : phi + Math.PI * 2.;
+    
+    int indexPhi = (int) Math.floor(phi/_deltaPhi);
+    if (indexPhi < 0) indexPhi = 0;
+    if (indexPhi >= _nPhi) indexPhi = _nPhi -1;
+    
+    double rMiddle = r * Math.cos(phi - _deltaPhi*(indexPhi+.5));
+    int indexR = (int) Math.floor((rMiddle - _rMiddleMin) / _deltaRMiddle);
+    if ((indexR < 0) || (indexR >= _nRadial)) return new int[0];
+    
+    return new int[]{(_nRadial * indexPhi) + indexR};
+  }
+  
+  /**
+   * Returns maximum postfix value that can be returned by
+   * {@link #makePostfix(SimTrackerHit)} method of this <tt>Segmenter</tt> object.
+   */
+  protected int getMaxPostfix() {
+    return (_nRadial * _nPhi) - 1;
+  }
+
+  /**
+   * 
+   * Creates a new {@link Sensor} object given the <tt>postfix</tt>.
+   */
+  protected Sensor makeSensor(int postfix) {
+    int indexR = postfix % _nRadial;
+    int indexPhi = postfix / _nRadial;
+    double r = _rMin + indexR * _deltaR;
+    double phi = (indexPhi + 1) * _deltaPhi;
+    Hep3Vector origin = new BasicHep3Vector(r*Math.cos(phi), r*Math.sin(phi), _z);
+    RefFrameCartesian rf =
+         new RefFrameCartesian(origin, _rotation[indexPhi], _u[indexPhi], _v[indexPhi], ConstHep3Vector.V001);
+    return new Sensor(_sd, _de, postfixToID(postfix), _sType[indexR], rf);
+  }
+
+// -- Private parts :  ---------------------------------------------------------
+  
+  Subdetector _sd;
+  IDetectorElement _de;
+  
+  boolean _left;
+  double _pitch;
+  
+  int _nPhi;
+  int _nRadial;
+  
+  double _z;
+  
+  double _rMin;
+  double _rMiddleMin;
+  
+  double _deltaPhi;
+  double _deltaR;
+  double _deltaRMiddle;
+  
+  SensorType[] _sType;
+  IRotation3D[] _rotation;
+  ConstHep3Vector[] _u, _v;
+}

lcsim-contrib/src/main/java/org/lcsim/contrib/onoprien/geom/tracker/lib/segmenter
DiskTrackerSegmenter.java added at 1.1
diff -N DiskTrackerSegmenter.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ DiskTrackerSegmenter.java	8 Jul 2009 15:59:41 -0000	1.1
@@ -0,0 +1,104 @@
+package org.lcsim.contrib.onoprien.geom.tracker.lib.segmenter;
+
+import java.util.*;
+
+import org.lcsim.detector.IDetectorElement;
+import org.lcsim.event.SimTrackerHit;
+import org.lcsim.geometry.Detector;
+import org.lcsim.geometry.Subdetector;
+
+import org.lcsim.contrib.onoprien.geom.tracker.AbstractSegmenter;
+import org.lcsim.contrib.onoprien.geom.tracker.ForwardingSegmenter;
+
+/**
+ * Forwarding segmenter that chooses daughter segmenter based on the {@link IDetectorElement}
+ * associated with the hit. Daughter segmenters are prefixed in the order of increasing Z
+ * of the disks they handle. Subclasses should implement {@link #assignSegmenter(IDetectorElement)}
+ * method that assigns segmenters to disks.
+ *
+ * @author D. Onoprienko
+ * @version $Id: DiskTrackerSegmenter.java,v 1.1 2009/07/08 15:59:41 onoprien Exp $
+ */
+abstract public class DiskTrackerSegmenter extends ForwardingSegmenter {
+  
+// -- Constructors :  ----------------------------------------------------------
+  
+  public DiskTrackerSegmenter(String subdetectorName) {
+    _subdName = subdetectorName;
+  }
+  
+// -- Choosing daughter Segmenter :  -------------------------------------------
+
+  /**
+   * Returns daughter <tt>Segmenter</tt> that can handle the given hit.
+   */
+  public AbstractSegmenter chooseSegmenter(SimTrackerHit hit) {
+    return _deToSegmenter.get(hit.getDetectorElement());
+  }
+  
+// -- Initialization :  --------------------------------------------------------
+  
+  public void detectorChanged(Detector detector) {
+    _sd = detector.getSubdetector(_subdName);
+    if (_sd == null) return;
+    _dElements = AbstractSegmenter.getLeaves(_sd.getDetectorElement());
+    Collections.sort(_dElements, new Comparator<IDetectorElement>() {
+      public int compare(IDetectorElement s1, IDetectorElement s2) {
+        return (int)Math.signum(s1.getGeometry().getPosition().z()-s2.getGeometry().getPosition().z());
+      }
+    });
+    _deToSegmenter = new HashMap<IDetectorElement,AbstractSegmenter>();
+    removeAllDaughterSegmenters();
+    for (IDetectorElement de : _dElements) {
+      AbstractSegmenter segmenter = assignSegmenter(de);
+      addDaughterSegmenter(segmenter);
+      _deToSegmenter.put(de, segmenter);
+    }
+    updateDaughterSegmenters(detector);
+  }
+  
+  /**
+   * Subclasses should implement this method to return <tt>Segmenter</tt> that 
+   * handles hits in the given <tt>DetectorElement</tt>.
+   */
+  abstract public AbstractSegmenter assignSegmenter(IDetectorElement de);
+  
+// -- Utility methods :  -------------------------------------------------------
+  
+  /**
+   * Returns layer number for the disk.
+   */
+  public int getLayer(IDetectorElement de) {
+    int index = _dElements.indexOf(de);
+    int nLayers = _dElements.size()/2;
+    return (index < nLayers) ? nLayers-index-1 : index - nLayers;
+  }
+  
+  /**
+   * Returns superlayer number for the disk.
+   * Superlayer is a pair of sensor disks on opposite sides of the same support disk.
+   */
+  public int getSuperlayer(IDetectorElement de) {
+    return getLayer(de)/2;
+  }
+  
+  /**
+   * Returns <tt>true</tt> if the disk is on the side of a superlayer that faces 
+   * the center of the detector.
+   */
+  public boolean isInner(IDetectorElement de) {
+    return (getLayer(de) % 2) == 0;
+  }
+  
+  protected int getOtherSideIndex(int daughterIndex) {
+    return (daughterIndex % 2 == 0) ? daughterIndex + 1 : daughterIndex - 1 ;
+  }
+
+// -- Private parts :  ---------------------------------------------------------
+  
+  protected String _subdName;
+  protected Subdetector _sd;
+  protected List<IDetectorElement> _dElements;
+  
+  protected HashMap<IDetectorElement,AbstractSegmenter> _deToSegmenter;
+}

lcsim-contrib/src/main/java/org/lcsim/contrib/onoprien/geom/tracker/lib/segmenter
DiskTrackerToRingsSegmenter.java added at 1.1
diff -N DiskTrackerToRingsSegmenter.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ DiskTrackerToRingsSegmenter.java	8 Jul 2009 15:59:41 -0000	1.1
@@ -0,0 +1,219 @@
+package org.lcsim.contrib.onoprien.geom.tracker.lib.segmenter;
+
+import java.util.*;
+
+import hep.physics.vec.BasicHep3Vector;
+import hep.physics.vec.Hep3Vector;
+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.IRotation3D;
+import org.lcsim.detector.Transform3D;
+import org.lcsim.detector.Translation3D;
+import org.lcsim.detector.Rotation3D;
+import org.lcsim.detector.solids.Tube;
+
+import org.lcsim.contrib.onoprien.geom.tracker.AbstractSegmenter;
+import org.lcsim.contrib.onoprien.geom.tracker.RegionSegmenter;
+import org.lcsim.contrib.onoprien.geom.tracker.Sensor;
+import org.lcsim.contrib.onoprien.geom.tracker.SensorType;
+import org.lcsim.contrib.onoprien.geom.tracker.lib.sensortype.Ring;
+import org.lcsim.contrib.onoprien.util.vector.ConstHep3Vector;
+import org.lcsim.contrib.onoprien.util.transform.IRefFrame;
+import org.lcsim.contrib.onoprien.util.transform.RefFrameCartesian;
+
+/**
+ * 
+ * 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
+ * of the detector are rotated by an angle set through a call to 
+ * {@link #setStereoAngle(double angle)}.
+ * 
+ * @author D.Onoprienko
+ * @version $Id: DiskTrackerToRingsSegmenter.java,v 1.1 2009/07/08 15:59:41 onoprien Exp $
+ */
+public class DiskTrackerToRingsSegmenter extends RegionSegmenter {
+  
+// -- Constructors and initialization :  ---------------------------------------
+  
+  /**
+   * 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;
+    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);
+  }
+
+  /** 
+   * Detector-dependent initialization.
+   */
+  public void detectorChanged(Detector detector) {
+    super.detectorChanged(detector);
+    _sd = detector.getSubdetector(_sdName);
+    if (_sd == null) return;
+    _detElts = AbstractSegmenter.getLeaves(_sd.getDetectorElement());
+    Collections.sort(_detElts, new Comparator<IDetectorElement>() {
+      public int compare(IDetectorElement s1, IDetectorElement s2) {
+        return (int)Math.signum(s1.getGeometry().getPosition().z()-s2.getGeometry().getPosition().z());
+      }
+    });
+    _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];
+    _z = new double[_nDisks];
+    int postfix = 0;
+    for (IDetectorElement del : _detElts) {
+      IGeometryInfo gInfo = del.getGeometry();
+      Tube solid = (Tube) gInfo.getLogicalVolume().getSolid();
+      _radiusInner[postfix] = solid.getInnerRadius();
+      _radiusOuter[postfix] = solid.getOuterRadius();
+      _z[postfix] = gInfo.getPosition().z();
+      postfix++;
+    }
+  }
+  
+// -- Setters :  ---------------------------------------------------------------
+
+  /**
+   * Set strip width for all disks.
+   */
+  public void setStripWidth(double pitch) {
+    _stripWidth = new double[]{pitch};
+  }
+
+  /**
+   * 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 = 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();
+  }
+
+  /**
+   * Set stereo angle.
+   */
+  public void setStereoAngle(double angle) {
+    _rot1 = (Math.abs(angle) < 0.0001) ? null : Rotation3D.passiveZRotation(angle);
+    if (_rot1 != null) {
+      _u1 = new ConstHep3Vector(_rot1.rotated(ConstHep3Vector.V100));
+      _v1 = new ConstHep3Vector(_rot1.rotated(ConstHep3Vector.V010));
+    }
+  }
+
+// -- Implementing RegionSegmenter :  ------------------------------------------
+
+  /**
+   * Returns sensor ID postfix corresponding to the given position.
+   */
+  public int[] makePostfix(SimTrackerHit hit) {
+    int layer = hit.getLayer();
+    return new int[]{hit.getPoint()[2] < 0. ? _nLayers - layer - 1  : _nLayers + layer };
+  }
+  
+  /**
+   * Returns maximum postfix value that can be returned by
+   * {@link #makePostfix(SimTrackerHit)} method of this <tt>Segmenter</tt>.
+   */
+  public int getMaxPostfix() {
+    return _nDisks - 1;
+  }
+
+  /** Creates a {@link Sensor} object given the ID. */
+  public Sensor makeSensor(int postfix) {
+    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();
+    Translation3D translation = new Translation3D(0.,0.,-_z[postfix]);
+    IRefFrame rf;
+    if (layer % 2 == 0) {
+      rf = new RefFrameCartesian(new Transform3D(translation), null,
+              ConstHep3Vector.V100, ConstHep3Vector.V010, ConstHep3Vector.V001);
+    } else {
+      if (_rot1 == null) {
+        rf = new RefFrameCartesian(new Transform3D(translation), null,
+              ConstHep3Vector.V100, ConstHep3Vector.V010, ConstHep3Vector.V001);
+      } else {
+        rf = new RefFrameCartesian(new Transform3D(translation, _rot1), null, _u1, _v1, ConstHep3Vector.V001);
+      }
+    }
+    return new Sensor(_sd, _detElts.get(postfix), postfixToID(postfix), type, rf);
+  }
+  
+// -- Private parts :  ---------------------------------------------------------
+  
+  String _sdName;
+  private Subdetector _sd;
+  private List<IDetectorElement> _detElts;
+  
+  private int _nDisks;
+  private int _nLayers;
+  private double[] _radiusInner;
+  private double[] _radiusOuter;
+  private double[] _z;
+  private double[] _stripLength;
+  private double[] _stripWidth;
+  
+  private IRotation3D _rot1;
+  private ConstHep3Vector _u1, _v1;
+}

lcsim-contrib/src/main/java/org/lcsim/contrib/onoprien/geom/tracker/lib/segmenter
DiskTrackerToWedgesSegmenter.java added at 1.1
diff -N DiskTrackerToWedgesSegmenter.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ DiskTrackerToWedgesSegmenter.java	8 Jul 2009 15:59:41 -0000	1.1
@@ -0,0 +1,155 @@
+package org.lcsim.contrib.onoprien.geom.tracker.lib.segmenter;
+
+import java.util.*;
+
+import org.lcsim.detector.IDetectorElement;
+import org.lcsim.detector.IGeometryInfo;
+import org.lcsim.detector.IPhysicalVolume;
+import org.lcsim.detector.solids.Tube;
+
+import org.lcsim.contrib.onoprien.geom.tracker.AbstractSegmenter;
+
+/**
+ *
+ *
+ * @author D. Onoprienko
+ * @version $Id: DiskTrackerToWedgesSegmenter.java,v 1.1 2009/07/08 15:59:41 onoprien Exp $
+ */
+public class DiskTrackerToWedgesSegmenter extends DiskTrackerSegmenter {
+  
+// -- Constructors :  ----------------------------------------------------------
+  
+  public DiskTrackerToWedgesSegmenter(String subdetectorName) {
+    super(subdetectorName);
+  }
+  
+// -- Implementing DiskTrackerSegmenter :  -------------------------------------
+  
+  /**
+   * Return <tt>Segmenter</tt> that handles hits in the given <tt>DetectorElement</tt>.
+   */
+  public AbstractSegmenter assignSegmenter(IDetectorElement de) {
+    
+    checkGeometry();
+    
+    int nRadialSlices;
+    if (_radialSlicesBySuperlayer == null) {
+      IGeometryInfo gInfo = de.getGeometry();
+      Tube solid = (Tube) gInfo.getLogicalVolume().getSolid();
+      double radiusInner = solid.getInnerRadius();
+      double radiusOuter = solid.getOuterRadius();
+      nRadialSlices = (int)Math.round((radiusOuter - radiusInner)/_stripLength);
+    } else {
+      nRadialSlices = _radialSlicesBySuperlayer[getSuperlayer(de)];
+    }
+    
+    int nPhiSlices;
+    if (_phiSlicesBySuperlayer == null) {
+      nPhiSlices = _phiSlices;
+    } else {
+      nPhiSlices = _phiSlicesBySuperlayer[getSuperlayer(de)];
+    }
+   
+    double pitch;
+    if (_pitchBySuperlayer == null) {
+      pitch = _pitch;
+    } else {
+      pitch = _pitchBySuperlayer[getSuperlayer(de)];
+    }
+    
+    boolean left = isInner(de);
+    
+    return new DiskToWedgesSegmenter(_sd, de, nRadialSlices, nPhiSlices, pitch, left);
+  }
+
+// -- Stereo partners :  -------------------------------------------------------
+  
+  /**
+   * Returns a list of <tt>Sensors</tt> that might contain hits that should be combined
+   * with hits in the <tt>Sensor</tt> whose <tt>sensorID</tt> is supplied as an argument
+   * to form stereo pairs. 
+   */
+  public List<Integer> getStereoPartners(int sensorID) {
+    int partnerDisk = getOtherSideIndex(idToDaughterIndex(sensorID));
+    List<Integer> out = new ArrayList<Integer>(1);
+    out.add((partnerDisk << _daughterPostfixLength) | (sensorID & ~_daughterIdMask));
+    return out;
+  }
+
+// -- Setters :  ---------------------------------------------------------------
+  
+  /**
+   * Set strip length.
+   * The actual strip length in each disk will be adjusted to create an integral
+   * number of radial slices.
+   */
+  public void setStripLength(double length) {
+    _radialSlicesBySuperlayer = null;
+    _stripLength = length;
+  }
+  
+  /**
+   * Set the number of radial slices in each superlayer.
+   */
+  public void setNumberOfRadialSlices(int[] nRadialSlices) {
+    //_radialSlicesBySuperlayer = Arrays.copyOf(nRadialSlices, nRadialSlices.length); // Need JDK 1.6
+    _radialSlicesBySuperlayer = nRadialSlices;
+  }
+  
+  /**
+   * Set the number of axial slices in all superlayers.
+   */
+  public void setNumberOfPhiSlices(int nPhiSlices) {
+    _phiSlicesBySuperlayer = null;
+    _phiSlices = nPhiSlices;
+  }
+  
+  /**
+   * Set the number of axial slices in each superlayer.
+   */
+  public void setNumberOfPhiSlices(int[] nPhiSlices) {
+    //_phiSlicesBySuperlayer = Arrays.copyOf(nPhiSlices, nPhiSlices.length); // Need JDK 1.6
+    _phiSlicesBySuperlayer = nPhiSlices;
+  }
+  
+  /**
+   * Set the strip width in all superlayers.
+   */
+  public void setStripWidth(double pitch) {
+    _pitchBySuperlayer = null;
+    _pitch = pitch;
+  }
+  
+  /**
+   * Set the strip width in each superlayer.
+   */
+  public void setStripWidth(double[] pitch) {
+    //_pitchBySuperlayer = Arrays.copyOf(pitch, pitch.length); // Need JDK 1.6
+    _pitchBySuperlayer = pitch;
+  }
+  
+// -- Helpers :  ---------------------------------------------------------------
+  
+  protected void checkGeometry() {
+    int nDisks = _dElements.size()/4;
+    String m1 = "Disk tracker "+_subdName +" contains "+nDisks +" disks in each endcap, but you only supplied ";
+    if (_radialSlicesBySuperlayer != null && _radialSlicesBySuperlayer.length < nDisks ) {
+      throw new RuntimeException(m1 + "number of radial slices for " + _radialSlicesBySuperlayer.length + " superlayers");
+    } else if (_phiSlicesBySuperlayer != null && _phiSlicesBySuperlayer.length < nDisks ) {
+      throw new RuntimeException(m1 + "number of phi slices for " + _radialSlicesBySuperlayer.length + " superlayers");
+    } else if (_pitchBySuperlayer != null && _pitchBySuperlayer.length < nDisks ) {
+      throw new RuntimeException(m1 + "strip widths for " + _radialSlicesBySuperlayer.length + " superlayers");
+    }
+  }
+    
+// -- Private parts :  ---------------------------------------------------------
+  
+  double _stripLength;
+  int[] _radialSlicesBySuperlayer;
+
+  int _phiSlices;
+  int[] _phiSlicesBySuperlayer;
+  
+  double _pitch;
+  double[] _pitchBySuperlayer;
+}

lcsim-contrib/src/main/java/org/lcsim/contrib/onoprien/geom/tracker/lib/segmenter
SubdetectorBasedSegmenter.java added at 1.1
diff -N SubdetectorBasedSegmenter.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ SubdetectorBasedSegmenter.java	8 Jul 2009 15:59:41 -0000	1.1
@@ -0,0 +1,80 @@
+package org.lcsim.contrib.onoprien.geom.tracker.lib.segmenter;
+
+import java.util.*;
+
+import org.lcsim.geometry.Detector;
+import org.lcsim.geometry.Subdetector;
+import org.lcsim.event.SimTrackerHit;
+
+import org.lcsim.contrib.onoprien.geom.tracker.AbstractSegmenter;
+import org.lcsim.contrib.onoprien.geom.tracker.ForwardingSegmenter;
+import org.lcsim.contrib.onoprien.geom.tracker.SegmentationManager;
+import org.lcsim.contrib.onoprien.geom.tracker.Sensor;
+
+/**
+ * <tt>Segmenter</tt> that forwards <tt>postfix</tt> and {@link Sensor} creation calls 
+ * to daughter Segmenters based on subdetector where the hit occured.
+ * 
+ * 
+ * @author D.Onoprienko
+ * @version $Id: SubdetectorBasedSegmenter.java,v 1.1 2009/07/08 15:59:41 onoprien Exp $
+ */
+public class SubdetectorBasedSegmenter extends ForwardingSegmenter {
+  
+// -- Constructors and initialization :  ---------------------------------------
+  
+  /** Create an instance of <tt>SubdetectorBasedSegmenter</tt>. */
+  public SubdetectorBasedSegmenter() {
+    _subdetectorNames = new ArrayList<String>();
+    _segmenters = new ArrayList<AbstractSegmenter>();
+  }
+  
+  /** 
+   * Detector dependent initialization.
+   */
+  public void detectorChanged(Detector detector) {
+    _subdetectorNames.trimToSize();
+    _segmenters.trimToSize();
+    _sdToSegmenter = new HashMap<Subdetector, AbstractSegmenter>();
+    removeAllDaughterSegmenters();
+    for (int i=0; i<_segmenters.size(); i++) {
+      String name = _subdetectorNames.get(i);
+      Subdetector subDet = detector.getSubdetector(name);
+      if (subDet != null) {
+        AbstractSegmenter segmenter = _segmenters.get(i);
+        _sdToSegmenter.put(subDet, segmenter);
+        addDaughterSegmenter(segmenter);
+      }
+    }
+    super.detectorChanged(detector);
+    //updateDaughterSegmenters(detector);
+  }
+  
+// -- Setters :  ---------------------------------------------------------------
+
+  /** 
+   * Set segmenter that will handle a particular subdetector.
+   *
+   * @param subdetectorName  Name of the subdetector to be handled by the supplied <tt>Segmenter</tt>
+   * @param segmenter        <tt>Segmenter</tt> to be used
+   */
+  public void setSegmenter(String subdetectorName, AbstractSegmenter segmenter) {
+    _subdetectorNames.add(subdetectorName);
+    _segmenters.add(segmenter);
+  }
+  
+// -- Choosing Segmenter :  ----------------------------------------------------
+  
+  /**
+   * Returns daughter <tt>Segmenter</tt> that can handle the given hit.
+   */
+  public AbstractSegmenter chooseSegmenter(SimTrackerHit hit) {
+    return _sdToSegmenter.get(hit.getSubdetector());
+  }
+  
+// -- Private parts :  ---------------------------------------------------------
+  
+  private ArrayList<String> _subdetectorNames;
+  private ArrayList<AbstractSegmenter> _segmenters;
+  private HashMap<Subdetector, AbstractSegmenter> _sdToSegmenter;
+}

lcsim-contrib/src/main/java/org/lcsim/contrib/onoprien/geom/tracker/lib/segmenter
package-info.java added at 1.1
diff -N package-info.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ package-info.java	8 Jul 2009 15:59:41 -0000	1.1
@@ -0,0 +1,4 @@
+/**
+ * Library of classes implementing {@link org.lcsim.contrib.onoprien.geom.tracker.Segmenter} interface.
+ */
+package org.lcsim.contrib.onoprien.geom.tracker.lib.segmenter;

lcsim-contrib/src/main/java/org/lcsim/contrib/onoprien/geom/tracker/lib/sensortype
Cylinder.java added at 1.1
diff -N Cylinder.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Cylinder.java	8 Jul 2009 15:59:41 -0000	1.1
@@ -0,0 +1,125 @@
+package org.lcsim.contrib.onoprien.geom.tracker.lib.sensortype;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import hep.physics.vec.BasicHep3Vector;
+import hep.physics.vec.Hep3Vector;
+
+import org.lcsim.contrib.onoprien.geom.tracker.SensorType;
+import org.lcsim.contrib.onoprien.data.ITrackerHit;
+import org.lcsim.contrib.onoprien.util.vector.ConstHep3Vector;
+import org.lcsim.contrib.onoprien.util.transform.IRefFrame;
+import org.lcsim.contrib.onoprien.util.transform.RefFrameCylinder;
+import org.lcsim.contrib.onoprien.util.transform.RefFrameLocalOnCylinder;
+
+/**
+ * This class represents a cylindrical sensor with pixels or strips parallel to its axis.
+ * <p>
+ * The reference frame is (U,V,W = R0*Phi,Z,R-R0), where R0 is the reference surface
+ * radius supplied to the constructor.
+ * 
+ * 
+ * @author D.Onoprienko
+ * @version $Id: Cylinder.java,v 1.1 2009/07/08 15:59:41 onoprien Exp $
+ */
+public class Cylinder extends Rectangle {
+  
+// -- Constructors :  ----------------------------------------------------------
+  
+  /**
+   * Create <tt>Cylinder</tt> instance.
+   * The <tt>center</tt> parameter controls offsets in the local reference frame.
+   *
+   * @param length      Length of the cylinder (along strip direction).
+   * @param radius      Radius of the cylinder (average between inner and outer redii).
+   * @param nLength     Number of divisions along the cylinder length.
+   * @param nPhi        Number of divisions in phi.
+   */
+  public Cylinder(double radius, double length, int nPhi, int nLength) {
+    super(2.*Math.PI*radius, length, nPhi, nLength);
+  }
+  
+  /**
+   * Create <tt>Cylinder</tt> instance.
+   * Strip width will be adjusted to make sure integral number of strips fits the 
+   * circumference of the cylinder.
+   *
+   * @param length       Length of the cylinder (along strip direction).
+   * @param radius       Radius of the cylinder.
+   * @param stripPitch   Strip width.
+   * @param stripLength  Strip length.
+   */
+  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));
+  }
+
+// -----------------------------------------------------------------------------
+
+  /**
+   * Converts a point in local sensor coordinates to channel ID.
+   * Returns -1 if the point is outside of sensor sensitive area.
+   */
+  public int getChannelID(Hep3Vector point) {
+
+    double u = point.x();
+    double v = point.y();
+
+    int nV = (int) Math.floor((v-_vLow)/_length);
+    if ((nV < 0) || (nV >= _nDivV)) return -1;
+
+    int nU = (int) Math.floor((u-_uLow)/_pitch); 
+    while (nU < 0) nU += _nDivU;
+    while (nU >= _nDivU) nU -= _nDivU;
+
+    return nV*_nDivU + nU;
+  }
+  
+  /**
+   * Returns local cartesian reference frame at the specified position in local sensor coordinates.
+   */
+  public IRefFrame getLocalFrame(IRefFrame sensorFrame, Hep3Vector position) {
+    return new RefFrameLocalOnCylinder((RefFrameCylinder)sensorFrame, position);
+  }
+  
+  /**
+   * Returns channel ID of a neighbor channel.
+   * Returns -1 if the channel defined by shifts does not exist on this sensor.
+   *
+   * @param channelID  ID of the original channel
+   * @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 shiftW) {
+    int nV = (channelID / _nDivU) + shiftV;
+    if (nV < 0 || nV >= _nDivV || shiftW != 0) return -1;
+    int nU = (channelID % _nDivU) + shiftU;
+    while (nU < 0) nU += _nDivU;
+    while (nU >= _nDivU) nU -= _nDivU;
+    return nV*_nDivU + nU;
+  }
+  
+  /** 
+   * Returns array of IDs of all immediate neighbor channels. 
+   * For strips ({@link #getHitDimension()} returns 1), this method looks for neighbors
+   * in U direction only. Therefore, each strip has 1 or 2 neighbors. For pixels
+   * ({@link #getHitDimension()} returns 2), up to 8 neighbors can be found.
+   */
+  public List<Integer> getNeighbors(int channelID) {
+    int nU = channelID % _nDivU;
+    int nV = channelID / _nDivU;
+    ArrayList<Integer> out = new ArrayList<Integer>(8);
+    int vDown = ((_hitType.nMeasured() == 2) && (nV > 0)) ? nV-1 : nV;
+    int vUp = ((_hitType.nMeasured() == 2) && (nV < _nDivV-1)) ? nV+1 : nV;
+    for (int iV = vDown; iV < vUp; iV++) {
+      for (int iU = nU-1; iU < nU+1; iU++) {
+        while (nU < 0) nU += _nDivU;
+        while (nU >= _nDivU) nU -= _nDivU;
+        out.add(nV*_nDivU + nU);
+      }
+    }
+    return out;
+  }
+
+}

lcsim-contrib/src/main/java/org/lcsim/contrib/onoprien/geom/tracker/lib/sensortype
Hexagon.java added at 1.1
diff -N Hexagon.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Hexagon.java	8 Jul 2009 15:59:41 -0000	1.1
@@ -0,0 +1,149 @@
+package org.lcsim.contrib.onoprien.geom.tracker.lib.sensortype;
+
+import java.util.*;
+
+import hep.physics.vec.BasicHep3Vector;
+import hep.physics.vec.Hep3Vector;
+
+import org.lcsim.contrib.onoprien.geom.tracker.SensorType;
+import org.lcsim.contrib.onoprien.data.ITrackerHit;
+import org.lcsim.contrib.onoprien.util.vector.ConstHep3Vector;
+import org.lcsim.contrib.onoprien.util.transform.IRefFrame;
+
+/**
+ * This class represents a hexagonal sensor with strips parallel to its side.
+ * The reference frame origin is at the center of the sensor.
+ * <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: Hexagon.java,v 1.1 2009/07/08 15:59:41 onoprien Exp $
+ */
+public class Hexagon implements SensorType {
+  
+// -- Constructors :  ----------------------------------------------------------
+  
+  /**
+   * Create <tt>Hexagon</tt> instance.
+   *
+   * @param sideLength      Length of the hexagon side.
+   * @param nU              Number of divisions along U (measurement direction, perpendicular to strips).
+   */
+  public Hexagon(double sideLength, int nU) {
+    _side = sideLength;
+    _halfWidth = sideLength*COSPI6;
+    _nDivU = nU;
+    _pitch = (2.*_halfWidth)/nU;
+  }
+
+// -----------------------------------------------------------------------------
+
+  /**
+   * Converts a point in local sensor coordinates to channel ID.
+   * Returns -1 if the point is outside of sensor sensitive area.
+   */
+  public int getChannelID(Hep3Vector point) {
+    
+//    if (Math.abs(point.z()) > _halfThick) return -1;
+
+    double u = point.x();
+    double v = point.y();
+    if (Math.abs(u) > _halfWidth || Math.abs(v) > _side - Math.abs(u)*TANPI6) return -1;
+    
+    int nU = (int) Math.floor((u+_halfWidth)/_pitch); if (nU == _nDivU) nU--;
+    return nU;
+  }
+  
+  /**
+   * Returns position of the center of the given channel, in local sensor coordinates.
+   */
+  public Hep3Vector getChannelPosition(int channelID) {
+    double u = (channelID + .5) * _pitch - _halfWidth;
+    return new BasicHep3Vector(u,0.,0.);
+  }
+
+  /** Returns maximum possible channel ID on this sensor. */
+  public int getMaxChannelID() {
+    return  _nDivU - 1;
+  }
+  
+  /** Returns <tt>true</tt> if channel with this ID exists on this sensor. */
+  public boolean isValidChannelID(int channelID) {
+    return channelID > -1 && channelID < _nDivU;
+  }
+  
+  /**
+   * Returns dimensions of the given channel along U, V, W.
+   */
+  public Hep3Vector getChannelDimensions(int channelID) {
+    double u = (channelID + .5) * _pitch - _halfWidth;
+    double stripLength = 2.* (_side - Math.abs(u)*TANPI6);
+    return new BasicHep3Vector(_pitch, stripLength, 0.);
+  }
+  
+  
+  /**
+   * Returns the dimension of a measurement by this type of sensor (<tt>STRIP</tt> since 
+   * <tt>WedgeSideParallel</tt> is always tiled with strips).
+   */
+  public ITrackerHit.Type getHitType() {return ITrackerHit.Type.STRIP;}
+  
+  /**
+   * 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;
+  }
+  
+  /**
+   * Returns channel ID of a neighbor channel.
+   * Returns -1 if the channel defined by shifts does not exist on this sensor.
+   *
+   * @param channelID  ID of the original channel
+   * @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 shiftW) {
+    int nU = channelID + shiftU;
+    return (nU < 0 || nU >= _nDivU || shiftV != 0 || shiftW != 0) ? -1 : nU ;
+  }
+  
+  /** Returns array of IDs of all immediate neighbor channels. */
+  public List<Integer> getNeighbors(int channelID) {
+    ArrayList<Integer> out = new ArrayList<Integer>(2);
+    if (channelID > 0) out.add(channelID - 1);
+    if (channelID < (_nDivU - 1)) out.add(channelID + 1);
+    return out;
+  }
+  
+  /**
+   * Returns a list of vectors that correspond to corners of the sensor, in sensor reference frame.
+   * Useful for drawing sensors and event display.
+   */
+  public List<Hep3Vector> getCorners() {
+    double a = _side/2.;
+    double b = _side/Math.sqrt(2.);
+    return Arrays.asList(new Hep3Vector[]{new ConstHep3Vector(-b,   -a, 0.),
+                                          new ConstHep3Vector(-b,    a, 0.),
+                                          new ConstHep3Vector(0.,  a+b, 0.),
+                                          new ConstHep3Vector( b,    a, 0.),
+                                          new ConstHep3Vector( b,   -a, 0.),
+                                          new ConstHep3Vector(0., -a-b, 0.)});
+  }
+
+// -- Private parts :  ---------------------------------------------------------
+  
+  protected double _side;
+  protected double _halfWidth;
+  
+  protected double _pitch;
+  
+  protected int _nDivU;
+  
+  protected final double COSPI6 = Math.sqrt(3.)/2.;
+  protected final double TANPI6 = 1./Math.sqrt(3.);
+}

lcsim-contrib/src/main/java/org/lcsim/contrib/onoprien/geom/tracker/lib/sensortype
Rectangle.java added at 1.1
diff -N Rectangle.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Rectangle.java	8 Jul 2009 15:59:41 -0000	1.1
@@ -0,0 +1,290 @@
+package org.lcsim.contrib.onoprien.geom.tracker.lib.sensortype;
+
+import java.util.*;
+
+import hep.physics.vec.BasicHep3Vector;
+import hep.physics.vec.Hep3Vector;
+
+import org.lcsim.contrib.onoprien.geom.tracker.SensorType;
+import org.lcsim.contrib.onoprien.data.ITrackerHit;
+import org.lcsim.contrib.onoprien.util.vector.ConstHep3Vector;
+import org.lcsim.contrib.onoprien.util.transform.IRefFrame;
+
+/**
+ * This class represents a rectangular sensor with rectangular strips or pixel 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: Rectangle.java,v 1.1 2009/07/08 15:59:41 onoprien Exp $
+ */
+public class Rectangle implements SensorType {
+  
+// -- Constructors :  ----------------------------------------------------------
+  
+  /** Default constructor for use by subclusses. No initialization. */
+  public Rectangle() {}
+  
+  /**
+   * Create an instance of <tt>Rectangle</tt>.
+   * The <tt>center</tt> parameter controls how the local reference frame origin
+   * is positioned with respect to the cuboid defining the sensor volume.
+   *
+   * @param width       Width of the sensor.
+   * @param length      Length of the sensor (along strip direction).
+   * @param nWidth      Number of divisions across the sensor width.
+   * @param nLength     Number of divisions along the sensor length.
+   * @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, int nWidth, int nLength, double centerU, double centerV) {
+    if (nLength == 0) nLength = 1;
+    _uLow = centerU - width/2.;
+    _vLow = centerV - length/2.;
+    _pitch = width/nWidth;
+    _length = length/nLength;
+    _hitType = (_length/_pitch < 4.) ? ITrackerHit.Type.PIXEL : ITrackerHit.Type.STRIP;
+    _nDivV = nLength;
+    _nDivU = nWidth;
+  }
+  
+  /**
+   * Create <tt>Rectangle</tt> instance.
+   * 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 nWidth      Number of divisions across the sensor width.
+   * @param nLength     Number of divisions along the sensor length.
+   */
+  public Rectangle(double width, double length, int nWidth, int nLength) {
+    this(width, length, nWidth, nLength, 0.,0.);
+  }
+  
+  /**
+   * Create <tt>Rectangle</tt> instance.
+   * The <tt>center</tt> parameter controls how the local reference frame origin
+   * is positioned with respect to the cuboid defining the sensor volume.
+   * 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 stripPitch  Strip width.
+   * @param nLength     Number of divisions along the sensor length.
+   * @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 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 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 stripPitch  Strip width.
+   * @param nLength     Number of divisions along the sensor length.
+   */
+  public Rectangle(double width, double length, double stripPitch, int nLength) {
+    this(width, length, (int)Math.round(width/stripPitch), nLength, 0.,0.);
+  }
+  
+  /**
+   * Create <tt>Rectangle</tt> instance.
+   * The <tt>center</tt> parameter controls how the local reference frame origin
+   * is positioned with respect to the cuboid defining the sensor volume.
+   * 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 nWidth        Number of divisions across the sensor width.
+   * @param stripLength   Strip length.
+   * @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, 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 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 nWidth        Number of divisions across the sensor width.
+   * @param stripLength   Strip length.
+   */
+  public Rectangle(double width, double length, int nWidth, double stripLength) {
+    this(width, length, nWidth, (int)Math.round(length/stripLength), 0.,0.);
+  }
+  
+  /**
+   * Create <tt>Rectangle</tt> instance.
+   * The <tt>center</tt> parameter controls how the local reference frame origin
+   * is positioned with respect to the cuboid defining the sensor volume.
+   * 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 stripPitch    Strip width.
+   * @param stripLength   Strip length.
+   * @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 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 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 stripPitch    Strip width.
+   * @param stripLength   Strip length.
+   */
+  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 :  ---------------------------------------------------------------
+  
+  /**
+   * Set the dimension of a measurement by this type of sensor (1 for strips, 2 for pixels, etc).
+   */
+  public void setHitType(ITrackerHit.Type hitType) {
+    _hitType = hitType;
+  }
+    
+// -----------------------------------------------------------------------------
+
+  /**
+   * Converts a point in local sensor coordinates to channel ID.
+   * Returns -1 if the point is outside of sensor sensitive area.
+   */
+  public int getChannelID(Hep3Vector point) {
+
+    double u = point.x();
+    double v = point.y();
+    
+    int nU = (int) Math.floor((u-_uLow)/_pitch); 
+    if ((nU < 0) || (nU >= _nDivU)) return -1;
+    int nV = (int) Math.floor((v-_vLow)/_length);
+    if ((nV < 0) || (nV >= _nDivV)) return -1;
+    return nV*_nDivU + nU;
+  }
+  
+  /**
+   * Returns position of the center of the given channel, in local sensor coordinates.
+   */
+  public Hep3Vector getChannelPosition(int channelID) {
+    int nU = channelID % _nDivU;
+    int nV = channelID / _nDivU;
+    double u = (nU + .5) * _pitch + _uLow;
+    double v = (nV + .5) * _length + _vLow;
+    return new BasicHep3Vector(u,v,0.);
+  }
+
+  /** Returns maximum possible channel ID on this sensor. */
+  public int getMaxChannelID() {
+    return  _nDivU * _nDivV - 1;
+  }
+  
+  /** Returns <tt>true</tt> if channel with this ID exists on this sensor. */
+  public boolean isValidChannelID(int channelID) {
+    return channelID > -1 && channelID < (_nDivU * _nDivV);
+  }
+  
+  /**
+   * Returns dimensions of the given channel along U, V, W.
+   */
+  public Hep3Vector getChannelDimensions(int channelID) {
+    return new BasicHep3Vector(_pitch, _length, 0.);
+  }
+  
+  
+  /**
+   * Returns the type of hits produced by this type of sensor.
+   */
+  public ITrackerHit.Type getHitType() {
+    return _hitType;
+  }
+  
+  /**
+   * 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;
+  }
+  
+  /**
+   * Returns channel ID of a neighbor channel.
+   * Returns -1 if the channel defined by shifts does not exist on this sensor.
+   *
+   * @param channelID  ID of the original channel
+   * @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 shiftW) {
+    if (shiftW != 0) return -1;
+    int nU = (channelID % _nDivU) + shiftU;
+    if ((nU < 0) || (nU >= _nDivU)) return -1;
+    int nV = (channelID / _nDivU) + shiftV;
+    if ((nV < 0) || (nV >= _nDivV)) return -1;
+    return nV*_nDivU + nU;
+  }
+  
+  /** Returns array of IDs of all immediate neighbor channels. */
+  public List<Integer> getNeighbors(int channelID) {
+    int nU = channelID % _nDivU;
+    int nV = channelID / _nDivU;
+    ArrayList<Integer> out = new ArrayList<Integer>(8);
+    int vDown = ((_hitType.nMeasured() == 2) && (nV > 0)) ? nV-1 : nV;
+    int vUp = ((_hitType.nMeasured() == 2) && (nV < _nDivV-1)) ? nV+1 : nV;
+    int uDown = (nU > 0) ? nU-1 : nU;
+    int uUp = (nU < _nDivU-1) ? nU+1 : nU;
+    for (int iV = vDown; iV < vUp; iV++) {
+      for (int iU = uDown; iU < uUp; iU++) {
+        out.add(nV*_nDivU + nU);
+      }
+    }
+    return out;
+  }
+  
+  /**
+   * Returns a list of vectors that correspond to corners of the sensor, in sensor reference frame.
+   * Useful for drawing sensors and event display.
+   */
+  public List<Hep3Vector> getCorners() {
+    double uHigh = _uLow + _pitch*_nDivU;
+    double vHigh = _vLow + _length*_nDivV;
+    return Arrays.asList(new Hep3Vector[]{new ConstHep3Vector(_uLow, _vLow, 0.),
+                                          new ConstHep3Vector(_uLow, vHigh, 0.),
+                                          new ConstHep3Vector(uHigh, vHigh, 0.),
+                                          new ConstHep3Vector(uHigh, _vLow, 0.)});
+  }
+  
+// -- Private parts :  ---------------------------------------------------------
+  
+  protected double _uLow;
+  protected double _vLow;
+  
+  protected double _pitch;
+  protected double _length;
+  
+  protected ITrackerHit.Type _hitType;
+  
+  protected int _nDivU;
+  protected int _nDivV;
+}

lcsim-contrib/src/main/java/org/lcsim/contrib/onoprien/geom/tracker/lib/sensortype
Ring.java added at 1.1
diff -N Ring.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Ring.java	8 Jul 2009 15:59:41 -0000	1.1
@@ -0,0 +1,101 @@
+package org.lcsim.contrib.onoprien.geom.tracker.lib.sensortype;
+
+import java.util.*;
+
+import hep.physics.vec.BasicHep3Vector;
+import hep.physics.vec.Hep3Vector;
+
+import org.lcsim.contrib.onoprien.util.vector.ConstHep3Vector;
+
+/**
+ * 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. 
+ * <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 channel (strip or pixel) to which the point belongs is ouside the ring.
+ *
+ * @author D.Onoprienko
+ * @version $Id: Ring.java,v 1.1 2009/07/08 15:59:41 onoprien Exp $
+ */
+public class Ring extends Rectangle {
+  
+// -- Constructors :  ----------------------------------------------------------
+  
+  /**
+   * Create <tt>Ring</tt> instance.
+   *
+   * @param radiusMin   Inside radius of the ring.
+   * @param radiusMax   Outside radius of the ring.
+   * @param pitch       Width of a strip.
+   * @param length      Length of a strip.
+   */
+  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;
+  }
+  
+// -----------------------------------------------------------------------------
+
+  /**
+   * Converts a point in local sensor coordinates to channel ID.
+   * Returns -1 if the point is outside of sensor sensitive area.
+   */
+  public int getChannelID(Hep3Vector point) {
+    int channel = super.getChannelID(point);
+    return isValidChannelID(channel) ? channel : -1;
+  }
+  
+  /**
+   * Returns channel ID of a neighbor channel.
+   * Returns -1 if the channel defined by shifts does not exist on this sensor.
+   *
+   * @param channelID  ID of the original channel
+   * @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 shiftW) {
+    int neighbor = super.getNeighbor(channelID, shiftU, shiftV, shiftW);
+    return isValidChannelID(neighbor) ? neighbor : -1;
+  }
+  
+  /** 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());
+    for (int neighbor : raw) {
+      if (isValidChannelID(neighbor)) out.add(neighbor);
+    }
+    return out;
+  }
+
+  /**
+   * Returns <tt>true</tt> if the center of the channel is inside the ring.
+   */
+  public boolean isValidChannelID(int channelID) {
+    if (!super.isValidChannelID(channelID)) return false;
+    double r = getChannelPosition(channelID).magnitude();
+    return r > _rMin && r < _rMax;
+  }
+  
+  /**
+   * Returns a list of vectors that correspond to corners of the sensor, in sensor reference frame.
+   * Useful for drawing sensors and event display.
+   */
+  public List<Hep3Vector> getCorners() {
+    return Arrays.asList(new Hep3Vector[]{new ConstHep3Vector(-_rMax,-_rMax,0.),
+                                          new ConstHep3Vector(-_rMax,_rMax,0.),
+                                          new ConstHep3Vector(_rMax,_rMax,0.),
+                                          new ConstHep3Vector(_rMax,-_rMax,0.)});
+  }
+
+// -- Private parts :  ---------------------------------------------------------
+  
+  protected double _rMin;
+  protected double _rMax;
+}

lcsim-contrib/src/main/java/org/lcsim/contrib/onoprien/geom/tracker/lib/sensortype
WedgeSideParallel.java added at 1.1
diff -N WedgeSideParallel.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ WedgeSideParallel.java	8 Jul 2009 15:59:41 -0000	1.1
@@ -0,0 +1,191 @@
+package org.lcsim.contrib.onoprien.geom.tracker.lib.sensortype;
+
+import java.util.*;
+
+import hep.physics.vec.BasicHep3Vector;
+import hep.physics.vec.Hep3Vector;
+
+import org.lcsim.contrib.onoprien.geom.tracker.SensorType;
+import org.lcsim.contrib.onoprien.data.ITrackerHit;
+import org.lcsim.contrib.onoprien.util.vector.ConstHep3Vector;
+import org.lcsim.contrib.onoprien.util.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 2009/07/08 15:59:41 onoprien Exp $
+ */
+public class WedgeSideParallel implements SensorType {
+  
+// -- Constructors :  ----------------------------------------------------------
+  
+  public WedgeSideParallel(boolean left, double shortBase, double longBase, double angle, double pitch) {
+    _left = left;
+    _pitch = pitch;
+    _tan = Math.tan(angle/2.);
+    _cotan2 = 1./Math.tan(angle);
+    _side = ((longBase - shortBase)/2.)/Math.sin(angle/2.);
+    _maxID = (int) Math.floor((longBase * Math.cos(angle/2.))/pitch);
+    _uCorner = shortBase * Math.cos(angle/2.);
+    _offset = (left) ? 0. : (_maxID * pitch) - _uCorner;
+    _vConst = - (shortBase/2.) / Math.sin(angle/2.);
+    
+  }
+
+  public WedgeSideParallel(double rMin, double side, double angle, double pitch, boolean left) {
+    _left = left;
+    _side = side;
+    _tan = Math.tan(angle/2.);
+    _cotan2 = 1./Math.tan(angle);
+    _pitch = pitch;
+    _maxID = (int) Math.floor(((rMin+side)*Math.sin(angle))/pitch);
+    _uCorner = rMin * Math.sin(angle);
+    _offset = (left) ? 0. : (_maxID * pitch) - _uCorner;
+    _vConst = - rMin;
+  }
+// -----------------------------------------------------------------------------
+
+  /**
+   * Converts a point in local sensor coordinates to channel ID.
+   * Returns -1 if the point is outside of sensor sensitive area.
+   */
+  public int getChannelID(Hep3Vector point) {
+    double u = point.x();
+    int channel = (int) Math.floor((u + _offset) / _pitch);
+    return ((channel < 0) || (channel > _maxID)) ? -1 : channel;
+  }
+  
+  /**
+   * Returns position of the center of a given channel, in local sensor coordinates.
+   */
+  public Hep3Vector getChannelPosition(int channelID) {
+    double u = ((channelID + .5) * _pitch) - _offset;
+    double v;
+    if (_left) {
+      if (u < _uCorner) {
+        v = _side/2. - u * _tan;
+      } else {
+        v = ((_side - u * _tan) + (u * _cotan2 + _vConst) )/2.;
+      }
+    } else {
+      if (u < 0.) {
+        v = (_side + u * _tan - u * _cotan2 )/2.;
+      } else {
+        v = _side/2. + u * _tan;
+      }
+    }
+    return new BasicHep3Vector(u,v,0.);
+  }
+  
+  /** Returns maximum channel ID on this sensor. */
+  public int getMaxChannelID() {
+    return _maxID;
+  }
+  
+  /** Returns <tt>true</tt> if channel with this ID exists on this sensor. */
+  public boolean isValidChannelID(int channelID) {
+    return channelID > -1 && channelID <= _maxID;
+  }
+  
+  /** Returns dimensions of a given channel along U, V, W. */
+  public Hep3Vector getChannelDimensions(int channelID) {
+    double u = ((channelID + .5) * _pitch) - _offset;
+    double length;
+    if (_left) {
+      if (u < _uCorner) {
+        length = _side;
+      } else {
+        length = (_side - u * _tan) - (u * _cotan2 + _vConst);
+      }
+    } else {
+      if (u < 0.) {
+        length = (_side + u * _tan) + u * _cotan2 ;
+      } else {
+        length = _side;
+      }
+    }
+    return new BasicHep3Vector(_pitch, length, 0.);
+  }
+  
+  /**
+   * Returns the dimension of a measurement by this type of sensor (<tt>STRIP</tt> since 
+   * <tt>WedgeSideParallel</tt> is always tiled with strips).
+   */
+  public ITrackerHit.Type getHitType() {return ITrackerHit.Type.STRIP;}
+  
+  /**
+   * 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;
+  }
+  
+  /**
+   * Returns ID of a channel obtained by shifting the given channel by the given
+   * number of channels in the given direction along the local reference frame axis. 
+   * Returns <tt>-1</tt> if shifting puts the point outside of the sensor boundaries.
+   * Throws <tt>IllegalArgumentException</tt> if this type of sensor does not have a
+   * concept of a neighbor in the given direction. 
+   *
+   * @param channelID  ID of the original channel
+   * @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, int shiftW) {
+    if (shiftV != 0 || shiftW != 0) return -1;
+    int channel = channelID + shiftU;
+    return ((channel < 0) || (channel > _maxID)) ? -1 : channel;
+  }
+  
+  /**
+   * Returns array of IDs of all immediate neighbor channels.
+   */
+  public List<Integer> getNeighbors(int channelID) {
+    ArrayList<Integer> out = new ArrayList<Integer>(2);
+    if (channelID > 0) out.add(channelID - 1);
+    if (channelID < _maxID) out.add(channelID + 1);
+    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 List<Hep3Vector> getCorners() {
+    ArrayList<Hep3Vector> out = new ArrayList<Hep3Vector>(4);
+    out.add(ConstHep3Vector.V000);
+    if (_left) {
+      out.add(new ConstHep3Vector(0.,_side,0.));
+      double u = (_side - _vConst) * Math.sin(2.*Math.atan(_tan));
+      out.add(new ConstHep3Vector(u, _side - u * _tan, 0.));
+      out.add(new ConstHep3Vector(_uCorner, - _uCorner * _tan, 0.));
+    } else {;
+      double u = - _side * Math.sin(2.*Math.atan(_tan));
+      out.add(new ConstHep3Vector(u, - u * _cotan2, 0.));
+      out.add(new ConstHep3Vector(_uCorner, _side + _uCorner * _tan, 0.));
+      out.add(new ConstHep3Vector(_uCorner, _uCorner * _tan, 0.));
+    }
+    return out;
+  }
+  
+// -- Private parts :  ---------------------------------------------------------
+  
+  private boolean _left;
+  
+  private int _maxID;
+  private double _offset;
+  private double _pitch;
+  private double _side;
+  private double _tan;
+  private double _cotan2;
+  private double _uCorner;
+  private double _vConst;
+  
+}

lcsim-contrib/src/main/java/org/lcsim/contrib/onoprien/geom/tracker/lib/sensortype
package-info.java added at 1.1
diff -N package-info.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ package-info.java	8 Jul 2009 15:59:41 -0000	1.1
@@ -0,0 +1,9 @@
+/**
+ * Library of classes implementing {@link org.lcsim.contrib.onoprien.geom.tracker.SensorType SensorType} interface.
+ * <p>
+ * Each class describes a sensor of a particular (usually parameterized) shape. 
+ * New shapes can be defined by either implementing
+ * {@link org.lcsim.contrib.onoprien.geom.tracker.SensorType SensorType} from scratch,
+ * or subclassing one of the existing implementations.
+ */
+package org.lcsim.contrib.onoprien.geom.tracker.lib.sensortype;
CVSspam 0.2.8