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