Commit in GeomConverter/src/org/lcsim/geometry/compact/converter/lcdd on MAIN
HPSEcal3.java+188-691.1 -> 1.2
add crystal removal by indices

GeomConverter/src/org/lcsim/geometry/compact/converter/lcdd
HPSEcal3.java 1.1 -> 1.2
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"));
     }
CVSspam 0.2.8