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