GeomConverter/src/org/lcsim/geometry/compact/converter/lcdd
diff -N HPSTracker.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ HPSTracker.java 11 Jan 2012 23:12:04 -0000 1.1
@@ -0,0 +1,462 @@
+package org.lcsim.geometry.compact.converter.lcdd;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.jdom.DataConversionException;
+import org.jdom.Element;
+import org.jdom.JDOMException;
+import org.lcsim.geometry.compact.converter.lcdd.util.Box;
+import org.lcsim.geometry.compact.converter.lcdd.util.LCDD;
+import org.lcsim.geometry.compact.converter.lcdd.util.Material;
+import org.lcsim.geometry.compact.converter.lcdd.util.PhysVol;
+import org.lcsim.geometry.compact.converter.lcdd.util.Position;
+import org.lcsim.geometry.compact.converter.lcdd.util.Rotation;
+import org.lcsim.geometry.compact.converter.lcdd.util.SensitiveDetector;
+import org.lcsim.geometry.compact.converter.lcdd.util.Volume;
+
+/**
+ * An LCDD converter for a Silicon endcap tracker model based on Bill Cooper's design from
+ * <a href="http://ilcagenda.linearcollider.org/materialDisplay.py?contribId=58&sessionId=1&materialId=slides&confId=2784">Boulder SiD Workshop 2008</a>.
+ *
+ * @author jeremym
+ */
+public class HPSTracker extends LCDDSubdetector {
+
+ Map<String, ModuleParameters> moduleParameters = new HashMap<String, ModuleParameters>();
+ Map<String, Volume> modules = new HashMap<String, Volume>();
+ Material vacuum;
+ //static VisAttributes blah = null;
+
+ public HPSTracker(Element node) throws JDOMException
+ {
+ super(node);
+ }
+
+ void addToLCDD(LCDD lcdd, SensitiveDetector sd) throws JDOMException
+ {
+ // DEBUG
+ //blah = new VisAttributes("TkrTestVisXYZ");
+ //blah.setColor((float)1.0,(float)0.,(float)0.,(float)1.0);
+ //lcdd.add(blah);
+ /////////////////////
+
+ int sysId = node.getAttribute("id").getIntValue();
+ String subdetName = node.getAttributeValue("name");
+ vacuum = lcdd.getMaterial("Vacuum");
+ boolean reflect;
+
+ if (node.getAttribute("reflect") != null) {
+ reflect = node.getAttribute("reflect").getBooleanValue();
+ } else {
+ reflect = true;
+ }
+
+ boolean flipSA=false;
+ if ( node.getAttribute( "flipSA" ) != null )
+ {
+ flipSA = node.getAttribute( "flipSA" ).getBooleanValue();
+ }
+
+ for (Iterator i = node.getChildren("module").iterator(); i.hasNext();) {
+ Element module = (Element) i.next();
+ String moduleName = module.getAttributeValue("name");
+ moduleParameters.put(moduleName, new ModuleParameters(module));
+ modules.put(moduleName, makeModule(moduleParameters.get(moduleName), sd, lcdd));
+ }
+
+ for (Iterator i = node.getChildren("layer").iterator(); i.hasNext();) {
+
+ Element layerElement = (Element) i.next();
+ int layerId = layerElement.getAttribute("id").getIntValue();
+ int ringCount = 0;
+ int moduleNumber = 0;
+
+ for (Iterator j = layerElement.getChildren("quadrant").iterator(); j.hasNext();) {
+ Element ringElement = (Element) j.next();
+ double zLayer = ringElement.getAttribute("z").getDoubleValue();
+ double dz = ringElement.getAttribute("dz").getDoubleValue();
+ double xStart = ringElement.getAttribute("xStart").getDoubleValue();
+ double xStep = ringElement.getAttribute("xStep").getDoubleValue();
+ int nx = ringElement.getAttribute("nx").getIntValue();
+ double yStart = ringElement.getAttribute("yStart").getDoubleValue();
+ int ny = ringElement.getAttribute("ny").getIntValue();
+ double yStep = ringElement.getAttribute("yStep").getDoubleValue();
+ double phi0 = 0;
+ if (ringElement.getAttribute("phi0") != null) {
+ phi0 = ringElement.getAttribute("phi0").getDoubleValue();
+ }
+ String module = ringElement.getAttributeValue("module");
+
+ Volume moduleVolume = modules.get(module);
+ if (moduleVolume == null) {
+ throw new RuntimeException("Module " + module + " was not found.");
+ }
+
+ double x, y, z;
+ z = zLayer;
+ x = xStart;
+
+ for (int k = 0; k < nx; k++) {
+ y = yStart;
+ for (int kk = 0; kk < ny; kk++) {
+ String moduleBaseName = subdetName + "_layer" + layerId + "_module" + moduleNumber;
+
+ Position p = new Position(moduleBaseName + "_position");
+
+ p.setX(x);
+ p.setY(y);
+ p.setZ(z+ dz);
+ Rotation rot = new Rotation(moduleBaseName + "_rotation");
+ rot.setX(-Math.PI / 2);
+ rot.setY(Math.PI / 2+phi0);
+ rot.setZ(0);
+
+ lcdd.add(p);
+ lcdd.add(rot);
+
+ PhysVol pv = new PhysVol(moduleVolume, lcdd.getTrackingVolume(), p, rot);
+ pv.addPhysVolID("system", sysId);
+
+ pv.addPhysVolID("barrel", 0);
+ pv.addPhysVolID("layer", layerId);
+ pv.addPhysVolID("module", moduleNumber);
+ ++moduleNumber;
+ if (reflect) {
+ Position pr = new Position(moduleBaseName + "_reflect_position");
+ pr.setX(x);
+ pr.setY(-y);
+ pr.setZ(z + dz);
+ Rotation rotr = new Rotation(moduleBaseName + "_reflect_rotation");
+ double rphi0=phi0;
+ if(flipSA) rphi0=-rphi0;
+ rotr.setX(-Math.PI / 2);
+ rotr.setY(Math.PI / 2+rphi0);
+ rotr.setZ(0);
+
+ lcdd.add(pr);
+ lcdd.add(rotr);
+
+ //System.out.println("Reflecting "+ x+" "+y+" "+z);
+ PhysVol pvr = new PhysVol(moduleVolume, lcdd.getTrackingVolume(), pr, rotr);
+ pvr.addPhysVolID("system", sysId);
+ pvr.addPhysVolID("barrel", 0);
+ pvr.addPhysVolID("layer", layerId);
+ pvr.addPhysVolID("module", moduleNumber);
+
+ }
+ dz = -dz;
+ y += yStep;
+ ++moduleNumber;
+ }
+ x += xStep;
+ }
+ }
+ }
+ }
+
+ private Volume makeModule(ModuleParameters params, SensitiveDetector sd, LCDD lcdd)
+ {
+ double thickness = params.getThickness();
+ double x, y;
+ x = params.getDimension(0);
+ y = params.getDimension(1);
+
+ Box box = new Box(params.getName() + "Box", x, y, thickness);
+ lcdd.add(box);
+
+ Volume moduleVolume = new Volume(params.getName() + "Volume", box, vacuum);
+ makeModuleComponents(moduleVolume, params, sd, lcdd);
+ //moduleVolume.setVisAttributes(blah);
+ lcdd.add(moduleVolume);
+
+ if (params.getVis() != null) {
+ moduleVolume.setVisAttributes(lcdd.getVisAttributes(params.getVis()));
+ }
+
+ return moduleVolume;
+ }
+
+ private void makeModuleComponents(
+ Volume moduleVolume,
+ ModuleParameters moduleParameters,
+ SensitiveDetector sd,
+ LCDD lcdd)
+ {
+ Box envelope = (Box) lcdd.getSolid(moduleVolume.getSolidRef());
+
+ double moduleX = envelope.getX();
+ double moduleY = envelope.getY();
+
+ //System.out.println("moduleX="+moduleX);
+ //System.out.println("moduleY="+moduleY);
+
+ double posZ = -moduleParameters.getThickness() / 2;
+
+ String moduleName = moduleVolume.getVolumeName();
+
+ int sensor = 0;
+ for (ModuleComponentParameters component : moduleParameters) {
+ //System.out.println("making component...");
+
+ double thickness = component.getThickness();
+
+ Material material = null;
+ try {
+ material = lcdd.getMaterial(component.getMaterialName());
+ } catch (JDOMException except) {
+ throw new RuntimeException(except);
+ }
+ boolean sensitive = component.isSensitive();
+ int componentNumber = component.getComponentNumber();
+
+ posZ += thickness / 2;
+
+ //System.out.println("posY="+posY);
+
+ String componentName = moduleName + "_component" + componentNumber;
+
+ //System.out.println("componentBox = " + moduleX + ", " + moduleY + "," + thickness);
+ Box componentBox = new Box(componentName + "Box", moduleX, moduleY, thickness);
+ lcdd.add(componentBox);
+
+ Volume componentVolume = new Volume(componentName, componentBox, material);
+
+ Position position = new Position(componentName + "_position", 0., 0., posZ);
+ lcdd.add(position);
+ Rotation rotation = new Rotation(componentName + "_rotation");
+ lcdd.add(rotation);
+
+ PhysVol pv = new PhysVol(componentVolume, moduleVolume, position, rotation);
+ pv.addPhysVolID("component", componentNumber);
+
+ if (sensitive) {
+ if (sensor > 1) {
+ throw new RuntimeException("Maximum of 2 sensors per module.");
+ }
+
+ // Build an child sensor volume to allow dead areas.
+
+ String sensorName = componentName + "Sensor" + sensor;
+
+ double sensorX = component.getDimensionX();
+ //System.out.println("sensorX="+sensorX);
+ if (sensorX > moduleX)
+ throw new RuntimeException("Sensor X dimension " + sensorX + " is too big for module.");
+
+ double sensorY = component.getDimensionY();
+ //System.out.println("sensorY="+sensorY);
+ if (sensorY > moduleY)
+ throw new RuntimeException("Sensor Y dimension " + sensorY + " is too big for module.");
+
+ //System.out.println("sensorBox = "+sensorX+", " + sensorY + ", " + thickness);
+ Box sensorBox = new Box(sensorName + "Box", sensorX, sensorY, thickness);
+ lcdd.add(sensorBox);
+
+ Volume sensorVol = new Volume(sensorName, sensorBox, material);
+ sensorVol.setSensitiveDetector(sd);
+ //sensorVol.setVisAttributes(blah);
+ lcdd.add(sensorVol);
+
+ Position sensorPosition = new Position(sensorName+"Position",0,0,0);
+ lcdd.add(sensorPosition);
+ Rotation sensorRotation = new Rotation(sensorName+"Rotation",0,0,0);
+ lcdd.add(sensorRotation);
+
+ PhysVol sensorPhysVol = new PhysVol(sensorVol, componentVolume, sensorPosition, sensorRotation);
+ sensorPhysVol.addPhysVolID("sensor", sensor);
+
+ ++sensor;
+ }
+
+ // Add component volume after (possible) sensor child volume.
+ lcdd.add(componentVolume);
+
+ // Set vis attributes of component.
+ if (component.getVis() != null) {
+ componentVolume.setVisAttributes(lcdd.getVisAttributes(component.getVis()));
+ }
+
+ // Step to next component placement position.
+ posZ += thickness / 2;
+ }
+ }
+
+ public boolean isTracker()
+ {
+ return true;
+ }
+
+ static class ModuleComponentParameters
+ {
+ protected String materialName;
+ protected double thickness;
+ protected boolean sensitive;
+ protected int componentNumber;
+ protected String vis;
+ protected double dimX, dimY;
+
+ public ModuleComponentParameters(double dimX, double dimY, double thickness, String materialName, int componentNumber, boolean sensitive, String vis)
+ {
+ this.dimX = dimX;
+ this.dimY = dimY;
+ this.thickness = thickness;
+ this.materialName = materialName;
+ this.sensitive = sensitive;
+ this.componentNumber = componentNumber;
+ this.vis = vis;
+ }
+
+ public double getThickness()
+ {
+ return thickness;
+ }
+
+ public double getDimensionX()
+ {
+ return dimX;
+ }
+
+ public double getDimensionY()
+ {
+ return dimY;
+ }
+
+ public String getMaterialName()
+ {
+ return materialName;
+ }
+
+ public boolean isSensitive()
+ {
+ return sensitive;
+ }
+
+ public int getComponentNumber()
+ {
+ return componentNumber;
+ }
+
+ public String getVis()
+ {
+ return vis;
+ }
+ }
+
+ static class ModuleParameters extends ArrayList<ModuleComponentParameters>
+ {
+ double thickness;
+ String name;
+ double dimensions[] = new double[3];
+ String vis;
+
+ public ModuleParameters(Element element)
+ {
+ name = element.getAttributeValue("name");
+
+ if (element.getAttribute("vis") != null)
+ this.vis = element.getAttribute("vis").getValue();
+
+ // Optional dimension parameters (not always present).
+ if (element.getChild("trd") != null)
+ {
+ Element trd = element.getChild("trd");
+ try
+ {
+ dimensions[0] = trd.getAttribute("x1").getDoubleValue();
+ dimensions[1] = trd.getAttribute("x2").getDoubleValue();
+ dimensions[2] = trd.getAttribute("z").getDoubleValue();
+ }
+ catch (DataConversionException x)
+ {
+ throw new RuntimeException(x);
+ }
+ }
+ else if (element.getChild("box") != null)
+ {
+ Element box = element.getChild("box");
+ try
+ {
+ dimensions[0] = box.getAttribute("x").getDoubleValue();
+ dimensions[1] = box.getAttribute("y").getDoubleValue();
+ }
+ catch (DataConversionException x)
+ {
+ throw new RuntimeException(x);
+ }
+ }
+
+ int cntr=0;
+ for (Object o : element.getChildren("module_component"))
+ {
+ try {
+
+ Element e = (Element)o;
+
+ double thickness = e.getAttribute("thickness").getDoubleValue();
+
+ String materialName = e.getAttributeValue("material");
+
+ boolean sensitive = false;
+ if (e.getAttribute("sensitive") != null)
+ sensitive = e.getAttribute("sensitive").getBooleanValue();
+ String componentVis = null;
+ if (e.getAttribute("vis") != null)
+ componentVis = e.getAttribute("vis").getValue();
+
+ // Sensors may have reduced dimensions for dead area.
+ double x = dimensions[0]; // default
+ double y = dimensions[1]; // default
+ if (sensitive && e.getChild("dimensions") != null)
+ {
+ Element dimensions = e.getChild("dimensions");
+ x = dimensions.getAttribute("x").getDoubleValue();
+ y = dimensions.getAttribute("y").getDoubleValue();
+ //System.out.println("x,y="+x+","+y);
+ }
+ add(new ModuleComponentParameters(x, y, thickness, materialName, cntr, sensitive, componentVis));
+ }
+ catch (JDOMException x)
+ {
+ throw new RuntimeException(x);
+ }
+ ++cntr;
+ }
+
+ calculateThickness();
+ }
+
+ public void calculateThickness()
+ {
+ thickness = 0.; // reset thickness
+ for (ModuleComponentParameters p : this)
+ {
+ thickness += p.getThickness();
+ }
+ }
+
+ public double getThickness()
+ {
+ return thickness;
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public double getDimension(int i)
+ {
+ if (i > (dimensions.length - 1) || i < 0)
+ throw new RuntimeException("Invalid dimensions index: " + i);
+ return dimensions[i];
+ }
+
+ public String getVis()
+ {
+ return vis;
+ }
+ }
+}