Commit in GeomConverter on MAIN | |||
src/org/lcsim/geometry/compact/converter/lcdd/HPSMuonCalorimeter.java | +226 | added 1.1 | |
testResources/org/lcsim/geometry/subdetector/HPSMuonCalorimeterTest.xml | +42 | added 1.1 | |
+268 |
JM: work in progress on implementing HPS muon detector with Maurik
diff -N HPSMuonCalorimeter.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ HPSMuonCalorimeter.java 12 Sep 2012 23:30:45 -0000 1.1 @@ -0,0 +1,226 @@
+package org.lcsim.geometry.compact.converter.lcdd; + +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; + +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.Trap; +import org.lcsim.geometry.compact.converter.lcdd.util.Volume; + +/** + * + * To build: + * + * cd GeomConverter + * mvn clean install -DskipTests=true + * + * To generate LCDD from test geometry: + * + * java -jar ./target/GeomConverter-2.5-SNAPSHOT-bin.jar -o lcdd ./testResources/org/lcsim/geometry/subdetector/HPSMuonCalorimeterTest.xml ./HPSMuonCalorimeterTest.lcdd + * + * Parameters (initially from python): + * + * vertseg_gap <= vertical gaps between hodoscopes e.g. scintillator strips + * vertseg_num <= number of readout strips in first layer + * vertseg_size <= vertical dimension of strip + * from_target <= distance from front face to target + * absorber_layers <= how many absorber layers? + * absorber_thicknesses <= thickness of each absorber layer + * gaps <= horizontal gap between each strips and absorber + * sensor_thickness <= thickness of absorber + * theta1 <= fan out angle in y of the vacuum box (?) + * absorber_width <= 1st layer absorber width + * fan_out <= make absorbers all the same width or fan them out as depth increases + * connecting_width <= when fan_out is false then set how far in the connecting iron piece goes (?) + * theta4 <= fan out angle + * alum_plate_width <= width of the aluminum plate + * alum_side_width <= width of the side wall of the vacuum system + * alum_airgap <= gap between alum plate and iron chunks + * al_extra[1-3] <= see diagram (???) + * vac_pullz <= how far to extend the vacuum (-z) towards ecal + * vac_pushz <= how far to extend the vacuum (+z) beyond muon detector + * + * Example XML: + * <parameters vertseg_gap="0.01*cm" vertseg_num="8" vertseg_size="3.0*cm" from_target="185.0*cm" gap="0.2*cm" + * sensor_thickness="1.0*cm" theta1="0.025" absorber_width="50.0*cm" fan_out="true" + * connecting_width="40.0*cm" theta4="0.0873" /> + * <absorber_thicknesses>68.0 68.0 68.0 68.0 150.0 150.0 150.0</absorber_thicknesses> + * <vacuum alum_plate_width="1.0*cm" alum_side_width="1.0*cm" alum_airgap="0.01*cm" al_extra1="35.0*cm" + * al_extra2="20.0*cm" al_extra3="5.0*cm" /> + * + * @author jeremym + * @version $Id: HPSMuonCalorimeter.java,v 1.1 2012/09/12 23:30:45 jeremy Exp $ + */ +public class HPSMuonCalorimeter extends LCDDSubdetector { + + HPSMuonCalorimeter(Element node) throws JDOMException { + super(node); + } + + void addToLCDD(LCDD lcdd, SensitiveDetector sens) throws JDOMException { + + String name = node.getAttributeValue("name"); + int id = node.getAttribute("id").getIntValue(); + + // Get muon calorimeter parameters. + Element parameters = node.getChild("parameters"); + double vertseg_gap = parameters.getAttribute("vertseg_gap").getDoubleValue(); + int vertseg_num = parameters.getAttribute("vertseg_num").getIntValue(); + double vertseg_size = parameters.getAttribute("vertseg_size").getDoubleValue(); + double from_target = parameters.getAttribute("from_target").getDoubleValue(); + double gap = parameters.getAttribute("gap").getDoubleValue(); + double sensor_thickness = parameters.getAttribute("sensor_thickness").getDoubleValue(); + double theta1 = parameters.getAttribute("theta1").getDoubleValue(); + double absorber_width = parameters.getAttribute("absorber_width").getDoubleValue(); + boolean fan_out = parameters.getAttribute("fan_out").getBooleanValue(); + double connecting_width = parameters.getAttribute("connecting_width").getDoubleValue(); + double theta4 = parameters.getAttribute("theta4").getDoubleValue(); + + // Get the absorber thicknesses. These are hard-coded to be in mm because I don't know + // how to convert the array on the fly to arbitrary units. + String s = node.getChild("absorber_thicknesses").getText(); + StringTokenizer st = new StringTokenizer(s); + List<Double> depth = new ArrayList<Double>(); + while (st.hasMoreElements()) { + depth.add(Double.parseDouble((String)st.nextElement())); + } + + // Get vacuum box parameters. + Element vacuum = node.getChild("vacuum"); + double alum_plate_width = vacuum.getAttribute("alum_plate_width").getDoubleValue(); + double alum_side_width = vacuum.getAttribute("alum_side_width").getDoubleValue(); + double alum_airgap = vacuum.getAttribute("alum_airgap").getDoubleValue(); + double al_extra1 = vacuum.getAttribute("al_extra1").getDoubleValue(); + double al_extra2 = vacuum.getAttribute("al_extra2").getDoubleValue(); + double al_extra3 = vacuum.getAttribute("al_extra3").getDoubleValue(); + + // Computed values. + int nabsorbers = depth.size(); + double absorber_total_depth = 0.; + for (Double a : depth) { + absorber_total_depth += a; + } + double gaps_total_depth = (nabsorbers)*gap; + + //System.out.println("absorber_total_depth="+absorber_total_depth); + //System.out.println("gaps_total_depth="+gaps_total_depth); + + // Total detector depth. + double md_depth = absorber_total_depth + 2*gaps_total_depth - gap + nabsorbers*sensor_thickness; + //System.out.println("md_depth="+md_depth); + + // Z position of muon detector. + double vac_pullz = al_extra3; + double vac_pushz = al_extra1; + double muon_box_z = from_target + 0.5*md_depth - 0.5*Math.max(vac_pullz, al_extra3) + 0.5*Math.max(vac_pushz,al_extra1); + + //System.out.println("muon_box_z = " + muon_box_z); + + double md_mid = from_target - muon_box_z + 0.5*md_depth; + //System.out.println("muon_mid = " + md_mid); + + double z = from_target - muon_box_z + depth.get(0)/2; + //System.out.println("z="+z); + + double theta2 = Math.atan( (vertseg_num*vertseg_size+(vertseg_num-1)*vertseg_gap+(from_target+depth.get(0)+gap)*Math.tan(theta1) )/ (from_target+depth.get(0)+gap)); + double theta3 = Math.atan(absorber_width/(from_target)); + double theta = 0.5*(theta1+theta2); + + //System.out.println("theta2="+theta2); + //System.out.println("theta3="+theta3); + //System.out.println("theta="+theta); + + double tt1 = Math.tan(theta1); + double tt2 = Math.tan(theta2); + //System.out.println("theta3="+theta3); + double tt3 = Math.tan(theta3); + double tt4 = Math.tan(theta4); + double tt34 = Math.tan( (theta3+theta4)/2 ); + double tt = Math.tan(theta); + + // Place crystals in world volume. + Volume world = lcdd.pickMotherVolume(this); + + // Position of mother volume in the world. + Position md_pos = new Position(name + "_pos", 0, 0, muon_box_z); + lcdd.add(md_pos); + + // Compute dimensions of mother box. + double md_x, md_y, md_z; + double spacing = 20.; + //System.out.println("tt3="+tt3); + //System.out.println("md_x1="+((from_target+md_depth+al_extra1)*tt3+al_extra2)); + //System.out.println("md_x2="+(from_target+md_depth+vac_pushz)*tt3); + md_x = Math.max((from_target+md_depth+al_extra1)*tt3+al_extra2,(from_target+md_depth+vac_pushz)*tt3)+spacing; + md_y = (from_target+md_depth)*tt2+spacing; + md_z = .5*md_depth+.5*Math.max(al_extra1,vac_pushz)+.5*Math.max(al_extra3,vac_pullz); + + //System.out.println("md_x = " + md_x); + //System.out.println("md_y = " + md_y); + //System.out.println("md_z = " + md_z); + + // Create mother box. + Box muonBox = new Box(name + "_box", md_x*2, md_y*2, md_z*2); + lcdd.add(muonBox); + + Material air = lcdd.getMaterial("Air"); + + Volume md_vol = new Volume(name + "_vol", muonBox, air); + + Material iron = lcdd.getMaterial("Iron"); + + Rotation rot = new Rotation(name+"_absorber_rot", 0, 0, Math.PI/2); + lcdd.add(rot); + for (int i=0; i<nabsorbers; i++) { + + double gz = z + muon_box_z; + //System.out.println("gz="+gz); + + String base_name = name + "_layer" + i; + String abs_base_name = base_name + "_abs_"; + + Position top_pos = new Position(abs_base_name+"top_pos", 0, gz*tt, z); + lcdd.add(top_pos); + + Trap abs_top_trap = new Trap(abs_base_name+"top_trap", + .5*depth.get(i), + -theta, + 0., + ((gz-depth.get(i)/2)*tt3), + .5*(gz-depth.get(i)/2)*(tt2-tt1), + .5*(gz-depth.get(i)/2)*(tt2-tt1), + 0., + ((gz+depth.get(i)/2)*tt3), + .5*(gz+depth.get(i)/2)*(tt2-tt1), + .5*(gz+depth.get(i)/2)*(tt2-tt1), + 0); + lcdd.add(abs_top_trap); + Volume abs_top_vol = new Volume(abs_base_name+"vol", abs_top_trap, iron); + lcdd.add(abs_top_vol); + PhysVol abs_top_pv = new PhysVol(abs_top_vol, md_vol, top_pos, rot); + + // CONTINUE CODING HERE + + if (i != (nabsorbers - 1)) + z = z + .5*depth.get(i)+.5*depth.get(i+1)+2*gap+sensor_thickness; + } // nabsorbers loop + + lcdd.add(md_vol); + Rotation md_rot = new Rotation(name + "_rot"); + lcdd.add(md_rot); + PhysVol md_pv = new PhysVol(md_vol, world, md_pos, md_rot); + } + + public boolean isCalorimeter() { + return true; + } +}
\ No newline at end of file
diff -N HPSMuonCalorimeterTest.xml --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ HPSMuonCalorimeterTest.xml 12 Sep 2012 23:30:45 -0000 1.1 @@ -0,0 +1,42 @@
+<lccdd xmlns:compact="http://www.lcsim.org/schemas/compact/1.0" + xmlns:xs="http://www.w3.org/2001/XMLSchema-instance" + xs:noNamespaceSchemaLocation="http://www.lcsim.org/schemas/compact/1.0/compact.xsd"> + + <info name="HPSMuonCalorimeterTest"/> + + <define> + <!-- world volume --> + <constant name="world_side" value="10000.0*cm" /> + <constant name="world_x" value="world_side" /> + <constant name="world_y" value="world_side" /> + <constant name="world_z" value="world_side" /> + + <!-- tracking region --> + <constant name="tracking_region_radius" value="200.0*cm"/> + <constant name="tracking_region_min" value="5.0*cm"/> + <constant name="tracking_region_zmax" value="100.0*cm"/> + + </define> + + <materials> + </materials> + + <detectors> + <detector id="2" name="MUON" type="HPSMuonCalorimeter" insideTrackingVolume="false" readout="MUON_HITS"> + <parameters vertseg_gap="0.01*cm" vertseg_num="8" vertseg_size="3.0*cm" from_target="185.0*cm" gap="0.2*cm" + sensor_thickness="1.0*cm" theta1="0.025" absorber_width="50.0*cm" fan_out="true" + connecting_width="40.0*cm" theta4="0.0873" /> + <absorber_thicknesses>68.0 68.0 68.0 68.0 150.0 150.0 150.0</absorber_thicknesses> + <vacuum alum_plate_width="1.0*cm" alum_side_width="1.0*cm" alum_airgap="0.01*cm" al_extra1="35.0*cm" + al_extra2="20.0*cm" al_extra3="5.0*cm" /> + </detector> + </detectors> + + <readouts> + <readout name="MUON_HITS"> + <segmentation type="GridXYZ" gridSizeX="0.0" gridSizeY="0.0" gridSizeZ="0.0" /> + <id>system:6,side:-2,layer:4,ix:-8,iy:-6</id> + </readout> + </readouts> + +</lccdd>
Use REPLY-ALL to reply to list
To unsubscribe from the LCD-CVS list, click the following link:
https://listserv.slac.stanford.edu/cgi-bin/wa?SUBED1=LCD-CVS&A=1