Print

Print


Commit in GeomConverter/src/org/lcsim/geometry/segmentation on MAIN
GridXYZ.java+23-11.24 -> 1.25
NonprojectiveCylinder.java+56-121.25 -> 1.26
+79-13
2 modified files
MJC: Re-introduce geometry fixes, now a lot faster

GeomConverter/src/org/lcsim/geometry/segmentation
GridXYZ.java 1.24 -> 1.25
diff -u -r1.24 -r1.25
--- GridXYZ.java	20 May 2008 18:19:40 -0000	1.24
+++ GridXYZ.java	23 May 2008 00:27:33 -0000	1.25
@@ -101,6 +101,7 @@
         double dy = gridSizeY;
         int zBins = detector.getLayering().getLayerCount();
         double Rmax = ((CylindricalCalorimeter) detector).getOuterRadius();
+	double Rmin = this.getRMin();
 
         int size = 0;
         int refLayer = values[layerIndex];
@@ -115,6 +116,8 @@
 
             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);
@@ -155,7 +158,26 @@
 
 // 		    System.out.println("Adding neighbor: "+ilay+" "+ix+" "
 // 				       +iy+", total="+ (size+1));
-                    result[size++] = encoder.setValue(yIndex, iy);
+                    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;
+		    }
                 }
             }
         }

GeomConverter/src/org/lcsim/geometry/segmentation
NonprojectiveCylinder.java 1.25 -> 1.26
diff -u -r1.25 -r1.26
--- NonprojectiveCylinder.java	20 May 2008 18:19:40 -0000	1.25
+++ NonprojectiveCylinder.java	23 May 2008 00:27:33 -0000	1.26
@@ -138,6 +138,7 @@
         IDEncoder gnEncoder = new IDEncoder(descriptor);
         BaseIDDecoder gnDecoder = new BaseIDDecoder(descriptor);
         gnEncoder.setValues(values);
+        long origID = gnEncoder.getID();
         gnDecoder.setID(gnEncoder.getID());
 
         int nMax = (2*layerRange + 1)*(2*zRange + 1)*(2*phiRange + 1) - 1;
@@ -147,7 +148,40 @@
         double theta = getTheta();
         double phi = getPhi();
 
-        int zBins = (int) Math.floor((getZMax() - getZMin()) / getGridSizeZ());
+        // Be careful with # of Z bins.
+	// The rules are:
+	//   * A cell is valid if its center has (z >= getZMin() && z <= getZMax())
+	//   * The center of a bin is always at z = (integer + 0.5) * gridSizeZ
+	//      => Bins are arranged about z=0, with a bin edge at z=0
+	//      => If getZMin()==-getZMax() then there is always an even number of bins
+	//
+	// If things are nicely symmetric, i.e. getZMin()==-getZMax(), then this turns
+	// into a very easy problem: if we have n bins ON EACH SIDE (for integer n) then
+	//       n - 0.5 <= zMax/gridSizeZ < n + 0.5
+	// and so we can work backwards (and add in the other half) to obtain the total
+	// number of bins 2n as 2*Math.round((zMax-zMin)/(2.0*gridSizeZ)).
+	//
+	// If things are not symmetric but span the z=0 point then we're OK as long as
+	// we're careful -- the easiest way to look at it is to do each half of the
+	// detector separately:
+	//    Number of bins in z>0:  Math.round((zMax - 0.0)/gridSizeZ)
+	//    Number of bins in z<0:  Math.round((0.0 - zMin)/gridSizeZ)
+	//
+	// If things are asymmetric and do not include z=0 then things are more tricky again.
+	// We'd have to work like this:
+	//    a) find the first bin-center z1 after GetZMin()
+	//    b) find the last bin-center z2 before GetZMax()
+	//    c) count number of bins as Math.round((z2-z1)/gridSizeZ)
+	// where 
+	//   z1 = gridSizeZ * (Math.ceil ((zMin/gridSizeZ)+0.5) - 0.5)
+	//   z2 = gridSizeZ * (Math.floor((zMax/gridSizeZ)-0.5) + 0.5)
+	//
+	// So the most general form for the number of bins should be
+	//   Math.round( (gridSizeZ*(Math.floor((zMax/gridSizeZ)-0.5)+0.5) - gridSizeZ*(Math.floor((zMax/gridSizeZ)-0.5)+0.5) ) / gridSizeZ )
+	//
+	// ... but we will assume that the detector is symmetric here -- that is true
+	// for any barrel calorimeter generated from a compact.xml geometry file.
+	int zBins = 2 * (int) Math.round( (getZMax()-getZMin())/(2.0*getGridSizeZ()) );
 
         int size = 0;
         for (int i = -layerRange; i <= layerRange; ++i)
@@ -159,24 +193,34 @@
             gnEncoder.setValue(layerIndex, ilay);
 
             double dphi = this.computeDeltaPhiForLayer(ilay);
-            int phiBins = (int) Math.floor(2 * Math.PI / dphi);
+            int phiBins = (int) Math.round(2 * Math.PI / dphi); // Use round() not floor() since a floor() was already applied in the definition of dphi
 
-            double cylR = getRadiusSensitiveMid(ilay);
-            double x = cylR * Math.cos(phi);
-            double y = cylR * Math.sin(phi);
-            double z = cylR / Math.tan(theta);
-
-            long id = this.findCellContainingXYZ(x,y,z);
-            if(id==0) continue;
+	    if (i != 0) {
+                double cylR = getRadiusSensitiveMid(ilay);
+                double x = cylR * Math.cos(phi);
+                double y = cylR * Math.sin(phi);
+                double z = cylR / Math.tan(theta);
+
+                long id = this.findCellContainingXYZ(x,y,z);
+                if(id==0) continue;
+                // save indices in a new array, as values[] keeps the original ref
+                gnDecoder.setID(id);
+            } else {
+		// This is the original layer => center cell is just the original cell
+                gnDecoder.setID(origID);
+            }
 
-            // save indices in a new array, as values[] keeps the original ref
-            gnDecoder.setID(id);
             for (int j = -zRange; j <= zRange; ++j)
             {
                 int iz = gnDecoder.getValue(zIndex) + j;
 
-                if (iz < -zBins / 2 || iz >= zBins / 2)
+                if (iz < -zBins / 2 || iz >= zBins / 2) {
+		    // We make the implicit assumption that detector is symmetric, and so number 
+		    // of bins is even and looks like [-n, +n-1]. For example, for the
+		    // very simple case of two bins, the range of bin indices is {-1, 0}.
+		    // In this instance we're outside the valid range, so skip this bin.
                     continue;
+		}
                 gnEncoder.setValue(zIndex, iz);
 
                 for (int k = -phiRange; k <= phiRange; ++k)
CVSspam 0.2.8