1 added + 6 modified, total 7 files
GeomConverter/src/org/lcsim/geometry/segmentation
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
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
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
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
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
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
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