Print

Print


Commit in GeomConverter/src/org/lcsim/geometry/segmentation on MAIN
BarrelCylinderSegmentationBase.java+63added 1.1
GridXYZ.java+274-461.16 -> 1.17
NonprojectiveCylinder.java+14-781.17 -> 1.18
ProjectiveCylinder.java+41-11.19 -> 1.20
ProjectiveZPlane.java+105-211.17 -> 1.18
SegmentationBase.java+63-61.7 -> 1.8
SegmentationUtil.java+8-81.1 -> 1.2
+568-160
1 added + 6 modified, total 7 files
GL: Neighbor-finding code in endcaps, and findCellContainingXYZ() moved to SegmentationBase

GeomConverter/src/org/lcsim/geometry/segmentation
BarrelCylinderSegmentationBase.java added at 1.1
diff -N BarrelCylinderSegmentationBase.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ BarrelCylinderSegmentationBase.java	7 Dec 2005 10:39:37 -0000	1.1
@@ -0,0 +1,63 @@
+/*
+ * BarrelCylinderSegmentationBase.java
+ *
+ * 20051124 - G.Lima - Created
+ */
+
+package org.lcsim.geometry.segmentation;
+
+import org.jdom.Element;
+import org.lcsim.geometry.layer.Layer;
+import org.lcsim.geometry.layer.LayerStack;
+
+/**
+ * Base implementation of a barrel segmentation, it provides common
+ * code implementation.
+ *
+ * @author Guilherme Lima
+ * @versoin $Id: BarrelCylinderSegmentationBase.java,v 1.1 2005/12/07 10:39:37 lima Exp $
+ */
+public abstract class BarrelCylinderSegmentationBase extends SegmentationBase
+{
+    public BarrelCylinderSegmentationBase(Element e)
+    {
+        super(e);
+    }
+
+    /**
+     * Return the layer number based on the radial distance to cylinder axis.
+     *
+     * @param r radial distance to cylinder axis
+     * @return layer number of layer corresponding to that distance
+     * (may be either in absorber or live material)
+     */
+    public int getLayerBin(double r) {
+	// In order to be general, we should not assume that all
+	// layers have the same thickness.  Therefore, one has to
+	// guess the starting layer (based on average thickness), and
+	// then navigate through layers until one finds the right one
+	double depth = r - getRMin();
+	double mean_t = (getRMax()-getRMin()) / getNumberOfLayers();
+
+	int ilay = (int)Math.floor( depth / mean_t );
+	LayerStack stack = getLayering().getLayers();
+	Layer layer = stack.getLayer(ilay);
+	double depHi = stack.getThicknessToLayerBack(ilay);
+	double depLo = depHi - layer.getThickness();
+	for(;;) {
+	  if( depth>depLo && depth<=depHi ) return ilay;
+	  if( depth<=depLo ) {
+	      --ilay;
+	      depHi = depLo;
+	      layer = stack.getLayer(ilay);
+	      depLo -= layer.getThickness();
+	  }
+	  if( depth>depHi ) {
+	      ++ilay;
+	      depLo = depHi;
+	      layer = stack.getLayer(ilay);
+	      depHi += layer.getThickness();
+	  }
+	}
+    }
+}

GeomConverter/src/org/lcsim/geometry/segmentation
GridXYZ.java 1.16 -> 1.17
diff -u -r1.16 -r1.17
--- GridXYZ.java	28 Oct 2005 00:34:23 -0000	1.16
+++ GridXYZ.java	7 Dec 2005 10:39:37 -0000	1.17
@@ -14,6 +14,10 @@
 import org.jdom.Element;
 
 import org.lcsim.geometry.util.IDDescriptor;
+import org.lcsim.geometry.util.IDEncoder;
+import org.lcsim.geometry.layer.Layer;
+import org.lcsim.geometry.layer.LayerStack;
+import org.lcsim.geometry.subdetector.CylindricalCalorimeter;
 
 /**
  * @author jeremym
@@ -27,104 +31,228 @@
     private double gridSizeX = 0;
     private double gridSizeY = 0;
     private double gridSizeZ = 0;
-    
+
     private int xIndex = -1;
     private int yIndex = -1;
     private int zIndex = -1;
-    
+
     private double[] _localPos = { 0, 0, 0};
     private double[] _globalPos = { 0, 0, 0};
-    
-    public double getGridSizeX()
-    {
-        return gridSizeX;
-    }
-    
-    public double getGridSizeY()
-    {
-        return gridSizeY;
-    }
-    
-    public double getGridSizeZ()
-    {
-        return gridSizeZ;
-    }
-    
+
     /** Creates a new instance of GridXYZ */
     public GridXYZ(Element node) throws DataConversionException
     {
         super(node);
-        
+
         if ( node.getAttribute("gridSizeX") != null )
         {
             gridSizeX = node.getAttribute("gridSizeX").getDoubleValue();
         }
-        
+
         if ( node.getAttribute("gridSizeY") != null )
         {
             gridSizeY = node.getAttribute("gridSizeY").getDoubleValue();
         }
-        
+
         if ( node.getAttribute("gridSizeZ") != null )
         {
             gridSizeZ = node.getAttribute("gridSizeZ").getDoubleValue();
         }
     }
-    
-    /* FIXME: Implementation requires very specific information about the subdetector topology. --JM */
-    public long[] getNeighbourIDs(int a, int b, int c)
+
+    /** Find neighbouring cells to the current cell.
+     *
+     * Cell neighbors are found based on the direction (theta,phi) of
+     * the reference cell w.r.t the origin.
+     *
+     * @see org.lcsim.geometry.segmentation.SegmentationBase#setID()
+     * @return array of cellIDs for the neighbouring cells
+     */
+    public long[] getNeighbourIDs(int layerRange, int xRange, int yRange)
     {
-        return new long[3];
+//       System.out.println("Nonproj neighbs: "+layerRange+" "+xRange+" "+yRange);
+      IDEncoder encoder = new IDEncoder( descriptor );
+      encoder.setValues(values);
+      long saveID = encoder.getID();
+
+      int klay = values[layerIndex];
+      int kx   = values[xIndex];
+      int ky   = values[yIndex];
+//       System.out.println("Ref.ID: ref="+klay+" "+kx+" "+ky
+// 			 +" (hex "+Long.toHexString(saveID)+")");
+//       long system = (saveID>>7) & 0x1ff;
+//       System.out.println("hit pos: x="+getX()+", y="+getY()+", z="+getZ()+", system="+system);
+
+      int nMax = (2*layerRange + 1)*(2*xRange + 1)*(2*yRange + 1) - 1;
+      long[] result = new long[nMax];
+
+      // theta and phi are used to find central neighbors in other layers
+      double theta = getTheta();
+      double phi = getPhi();
+
+      // this is not general, but specific to endcaps
+      double dx = gridSizeX;
+      double dy = gridSizeY;
+      int zBins = detector.getLayering().getLayerCount();
+      double Rmax = ((CylindricalCalorimeter)detector).getOuterRadius();
+
+      int size = 0;
+      int refLayer = values[layerIndex];
+      boolean isNegativeZ = getZ()<0 ? true : false;
+      for (int i=-layerRange; i<=layerRange; ++i) {
+	int ilay = refLayer + i;
+
+	if (ilay<0 || ilay>=zBins ) continue;
+	encoder.setValue(layerIndex,ilay);
+
+	int xBins = (int)Math.ceil( 2*Rmax / dx );
+	int yBins = xBins;
+
+	// project theta,phi to sensitive middle of current layer
+	double z = getDepthSensitiveMid( ilay );
+	if( isNegativeZ ) z = -z;
+	double rho = z * Math.tan(theta);
+	double x = rho * Math.cos(phi);
+	double y = rho * Math.sin(phi);
+//  	System.out.println("layer "+ilay+", cylR="+rho
+//  			   +", theta="+(theta*180./Math.PI)
+// 			   +", phi="+(phi*180./Math.PI)
+//  			   +", rvec=( "+x+", "+y+", "+z+")");
+
+ 	long id = this.findCellContainingXYZ(x,y,z);
+ 	if(id==0) continue;
+
+	this.setID(id);
+// 	System.out.println("from findXYZ: x="+getX()+", y="+getY()+", z="+getZ());
+ 	for (int j=-xRange; j<=xRange; ++j) {
+	  int ix = values[xIndex] + j;
+
+ 	  if (ix<-xBins/2 || ix>=xBins/2) continue;
+ 	  encoder.setValue(xIndex,ix);
+
+ 	  for (int k=-yRange; k<=yRange; ++k) {
+	    // skip reference cell
+	    if (i==0 && j==0 && k==0) continue;
+
+ 	    int iy = values[yIndex] + k;
+	    if (iy<-yBins/2 || iy>=yBins/2) continue;
+
+//    	    System.out.println("Adding neighbor: "+ilay+" "+ix+" "+iy
+//  			       +", total="+ (size+1));
+ 	    result[size++] = encoder.setValue(yIndex,iy);
+	  }
+ 	}
+      }
+
+      // reset encoder and decoder
+      this.setID(saveID);
+      if(size < result.length) {
+// 	  int kklay = values[layerIndex];
+// 	  int kkx = values[xIndex];
+// 	  int kky = values[yIndex];
+//  	  System.out.println("In a border? Neighbors="+size+"/"+result.length
+//  			     +", ref="+kklay+" "+kkx+" "+kky);
+
+	  long[] temp = new long[size];
+	  System.arraycopy(result,0,temp,0,size);
+	  result = temp;
+      }
+
+//       int kklay = values[layerIndex];
+//       int kkx = values[xIndex];
+//       int kky = values[yIndex];
+//       System.out.println("Neighbors="+size+"/"+result.length
+// 			 +", ref="+kklay+" "+kkx+" "+kky
+// 			 +" (hex "+Long.toHexString(encoder.getID())+")");
+
+//       System.out.println("Leaving getNeighbours: current id="
+// 			 +values[layerIndex]+" "+values[xIndex]
+// 			 +" "+values[yIndex]);
+      return result;
+    }
+
+    // Not for public use, this is needed to calculate positions
+    // and number of cells, etc.
+    public double getZMin() {
+	return ((CylindricalCalorimeter)detector).getZMin();
     }
-        
+
+    public double getZMax() {
+	return ((CylindricalCalorimeter)detector).getZMax();
+    }
+
+    public double getRMin() {
+	return ((CylindricalCalorimeter)detector).getInnerRadius();
+    }
+
+    public double getRMax() {
+	return ((CylindricalCalorimeter)detector).getOuterRadius();
+    }
+
+    /** FIXME: Doesn't belong here, as it is always generally derivable from x and y. */
     public double getPhi()
     {
-        return SegmentationUtil.getPhi(getX(), getY() );
+        double phi = atan2(getY(), getX() );
+
+        if ( phi < 0 )
+        {
+            phi += 2 * PI;
+        }
+
+        return phi;
     }
-    
+
+    /** FIXME: Doesn't belong here, as it is always computable given x and y. */
     public double getTheta()
     {
-        return SegmentationUtil.getTheta(getX(), getY(), getZ() );
+        double theta = atan(getCylindricalRadiusFromPosition() / getZ() );
+
+        if ( theta < 0 )
+        {
+            theta += PI;
+        }
+
+        return theta;
     }
-    
+
     public double getX()
     {
         return getPosition()[0];
     }
-    
+
     public double getY()
     {
         return getPosition()[1];
     }
-    
+
     public double getZ()
     {
         return getPosition()[2];
     }
-    
+
     public double[] getPosition()
     {
         return _globalPos;
     }
-    
+
     private void computePosition()
     {
         computeLocalPosition();
         computeGlobalPosition();
     }
-    
+
     private void computeLocalPosition()
     {
         computeLocalX();
         computeLocalY();
         computeLocalZ();
     }
-    
+
     private void computeGlobalPosition()
     {
         _globalPos = transformLocalToGlobal(_localPos);
     }
-    
+
     private void computeLocalX()
     {
         if ( xIndex != -1 )
@@ -132,7 +260,7 @@
             _localPos[0] = (((double)getValue(xIndex)) + 0.5) * gridSizeX;
         }
     }
-    
+
     private void computeLocalY()
     {
         if ( yIndex != -1 )
@@ -140,7 +268,7 @@
             _localPos[1] = (((double)getValue(yIndex)) + 0.5) * gridSizeY;
         }
     }
-    
+
     private void computeLocalZ()
     {
         if ( zIndex != -1 )
@@ -148,19 +276,19 @@
             _localPos[2] = (((double)getValue(zIndex)) + 0.5) * gridSizeZ;
         }
     }
-    
+
     /** Overridden to cache the global position. */
     public void setID(long id)
     {
         super.setID(id);
         computePosition();
     }
-    
+
     public double getCylindricalRadiusFromPosition()
     {
         return sqrt(getX() * getX() + getY() * getY() );
     }
-    
+
     /**
      * Check for a valid grid size for each of XYZ.
      * If the grid is not valid, then leave those
@@ -172,20 +300,120 @@
     public void setIDDescription(IDDescriptor id)
     {
         super.setIDDescription(id);
-        
+
         if ( gridSizeX != 0 )
         {
             xIndex = id.indexOf("x");
         }
-        
+
         if ( gridSizeY != 0 )
         {
             yIndex = id.indexOf("y");
         }
-        
+
         if ( gridSizeZ != 0 )
         {
             zIndex = id.indexOf("z");
         }
     }
-}
\ No newline at end of file
+
+    /**
+     * Returns positive distance from IR to center of sensitive slice
+     * of any layer
+     * @param layer layer index
+     */
+    private double getDepthSensitiveMid(int ilay) {
+	LayerStack stack = detector.getLayering().getLayers();
+	Layer layer = stack.getLayer(ilay);
+
+	double preLayers = 0;
+	if(ilay>0) preLayers = stack.getSectionThickness(0,ilay-1);
+
+	return this.getZMin() + preLayers + layer.getThicknessToSensitiveMid();
+    }
+
+    /**
+     * Return the cell which contains a given point (x,y,z).  If point is
+     * not contained in this component, zero is returned.
+     *
+     * @param x,y,z cartesian coordinates of the point
+     * @return ID of cell containing the point (maybe either in
+     * absorber or live material)
+     */
+    public long findCellContainingXYZ(double x, double y, double z) {
+
+	// validate point
+	double absz = Math.abs(z);
+	if(absz<getZMin()) return 0;
+	if(absz>getZMax()) return 0;
+	double rho = Math.sqrt(x*x+y*y);
+	if(rho<getRMin()) return 0;
+	if(rho>getRMax()) return 0;
+
+	// ok, point is valid, so a valid ID should be returned
+	int ix = getXBin(x);
+	int iy = getYBin(y);
+	int ilay = getLayerBin(absz);
+
+	IDEncoder enc = new IDEncoder(descriptor);
+	enc.setValues(values);
+	enc.setValue(layerIndex, ilay);
+	enc.setValue(xIndex, ix);
+	enc.setValue(yIndex, iy);
+	long resultID = enc.getID();
+	return resultID;
+    }
+
+    public int getLayerBin(double z) {
+      // In order to be general, we should not assume that all
+      // layers have the same thickness.  Therefore, one has to
+      // guess the starting layer (based on average thickness), and
+      // then navigate through layers until one finds the right one
+      double depth = z - getZMin();
+      double mean_t = (getZMax()-getZMin()) / getNumberOfLayers();
+
+      int ilay = (int)Math.floor( depth / mean_t );
+      LayerStack stack = getLayering().getLayers();
+      Layer layer = stack.getLayer(ilay);
+      double depHi = stack.getThicknessToLayerBack(ilay);
+      double depLo = depHi - layer.getThickness();
+      for(;;) {
+	if( depth>depLo && depth<=depHi ) return ilay;
+	if( depth<=depLo ) {
+	  --ilay;
+	  depHi = depLo;
+	  layer = stack.getLayer(ilay);
+	  depLo -= layer.getThickness();
+	}
+	if( depth>depHi ) {
+	  ++ilay;
+	  depLo = depHi;
+	  layer = stack.getLayer(ilay);
+	  depHi += layer.getThickness();
+	}
+      }
+    }
+
+    public int getXBin(double x) {
+	return getBin( x, gridSizeX );
+    }
+    public int getYBin(double y) {
+	return getBin( y, gridSizeY );
+    }
+
+    public int getBin(double u, double gridSizeU) {
+      int numBins = (int)Math.floor( 2*getRMax() / gridSizeU );
+      double u0 = gridSizeU / 2;
+      int iu = (int)Math.floor((u-u0)/gridSizeU + 0.5);
+      return iu;
+    }
+
+    public double getGridSizeX() { return gridSizeX; }
+    public double getGridSizeY() { return gridSizeY; }
+    public double getGridSizeZ() { return gridSizeZ; }
+
+    private int flag1 = 0;
+    private int flag2 = 0;
+    private int flag3 = 0;
+    private int flag4 = 0;
+}

GeomConverter/src/org/lcsim/geometry/segmentation
NonprojectiveCylinder.java 1.17 -> 1.18
diff -u -r1.17 -r1.18
--- NonprojectiveCylinder.java	28 Oct 2005 00:34:23 -0000	1.17
+++ NonprojectiveCylinder.java	7 Dec 2005 10:39:37 -0000	1.18
@@ -15,19 +15,17 @@
 import org.jdom.Element;
 import org.lcsim.geometry.layer.Layer;
 import org.lcsim.geometry.layer.LayerStack;
-import org.lcsim.geometry.CylindricalSubdetector;
 import org.lcsim.geometry.util.BaseIDDecoder;
 import org.lcsim.geometry.util.IDDescriptor;
 import org.lcsim.geometry.util.IDEncoder;
 
-
 /**
  * @author jeremym
  *
  * Nonprojective segmentation of a cylinder with delta z and phi as parameters.
  *
  */
-public class NonprojectiveCylinder extends SegmentationBase
+public class NonprojectiveCylinder extends BarrelCylinderSegmentationBase
 {
     private double gridSizePhi;
     private double gridSizeZ;
@@ -69,8 +67,9 @@
 
     public double getTheta()
     {
-        /** theta = atan( sqrt((x^2 + y^2) / z) ) */
-        double theta = atan(sqrt((getX() * getX()) + (getY() * getY()) ) / getZ() );
+	double x = this.getX();
+	double y = this.getY();
+        double theta = atan( sqrt(x*x + y*y)  / getZ() );
 
         /** Normalize to positive theta. */
         if ( theta < 0 )
@@ -101,7 +100,7 @@
     public double computeDeltaPhiForLayer(int layer)
     {
 //        double circ = detector.getLayering().getDistanceToLayerSensorMid(layer) * ( 2 * PI );
-        double circ = getDistanceToSensitive( getLayer() ) * ( 2 * PI );
+        double circ = getDistanceToSensitive( layer ) * ( 2 * PI );
         int nphi = (int)Math.floor( circ / gridSizePhi );
         double deltaPhi = (2 * PI) / nphi;
         return deltaPhi;
@@ -143,7 +142,7 @@
 
       int nMax = (2*layerRange + 1)*(2*zRange + 1)*(2*phiRange + 1) - 1;
       long[] result = new long[nMax];
-      
+
       // theta and phi are used to find central neighbors in other layers
       double theta = getTheta();
       double phi = getPhi();
@@ -197,34 +196,12 @@
 	  System.arraycopy(result,0,temp,0,size);
 	  result = temp;
       }
- 
-      return result;
-    }
-
-    // Not for public use, this is needed to calculate positions
-    // and number of cells, etc.
-    /*
-     * FIXME: Are these next four functions really needed? --JM
-     */
-    private double getZMin() {
-	return ((CylindricalSubdetector)detector).getZMin();
-    }
 
-    private double getZMax() {
-	return ((CylindricalSubdetector)detector).getZMax();
-    }
-
-    private double getRMin() {
-	return ((CylindricalSubdetector)detector).getInnerRadius();
-    }
-
-    private double getRMax() {
-	return ((CylindricalSubdetector)detector).getOuterRadius();
+      return result;
     }
 
     /**
-     * Return the cell which contains a given point (x,y,z), or null.
-     * Side effect: encoder will be reset to the ID returned by this method.(not anymore...???)
+     * Return the cell which contains a given point (x,y,z), or zero.
      *
      * @param x,y,z cartesian coordinates of the point
      * @return ID of cell containing the point (maybe either in
@@ -233,23 +210,11 @@
     public long findCellContainingXYZ(double x, double y, double z) {
 
 	// validate point
-	if(z<getZMin()) {
-	    System.out.println("find: fail z<zmin: z="+z);
-	    return 0;
-	}
-	if(z>getZMax()) {
-	    System.out.println("find: fail z>zmax: z="+z);
-	    return 0;
-	}
+	if(z<getZMin()) return 0;
+	if(z>getZMax()) return 0;
 	double rho = Math.sqrt(x*x+y*y);
-	if(rho<getRMin()) {
-	    System.out.println("find: fail rho<Rmin: rho="+rho);
-	    return 0;
-	}
-	if(rho>getRMax()) {
-	    System.out.println("find: fail rho>Rmax: rho="+rho);
-	    return 0;
-	}
+	if(rho<getRMin()) return 0;
+	if(rho>getRMax()) return 0;
 
 	// ok, point is valid, so a valid ID should be returned
 	int ilay = getLayerBin(rho);
@@ -260,6 +225,7 @@
 	int iphi = getPhiBin(ilay,phi);
 
 	IDEncoder enc = new IDEncoder(descriptor);
+	enc.setValues(values);
 	enc.setValue("layer",ilay);
 	enc.setValue(zIndex,iz);
 	enc.setValue(phiIndex,iphi);
@@ -268,36 +234,6 @@
 	return resultID;
     }
 
-    public int getLayerBin(double r) {
-	// In order to be general, we should not assume that all
-	// layers have the same thickness.  Therefore, one has to
-	// guess the starting layer (based on average thickness), and
-	// then navigate trhough layers until one finds the right one
-	double depth = r - getRMin();
-	double mean_t = (getRMax()-getRMin()) / getNumberOfLayers();
-
-	int ilay = (int)Math.floor( depth / mean_t );
-	LayerStack stack = getLayering().getLayers();
-	Layer layer = stack.getLayer(ilay);
-	double depHi = stack.getThicknessToLayerBack(ilay);
-	double depLo = depHi - layer.getThickness();
-	for(;;) {
-	  if( depth>depLo && depth<=depHi ) return ilay;
-	  if( depth<=depLo ) {
-	      --ilay;
-	      depHi = depLo;
-	      layer = stack.getLayer(ilay);
-	      depLo -= layer.getThickness();
-	  }
-	  if( depth>depHi ) {
-	      ++ilay;
-	      depLo = depHi;
-	      layer = stack.getLayer(ilay);
-	      depHi += layer.getThickness();
-	  }
-	}
-    }
-
     public int getPhiBin(int ilay, double phi) {
       // phic is phi at center of cells with iphi=0
       double deltaPhi = this.computeDeltaPhiForLayer(ilay);
@@ -347,7 +283,7 @@
 //			  +">");
 //    }
 
-    
+
 //    public static int getSysBE( long cellid ) {
 //	return (int)((cellid>>16) & 0x3f);
 //    }

GeomConverter/src/org/lcsim/geometry/segmentation
ProjectiveCylinder.java 1.19 -> 1.20
diff -u -r1.19 -r1.20
--- ProjectiveCylinder.java	28 Oct 2005 00:34:23 -0000	1.19
+++ ProjectiveCylinder.java	7 Dec 2005 10:39:37 -0000	1.20
@@ -11,7 +11,7 @@
  *
  * @author tonyj
  */
-public class ProjectiveCylinder extends SegmentationBase
+public class ProjectiveCylinder extends BarrelCylinderSegmentationBase
 {
    private int thetaBins;
    private int phiBins;
@@ -113,4 +113,44 @@
     public int getPhiBins() {
 	return phiBins;
     }
+
+    /**
+     * Return the cell which contains a given point (x,y,z), or zero.
+     *
+     * @param x,y,z cartesian coordinates of the point
+     * @return ID of cell containing the point (maybe either in
+     * absorber or live material)
+     */
+    public long findCellContainingXYZ(double x, double y, double z) {
+
+	// validate point
+	if(z<getZMin()) return 0;
+	if(z>getZMax()) return 0;
+	double rho = Math.sqrt(x*x+y*y);
+	if(rho<getRMin()) return 0;
+	if(rho>getRMax()) return 0;
+
+	// ok, point is valid, so a valid ID should be returned
+	int ilay = getLayerBin(rho);
+
+	double phi = Math.atan2( y, x );
+	if(phi<0) phi += 2*Math.PI;
+	int iphi = (int)( phi / phiBins );
+
+	double theta = Math.atan2( rho, z );
+	if(theta<0) {
+	    // If never prints out, the whole if can be dropped
+	    System.out.println("ProjCylinder: Is this really needed?!?");
+	    theta += 2.*Math.PI;
+	}
+	int itheta = (int)(theta/thetaBins);
+
+	IDEncoder enc = new IDEncoder(descriptor);
+	enc.setValue("layer",ilay);
+	enc.setValue(thetaIndex,itheta);
+	enc.setValue(phiIndex,iphi);
+	long resultID = enc.getID();
+
+	return resultID;
+    }
 }

GeomConverter/src/org/lcsim/geometry/segmentation
ProjectiveZPlane.java 1.17 -> 1.18
diff -u -r1.17 -r1.18
--- ProjectiveZPlane.java	28 Oct 2005 00:34:23 -0000	1.17
+++ ProjectiveZPlane.java	7 Dec 2005 10:39:37 -0000	1.18
@@ -2,11 +2,15 @@
 
 import static java.lang.Math.PI;
 import static java.lang.Math.tan;
+import java.lang.RuntimeException;
 import org.jdom.DataConversionException;
 import org.jdom.Element;
 import org.lcsim.geometry.util.IDDescriptor;
 import org.lcsim.geometry.util.IDEncoder;
 import org.lcsim.geometry.Layered;
+import org.lcsim.geometry.layer.Layer;
+import org.lcsim.geometry.layer.Layering;
+import org.lcsim.geometry.layer.LayerStack;
 
 /**
  * @author tonyj
@@ -15,20 +19,20 @@
 {
     private int thetaBins;
     private int phiBins;
-    
+
     private int thetaIndex;
     private int phiIndex;
-    
+
     private double thetaDim = 0;
     private double phiDim = 0;
-    
+
     ProjectiveZPlane(Element node) throws DataConversionException
     {
         super(node);
         thetaBins = node.getAttribute("thetaBins").getIntValue();
         phiBins = node.getAttribute("phiBins").getIntValue();
     }
-     
+
     public int getThetaBins()
     {
         return thetaBins;
@@ -37,75 +41,75 @@
     {
         return phiBins;
     }
-    
+
     public double getPhi()
     {
         double phi = (Math.PI*2) * ((getValue(phiIndex)+0.5)/phiBins);
         return phi;
     }
-    
+
     public double getTheta()
     {
         return (Math.PI) * ((getValue(thetaIndex)+0.5)/thetaBins);
     }
-    
+
     public double getX()
     {
         return getSphericalRadius() * Math.cos(getPhi());
     }
-    
+
     public double getY()
     {
         return getSphericalRadius() * Math.sin(getPhi());
     }
-    
+
     public double getZ()
     {
         return -Math.signum(getTheta()-PI/2) * getDistanceToSensitive(getLayer() );
     }
-    
+
     private double getSphericalRadius()
     {
         return getZ() * tan(getTheta() );
     }
-    
+
     public void setIDDescription(IDDescriptor id)
     {
         super.setIDDescription(id);
-        
+
         phiIndex = id.indexOf("phi");
         thetaIndex = id.indexOf("theta");
     }
-    
+
     public long[] getNeighbourIDs(int deltaLayer, int deltaTheta, int deltaPhi)
     {
 	IDEncoder encoder = new IDEncoder( descriptor );
         encoder.setValues(values);
-        
+
         int nMax = (2*deltaLayer + 1)*(2*deltaTheta + 1)*(2*deltaPhi + 1) - 1;
         int size = 0;
         long[] result = new long[nMax];
         for (int i=-deltaLayer;i<=deltaLayer;i++)
         {
             int l = values[layerIndex] + i;
-            
+
             if (l<0 || l>= getNumberOfLayers() ) continue;
             encoder.setValue(layerIndex,l);
-            
+
             for (int j=-deltaTheta;j<=deltaTheta;j++)
             {
                 int t = values[thetaIndex] + j;
-                
+
                 if (t<0 || t>=thetaBins) continue;
                 encoder.setValue(thetaIndex,t);
-                
+
                 for (int k=-deltaPhi;k<=deltaPhi;k++)
                 {
                     if (i==0 && j==0 && k==0) continue;
-                    
+
                     int p = values[phiIndex] + k;
                     if (p<0 || p>=phiBins) continue;
-                    
+
                     result[size++] = encoder.setValue(phiIndex,p);
                 }
             }
@@ -118,9 +122,89 @@
         }
         return result;
     }
-    
+
     public boolean supportsNeighbours()
     {
         return true;
     }
+
+    /**
+     * Return the cell which contains a given point (x,y,z), or zero.
+     *
+     * @param x,y,z cartesian coordinates of the point
+     * @return ID of cell containing the point (maybe either in
+     * absorber or live material)
+     */
+    public long findCellContainingXYZ(double x, double y, double z) {
+
+	// validate point
+	if(z<getZMin()) return 0;
+	if(z>getZMax()) return 0;
+	double rho = Math.sqrt(x*x+y*y);
+	if(rho<getRMin()) return 0;
+	if(rho>getRMax()) return 0;
+
+	// ok, point is valid, so a valid ID should be returned
+	int ilay = getLayerBin(rho);
+
+	double phi = Math.atan2( y, x );
+	if(phi<0) phi += 2*Math.PI;
+	int iphi = (int)( phi / phiBins );
+
+	double theta = Math.atan2( rho, z );
+	if(theta<0) {
+	    // If never prints out, the whole if can be dropped
+	    System.out.println("ProjCylinder: Is this really needed?!?");
+	    theta += 2.*Math.PI;
+	}
+	int itheta = (int)(theta/thetaBins);
+
+	IDEncoder enc = new IDEncoder(descriptor);
+	enc.setValue("layer",ilay);
+	enc.setValue(thetaIndex,itheta);
+	enc.setValue(phiIndex,iphi);
+	long resultID = enc.getID();
+
+	return resultID;
+    }
+
+    /**
+     * Return the layer number based on the z-coordinate
+     *
+     * @param z z-coordinate
+     * @return layer number of layer corresponding to that distance
+     * (may be either in absorber or live material)
+     * @throws RuntimeException if abs(z)<zMin
+     */
+    public int getLayerBin(double z) {
+	// In order to be general, we should not assume that all
+	// layers have the same thickness.  Therefore, one has to
+	// guess the starting layer (based on average thickness), and
+	// then navigate through layers until one finds the right one
+	double depth = Math.abs(z) - getZMin();
+	if(depth<0) throw new RuntimeException("ProjectiveZPlane: Error: z < zMin, z="+z+", zMin="+this.getZMin());
+
+	double mean_t = (getZMax()-getZMin()) / getNumberOfLayers();
+
+	int ilay = (int)Math.floor( depth / mean_t );
+	LayerStack stack = getLayering().getLayers();
+	Layer layer = stack.getLayer(ilay);
+	double depHi = stack.getThicknessToLayerBack(ilay);
+	double depLo = depHi - layer.getThickness();
+	for(;;) {
+	  if( depth>depLo && depth<=depHi ) return ilay;
+	  if( depth<=depLo ) {
+	      --ilay;
+	      depHi = depLo;
+	      layer = stack.getLayer(ilay);
+	      depLo -= layer.getThickness();
+	  }
+	  if( depth>depHi ) {
+	      ++ilay;
+	      depLo = depHi;
+	      layer = stack.getLayer(ilay);
+	      depHi += layer.getThickness();
+	  }
+	}
+    }
 }

GeomConverter/src/org/lcsim/geometry/segmentation
SegmentationBase.java 1.7 -> 1.8
diff -u -r1.7 -r1.8
--- SegmentationBase.java	28 Oct 2005 00:34:23 -0000	1.7
+++ SegmentationBase.java	7 Dec 2005 10:39:37 -0000	1.8
@@ -9,6 +9,8 @@
 import org.lcsim.geometry.Layered;
 import org.jdom.Element;
 import org.lcsim.geometry.layer.Layering;
+import org.lcsim.geometry.CylindricalSubdetector;
+import hep.physics.vec.Hep3Vector;
 
 /**
  * @author jeremym
@@ -16,13 +18,13 @@
  * Base implementation of segmentation
  *
  */
-public class SegmentationBase extends org.lcsim.geometry.compact.Segmentation
+public abstract class SegmentationBase extends org.lcsim.geometry.compact.Segmentation
 {
     public SegmentationBase(Element e)
     {
         super(e);
     }
-    
+
     /**
      * FIXME: Should be renamed as it is actually returning the distance to the
      * midpoint of the sensitive layer.
@@ -33,7 +35,41 @@
     {
         return ((Layered)detector).getLayering().getDistanceToLayerSensorMid(layer);
     }
-    
+
+    /**
+     * Returns the cell which contains a given point (x,y,z).
+     *
+     * @param x,y,z cartesian coordinates of the point
+     * @return ID of cell containing the point (maybe either in
+     * absorber or live material), or <em>zero</em> if the point is
+     * not inside this component.
+     */
+    abstract public long findCellContainingXYZ(double x, double y, double z);
+
+    /**
+     * Returns the cell which contains a given point (x,y,z).
+     *
+     * @param pos 3-dim array with cartesian coordinates of the point
+     * @return ID of cell containing the point (maybe either in
+     * absorber or live material), or <em>zero</em> if the point is
+     * not inside this component.
+     */
+    public long findCellContainingXYZ(double[] pos) {
+	return findCellContainingXYZ( pos[0], pos[1], pos[2] );
+    }
+
+    /**
+     * Returns the cell which contains a given point (x,y,z).
+     *
+     * @param pos Hep3Vector with cartesian coordinates of the point
+     * @return ID of cell containing the point (maybe either in
+     * absorber or live material), or <em>zero</em> if the point is
+     * not inside this component.
+     */
+    public long findCellContainingXYZ(Hep3Vector pos) {
+	return findCellContainingXYZ( pos.x(), pos.y(), pos.z() );
+    }
+
     /*
      * FIXME: Does this belong here?
      */
@@ -41,14 +77,35 @@
     {
         return ((Layered)detector).getLayering().getLayerCount();
     }
-    
+
     protected double[] transformLocalToGlobal(double[] localPos)
     {
         return detector.transformLocalToGlobal(localPos);
     }
-    
+
     protected Layering getLayering()
     {
         return ((Layered)detector).getLayering();
     }
-}
\ No newline at end of file
+
+    // Not for public use, this is needed to calculate positions
+    // and number of cells, etc.
+    /*
+     * FIXME: Are these next four functions really needed? --JM
+     */
+    protected double getZMin() {
+	return ((CylindricalSubdetector)detector).getZMin();
+    }
+
+    protected double getZMax() {
+	return ((CylindricalSubdetector)detector).getZMax();
+    }
+
+    protected double getRMin() {
+	return ((CylindricalSubdetector)detector).getInnerRadius();
+    }
+
+    protected double getRMax() {
+	return ((CylindricalSubdetector)detector).getOuterRadius();
+    }
+}

GeomConverter/src/org/lcsim/geometry/segmentation
SegmentationUtil.java 1.1 -> 1.2
diff -u -r1.1 -r1.2
--- SegmentationUtil.java	26 Sep 2005 19:24:05 -0000	1.1
+++ SegmentationUtil.java	7 Dec 2005 10:39:37 -0000	1.2
@@ -19,33 +19,33 @@
 {
     private SegmentationUtil()
     {}
-    
+
     public static double getPhi(double x, double y)
     {
         double phi = atan2(x, y);
-        
+
         if ( phi < 0 )
         {
             phi += 2 * PI;
         }
-        
+
         return phi;
     }
-    
+
     public static double getTheta(double x, double y, double z)
     {
         double theta = atan(getCylindricalRadius(x, y) / z );
-        
+
         if ( theta < 0 )
         {
             theta += PI;
         }
-        
+
         return theta;
     }
-    
+
     public static double getCylindricalRadius(double x, double y)
     {
         return sqrt(x * x + y * y);
-    }    
+    }
 }
CVSspam 0.2.8