1 package org.lcsim.detector.converter.compact;
2
3 import static java.lang.Math.PI;
4 import static java.lang.Math.tan;
5
6 import java.util.Iterator;
7
8 import org.jdom.Attribute;
9 import org.jdom.DataConversionException;
10 import org.jdom.Element;
11 import org.lcsim.detector.DetectorElement;
12 import org.lcsim.detector.IDetectorElement;
13 import org.lcsim.detector.ILogicalVolume;
14 import org.lcsim.detector.IPhysicalVolume;
15 import org.lcsim.detector.IRotation3D;
16 import org.lcsim.detector.ITransform3D;
17 import org.lcsim.detector.ITranslation3D;
18 import org.lcsim.detector.LogicalVolume;
19 import org.lcsim.detector.PhysicalVolume;
20 import org.lcsim.detector.RotationPassiveXYZ;
21 import org.lcsim.detector.Transform3D;
22 import org.lcsim.detector.Translation3D;
23 import org.lcsim.detector.identifier.ExpandedIdentifier;
24 import org.lcsim.detector.identifier.IExpandedIdentifier;
25 import org.lcsim.detector.identifier.IIdentifier;
26 import org.lcsim.detector.identifier.IIdentifierHelper;
27 import org.lcsim.detector.material.IMaterial;
28 import org.lcsim.detector.material.MaterialStore;
29 import org.lcsim.detector.solids.Box;
30 import org.lcsim.detector.solids.Trd;
31 import org.lcsim.geometry.compact.Detector;
32 import org.lcsim.geometry.compact.Subdetector;
33 import org.lcsim.geometry.layer.Layer;
34 import org.lcsim.geometry.layer.Layering;
35 import org.lcsim.geometry.subdetector.PolyhedraBarrelCalorimeter2;
36
37
38
39
40
41
42
43
44
45
46 public class PolyhedraBarrelCalorimeter2Converter extends AbstractSubdetectorConverter
47 {
48 public void convert( Subdetector subdet, Detector detector )
49 {
50
51 int sysId = subdet.getSystemID();
52 String subdetName = subdet.getName();
53 PolyhedraBarrelCalorimeter2 cal = ( PolyhedraBarrelCalorimeter2 ) subdet;
54 int nsides = cal.getNumberOfSides();
55 double innerR = cal.getInnerRadius();
56 Layering layering = cal.getLayering();
57 double thickness = layering.getThickness();
58 double z = cal.getZLength();
59
60
61 double gap = 0;
62 if ( subdet.getNode().getAttribute( "gap" ) != null )
63 {
64 try
65 {
66 gap = subdet.getNode().getAttribute( "gap" ).getDoubleValue();
67 }
68 catch ( DataConversionException e )
69 {
70 throw new RuntimeException( e );
71 }
72 }
73
74
75 IMaterial air = MaterialStore.getInstance().get( "Air" );
76 IMaterial gapMaterial = air;
77 if ( subdet.getNode().getAttribute( "material" ) != null )
78 {
79 gapMaterial = MaterialStore.getInstance().get( subdet.getNode().getAttributeValue( "material" ) );
80 }
81
82
83 double innerAngle = Math.PI * 2 / nsides;
84 double halfInnerAngle = innerAngle / 2;
85 double innerFaceLength = innerR * tan( halfInnerAngle ) * 2;
86 double rmax = innerR + thickness;
87 double outerFaceLength = rmax * tan( halfInnerAngle ) * 2;
88 double sectCenter = innerR + thickness / 2;
89 double layerOuterAngle = ( PI - innerAngle ) / 2;
90 double layerInnerAngle = ( PI / 2 - layerOuterAngle );
91
92
93 Trd staveTrdOuter = new Trd( subdet.getName() + "_stave_trap_outer",
94 innerFaceLength / 2,
95 outerFaceLength / 2,
96 z / 2,
97 z / 2,
98 thickness / 2 );
99
100
101 ILogicalVolume staveOuterLogicalVolume = new LogicalVolume( subdetName + "_stave_outer",
102 staveTrdOuter,
103 gapMaterial );
104
105
106 Trd staveTrdInner = new Trd( subdet.getName() + "_stave_trap_inner",
107 innerFaceLength / 2 - gap,
108 outerFaceLength / 2 - gap,
109 z / 2,
110 z / 2,
111 thickness / 2 );
112
113
114 ILogicalVolume staveInnerLogicalVolume = new LogicalVolume( subdetName + "_stave_inner", staveTrdInner, air );
115
116
117 new PhysicalVolume( new Transform3D(), subdetName, staveInnerLogicalVolume, staveOuterLogicalVolume, 0 );
118
119
120 double staveThickness = thickness;
121 int layerNumber = 0;
122 double layerZ = -( staveThickness / 2 );
123 double layerX = staveTrdInner.getXHalfLength1() * 2;
124
125
126 for ( Iterator i = subdet.getNode().getChildren( "layer" ).iterator(); i.hasNext(); )
127 {
128 Element layer_element = ( Element ) i.next();
129
130
131 Layer layer = layering.getLayer( layerNumber );
132
133
134 int repeat;
135 try
136 {
137 repeat = ( int ) layer_element.getAttribute( "repeat" ).getDoubleValue();
138 }
139 catch ( Exception x )
140 {
141 throw new RuntimeException( x );
142 }
143
144
145 for ( int j = 0; j < repeat; j++ )
146 {
147
148 String layerName = subdetName + "_stave_layer" + layerNumber;
149
150
151 double layerThickness = layer.getThickness();
152
153
154 layerZ += layerThickness / 2;
155
156
157 ITranslation3D layer_position = new Translation3D( 0, 0, layerZ );
158
159
160 Box layerBox = new Box( layerName + "_box", layerX / 2, z / 2, layerThickness / 2 );
161
162
163 ILogicalVolume layerVolume = new LogicalVolume( layerName, layerBox, air );
164
165
166 double sliceZ = -( layerThickness / 2 );
167
168
169 int sliceNumber = 0;
170
171
172 for ( Iterator k = layer_element.getChildren( "slice" ).iterator(); k.hasNext(); )
173 {
174 Element sliceElement = ( Element ) k.next();
175
176 String sliceName = layerName + "_slice" + sliceNumber;
177
178
179 boolean sensitive = false;
180 try
181 {
182 if ( sliceElement.getAttribute( "sensitive" ) != null )
183 {
184 Attribute s = sliceElement.getAttribute( "sensitive" );
185 sensitive = s != null && s.getBooleanValue();
186 }
187 }
188 catch ( Exception x )
189 {
190 throw new RuntimeException( x );
191 }
192
193
194 double sliceThickness;
195 try
196 {
197 sliceThickness = sliceElement.getAttribute( "thickness" ).getDoubleValue();
198 }
199 catch ( Exception x )
200 {
201 throw new RuntimeException( x );
202 }
203
204
205 sliceZ += sliceThickness / 2;
206
207
208 IMaterial sliceMaterial = MaterialStore.getInstance().get(
209 sliceElement.getAttributeValue( "material" ) );
210
211
212 ITranslation3D slicePosition = new Translation3D( 0, 0, sliceZ );
213 ITransform3D sliceTrans = new Transform3D( slicePosition );
214
215
216 Box sliceBox = new Box( sliceName + "_box", layerX / 2, z / 2, sliceThickness / 2 );
217
218
219 ILogicalVolume sliceVolume = new LogicalVolume( sliceName, sliceBox, sliceMaterial );
220
221
222 PhysicalVolume slicePlacement = new PhysicalVolume( sliceTrans,
223 sliceName,
224 sliceVolume,
225 layerVolume,
226 sliceNumber );
227
228
229 if ( sensitive )
230 slicePlacement.setSensitive( true );
231
232
233 sliceZ += sliceThickness / 2;
234
235
236 ++sliceNumber;
237 }
238
239
240 new PhysicalVolume( new Transform3D( layer_position ),
241 layerName,
242 layerVolume,
243 staveInnerLogicalVolume,
244 layerNumber );
245
246
247 layerX += layerThickness * tan( layerInnerAngle ) * 2;
248
249
250 layerZ += layerThickness / 2;
251
252
253 ++layerNumber;
254 }
255 }
256
257
258 for ( int i = 0; i < nsides; i++ )
259 {
260
261 double phi = -( 2 * Math.PI * ( ( double ) i ) / nsides - Math.PI / 2 );
262 double zc = -phi + Math.PI / 2;
263 double x = sectCenter * Math.cos( phi );
264 double y = sectCenter * Math.sin( phi );
265
266
267 ITranslation3D trans = new Translation3D( x, y, 0 );
268 IRotation3D rotate = new RotationPassiveXYZ( Math.PI / 2, 0, zc );
269 ITransform3D transform = new Transform3D( trans, rotate );
270
271
272 String name = subdetName + "_module" + i;
273 new PhysicalVolume( transform, name, staveOuterLogicalVolume, detector.getDetectorElement().getGeometry()
274 .getLogicalVolume(), i );
275
276
277 new DetectorElement( subdet.getName() + "_module" + i, subdet.getDetectorElement(), "/" + name );
278 }
279
280
281 IIdentifierHelper helper = cal.getDetectorElement().getIdentifierHelper();
282
283
284
285
286 for ( IDetectorElement outerStave : subdet.getDetectorElement().getChildren() )
287 {
288
289 for ( IPhysicalVolume innerStave : outerStave.getGeometry().getLogicalVolume().getDaughters() )
290 {
291
292 int staveNum = outerStave.getGeometry().getPhysicalVolume().getCopyNumber();
293
294
295 for ( IPhysicalVolume layer : innerStave.getLogicalVolume().getDaughters() )
296 {
297
298 for ( IPhysicalVolume slice : layer.getLogicalVolume().getDaughters() )
299 {
300
301 IExpandedIdentifier expId = new ExpandedIdentifier( helper.getIdentifierDictionary()
302 .getNumberOfFields() );
303
304
305 expId.setValue( helper.getFieldIndex( "system" ), sysId );
306 expId.setValue( helper.getFieldIndex( "barrel" ), 0 );
307 expId.setValue( helper.getFieldIndex( "module" ), outerStave.getGeometry().getPhysicalVolume()
308 .getCopyNumber() );
309 expId.setValue( helper.getFieldIndex( "layer" ), layer.getCopyNumber() );
310 expId.setValue( helper.getFieldIndex( "slice" ), slice.getCopyNumber() );
311
312
313 IIdentifier id = helper.pack( expId );
314
315
316 if ( slice.isSensitive() )
317 {
318 new DetectorElement( subdetName + "_module" + staveNum + "_layer" + layer.getCopyNumber() + "_slice" + slice
319 .getCopyNumber(),
320 outerStave,
321 "/" + outerStave.getGeometry().getPhysicalVolume().getName() + "/" + innerStave
322 .getName() + "/" + layer.getName() + "/" + slice.getName(),
323 id );
324 }
325 }
326 }
327 }
328 }
329
330 }
331
332 public Class getSubdetectorType()
333 {
334 return PolyhedraBarrelCalorimeter2.class;
335 }
336 }