GeomConverter/src/org/lcsim/geometry/compact/converter/lcdd
diff -u -r1.1 -r1.2
--- HPSEcal3.java 24 Aug 2011 22:10:16 -0000 1.1
+++ HPSEcal3.java 29 Aug 2011 23:06:07 -0000 1.2
@@ -5,6 +5,9 @@
import static java.lang.Math.sin;
import static java.lang.Math.tan;
+import java.util.ArrayList;
+import java.util.List;
+
import org.jdom.Element;
import org.jdom.JDOMException;
import org.lcsim.geometry.compact.converter.lcdd.util.Box;
@@ -20,27 +23,41 @@
/**
* LCDD model for the HPS inner ECal.
*
- * Coordinate System Notes:
+ * Coordinate System defined as follows:
*
- * Beam travels in +X direction.
- * Magnetic field is -Z.
- * Y is the beam bend plane.
+ * <ul>
+ * <li>Beam travels in +X direction.</li>
+ * <li>Magnetic field is in -Z.</li>
+ * <li>Y is the beam bend plane.</li>
+ * </ul>
*
- * The dimensions element defines the crystal HALF dimensions: x1, x2, y1, y2, and z.
+ * The <dimensions> element defines the crystal HALF dimensions: x1, x2, y1, y2, and z.
*
- * The layout element defines the placement of the crystals.
+ * The <layout> element defines the placement of the crystals.
*
* <ul>
- * <li>beamgap - offset from the beamline in the Y coordinate</li>
+ * <li>beamgap - offset from the beamline in the Y coordinate of the top and bottom halves</li>
* <li>nx - number of crystals in X</li>
* <li>ny - number of crystals in Y along each side of beam</li>
- * <li>dface - distance from origin to the face of the calorimeter along X</li>
+ * <li>dface - distance from origin to the face of the calorimeter along Z</li>
* </ul>
*
+ * Under the layout element, <remove> tags can be included to exclude
+ * crystal placement by range. This element has the following parameters.
+ *
+ * <ul>
+ * <li>ixmin - minimum x index to exclude (inclusive)</li>
+ * <li>ixmax - maximum x index to exclude (inclusive)</li>
+ * <li>iymin - minimum y index to exclude (inclusive)</li>
+ * <li>iymax - maximum y index to exclude (inclusive)</li>
+ * </ul>
+ *
+ * To be excluded, a crystal's ID must pass all four of these min/max checks.
+ *
* @author Jeremy McCormick
* @author Tim Nelson
*
- * @version $Id: HPSEcal3.java,v 1.1 2011/08/24 22:10:16 jeremy Exp $
+ * @version $Id: HPSEcal3.java,v 1.2 2011/08/29 23:06:07 jeremy Exp $
*/
public class HPSEcal3 extends LCDDSubdetector
{
@@ -53,6 +70,73 @@
// Margin for mother volume.
static final double margin = 1.1;
+ List<CrystalRange> ranges = new ArrayList<CrystalRange>();
+
+ private static class CrystalRange
+ {
+ int ixmin;
+ int ixmax;
+ int iymin;
+ int iymax;
+
+ CrystalRange(Element elem) throws Exception
+ {
+ ixmin = ixmax = iymin = iymax = 0;
+
+ if (elem.getAttribute("ixmin") != null)
+ {
+ ixmin = elem.getAttribute("ixmin").getIntValue();
+ }
+ else
+ {
+ throw new RuntimeException("Missing ixmin parameter.");
+ }
+
+ if (elem.getAttribute("ixmax") != null)
+ {
+ ixmax = elem.getAttribute("ixmax").getIntValue();
+ }
+ else
+ {
+ throw new RuntimeException("Missing ixmax parameter.");
+ }
+
+ if (elem.getAttribute("iymin") != null)
+ {
+ iymin = elem.getAttribute("iymin").getIntValue();
+ }
+ else
+ {
+ throw new RuntimeException("Missing ixmax parameter.");
+ }
+
+ if (elem.getAttribute("iymax") != null)
+ {
+ iymax = elem.getAttribute("iymax").getIntValue();
+ }
+ else
+ {
+ throw new RuntimeException("Missing iymax parameter.");
+ }
+ }
+ }
+
+ private boolean checkRange(int ix, int iy, List<CrystalRange> ranges)
+ {
+ if (ranges.size() == 0)
+ return true;
+ for (CrystalRange range : ranges)
+ {
+ if ((ix >= range.ixmin && ix <= range.ixmax)
+ && ((iy >= range.iymin) && (iy <= range.iymax)))
+ {
+ return false;
+ }
+
+ }
+ return true;
+ }
+
HPSEcal3(Element node) throws JDOMException
{
super(node);
@@ -61,7 +145,7 @@
void addToLCDD(LCDD lcdd, SensitiveDetector sens) throws JDOMException
{
if (sens == null)
- throw new RuntimeException("SensitiveDetector is null!");
+ throw new RuntimeException("SensitiveDetector parameter points to null.");
// Crystal dimensions.
Element dimensions = node.getChild("dimensions");
@@ -81,6 +165,20 @@
int nx = layout.getAttribute("nx").getIntValue();
int ny = layout.getAttribute("ny").getIntValue();
double dface = layout.getAttribute("dface").getDoubleValue();
+
+ // Setup range of indices to be skipped.
+ for (Object obj : layout.getChildren("remove"))
+ {
+ Element remove = (Element)obj;
+ try
+ {
+ ranges.add(new CrystalRange(remove));
+ }
+ catch (Exception x)
+ {
+ throw new RuntimeException(x);
+ }
+ }
// Setup crystal logical volume.
Trapezoid crystalTrap = new Trapezoid("crystal_trap", dx1, dx2, dy1, dy2, dz);
@@ -169,7 +267,7 @@
}
// Set parameters for next crystal placement.
- // FIXME Need documentation here.
+ // FIXME Need documentation here on the crystal placement and rotation algorithm.
double thetay = coeffx*dthetay;
double zcorrx = dx1*(2*sin(coeffx*dthetay));
double xcorr = zcorrx*tan((coeffx-1)*dthetay);
@@ -180,50 +278,94 @@
double thetaz = 0;
String baseName = "crystal"+ix+"-"+iy;
-
- // Transform of positive.
- Position ipos =
- new Position(baseName+"_pos_pos", xcenter, -(beamgap+ycenter+tolerance), zcenter+tolerance+dface);
- Rotation irot =
- new Rotation(baseName+"_rot_pos", -thetax, -thetay, thetaz);
- define.addPosition(ipos);
- define.addRotation(irot);
+ //
+ // Bottom section.
+ //
+
+ if (checkRange(ix, -iy, ranges))
+ {
+ // Transform of positive bottom crystal.
+ Position iposBot =
+ new Position(baseName+"_pos_pos_bot", xcenter, -(beamgap+ycenter+tolerance), zcenter+tolerance+dface);
+ //System.out.println("iposBot = " + iposBot.x() + ", " + iposBot.y() + " , " + iposBot.z() + " --> " + ix + ", " + -iy);
+ Rotation irotBot =
+ new Rotation(baseName+"_rot_pos_bot", -thetax, -thetay, thetaz);
+ define.addPosition(iposBot);
+ define.addRotation(irotBot);
- // Place positive crystal.
- PhysVol posCrystalPlacement = new PhysVol(crystalLogVol, world, ipos, irot);
+ // Place positive crystal.
+ PhysVol posCrystalPlacementBot = new PhysVol(crystalLogVol, world, iposBot, irotBot);
- // Add volume IDs.
- posCrystalPlacement.addPhysVolID("ix", ix);
- posCrystalPlacement.addPhysVolID("iy", iy);
+ // Add volume IDs.
+ posCrystalPlacementBot.addPhysVolID("ix", ix);
+ posCrystalPlacementBot.addPhysVolID("iy", -iy);
+ }
// Reflection to negative.
if (ix != 0)
{
- // Transform of negative.
- Position iposneg =
- new Position(baseName+"_pos_neg", -xcenter, -(beamgap+ycenter+tolerance), zcenter+tolerance+dface);
- Rotation irotneg =
- new Rotation(baseName+"_rot_neg", -thetax, thetay, thetaz);
-
- define.addPosition(iposneg);
- define.addRotation(irotneg);
-
- // Place negative crystal.
- PhysVol negCrystalPlacement = new PhysVol(crystalLogVol, world, iposneg, irotneg);
-
- // Add volume IDs.
- negCrystalPlacement.addPhysVolID("ix", -ix);
- negCrystalPlacement.addPhysVolID("iy", iy);
+ if (checkRange(-ix, -iy, ranges))
+ {
+ // Transform of negative.
+ Position iposnegBot =
+ new Position(baseName+"_pos_neg_bot", -xcenter, -(beamgap+ycenter+tolerance), zcenter+tolerance+dface);
+ Rotation irotnegBot =
+ new Rotation(baseName+"_rot_neg_bot", -thetax, thetay, thetaz);
+
+ define.addPosition(iposnegBot);
+ define.addRotation(irotnegBot);
+
+ // Place negative crystal.
+ PhysVol negCrystalPlacementBot = new PhysVol(crystalLogVol, world, iposnegBot, irotnegBot);
+
+ // Add volume IDs.
+ negCrystalPlacementBot.addPhysVolID("ix", -ix);
+ negCrystalPlacementBot.addPhysVolID("iy", -iy);
+ }
}
-
- // Transform of positive.
- Position iposBot =
- new Position(baseName+"_pos_pos", xcenter, -(ycenter-my+tolerance), zcenter-mz+tolerance);
- Rotation irotBot =
- new Rotation(baseName+"_rot_pos", -thetax, -thetay, thetaz);
+ if (checkRange(ix, iy, ranges))
+ {
+ // Transform of positive top crystal.
+ Position iposTop =
+ new Position(baseName+"_pos_pos_top", xcenter, beamgap+ycenter+tolerance, zcenter+tolerance+dface);
+ Rotation irotTop =
+ new Rotation(baseName+"_rot_pos_top", thetax, -thetay, thetaz);
+ define.addPosition(iposTop);
+ define.addRotation(irotTop);
+
+ // Place positive top crystal.
+ PhysVol posCrystalPlacementTop = new PhysVol(crystalLogVol, world, iposTop, irotTop);
+
+ // Add volume IDs.
+ posCrystalPlacementTop.addPhysVolID("ix", ix);
+ posCrystalPlacementTop.addPhysVolID("iy", iy);
+ }
+
+ // Reflection to negative.
+ if (ix != 0)
+ {
+ if (checkRange(-ix, iy, ranges))
+ {
+ // Transform of negative.
+ Position iposnegTop =
+ new Position(baseName+"_pos_neg_top", -xcenter, beamgap+ycenter+tolerance, zcenter+tolerance+dface);
+ Rotation irotnegTop =
+ new Rotation(baseName+"_rot_neg_top", thetax, thetay, thetaz);
+
+ define.addPosition(iposnegTop);
+ define.addRotation(irotnegTop);
+
+ // Place negative crystal.
+ PhysVol negCrystalPlacementTop = new PhysVol(crystalLogVol, world, iposnegTop, irotnegTop);
+ // Add volume IDs.
+ negCrystalPlacementTop.addPhysVolID("ix", -ix);
+ negCrystalPlacementTop.addPhysVolID("iy", iy);
+ }
+ }
+
// Increment running X and Z totals and include tolerance to avoid overlaps.
xcorrtot += xcorr;
zcorrtotx += zcorrx;
@@ -233,30 +375,7 @@
ycorrtot += ycorr;
zcorrtoty += zcorry;
}
-
- // Place the top section.
- /*
- Position mpostop = new Position(momVol.getVolumeName() + "_top_pos", 0, 0, 0);
- //Rotation mrottop = new Rotation(momVol.getVolumeName() + "_top_rot", 0, -Math.PI/2, (3*Math.PI)/2);
- Rotation mrottop = new Rotation(momVol.getVolumeName() + "_top_rot", 0, 0, 0);
- define.addPosition(mpostop);
- define.addRotation(mrottop);
- PhysVol topSide = new PhysVol(momVol, world, mpostop, mrottop);
- topSide.addPhysVolID("system", this.getSystemID());
- topSide.addPhysVolID("side", 1);
- */
-
- // Place the bottom section.
- /*
- Position mposbot = new Position(momVol.getVolumeName() + "_bot_pos", 0, -my-beamgap, dface+mz);
- Rotation mrotbot = new Rotation(momVol.getVolumeName() + "_bot_rot", 0, 0, Math.PI);
- define.addPosition(mposbot);
- define.addRotation(mrotbot);
- PhysVol botSide = new PhysVol(momVol, world, mposbot, mrotbot);
- botSide.addPhysVolID("system", this.getSystemID());
- botSide.addPhysVolID("side", -1);
- */
-
+
// Make the section box invisible.
momVol.setVisAttributes(lcdd.getVisAttributes("InvisibleWithDaughters"));
}