GeomConverter/src/org/lcsim/detector/converter/compact
diff -N HPSTrackerConverter.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ HPSTrackerConverter.java 13 Jan 2012 00:02:51 -0000 1.1
@@ -0,0 +1,515 @@
+package org.lcsim.detector.converter.compact;
+
+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.detector.DetectorElement;
+import org.lcsim.detector.DetectorIdentifierHelper;
+import org.lcsim.detector.DetectorIdentifierHelper.SystemMap;
+import org.lcsim.detector.IDetectorElement;
+import org.lcsim.detector.IPhysicalVolume;
+import org.lcsim.detector.IPhysicalVolumePath;
+import org.lcsim.detector.LogicalVolume;
+import org.lcsim.detector.PhysicalVolume;
+import org.lcsim.detector.RotationGeant;
+import org.lcsim.detector.Transform3D;
+import org.lcsim.detector.Translation3D;
+import org.lcsim.detector.identifier.ExpandedIdentifier;
+import org.lcsim.detector.identifier.IExpandedIdentifier;
+import org.lcsim.detector.identifier.IIdentifier;
+import org.lcsim.detector.identifier.IIdentifierDictionary;
+import org.lcsim.detector.identifier.IIdentifierHelper;
+import org.lcsim.detector.material.IMaterial;
+import org.lcsim.detector.material.MaterialStore;
+import org.lcsim.detector.solids.Box;
+import org.lcsim.detector.solids.Trd;
+import org.lcsim.detector.tracker.silicon.SiSensor;
+import org.lcsim.detector.tracker.silicon.SiTrackerIdentifierHelper;
+import org.lcsim.detector.tracker.silicon.SiTrackerModule;
+import org.lcsim.geometry.compact.Detector;
+import org.lcsim.geometry.compact.Subdetector;
+import org.lcsim.geometry.subdetector.HPSTracker;
+
+public class HPSTrackerConverter extends AbstractSubdetectorConverter
+{
+ Map<String, ModuleParameters> moduleParameters = new HashMap<String, ModuleParameters>();
+ Map<String, LogicalVolume> modules = new HashMap<String, LogicalVolume>();
+ IMaterial vacuum;
+
+ public IIdentifierHelper makeIdentifierHelper(Subdetector subdetector, SystemMap systemMap)
+ {
+ return new SiTrackerIdentifierHelper(subdetector.getDetectorElement(), makeIdentifierDictionary(subdetector), systemMap);
+ }
+
+ public void convert(Subdetector subdet, Detector detector)
+ {
+ System.out.println("HPSTrackerConverter: Converting...");
+ try
+ {
+ Element node = subdet.getNode();
+ String subdetName = node.getAttributeValue("name");
+ vacuum = MaterialStore.getInstance().get("Air");
+
+ boolean reflect = true;
+ if (node.getAttribute("reflect") != null)
+ {
+ reflect = node.getAttribute("reflect").getBooleanValue();
+ }
+
+ boolean flipSA = false;
+ if (node.getAttribute("flipSA") != null)
+ {
+ flipSA = node.getAttribute("flipSA").getBooleanValue();
+ }
+
+ IDetectorElement subdetDetElem = subdet.getDetectorElement();
+ DetectorIdentifierHelper helper = (DetectorIdentifierHelper) subdetDetElem.getIdentifierHelper();
+ int nfields = helper.getIdentifierDictionary().getNumberOfFields();
+ IDetectorElement endcapPos = null;
+ IDetectorElement endcapNeg = null;
+ try
+ {
+ // Positive endcap DE
+ IExpandedIdentifier endcapPosId = new ExpandedIdentifier(nfields);
+ endcapPosId.setValue(helper.getFieldIndex("system"), subdet.getSystemID());
+ endcapPosId.setValue(helper.getFieldIndex("barrel"), helper.getBarrelValue());
+ endcapPos = new DetectorElement(subdet.getName() + "_positive", subdetDetElem);
+ endcapPos.setIdentifier(helper.pack(endcapPosId));
+ if (reflect)
+ {
+ IExpandedIdentifier endcapNegId = new ExpandedIdentifier(nfields);
+ endcapNegId.setValue(helper.getFieldIndex("system"), subdet.getSystemID());
+ endcapNegId.setValue(helper.getFieldIndex("barrel"), helper.getBarrelValue());
+ endcapNeg = new DetectorElement(subdet.getName() + "_negative", subdetDetElem);
+ endcapNeg.setIdentifier(helper.pack(endcapNegId));
+ }
+ }
+ catch (Exception x)
+ {
+ throw new RuntimeException(x);
+ }
+
+ 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)));
+ }
+
+ for (Iterator i = node.getChildren("layer").iterator(); i.hasNext();)
+ {
+ Element layerElement = (Element) i.next();
+
+ int layerId = layerElement.getAttribute("id").getIntValue();
+
+ // Positive endcap layer.
+ IExpandedIdentifier layerPosId = new ExpandedIdentifier(nfields);
+ layerPosId.setValue(helper.getFieldIndex("system"), subdet.getSystemID());
+ layerPosId.setValue(helper.getFieldIndex("barrel"), helper.getBarrelValue());
+ layerPosId.setValue(helper.getFieldIndex("layer"), layerId);
+ IDetectorElement layerPos = new DetectorElement(endcapPos.getName() + "_layer" + layerId, endcapPos, helper.pack(layerPosId));
+
+ // Negative endcap layer.
+ IDetectorElement layerNeg = null;
+ if (reflect)
+ {
+ IExpandedIdentifier layerNegId = new ExpandedIdentifier(nfields);
+ layerNegId.setValue(helper.getFieldIndex("system"), subdet.getSystemID());
+ layerNegId.setValue(helper.getFieldIndex("barrel"), helper.getBarrelValue());
+ layerNegId.setValue(helper.getFieldIndex("layer"), layerId);
+ layerNeg = new DetectorElement(endcapNeg.getName() + "_layer_reflected" + layerId, endcapNeg, helper.pack(layerNegId));
+ }
+
+ 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");
+ LogicalVolume moduleVolume = modules.get(module);
+ if (moduleVolume == null)
+ {
+ throw new RuntimeException("Module " + module + " was not found.");
+ }
+
+ ModuleParameters modPars = moduleParameters.get(module);
+
+ double x, y, z;
+ z = zLayer;
+ x = xStart;
+ // System.out.println("Making modules...nx=" + nx + ";ny=" + ny);
+ for (int k = 0; k < nx; k++ )
+ {
+ y = yStart;
+ for (int kk = 0; kk < ny; kk++ )
+ {
+ String moduleBaseName = subdetName + "_layer" + layerId + "_module" + moduleNumber;
+
+ // Positive endcap module.
+ Translation3D p = new Translation3D(x, y, z + dz);
+
+ //RotationGeant rot = new RotationGeant(-Math.PI / 2, Math.PI / 2 + phi0, 0);
+ RotationGeant rot = new RotationGeant(0, 0, 0);
+ new PhysicalVolume(new Transform3D(p, rot), moduleBaseName, moduleVolume, detector.getTrackingVolume().getLogicalVolume(), 0);
+ String path = "/" + detector.getTrackingVolume().getName() + "/" + moduleBaseName;
+ IDetectorElement modulePos = new SiTrackerModule(moduleBaseName, layerPos, path, moduleNumber);
+ ++moduleNumber;
+
+ // System.out.println("Making module " + moduleBaseName + " @ " + layerPos.toString());
+ if (reflect)
+ {
+ Translation3D pr = new Translation3D(x, -y, z + dz);
+ double rphi0 = phi0;
+ if (flipSA)
+ rphi0 = -rphi0;
+
+ //RotationGeant rotr = new RotationGeant(-Math.PI / 2, Math.PI / 2 + rphi0, 0);
+ RotationGeant rotr = new RotationGeant(0, 0, 0);
+
+ String path2 = "/" + detector.getTrackingVolume().getName() + "/" + moduleBaseName + "_reflected";
+ new PhysicalVolume(new Transform3D(pr, rotr), moduleBaseName + "_reflected", moduleVolume, detector.getTrackingVolume().getLogicalVolume(), k);
+ new SiTrackerModule(moduleBaseName + "_reflected", layerNeg, path2, moduleNumber);
+ // System.out.println("Making module " + moduleBaseName + " @ " + layerNeg.toString());
+ }
+
+ dz = -dz;
+ y += yStep;
+ ++moduleNumber;
+ }
+ x += xStep;
+ }
+ }
+ }
+ }
+ catch (JDOMException except)
+ {
+ throw new RuntimeException(except);
+ }
+
+ // Create DetectorElements for the sensors.
+ setupSensorDetectorElements(subdet);
+ }
+
+ private LogicalVolume makeModule(ModuleParameters params)
+ {
+ double thickness = params.getThickness();
+ double x, y;
+ x = params.getDimension(0);
+ y = params.getDimension(1);
+
+ Box box = new Box(params.getName() + "Box", x / 2, y / 2, thickness / 2);
+ LogicalVolume volume = new LogicalVolume(params.getName() + "Volume", box, vacuum);
+ makeModuleComponents(volume, params);
+ return volume;
+ }
+
+ private void makeModuleComponents(LogicalVolume moduleVolume, ModuleParameters moduleParameters)
+ {
+ double moduleX = moduleParameters.getDimension(0);
+ double moduleY = moduleParameters.getDimension(1);
+
+ Box box = (Box)moduleVolume.getSolid();
+ double moduleZ = box.getZHalfLength() * 2;
+
+ double posZ = -moduleZ / 2;
+
+ String moduleName = moduleVolume.getName();
+
+ int sensor = 0;
+ for (ModuleComponentParameters component : moduleParameters)
+ {
+ double componentThickness = component.getThickness();
+
+ IMaterial material = MaterialStore.getInstance().get(component.getMaterialName());
+ if (material == null)
+ {
+ throw new RuntimeException("The material " + component.getMaterialName() + " does not exist in the materials database.");
+ }
+ boolean sensitive = component.isSensitive();
+ int componentNumber = component.getComponentNumber();
+
+ posZ += componentThickness / 2;
+
+ String componentName = moduleName + "_component" + componentNumber;
+
+ Box componentBox = new Box(componentName + "Box", moduleX / 2, moduleY / 2, componentThickness / 2);
+
+ LogicalVolume volume = new LogicalVolume(componentName, componentBox, material);
+
+ double zrot = 0;
+ if (sensitive)
+ {
+ if (sensor > 1)
+ {
+ throw new RuntimeException("Exceeded maximum of 2 sensors per module.");
+ }
+ // Flip 180 deg for 1st sensor.
+ if (sensor == 0)
+ {
+ zrot = Math.PI;
+ }
+ ++sensor;
+ }
+ Translation3D position = new Translation3D(0., 0., posZ);
+ RotationGeant rotation = new RotationGeant(0, 0, zrot);
+ PhysicalVolume pv = new PhysicalVolume(new Transform3D(position, rotation), componentName, volume, moduleVolume, componentNumber);
+ pv.setSensitive(sensitive);
+
+ posZ += componentThickness / 2;
+ }
+ }
+
+ private void setupSensorDetectorElements(Subdetector subdet)
+ {
+ SiTrackerIdentifierHelper helper = (SiTrackerIdentifierHelper) subdet.getDetectorElement().getIdentifierHelper();
+
+ for (IDetectorElement endcap : subdet.getDetectorElement().getChildren())
+ {
+ for (IDetectorElement layer : endcap.getChildren())
+ {
+ for (IDetectorElement module : layer.getChildren())
+ {
+ IPhysicalVolume modulePhysVol = module.getGeometry().getPhysicalVolume();
+ IPhysicalVolumePath modulePath = module.getGeometry().getPath();
+ int sensorId = 0;
+ for (IPhysicalVolume pv : modulePhysVol.getLogicalVolume().getDaughters())
+ {
+ if (pv.isSensitive())
+ {
+ IIdentifierDictionary iddict = subdet.getDetectorElement().getIdentifierHelper().getIdentifierDictionary();
+
+ ExpandedIdentifier expId = new ExpandedIdentifier(iddict.getNumberOfFields());
+ expId.setValue(iddict.getFieldIndex("system"), subdet.getSystemID());
+
+ if (helper.isEndcapPositive(endcap.getIdentifier()))
+ {
+ expId.setValue(iddict.getFieldIndex("barrel"), helper.getEndcapPositiveValue());
+ }
+ else if (helper.isEndcapNegative(endcap.getIdentifier()))
+ {
+ expId.setValue(iddict.getFieldIndex("barrel"), helper.getEndcapNegativeValue());
+ }
+ else if (helper.isBarrel(endcap.getIdentifier()))
+ {
+ expId.setValue(iddict.getFieldIndex("barrel"), helper.getBarrelValue());
+ }
+ else
+ {
+ throw new RuntimeException(endcap.getName() + " is not a positive or negative endcap!");
+ }
+ expId.setValue(iddict.getFieldIndex("layer"), layer.getIdentifierHelper().getValue(layer.getIdentifier(), "layer"));
+ expId.setValue(iddict.getFieldIndex("module"), ((SiTrackerModule) module).getModuleId());
+ expId.setValue(iddict.getFieldIndex("sensor"), sensorId);
+
+ IIdentifier id = iddict.pack(expId);
+
+ String sensorPath = modulePath.toString() + "/" + pv.getName();
+ String sensorName = module.getName() + "_sensor" + sensorId;
+
+ SiSensor sensor = new SiSensor(sensorId, sensorName, module, sensorPath, id);
+
+ ++sensorId;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ public Class getSubdetectorType()
+ {
+ return HPSTracker.class;
+ }
+
+ 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;
+ }
+ }
+
+}