GeomConverter/src/org/lcsim/geometry/segmentation
diff -u -r1.25 -r1.26
--- GridXYZ.java 23 May 2008 00:27:33 -0000 1.25
+++ GridXYZ.java 10 Sep 2009 01:13:31 -0000 1.26
@@ -7,477 +7,571 @@
import static java.lang.Math.atan;
import static java.lang.Math.atan2;
import static java.lang.Math.sqrt;
+import hep.physics.vec.BasicHep3Vector;
+import hep.physics.vec.Hep3Vector;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map.Entry;
import org.jdom.DataConversionException;
import org.jdom.Element;
-
-import org.lcsim.geometry.util.IDDescriptor;
-import org.lcsim.geometry.util.IDEncoder;
+import org.lcsim.detector.IDetectorElement;
+import org.lcsim.detector.identifier.IExpandedIdentifier;
+import org.lcsim.detector.identifier.IIdentifier;
+import org.lcsim.detector.identifier.IIdentifierDictionary;
+import org.lcsim.detector.identifier.IIdentifierField;
+import org.lcsim.detector.identifier.IIdentifierHelper;
+import org.lcsim.detector.identifier.Identifier;
+import org.lcsim.geometry.Subdetector;
import org.lcsim.geometry.layer.Layer;
import org.lcsim.geometry.layer.LayerStack;
import org.lcsim.geometry.subdetector.CylindricalCalorimeter;
+import org.lcsim.geometry.subdetector.PolyhedraBarrelCalorimeter;
+import org.lcsim.geometry.subdetector.PolyhedraEndcapCalorimeter;
+import org.lcsim.geometry.util.IDDescriptor;
+import org.lcsim.geometry.util.IDEncoder;
/**
* @author jeremym Cartesian XYZ grid segmentation, primarily used for readout
* of planes. This segmentation is based on a local coordinate system.
*/
+// FIXME: This class needs to be refactored. It is doing way to much and has too
+// many extra methods.
public class GridXYZ extends SegmentationBase
{
- 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 int barrelIndex = -1;
- private int systemIndex = -1;
-
- private double[] _localPos =
- { 0, 0, 0 };
-
- private double[] _globalPos =
- { 0, 0, 0 };
-
- /** 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();
- }
- }
-
- public boolean supportsNeighbours()
- {
- return true;
- }
-
- /**
- * 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.
- *
- * @return array of cellIDs for the neighbouring cells
- */
- public long[] getNeighbourIDs(int layerRange, int xRange, int yRange)
- {
- // 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();
- double Rmin = this.getRMin();
-
- 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;
- int rBinMin = (int) Math.floor(Rmin / dx); // Inner radius, in units of cell width
- int rBinMax = (int) Math.ceil(Rmax / dx); // Outer radius, in units of cell width
-
- // 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));
- long candidate = encoder.setValue(yIndex, iy);
- if (ix*ix + iy*iy >= (rBinMax-1)*(rBinMax-1) || ix*ix + iy*iy <= (rBinMin+1)*(rBinMin+1)) {
- // We're near the edge. Verify that this is actually a legal value:
- this.setID(candidate);
- double candAbsZ = Math.abs(this.getZ());
- double candRhoSq = (this.getX()*this.getX() + this.getY()*this.getY());
- boolean candValid = (candAbsZ >= getZMin() && candAbsZ <= getZMax() && candRhoSq >= (getRMin()*getRMin()) && candRhoSq <= (getRMax()*getRMax()));
- if (candValid) {
- // OK -- neighbour is at a legal spacepoint
- result[size++] = candidate;
- } else {
- // Failure -- this can happen if the "neighbour" was just us wandering off the grid
- // Not serious -- don't add the candidate to the output, but don't panic either.
- }
- // Reset ID to previous value
+ 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 int barrelIndex = -1;
+ private int systemIndex = -1;
+
+ private double[] localPosition =
+ { 0, 0, 0 };
+
+ private double[] globalPosition =
+ { 0, 0, 0 };
+
+ /** 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();
+ }
+ }
+
+ public boolean supportsNeighbours()
+ {
+ return true;
+ }
+
+ /**
+ * 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.
+ *
+ * @return array of cellIDs for the neighbouring cells
+ */
+ // FIXME: This method is overly complicated given that the grid will be symmetric
+ // about 0,0 through all layers for all the subdetectors that we define.
+ // Should just return same u,v and layer +-1.
+ public long[] getNeighbourIDs(int layerRange, int xRange, int yRange)
+ {
+ // 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();
+ double Rmin = this.getRMin();
+
+ 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;
+ int rBinMin = (int) Math.floor(Rmin / dx); // Inner radius, in units of cell width
+ int rBinMax = (int) Math.ceil(Rmax / dx); // Outer radius, in units of cell width
+
+ // 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);
- } else {
- // We're far from the edge. Go ahead and add it without spending CPU time on a check
- result[size++] = candidate;
- }
- }
- }
- }
-
- // reset encoder and decoder
- this.setID(saveID);
- if (size < result.length)
- {
- long[] temp = new long[size];
- 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.
- 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()
- {
- 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()
- {
- 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)
- {
- _localPos[0] = (((double) getValue(xIndex)) + 0.5) * gridSizeX;
- }
- }
-
- private void computeLocalY()
- {
- if (yIndex != -1)
- {
- _localPos[1] = (((double) getValue(yIndex)) + 0.5) * gridSizeY;
- }
- }
-
- private void computeLocalZ()
- {
- if (zIndex != -1)
- {
- _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 indices flagged with invalid values. It is actually okay
- * to have all 0's, because this will return the center of the volume, at
- * least in analogous Geant4 impl of this class.
- */
- 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");
- }
-
- try
- {
- barrelIndex = id.indexOf("barrel");
- }
- catch (IllegalArgumentException x)
- {
- barrelIndex = -1;
- }
- systemIndex = id.indexOf("system");
- }
-
- /**
- * 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 Cartesian X coordinate.
- * @param y Cartesian Y coordinate.
- * @param z Cartesian Z coordinate.
- *
- * @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);
- int ibar = ( z<0 ? 2 : 1 );
- int system = detector.getSystemID();
-
- IDEncoder enc = new IDEncoder(descriptor);
- enc.setValue(layerIndex, ilay);
- enc.setValue(xIndex, ix);
- enc.setValue(yIndex, iy);
- enc.setValue(barrelIndex, ibar);
- enc.setValue(systemIndex, system);
- 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;
- }
+ // 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));
+ long candidate = encoder.setValue(yIndex, iy);
+ if (ix*ix + iy*iy >= (rBinMax-1)*(rBinMax-1) || ix*ix + iy*iy <= (rBinMin+1)*(rBinMin+1)) {
+ // We're near the edge. Verify that this is actually a legal value:
+ this.setID(candidate);
+ double candAbsZ = Math.abs(this.getZ());
+ double candRhoSq = (this.getX()*this.getX() + this.getY()*this.getY());
+ boolean candValid = (candAbsZ >= getZMin() && candAbsZ <= getZMax() && candRhoSq >= (getRMin()*getRMin()) && candRhoSq <= (getRMax()*getRMax()));
+ if (candValid) {
+ // OK -- neighbour is at a legal spacepoint
+ result[size++] = candidate;
+ } else {
+ // Failure -- this can happen if the "neighbour" was just us wandering off the grid
+ // Not serious -- don't add the candidate to the output, but don't panic either.
+ }
+ // Reset ID to previous value
+ this.setID(id);
+ } else {
+ // We're far from the edge. Go ahead and add it without spending CPU time on a check
+ result[size++] = candidate;
+ }
+ }
+ }
+ }
+
+ // reset encoder and decoder
+ this.setID(saveID);
+ if (size < result.length)
+ {
+ long[] temp = new long[size];
+ 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: Following four methods use the specific subdetector type CylindricalCalorimeter
+ // but should NOT.
+
+ 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 computable from x and y.
+
+ public double getPhi()
+ {
+ 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()
+ {
+ 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 globalPosition;
+ }
+
+ private void computePosition()
+ {
+ computeLocalPosition();
+ computeGlobalPosition();
+ }
+
+ private void computeLocalPosition()
+ {
+ localPosition[0] = localPosition[1] = localPosition[2] = 0.0;
+ computeLocalX();
+ computeLocalY();
+ computeLocalZ();
+ }
+
+ List<Integer> geomFields;
+ IIdentifierHelper helper;
+ IIdentifierDictionary iddict;
+
+ // FIXME: This method needs to be generalized to all calorimeters, including the old endcaps.
+ // For the general computation to work, they will need to have properly defined sensor
+ // DetectorElements. Currently, it has a specific case for PolyhedraBarrel and PolyhedraEndcap.
+ private void computeGlobalPosition()
+ {
+ globalPosition[0] = globalPosition[1] = globalPosition[2] = 0.0;
+
+ // On the first time through, setup list with geometry fields.
+ // FIXME: How to set this up once at the beginning and not call from here?
+ if (geomFields == null)
+ {
+ geomFields = new ArrayList<Integer>();
+
+ helper = detector.getDetectorElement().getIdentifierHelper();
+ iddict = helper.getIdentifierDictionary();
+
+ for (Entry<Integer,IIdentifierField> field : iddict.getFieldIndexMap().entrySet())
+ {
+ String label = field.getValue().getLabel();
+ if (!label.equals("x") && !label.equals("y") && !label.equals("z"))
+ {
+ geomFields.add(field.getKey());
+ }
+ }
+ }
+
+ // Compute for PolyhedraBarrel and PolyhedraEndcap.
+ if (detector instanceof PolyhedraBarrelCalorimeter
+ || detector instanceof PolyhedraEndcapCalorimeter)
+ {
+ // Make an id only containing geometric fields and no segmentation fields.
+ IExpandedIdentifier geomIdExp = helper.unpack(new Identifier(this.getDecoder().getID()), geomFields);
+ IIdentifier geomId = helper.pack(geomIdExp);
+
+ // Find the DetectorElement associated with the geometry id.
+ List<IDetectorElement> deSearch = detector.getDetectorElement().findDetectorElement(geomId);
+
+ // Check if lookup failed.
+ if (deSearch == null || deSearch.size() == 0)
+ {
+ throw new RuntimeException("Failed to find DetectorElement with geometry id <" + geomIdExp.toString() + ">!");
+ }
+
+ // Set the DetectorElement associated to the hit.
+ 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 global position array.
+ globalPosition[0] = posVecGlobal.x();
+ globalPosition[1] = posVecGlobal.y();
+ globalPosition[2] = posVecGlobal.z();
+ }
+ // Other types, including CylindricalEndcapCalorimeter.
+ else
+ {
+ globalPosition = transformLocalToGlobal(localPosition);
+ }
+ }
+
+ public void setSubdetector(Subdetector subdet)
+ {
+ super.setSubdetector(subdet);
+ }
+
+ private void computeLocalX()
+ {
+ if (xIndex != -1)
+ {
+ localPosition[0] = (((double) getValue(xIndex)) + 0.5) * gridSizeX;
+ }
+ }
+
+ private void computeLocalY()
+ {
+ if (yIndex != -1)
+ {
+ localPosition[1] = (((double) getValue(yIndex)) + 0.5) * gridSizeY;
+ }
+ }
+
+ private void computeLocalZ()
+ {
+ if (zIndex != -1)
+ {
+ localPosition[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 indices flagged with invalid values. It is actually okay
+ * to have all 0's, because this will return the center of the volume, at
+ * least in analogous Geant4 impl of this class.
+ */
+ 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");
+ }
+
+ try
+ {
+ barrelIndex = id.indexOf("barrel");
+ }
+ catch (IllegalArgumentException x)
+ {
+ barrelIndex = -1;
+ }
+ systemIndex = id.indexOf("system");
+ }
+
+ /**
+ * Returns positive distance from IR to center of sensitive slice of any
+ * layer
+ *
+ * @param layer The 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 Cartesian X coordinate.
+ * @param y Cartesian Y coordinate.
+ * @param z Cartesian Z coordinate.
+ *
+ * @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);
+ int ibar = ( z<0 ? 2 : 1 );
+ int system = detector.getSystemID();
+
+ IDEncoder enc = new IDEncoder(descriptor);
+ enc.setValue(layerIndex, ilay);
+ enc.setValue(xIndex, ix);
+ enc.setValue(yIndex, iy);
+ enc.setValue(barrelIndex, ibar);
+ enc.setValue(systemIndex, system);
+ 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)
[truncated at 1000 lines; 33 more skipped]