Commit in GeomConverter/src/org/lcsim/geometry/segmentation on MAIN
AbstractCartesianGrid.java+322added 1.1
CartesianGridXY.java+20-2201.5 -> 1.6
CartesianGridXZ.java+17-2071.3 -> 1.4
+359-427
1 added + 2 modified, total 3 files
refactor the Cartesian grid classes by moving common functionality to new abstract base class

GeomConverter/src/org/lcsim/geometry/segmentation
AbstractCartesianGrid.java added at 1.1
diff -N AbstractCartesianGrid.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ AbstractCartesianGrid.java	8 Oct 2009 18:52:21 -0000	1.1
@@ -0,0 +1,322 @@
+package org.lcsim.geometry.segmentation;
+
+import hep.physics.vec.BasicHep3Vector;
+import hep.physics.vec.Hep3Vector;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.jdom.Element;
+import org.lcsim.detector.IDetectorElement;
+import org.lcsim.detector.identifier.ExpandedIdentifier;
+import org.lcsim.detector.identifier.IExpandedIdentifier;
+import org.lcsim.detector.identifier.IIdentifier;
+import org.lcsim.detector.identifier.IIdentifierHelper;
+import org.lcsim.detector.identifier.Identifier;
+import org.lcsim.geometry.util.IDDescriptor;
+
+/**
+ * Abstract base class for Cartesian grid segmentation types.
+ * This class computes positions in 3D space but only allows
+ * for two id fields that correspond to dimensions.  The 
+ * detailed Java geometry is used to generically transform
+ * 2D coordinates into 3D points in the detector.
+ * 
+ * @author jeremym
+ */
+public abstract class AbstractCartesianGrid extends SegmentationBase 
+{				
+	double[] localPosition = {0, 0, 0};
+	double[] globalPosition = {0, 0, 0};	
+	boolean needsCompute = true;	
+	List<Integer> geomFields;
+	
+	/**
+	 * Sub-types will set their grid values from the XML element.
+	 * This constructor basically does nothing.
+	 * 
+	 * @param segmentation The XML element for the segmentation.
+	 */
+	protected AbstractCartesianGrid(Element segmentation)
+	{
+		super(segmentation);
+	}
+	
+	/**
+	 * Using the current ID, compute the local position in the readout volume
+	 * and set the <code>localPosition</code> array.
+	 */
+	abstract protected void computeLocalPosition();
+	
+	/**
+	 * Make a list of fields that are geometric by stripping out this segmentation's
+	 * fields from the given <code>IDDescriptor</code>.
+	 * @param id The description of the Id.
+	 */
+	abstract protected void setupGeomFields(IDDescriptor id);
+	
+	/**
+	 * Check if the id is valid.  It must be in bounds of the readout volume it points to.
+	 * @param rawId
+	 * @return True if id is valid for this segmentation type; False if not.
+	 */
+	abstract public boolean boundsCheck(long rawId);
+	
+	/**
+	 * Set the segmentation field values on the given <code>IExpandedIdentifier</code>.
+	 * @param geomId The expanded id.
+	 * @param localPositionVec The local position of the hit.
+	 */
+	abstract protected void setSegmentationValues(IExpandedIdentifier geomId, Hep3Vector localPositionVec);
+	
+	/**
+	 * Create the neighbor ids list with the given parameters for layer and the two fields. 
+	 */ 
+	abstract public long[] getNeighbourIDs(int layerRange, int uRange, int vRange);
+		
+	/**
+	 * Compute the integer bin given a coordinate value and a grid size.
+	 * @param u The coordinate value.
+	 * @param gridSize The grid size.
+	 * @return The bin value.
+	 */
+	public final int getBin(double u, double gridSize)
+	{
+		double u0 = gridSize / 2;
+		int iu = (int) Math.floor((u - u0) / gridSize + 0.5);
+		return iu;
+	}
+	
+	/**
+	 * Compute the coordinate value given a bin. 
+	 * @param binValue The bin value.
+	 * @param gridSize The grid size.
+	 * @return The coordinate value.
+	 */
+	public final double computeCoordinate(int binValue, double gridSize)
+	{
+		return (((double) binValue) + 0.5) * gridSize;
+	}
+	
+	/**
+	 * Generic computation of hit's global position.  Set's the <code>globalPosition</code> array.
+	 */
+	protected final void computeGlobalPosition()
+	{											
+		// Make an id only containing geometric fields and no segmentation fields.
+		IExpandedIdentifier geomIdExp = detector.getDetectorElement().getIdentifierHelper().unpack(new Identifier(this.getDecoder().getID()), geomFields);
+		IIdentifier geomId = detector.getDetectorElement().getIdentifierHelper().pack(geomIdExp);
+
+		// Search for the the DetectorElement associated with the geometry id.
+		List<IDetectorElement> deSearch = detector.getDetectorElement().findDetectorElement(geomId);
+
+		// Check if the lookup failed.
+		if (deSearch == null || deSearch.size() == 0)
+		{
+			throw new RuntimeException("Failed to find DetectorElement with geometry id <" + geomIdExp.toString() + "> !");
+		}
+
+		// Set the DetectorElement to use for local to global transform.
+		IDetectorElement sensor = deSearch.get(0);
+		
+		// Create a vector of the local position.		
+		Hep3Vector posVecLocal = new BasicHep3Vector(localPosition[0], localPosition[1], localPosition[2]);		
+		
+		// Compute the global position of the hit using the DetectorElement.
+		Hep3Vector posVecGlobal = sensor.getGeometry().transformLocalToGlobal(posVecLocal);
+
+		// Set the internal global position array.
+		globalPosition[0] = posVecGlobal.x();
+		globalPosition[1] = posVecGlobal.y();
+		globalPosition[2] = posVecGlobal.z();
+	}
+		
+	/**
+	 * Find the readout cell given a global position in the 3D detector space.
+	 * @return The cell id for the position.
+	 */
+	public long findCellContainingXYZ(double x, double y, double z) 
+	{
+		Hep3Vector pos = new BasicHep3Vector(x,y,z);
+		IDetectorElement de = 
+			getSubdetector().getDetectorElement().findDetectorElement(pos);
+		if (!de.getGeometry().getPhysicalVolume().isSensitive())
+		{
+			throw new RuntimeException("The volume " + de.getName() + " is not sensitive.");
+		}
+		Hep3Vector localPositionVec = de.getGeometry().transformGlobalToLocal(pos);
+		ExpandedIdentifier geomId = new ExpandedIdentifier(de.getExpandedIdentifier());
+				
+		setSegmentationValues(geomId, localPositionVec);
+		
+		return getSubdetector().getDetectorElement().getIdentifierHelper().pack(geomId).getValue();
+	}
+	
+	/**
+	 * Get the position from the current cell ID.  Recomputes the position if necessary.
+	 * @return The position of the current cell.
+	 */
+	public final double[] getPosition()
+	{
+		if (needsCompute)
+		{
+			computePosition();
+			needsCompute = false;
+		}
+		return globalPosition;
+	}
+	
+	/**
+	 * Compute and cache the cell's global position.
+	 */
+	protected final void computePosition()
+	{
+		computeLocalPosition();
+		computeGlobalPosition();
+	}
+	
+	/**
+	 * Create an id with geometry fields only given an id including geometry and segmentation fields.
+	 * @param id The cell id.
+	 * @return A cell id with values for geometry fields only.
+	 */
+	protected final IIdentifier makeGeometryIdentifier(long id)
+	{
+		IExpandedIdentifier geomIdExp = detector.getDetectorElement().getIdentifierHelper().unpack(new Identifier(id), geomFields);
+		return detector.getDetectorElement().getIdentifierHelper().pack(geomIdExp);
+	}
+	
+	/**
+	 * We override this method to flag the decoder as dirty so that internal position data is 
+	 * recomputed next time a position is retrieved by the user.
+	 */
+	public final void setID(long id)
+	{
+		super.setID(id);
+		needsCompute = true;
+	}
+	
+	/**
+	 * We override this method to cache the geometry field information.
+	 */
+	public void setIDDescription(IDDescriptor id)
+	{
+		super.setIDDescription(id);
+		setupGeomFields(id);
+	}	
+	
+	/**
+	 * All implementations must support neighbor finding.
+	 * @return True.
+	 */
+	public final boolean supportsNeighbours()
+	{
+		return true;
+	}	
+	
+	/**
+	 * Get the X coordinate.
+	 * @return The X coordinate.
+	 */
+	public final double getX()
+	{
+		return getPosition()[0];
+	}
+	
+	/**
+	 * Get the Y coordinate.
+	 * @return The Y coordinate.
+	 */
+	public final double getY()
+	{
+		return getPosition()[1];
+	}
+	
+	/**
+	 * Get the Z coordinate.
+	 * @return The Z coordinate.
+	 */
+	public final double getZ()
+	{
+		return getPosition()[2];
+	}
+	
+	/**
+	 * Utility method for finding neighbors in layer and 2D segmentation grid..
+	 * @param layerRange
+	 * @param uRange
+	 * @param vRange
+	 * @param uIndex
+	 * @param vIndex
+	 * @return
+	 */
+	protected final long[] getNeighbourIDs(int layerRange, int uRange, int vRange, int uIndex, int vIndex)
+	{
+		if (this.getDecoder().getID() == 0)
+			throw new RuntimeException("No current ID is set.");
+		
+		// Get the IdentifierHelper.
+		IIdentifierHelper helper = detector.getDetectorElement().getIdentifierHelper();
+		
+		// Get number of layers.
+		int nlayers = this.getNumberOfLayers();
+		
+		// Current packed id.
+		IIdentifier currId = new Identifier(this.getDecoder().getID()); 
+		
+		// Set values for current id.
+		int currLayer = helper.getValue(currId, layerIndex);
+		int currU = helper.getValue(currId, uIndex);
+		int currV = helper.getValue(currId, vIndex);
+		
+		// Create an ExpandedIdentifier for the current id.
+		IExpandedIdentifier thisId = helper.unpack(currId);
+				
+		// Create return array.
+		List<Long> neighbors = new ArrayList<Long>();
+		
+		// Loop over layer range.
+		for (int ilayer=-layerRange; ilayer<=layerRange; ilayer++)
+		{
+			// Loop over X range.
+			for (int iu=-uRange; iu<=uRange; iu++)
+			{
+				// Loop over Y range.
+				for (int iv=-vRange; iv<=vRange; iv++)
+				{								
+					// Compute layer value.
+					int neighborLayer = currLayer + ilayer;
+					
+					if (neighborLayer >= 0 && neighborLayer < nlayers)
+					{						
+						// Compute x value.
+						int neighborU = currU + iu;
+						
+						// Compute y value.
+						int neighborV = currV + iv;
+						
+						// Create a new ExpandedIdenfier from the base Id.
+						ExpandedIdentifier neighborId = new ExpandedIdentifier(thisId);
+					
+						// Set the neighbor fields.
+						neighborId.setValue(layerIndex, neighborLayer);
+						neighborId.setValue(uIndex, neighborU);
+						neighborId.setValue(vIndex, neighborV);
+					
+						// Add the neighbor id to the return array.
+						neighbors.add(helper.pack(neighborId).getValue());					
+					}
+				}
+			}		
+		}
+		
+		long result[] = new long[neighbors.size()];		
+		int i = 0;
+		for (Long id : neighbors)
+		{
+			result[i] = id;
+			i++;
+		}
+		return result;
+	}	
+}
\ No newline at end of file

GeomConverter/src/org/lcsim/geometry/segmentation
CartesianGridXY.java 1.5 -> 1.6
diff -u -r1.5 -r1.6
--- CartesianGridXY.java	7 Oct 2009 21:24:39 -0000	1.5
+++ CartesianGridXY.java	8 Oct 2009 18:52:22 -0000	1.6
@@ -4,45 +4,31 @@
 import hep.physics.vec.Hep3Vector;
 
 import java.util.ArrayList;
-import java.util.List;
 
 import org.jdom.DataConversionException;
 import org.jdom.Element;
 import org.lcsim.detector.IDetectorElement;
 import org.lcsim.detector.IDetectorElementContainer;
-import org.lcsim.detector.identifier.ExpandedIdentifier;
 import org.lcsim.detector.identifier.IExpandedIdentifier;
 import org.lcsim.detector.identifier.IIdentifier;
 import org.lcsim.detector.identifier.IIdentifierHelper;
 import org.lcsim.detector.identifier.Identifier;
 import org.lcsim.detector.solids.Box;
 import org.lcsim.detector.solids.Inside;
-import org.lcsim.detector.solids.Trd;
 import org.lcsim.geometry.util.IDDescriptor;
 
 /**
- * Simplified XY grid based on GridXYZ segmentation.
+ * XY Cartesian grid segmentation.
  * 
  * @author jeremym
  */
-public class CartesianGridXY extends SegmentationBase
+public class CartesianGridXY extends AbstractCartesianGrid
 {	
 	private double gridSizeX = 0;
 	private double gridSizeY = 0;
 
 	private int xIndex = -1;
 	private int yIndex = -1;
-	private int layerIndex = -1;
-
-	private double[] localPosition =
-	{ 0, 0, 0 };
-
-	private double[] globalPosition =
-	{ 0, 0, 0 };
-	
-	private boolean needsCompute = true;
-	
-	List<Integer> geomFields;
 
 	public CartesianGridXY(Element node) throws DataConversionException
 	{
@@ -66,125 +52,28 @@
 			throw new RuntimeException("Missing gridSizeY parameter.");
 		}
 	}
-
-	public boolean supportsNeighbours()
-	{
-		return true;
-	}
 	
-	// TODO: Bounds check on x and y indices.
 	public long[] getNeighbourIDs(int layerRange, int xRange, int yRange)
 	{
-		if (this.getDecoder().getID() == 0)
-			throw new RuntimeException("No current ID is set.");
-		
-		// Get the IdentifierHelper.
-		IIdentifierHelper helper = detector.getDetectorElement().getIdentifierHelper();
-		
-		// Get number of layers.
-		int nlayers = this.getNumberOfLayers();
-		
-		// Current packed id.
-		IIdentifier currId = new Identifier(this.getDecoder().getID()); 
-		
-		// Set values for current id.
-		int currLayer = helper.getValue(currId, layerIndex);
-		int currX = helper.getValue(currId, xIndex);
-		int currY = helper.getValue(currId, yIndex);
-		
-		// Create an ExpandedIdentifier for the current id.
-		IExpandedIdentifier thisId = helper.unpack(currId);
-				
-		// Create return array.
-		List<Long> neighbors = new ArrayList<Long>();
-		
-		// Loop over layer range.
-		//int ineighbor = 0;
-		for (int ilayer=-layerRange; ilayer<=layerRange; ilayer++)
-		{
-			// Loop over X range.
-			for (int ix=-xRange; ix<=xRange; ix++)
-			{
-				// Loop over Y range.
-				for (int iy=-yRange; iy<=yRange; iy++)
-				{								
-					// Compute layer value.
-					int neighborLayer = currLayer + ilayer;
-					
-					if (neighborLayer >= 0 && neighborLayer < nlayers)
-					{						
-						// Compute x value.
-						int neighborX = currX + ix;
-						
-						// Compute y value.
-						int neighborY = currY + iy;
-						
-						// Create a new ExpandedIdenfier from the base Id.
-						ExpandedIdentifier neighborId = new ExpandedIdentifier(thisId);
-					
-						// Set the neighbor fields.
-						neighborId.setValue(layerIndex, neighborLayer);
-						neighborId.setValue(xIndex, neighborX);
-						neighborId.setValue(yIndex, neighborY);
-					
-						// Add the neighbor id to the return array.
-						neighbors.add(helper.pack(neighborId).getValue());					
-					}
-				}
-			}		
-		}
-		
-		long result[] = new long[neighbors.size()];		
-		int i = 0;
-		for (Long id : neighbors)
-		{
-			result[i] = id;
-			i++;
-		}
-		return result;
+		return getNeighbourIDs(layerRange, xRange, yRange, xIndex, yIndex);	
 	}
-	 
-	public long findCellContainingXYZ(double x, double y, double z) 
+	 	
+	protected void setSegmentationValues(IExpandedIdentifier geomId, Hep3Vector localPositionVec)
 	{
-		Hep3Vector pos = new BasicHep3Vector(x,y,z);
-		IDetectorElement de = 
-			getSubdetector().getDetectorElement().findDetectorElement(pos);
-		if (!de.getGeometry().getPhysicalVolume().isSensitive())
-		{
-			throw new RuntimeException("The volume " + de.getName() + " is not sensitive.");
-		}
-		Hep3Vector localPosition = de.getGeometry().transformGlobalToLocal(pos);
-		ExpandedIdentifier geomId = new ExpandedIdentifier(de.getExpandedIdentifier());
-		geomId.setValue(xIndex, getXBin(localPosition.x()));
-		geomId.setValue(yIndex, getYBin(localPosition.y()));
-		return getSubdetector().getDetectorElement().getIdentifierHelper().pack(geomId).getValue();
+		geomId.setValue(xIndex, getXBin(localPositionVec.x()));
+		geomId.setValue(yIndex, getYBin(localPositionVec.y()));
 	}
 	
-	// FIXME: Copied from GridXYZ.
-	public int getBin(double u, double gridSizeU)
-	{
-		double u0 = gridSizeU / 2;
-		int iu = (int) Math.floor((u - u0) / gridSizeU + 0.5);
-		return iu;
-	}
-
-	// FIXME: Copied from GridXYZ.
 	public int getXBin(double x)
 	{
 		return getBin(x, gridSizeX);
 	}
 
-	// FIXME: Copied from GridXYZ.
 	public int getYBin(double y)
 	{
 		return getBin(y, gridSizeY);
 	}
 	
-	public double computePosition(int binValue, double gridSize)
-	{
-		return (((double) binValue) + 0.5) * gridSize;
-	}
-		
 	public boolean boundsCheck(long rawId)
 	{
 		IIdentifier geomId = makeGeometryIdentifier(rawId);
@@ -198,8 +87,8 @@
 			return false;
 		}
 		IDetectorElement de = deSrch.get(0);
-		double xPos = computePosition(xVal, gridSizeX);
-		double yPos = computePosition(yVal, gridSizeY);
+		double xPos = computeCoordinate(xVal, gridSizeX);
+		double yPos = computeCoordinate(yVal, gridSizeY);
 		if (de.getGeometry().getLogicalVolume().getSolid() instanceof Box)
 		{			
 			Box sensorBox = (Box)de.getGeometry().getLogicalVolume().getSolid();
@@ -218,63 +107,21 @@
 		{
 			throw new RuntimeException("Don't know how to bounds check solid " + de.getGeometry().getLogicalVolume().getSolid().getName() + ".");
 		}
-	}
-	
-	public double[] getPosition()
-	{
-		if (needsCompute)
-		{
-			computePosition();
-			needsCompute = false;
-		}
-		return globalPosition;
-	}
-	
-	private void computeGlobalPosition()
-	{											
-		// Make an id only containing geometric fields and no segmentation fields.
-		IExpandedIdentifier geomIdExp = detector.getDetectorElement().getIdentifierHelper().unpack(new Identifier(this.getDecoder().getID()), geomFields);
-		IIdentifier geomId = detector.getDetectorElement().getIdentifierHelper().pack(geomIdExp);
-
-		// Search for the the DetectorElement associated with the geometry id.
-		List<IDetectorElement> deSearch = detector.getDetectorElement().findDetectorElement(geomId);
-
-		// Check if the lookup failed.
-		if (deSearch == null || deSearch.size() == 0)
-		{
-			throw new RuntimeException("Failed to find DetectorElement with geometry id <" + geomIdExp.toString() + "> !");
-		}
-
-		// Set the DetectorElement to use for local to global transform.
-		IDetectorElement sensor = deSearch.get(0);
-
-		// Create a vector of the local position.
-		Hep3Vector posVecLocal = new BasicHep3Vector(localPosition[0], localPosition[1], localPosition[2]);
-		
-		// Compute the global position of the hit using the DetectorElement.
-		Hep3Vector posVecGlobal = sensor.getGeometry().transformLocalToGlobal(posVecLocal);
-
-		// Set the internal global position array.
-		globalPosition[0] = posVecGlobal.x();
-		globalPosition[1] = posVecGlobal.y();
-		globalPosition[2] = posVecGlobal.z();
-	}
+	}	
 					
-	public void setID(long id)
-	{
-		super.setID(id);
-		needsCompute = true;
-	}
 
 	public void setIDDescription(IDDescriptor id)
 	{
 		super.setIDDescription(id);
-				
-                // TODO: put this setup code into separate method	
+		setupGeomFields(id);	
+	}
+	
+	public void setupGeomFields(IDDescriptor id)
+	{
 		if (geomFields == null)
 		{
 			geomFields = new ArrayList<Integer>();
-			
+
 			xIndex = id.indexOf("x");
 			yIndex = id.indexOf("y");
 			layerIndex = id.indexOf("layer");
@@ -289,23 +136,8 @@
 				}
 			}
 		}
-	}	
-	
-	public double getX()
-	{
-		return getPosition()[0];
-	}
-
-	public double getY()
-	{
-		return getPosition()[1];
-	}
-
-	public double getZ()
-	{
-		return getPosition()[2];
 	}
-	
+		
 	private void computeLocalX()
 	{	
 		localPosition[0] = (((double) getValue(xIndex)) + 0.5) * gridSizeX;	
@@ -316,42 +148,10 @@
 		localPosition[1] = (((double) getValue(yIndex)) + 0.5) * gridSizeY;
 	}
 	
-	private void computePosition()
-	{
-		computeLocalPosition();
-		computeGlobalPosition();
-	}
-
-	private void computeLocalPosition()
+	protected void computeLocalPosition()
 	{
 		localPosition[0] = localPosition[1] = localPosition[2] = 0.0;
 		computeLocalX();
 		computeLocalY();
-	}
-	
-	private IIdentifier makeGeometryIdentifier(long id)
-	{
-		IExpandedIdentifier geomIdExp = detector.getDetectorElement().getIdentifierHelper().unpack(new Identifier(id), geomFields);
-		return detector.getDetectorElement().getIdentifierHelper().pack(geomIdExp);
-	}
-/*	
-	public double getMinValue(String field, long id)
-	{
-		double min = 0;
-		if (field.equals("x"))
-		{
-			
-		}
-		else if (field.equals("y"))
-		{
-			
-		}
-		else
-		{
-			
-		}
-		return min;
-	}
-*/
-	
-}
+	}	
+}
\ No newline at end of file

GeomConverter/src/org/lcsim/geometry/segmentation
CartesianGridXZ.java 1.3 -> 1.4
diff -u -r1.3 -r1.4
--- CartesianGridXZ.java	7 Oct 2009 21:24:39 -0000	1.3
+++ CartesianGridXZ.java	8 Oct 2009 18:52:22 -0000	1.4
@@ -4,13 +4,11 @@
 import hep.physics.vec.Hep3Vector;
 
 import java.util.ArrayList;
-import java.util.List;
 
 import org.jdom.DataConversionException;
 import org.jdom.Element;
 import org.lcsim.detector.IDetectorElement;
 import org.lcsim.detector.IDetectorElementContainer;
-import org.lcsim.detector.identifier.ExpandedIdentifier;
 import org.lcsim.detector.identifier.IExpandedIdentifier;
 import org.lcsim.detector.identifier.IIdentifier;
 import org.lcsim.detector.identifier.IIdentifierHelper;
@@ -20,29 +18,18 @@
 import org.lcsim.geometry.util.IDDescriptor;
 
 /**
- * Simplified XY grid based on GridXYZ segmentation.
+ * XZ Cartesian grid segmentation. 
  * 
  * @author jeremym
  */
-public class CartesianGridXZ extends SegmentationBase
+public class CartesianGridXZ extends AbstractCartesianGrid
 {	
 	private double gridSizeX = 0;
 	private double gridSizeZ = 0;
 
 	private int xIndex = -1;
 	private int zIndex = -1;
-	private int layerIndex = -1;
-
-	private double[] localPosition =
-	{ 0, 0, 0 };
-
-	private double[] globalPosition =
-	{ 0, 0, 0 };
-	
-	private boolean needsCompute = true;
 	
-	List<Integer> geomFields;
-
 	public CartesianGridXZ(Element node) throws DataConversionException
 	{
 		super(node);
@@ -66,125 +53,27 @@
 		}
 	}
 
-	public boolean supportsNeighbours()
-	{
-		return true;
-	}
-	
-	// TODO: Bounds check on x and y indices.
-	// TODO: Put into util or superclass.
 	public long[] getNeighbourIDs(int layerRange, int xRange, int zRange)
 	{
-		if (this.getDecoder().getID() == 0)
-			throw new RuntimeException("No current ID is set.");
-		
-		// Get the IdentifierHelper.
-		IIdentifierHelper helper = detector.getDetectorElement().getIdentifierHelper();
-		
-		// Get number of layers.
-		int nlayers = this.getNumberOfLayers();
-		
-		// Current packed id.
-		IIdentifier currId = new Identifier(this.getDecoder().getID()); 
-		
-		// Set values for current id.
-		int currLayer = helper.getValue(currId, layerIndex);
-		int currX = helper.getValue(currId, xIndex);
-		int currZ = helper.getValue(currId, zIndex);
-		
-		// Create an ExpandedIdentifier for the current id.
-		IExpandedIdentifier thisId = helper.unpack(currId);
-				
-		// Create return array.
-		List<Long> neighbors = new ArrayList<Long>();
-		
-		// Loop over layer range.
-		for (int ilayer=-layerRange; ilayer<=layerRange; ilayer++)
-		{
-			// Loop over X range.
-			for (int ix=-xRange; ix<=xRange; ix++)
-			{
-				// Loop over Y range.
-				for (int iz=-zRange; iz<=zRange; iz++)
-				{								
-					// Compute layer value.
-					int neighborLayer = currLayer + ilayer;
-					
-					if (neighborLayer >= 0 && neighborLayer < nlayers)
-					{						
-						// Compute x value.
-						int neighborX = currX + ix;
-						
-						// Compute y value.
-						int neighborY = currZ + iz;
-						
-						// Create a new ExpandedIdenfier from the base Id.
-						ExpandedIdentifier neighborId = new ExpandedIdentifier(thisId);
-					
-						// Set the neighbor fields.
-						neighborId.setValue(layerIndex, neighborLayer);
-						neighborId.setValue(xIndex, neighborX);
-						neighborId.setValue(zIndex, neighborY);
-					
-						// Add the neighbor id to the return array.
-						neighbors.add(helper.pack(neighborId).getValue());					
-					}
-				}
-			}		
-		}
-		
-		long result[] = new long[neighbors.size()];		
-		int i = 0;
-		for (Long id : neighbors)
-		{
-			result[i] = id;
-			i++;
-		}
-		return result;
-	}
-	 
-	// TODO: Put into util or superclass.
-	public long findCellContainingXYZ(double x, double y, double z) 
-	{
-		Hep3Vector pos = new BasicHep3Vector(x,y,z);
-		IDetectorElement de = 
-			getSubdetector().getDetectorElement().findDetectorElement(pos);
-		if (!de.getGeometry().getPhysicalVolume().isSensitive())
-		{
-			throw new RuntimeException("The volume " + de.getName() + " is not sensitive.");
-		}
-		Hep3Vector localPosition = de.getGeometry().transformGlobalToLocal(pos);
-		ExpandedIdentifier geomId = new ExpandedIdentifier(de.getExpandedIdentifier());
-		geomId.setValue(xIndex, getXBin(localPosition.x()));
-		geomId.setValue(zIndex, getZBin(localPosition.z()));
-		return getSubdetector().getDetectorElement().getIdentifierHelper().pack(geomId).getValue();
+		return getNeighbourIDs(layerRange, xRange, zRange, xIndex, zIndex);	
 	}
-	
-	// FIXME: Copied from GridXYZ.
-	public int getBin(double u, double gridSizeU)
+	 	
+	protected void setSegmentationValues(IExpandedIdentifier geomId, Hep3Vector localPositionVec)
 	{
-		double u0 = gridSizeU / 2;
-		int iu = (int) Math.floor((u - u0) / gridSizeU + 0.5);
-		return iu;
+		geomId.setValue(xIndex, getXBin(localPositionVec.x()));
+		geomId.setValue(zIndex, getZBin(localPositionVec.z()));
 	}
 
-	// FIXME: Copied from GridXYZ.
 	public int getXBin(double x)
 	{
 		return getBin(x, gridSizeX);
 	}
 
-	// FIXME: Copied from GridXYZ.
 	public int getZBin(double z)
 	{
 		return getBin(z, gridSizeZ);
 	}
-	
-	public double computePosition(int binValue, double gridSize)
-	{
-		return (((double) binValue) + 0.5) * gridSize;
-	}
-		
+			
 	public boolean boundsCheck(long rawId)
 	{
 		IIdentifier geomId = makeGeometryIdentifier(rawId);
@@ -198,8 +87,8 @@
 			return false;
 		}
 		IDetectorElement de = deSrch.get(0);
-		double xPos = computePosition(xVal, gridSizeX);
-		double zPos = computePosition(zVal, gridSizeZ);
+		double xPos = computeCoordinate(xVal, gridSizeX);
+		double zPos = computeCoordinate(zVal, gridSizeZ);
 		if (de.getGeometry().getLogicalVolume().getSolid() instanceof Trd)
 		{
 			Trd sensorTrd = (Trd)de.getGeometry().getLogicalVolume().getSolid();
@@ -208,7 +97,7 @@
 			{
 				return true;
 			}
-			// TODO: Handle edge case with partial cells.  (How???)
+			// TODO: Handle edge case with cells that have centers slightly outside readout volume.
 			else
 			{
 				return false;
@@ -218,65 +107,14 @@
 		{
 			throw new RuntimeException("Don't know how to bounds check solid " + de.getGeometry().getLogicalVolume().getSolid().getName() + ".");
 		}
-	}
+	}			
 	
-	public double[] getPosition()
+	protected void setupGeomFields(IDDescriptor id)
 	{
-		if (needsCompute)
-		{
-			computePosition();
-			needsCompute = false;
-		}
-		return globalPosition;
-	}
-	
-	private void computeGlobalPosition()
-	{											
-		// Make an id only containing geometric fields and no segmentation fields.
-		IExpandedIdentifier geomIdExp = detector.getDetectorElement().getIdentifierHelper().unpack(new Identifier(this.getDecoder().getID()), geomFields);
-		IIdentifier geomId = detector.getDetectorElement().getIdentifierHelper().pack(geomIdExp);
-
-		// Search for the the DetectorElement associated with the geometry id.
-		List<IDetectorElement> deSearch = detector.getDetectorElement().findDetectorElement(geomId);
-
-		// Check if the lookup failed.
-		if (deSearch == null || deSearch.size() == 0)
-		{
-			throw new RuntimeException("Failed to find DetectorElement with geometry id <" + geomIdExp.toString() + "> !");
-		}
-
-		// Set the DetectorElement to use for local to global transform.
-		IDetectorElement sensor = deSearch.get(0);
-		
-		//System.out.println(sensor.getName() + " - " + sensor.getGeometry().getPosition());
-
-		// Create a vector of the local position.		
-		Hep3Vector posVecLocal = new BasicHep3Vector(localPosition[0], localPosition[1], localPosition[2]);
-		//System.out.println("posVecLocal: " + posVecLocal.toString());
-		
-		// Compute the global position of the hit using the DetectorElement.
-		Hep3Vector posVecGlobal = sensor.getGeometry().transformLocalToGlobal(posVecLocal);
-
-		// Set the internal global position array.
-		globalPosition[0] = posVecGlobal.x();
-		globalPosition[1] = posVecGlobal.y();
-		globalPosition[2] = posVecGlobal.z();
-	}
-					
-	public void setID(long id)
-	{
-		super.setID(id);
-		needsCompute = true;
-	}
-
-	public void setIDDescription(IDDescriptor id)
-	{
-		super.setIDDescription(id);
-					
 		if (geomFields == null)
 		{
 			geomFields = new ArrayList<Integer>();
-			
+
 			xIndex = id.indexOf("x");
 			zIndex = id.indexOf("z");
 			layerIndex = id.indexOf("layer");
@@ -291,23 +129,8 @@
 				}
 			}
 		}
-	}	
-	
-	public double getX()
-	{
-		return getPosition()[0];
 	}
-
-	public double getY()
-	{
-		return getPosition()[1];
-	}
-
-	public double getZ()
-	{
-		return getPosition()[2];
-	}
-	
+		
 	private void computeLocalX()
 	{	
 		localPosition[0] = (((double) getValue(xIndex)) + 0.5) * gridSizeX;	
@@ -318,23 +141,10 @@
 		localPosition[2] = (((double) getValue(zIndex)) + 0.5) * gridSizeZ;
 	}
 	
-	private void computePosition()
-	{
-		computeLocalPosition();
-		computeGlobalPosition();
-	}
-
-	private void computeLocalPosition()
+	protected void computeLocalPosition()
 	{
 		localPosition[0] = localPosition[1] = localPosition[2] = 0.0;
 		computeLocalX();
 		computeLocalZ();
-	}
-	
-	private IIdentifier makeGeometryIdentifier(long id)
-	{
-		IExpandedIdentifier geomIdExp = detector.getDetectorElement().getIdentifierHelper().unpack(new Identifier(id), geomFields);
-		return detector.getDetectorElement().getIdentifierHelper().pack(geomIdExp);
-	}
-	
+	}	
 }
\ No newline at end of file
CVSspam 0.2.8