1 package org.lcsim.geometry.compact.converter.lcdd;
2
3 import java.util.HashMap;
4 import java.util.Iterator;
5 import java.util.Map;
6
7 import org.jdom.Element;
8 import org.jdom.JDOMException;
9 import org.lcsim.geometry.compact.converter.SiTrackerModuleComponentParameters;
10 import org.lcsim.geometry.compact.converter.SiTrackerModuleParameters;
11 import org.lcsim.geometry.compact.converter.lcdd.util.LCDD;
12 import org.lcsim.geometry.compact.converter.lcdd.util.Material;
13 import org.lcsim.geometry.compact.converter.lcdd.util.PhysVol;
14 import org.lcsim.geometry.compact.converter.lcdd.util.Position;
15 import org.lcsim.geometry.compact.converter.lcdd.util.Rotation;
16 import org.lcsim.geometry.compact.converter.lcdd.util.SensitiveDetector;
17 import org.lcsim.geometry.compact.converter.lcdd.util.Trapezoid;
18 import org.lcsim.geometry.compact.converter.lcdd.util.Volume;
19
20
21
22
23
24
25
26 public class SiTrackerSpectrometer extends LCDDSubdetector {
27
28 Map<String, SiTrackerModuleParameters> moduleParameters = new HashMap<String, SiTrackerModuleParameters>();
29 Map<String, Volume> modules = new HashMap<String, Volume>();
30 Material vacuum;
31
32 public SiTrackerSpectrometer(Element node) throws JDOMException {
33 super(node);
34 }
35
36 void addToLCDD(LCDD lcdd, SensitiveDetector sd) throws JDOMException {
37 int sysId = node.getAttribute("id").getIntValue();
38 String subdetName = node.getAttributeValue("name");
39 vacuum = lcdd.getMaterial("Vacuum");
40 boolean reflect;
41 if (node.getAttribute("reflect") != null) {
42 reflect = node.getAttribute("reflect").getBooleanValue();
43 } else {
44 reflect = true;
45 }
46 boolean flipSA=false;
47 if ( node.getAttribute( "flipSA" ) != null )
48 {
49 flipSA = node.getAttribute( "flipSA" ).getBooleanValue();
50 }
51 for (Iterator i = node.getChildren("module").iterator(); i.hasNext();) {
52 Element module = (Element) i.next();
53 String moduleName = module.getAttributeValue("name");
54 moduleParameters.put(moduleName, new SiTrackerModuleParameters(module));
55 modules.put(moduleName, makeModule(moduleParameters.get(moduleName), sd, lcdd));
56 }
57
58 for (Iterator i = node.getChildren("layer").iterator(); i.hasNext();) {
59 Element layerElement = (Element) i.next();
60 int layerId = layerElement.getAttribute("id").getIntValue();
61 int ringCount = 0;
62 int moduleNumber = 0;
63 for (Iterator j = layerElement.getChildren("quadrant").iterator(); j.hasNext();) {
64 Element ringElement = (Element) j.next();
65 double zLayer = ringElement.getAttribute("z").getDoubleValue();
66 double dz = ringElement.getAttribute("dz").getDoubleValue();
67 double xStart = ringElement.getAttribute("xStart").getDoubleValue();
68 double xStep = ringElement.getAttribute("xStep").getDoubleValue();
69 int nx = ringElement.getAttribute("nx").getIntValue();
70 double yStart = ringElement.getAttribute("yStart").getDoubleValue();
71 int ny = ringElement.getAttribute("ny").getIntValue();
72 double yStep = ringElement.getAttribute("yStep").getDoubleValue();
73 double phi0 = 0;
74 if (ringElement.getAttribute("phi0") != null) {
75 phi0 = ringElement.getAttribute("phi0").getDoubleValue();
76 }
77 String module = ringElement.getAttributeValue("module");
78
79 Volume moduleVolume = modules.get(module);
80 if (moduleVolume == null) {
81 throw new RuntimeException("Module " + module + " was not found.");
82 }
83
84
85 double x, y, z;
86 z = zLayer;
87 x = xStart;
88
89 for (int k = 0; k < nx; k++) {
90 y = yStart;
91 for (int kk = 0; kk < ny; kk++) {
92 String moduleBaseName = subdetName + "_layer" + layerId + "_module" + moduleNumber;
93
94 Position p = new Position(moduleBaseName + "_position");
95
96 p.setX(x );
97 p.setY(y);
98 p.setZ(z+ dz);
99 Rotation rot = new Rotation(moduleBaseName + "_rotation");
100 rot.setX(-Math.PI / 2);
101 rot.setY(Math.PI / 2+phi0);
102 rot.setZ(0);
103
104
105 lcdd.add(p);
106 lcdd.add(rot);
107
108 PhysVol pv = new PhysVol(moduleVolume, lcdd.getTrackingVolume(), p, rot);
109 pv.addPhysVolID("system", sysId);
110
111 pv.addPhysVolID("barrel", 0);
112 pv.addPhysVolID("layer", layerId);
113 pv.addPhysVolID("module", moduleNumber);
114 ++moduleNumber;
115 if (reflect) {
116 Position pr = new Position(moduleBaseName + "_reflect_position");
117 pr.setX(x);
118 pr.setY(-y);
119 pr.setZ(z + dz);
120 Rotation rotr = new Rotation(moduleBaseName + "_reflect_rotation");
121 double rphi0=phi0;
122 if(flipSA) rphi0=-rphi0;
123 rotr.setX(-Math.PI / 2);
124 rotr.setY(Math.PI / 2+rphi0);
125 rotr.setZ(0);
126
127 lcdd.add(pr);
128 lcdd.add(rotr);
129 System.out.println("Reflecting "+ x+" "+y+" "+z);
130 PhysVol pvr = new PhysVol(moduleVolume, lcdd.getTrackingVolume(), pr, rotr);
131 pvr.addPhysVolID("system", sysId);
132 pvr.addPhysVolID("barrel", 0);
133 pvr.addPhysVolID("layer", layerId);
134 pvr.addPhysVolID("module", moduleNumber);
135
136 }
137 dz = -dz;
138 y += yStep;
139 ++moduleNumber;
140 }
141 x += xStep;
142 }
143 }
144 }
145 }
146
147 private Volume makeModule(SiTrackerModuleParameters params, SensitiveDetector sd, LCDD lcdd) {
148 double thickness = params.getThickness();
149 double dx1, dx2, dy1, dy2, dz;
150 dy1 = dy2 = thickness / 2;
151 dx1 = params.getDimension(0);
152 dx2 = params.getDimension(1);
153 dz = params.getDimension(2);
154 Trapezoid envelope = new Trapezoid(params.getName() + "Trd", dx1, dx2, dy1, dy2, dz);
155 lcdd.add(envelope);
156 Volume volume = new Volume(params.getName() + "Volume", envelope, vacuum);
157 makeModuleComponents(volume, params, sd, lcdd);
158 if (params.getVis() != null) {
159 volume.setVisAttributes(lcdd.getVisAttributes(params.getVis()));
160 }
161 lcdd.add(volume);
162 return volume;
163 }
164
165 private void makeModuleComponents(Volume moduleVolume, SiTrackerModuleParameters moduleParameters, SensitiveDetector sd, LCDD lcdd) {
166 Trapezoid trd = (Trapezoid) lcdd.getSolid(moduleVolume.getSolidRef());
167
168 double x1 = trd.x1();
169 double x2 = trd.x2();
170 double y1 = trd.y1();
171 double z = trd.z();
172
173 double posY = -y1;
174
175 String moduleName = moduleVolume.getVolumeName();
176
177 int sensor = 0;
178 for (SiTrackerModuleComponentParameters component : moduleParameters) {
179 double thickness = component.getThickness();
180
181 Material material = null;
182 try {
183 material = lcdd.getMaterial(component.getMaterialName());
184 } catch (JDOMException x) {
185 throw new RuntimeException(x);
186 }
187 boolean sensitive = component.isSensitive();
188 int componentNumber = component.getComponentNumber();
189
190 posY += thickness / 2;
191
192 String componentName = moduleName + "_component" + componentNumber;
193
194 Trapezoid sliceTrd = new Trapezoid(componentName + "_trd", x1, x2, thickness / 2, thickness / 2, z);
195 lcdd.add(sliceTrd);
196
197 Volume volume = new Volume(componentName, sliceTrd, material);
198 lcdd.add(volume);
199
200 Position position = new Position(componentName + "_position", 0., posY, 0);
201 lcdd.add(position);
202 Rotation rotation = new Rotation(componentName + "_rotation");
203 lcdd.add(rotation);
204
205 PhysVol pv = new PhysVol(volume, moduleVolume, position, rotation);
206 pv.addPhysVolID("component", componentNumber);
207
208 if (sensitive) {
209 if (sensor > 1) {
210 throw new RuntimeException("Maximum of 2 sensors per module.");
211 }
212 pv.addPhysVolID("sensor", sensor);
213 volume.setSensitiveDetector(sd);
214 ++sensor;
215 }
216
217 if (component.getVis() != null) {
218 volume.setVisAttributes(lcdd.getVisAttributes(component.getVis()));
219 }
220
221 posY += thickness / 2;
222 }
223 }
224
225 public boolean isTracker() {
226 return true;
227 }
228 }