1 package org.lcsim.detector.converter.compact;
2
3 import static java.lang.Math.cos;
4 import static java.lang.Math.sin;
5
6 import java.util.HashMap;
7 import java.util.Iterator;
8 import java.util.Map;
9
10 import org.jdom.DataConversionException;
11 import org.jdom.Element;
12 import org.lcsim.detector.IDetectorElement;
13 import org.lcsim.detector.ILogicalVolume;
14 import org.lcsim.detector.IPhysicalVolume;
15 import org.lcsim.detector.IPhysicalVolumePath;
16 import org.lcsim.detector.IRotation3D;
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.DetectorIdentifierHelper.SystemMap;
24 import org.lcsim.detector.identifier.ExpandedIdentifier;
25 import org.lcsim.detector.identifier.IIdentifier;
26 import org.lcsim.detector.identifier.IIdentifierDictionary;
27 import org.lcsim.detector.identifier.IIdentifierHelper;
28 import org.lcsim.detector.identifier.IdentifierDictionaryManager;
29 import org.lcsim.detector.identifier.IdentifierUtil;
30 import org.lcsim.detector.material.IMaterial;
31 import org.lcsim.detector.material.MaterialStore;
32 import org.lcsim.detector.solids.Box;
33 import org.lcsim.detector.solids.ISolid;
34 import org.lcsim.detector.solids.Tube;
35 import org.lcsim.detector.tracker.silicon.SiSensor;
36 import org.lcsim.detector.tracker.silicon.SiTrackerIdentifierHelper;
37 import org.lcsim.detector.tracker.silicon.SiTrackerLayer;
38 import org.lcsim.detector.tracker.silicon.SiTrackerModule;
39 import org.lcsim.geometry.compact.Detector;
40 import org.lcsim.geometry.compact.Subdetector;
41 import org.lcsim.geometry.subdetector.SiTrackerBarrel;
42
43 public class SiTrackerBarrelConverter extends AbstractSubdetectorConverter implements ISubdetectorConverter
44 {
45 public IIdentifierHelper makeIdentifierHelper( Subdetector subdetector, SystemMap systemMap )
46 {
47 return new SiTrackerIdentifierHelper( subdetector.getDetectorElement(),
48 makeIdentifierDictionary( subdetector ),
49 systemMap );
50 }
51
52 public void convert( Subdetector subdet, Detector detector )
53 {
54 Map< String, ILogicalVolume > modules = buildModules( subdet );
55
56 try
57 {
58 buildLayers( detector, subdet, modules );
59 }
60 catch ( DataConversionException x )
61 {
62 throw new RuntimeException( x );
63 }
64
65 setupSensorDetectorElements( subdet );
66 }
67
68 private Map< String, ILogicalVolume > buildModules( Subdetector subdet )
69 {
70 Map< String, ILogicalVolume > modules = new HashMap< String, ILogicalVolume >();
71
72 Element subdetElement = subdet.getNode();
73
74 for ( Iterator i = subdetElement.getChildren( "module" ).iterator(); i.hasNext(); )
75 {
76 Element module = ( Element ) i.next();
77 String module_name = module.getAttributeValue( "name" );
78 ILogicalVolume module_envelope;
79 try
80 {
81 module_envelope = buildModule( subdetElement, module_name );
82 modules.put( module_name, module_envelope );
83 }
84 catch ( Exception x )
85 {
86 throw new RuntimeException( x );
87 }
88 }
89
90 return modules;
91 }
92
93 private ILogicalVolume buildModule( Element subdetElement, String module_name ) throws Exception
94 {
95 String subdetName = subdetElement.getAttributeValue( "name" );
96 ILogicalVolume moduleLogVol = null;
97
98 Element moduleElement = null;
99 for ( Iterator i = subdetElement.getChildren( "module" ).iterator(); i.hasNext(); )
100 {
101 Element moduleCheck = ( Element ) i.next();
102 if ( moduleCheck.getAttributeValue( "name" ).compareTo( module_name ) == 0 )
103 {
104 moduleElement = moduleCheck;
105 }
106 }
107 if ( moduleElement == null )
108 {
109 throw new RuntimeException( "module <" + module_name + " was not found" );
110 }
111
112 Element moduleEnvelopeElement = moduleElement.getChild( "module_envelope" );
113
114
115 double moduleLength = moduleEnvelopeElement.getAttribute( "length" ).getDoubleValue();
116 double moduleWidth = moduleEnvelopeElement.getAttribute( "width" ).getDoubleValue();
117 double moduleThickness = moduleEnvelopeElement.getAttribute( "thickness" ).getDoubleValue();
118 ISolid moduleBox = new Box( module_name + "_box", moduleWidth / 2, moduleLength / 2, moduleThickness / 2 );
119
120
121 IMaterial air = MaterialStore.getInstance().get( "Air" );
122 moduleLogVol = new LogicalVolume( module_name, moduleBox, air );
123
124 int componentNumber = 0;
125 for ( Iterator j = moduleElement.getChildren( "module_component" ).iterator(); j.hasNext(); ++componentNumber )
126 {
127 Element componentElement = ( Element ) j.next();
128
129 boolean sensitive = ( ( componentElement.getAttribute( "sensitive" ) == null ) ? false : componentElement
130 .getAttribute( "sensitive" ).getBooleanValue() );
131
132 String componentName = module_name + "_component" + componentNumber;
133
134
135 double componentLength = componentElement.getAttribute( "length" ).getDoubleValue();
136 double componentWidth = componentElement.getAttribute( "width" ).getDoubleValue();
137 double componentThickness = componentElement.getAttribute( "thickness" ).getDoubleValue();
138 ISolid componentBox = new Box( componentName,
139 componentWidth / 2,
140 componentLength / 2,
141 componentThickness / 2 );
142
143 IMaterial componentMaterial = MaterialStore.getInstance().get(
144 componentElement.getAttributeValue( "material" ) );
145
146
147 ILogicalVolume componentLogVol = new LogicalVolume( componentName, componentBox, componentMaterial );
148
149
150 double px = 0, py = 0, pz = 0;
151
152 if ( componentElement.getChild( "position" ) != null )
153 {
154 Element pos_elem = componentElement.getChild( "position" );
155
156 if ( pos_elem.getAttribute( "x" ) != null )
157 {
158 px = pos_elem.getAttribute( "x" ).getDoubleValue();
159 }
160
161 if ( pos_elem.getAttribute( "y" ) != null )
162 {
163 py = pos_elem.getAttribute( "y" ).getDoubleValue();
164 }
165
166 if ( pos_elem.getAttribute( "z" ) != null )
167 {
168 pz = pos_elem.getAttribute( "z" ).getDoubleValue();
169 }
170 }
171
172 ITranslation3D pos = new Translation3D( px, py, pz );
173
174
175 double rx = 0, ry = 0, rz = 0;
176
177 if ( componentElement.getChild( "rotation" ) != null )
178 {
179 Element rot_elem = componentElement.getChild( "rotation" );
180
181 if ( rot_elem.getAttribute( "x" ) != null )
182 {
183 rx = rot_elem.getAttribute( "x" ).getDoubleValue();
184 }
185
186 if ( rot_elem.getAttribute( "y" ) != null )
187 {
188 ry = rot_elem.getAttribute( "y" ).getDoubleValue();
189 }
190
191 if ( rot_elem.getAttribute( "z" ) != null )
192 {
193 rz = rot_elem.getAttribute( "z" ).getDoubleValue();
194 }
195 }
196
197 IRotation3D rot = new RotationPassiveXYZ( rx, ry, rz );
198
199
200 Transform3D componentTransform = new Transform3D( pos, rot );
201
202 PhysicalVolume componentPhysVol = new PhysicalVolume( componentTransform,
203 componentName,
204 componentLogVol,
205 moduleLogVol,
206 componentNumber );
207
208 if ( sensitive )
209 {
210 componentPhysVol.setSensitive( true );
211 }
212
213 ++componentNumber;
214 }
215
216 return moduleLogVol;
217 }
218
219 private void buildLayers( Detector detector, Subdetector subdet, Map< String, ILogicalVolume > modules ) throws DataConversionException
220 {
221 Element node = subdet.getNode();
222 String detector_name = subdet.getName();
223
224
225
226 for ( Iterator i = node.getChildren( "layer" ).iterator(); i.hasNext(); )
227 {
228
229 Element layer_element = ( Element ) i.next();
230
231 int layern = layer_element.getAttribute( "id" ).getIntValue();
232
233
234 String module_name = layer_element.getAttributeValue( "module" );
235
236
237 ILogicalVolume moduleEnvelope = modules.get( module_name );
238
239
240 Element barrel_envelope = layer_element.getChild( "barrel_envelope" );
241
242
243 double ir = barrel_envelope.getAttribute( "inner_r" ).getDoubleValue();
244
245
246 double or = barrel_envelope.getAttribute( "outer_r" ).getDoubleValue();
247
248
249 double oz = barrel_envelope.getAttribute( "z_length" ).getDoubleValue();
250
251
252 String layer_name = detector_name + "_layer" + layern;
253
254
255
256 Tube layer_tube = new Tube( layer_name + "_tube", ir, or, oz / 2 );
257
258
259 IMaterial air = MaterialStore.getInstance().get( "Air" );
260 ILogicalVolume layer_volume = new LogicalVolume( layer_name, layer_tube, air );
261
262
263 IPhysicalVolume layer_envelope_physvol = new PhysicalVolume( null, layer_name, layer_volume, detector
264 .getTrackingVolume().getLogicalVolume(), layern );
265
266
267 String layerPath = "/tracking_region/" + layer_name;
268 IDetectorElement layerDE = new SiTrackerLayer( layer_name, subdet.getDetectorElement(), layerPath, layern );
269
270
271 Element rphi_layout = layer_element.getChild( "rphi_layout" );
272
273
274 double phi0 = rphi_layout.getAttribute( "phi0" ).getDoubleValue();
275
276
277 int nphi = rphi_layout.getAttribute( "nphi" ).getIntValue();
278 assert ( nphi > 0 );
279
280
281 double phi_tilt = rphi_layout.getAttribute( "phi_tilt" ).getDoubleValue();
282
283
284 double rc = rphi_layout.getAttribute( "rc" ).getDoubleValue();
285
286
287 double rphi_dr = 0.0;
288 if ( rphi_layout.getAttribute( "dr" ) != null )
289 {
290 rphi_dr = rphi_layout.getAttribute( "dr" ).getDoubleValue();
291 }
292
293
294 double phi_incr = ( Math.PI * 2 ) / nphi;
295
296
297 double phic = 0;
298 phic += phi0;
299
300
301 Element z_layout = layer_element.getChild( "z_layout" );
302
303
304 double z0 = z_layout.getAttribute( "z0" ).getDoubleValue();
305
306
307 double nz = z_layout.getAttribute( "nz" ).getIntValue();
308 assert ( nz > 0 );
309
310
311 double z_dr = z_layout.getAttribute( "dr" ).getDoubleValue();
312
313
314
315
316 double z_incr = ( 2.0 * z0 ) / ( nz - 1 );
317
318
319 double module_z = -z0;
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336 int moduleId = 0;
337
338
339 for ( int phicount = 0; phicount < nphi; phicount++ )
340 {
341
342 double dx = z_dr * cos( phic + phi_tilt );
343
344
345 double dy = z_dr * sin( phic + phi_tilt );
346
347
348 double x = rc * cos( phic );
349
350
351 double y = rc * sin( phic );
352
353
354 for ( int zcount = 0; zcount < nz; zcount++ )
355 {
356
357
358 String module_place_name = detector_name + "_layer" + layern + "_phi" + phicount + "_z" + zcount;
359
360 double z = module_z;
361
362
363
364
365
366
367
368
369
370
371
372
373
374 ITranslation3D module_position = new Translation3D( x, y, z );
375
376
377
378
379
380
381
382
383
384
385
386
387
388 double rotx = Math.PI / 2;
389 double roty = 0;
390 double rotz = ( ( Math.PI / 2 ) - phic - phi_tilt );
391
392 IRotation3D module_rotation = new RotationPassiveXYZ( rotx, roty, rotz );
393
394
395
396
397
398 Transform3D moduleTransform = new Transform3D( module_position, module_rotation );
399
400
401 IPhysicalVolume module_physvol = new PhysicalVolume( moduleTransform,
402 module_place_name,
403 moduleEnvelope,
404 layer_volume,
405 moduleId );
406
407 String modulePath = "/tracking_region/" + layer_name + "/" + module_place_name;
408
409 new SiTrackerModule( module_place_name, layerDE, modulePath, moduleId );
410
411
412 ++moduleId;
413
414
415 x += dx;
416 y += dy;
417
418
419 dx *= -1;
420 dy *= -1;
421
422
423 module_z += z_incr;
424
425
426 }
427
428
429 phic += phi_incr;
430
431
432 rc += rphi_dr;
433
434
435 rphi_dr *= -1;
436
437
438 module_z = -z0;
439 }
440 }
441 }
442
443 public Class getSubdetectorType()
444 {
445 return SiTrackerBarrel.class;
446 }
447
448 private void setupSensorDetectorElements( Subdetector subdet )
449 {
450 int moduleId = 0;
451 for ( IDetectorElement layer : subdet.getDetectorElement().getChildren() )
452 {
453 for ( IDetectorElement module : layer.getChildren() )
454 {
455 IPhysicalVolumePath modulePath = module.getGeometry().getPath();
456
457 IPhysicalVolume modulePhysVol = modulePath.getLeafVolume();
458
459 int sensorId = 0;
460 for ( IPhysicalVolume pv : modulePhysVol.getLogicalVolume().getDaughters() )
461 {
462
463 if ( pv.isSensitive() )
464 {
465 IIdentifierDictionary iddict = IdentifierDictionaryManager.getInstance()
466 .getIdentifierDictionary( subdet.getReadout().getName() );
467
468 ExpandedIdentifier expId = new ExpandedIdentifier( iddict.getNumberOfFields() );
469
470
471 expId.setValue( iddict.getFieldIndex( "system" ), subdet.getSystemID() );
472
473
474 expId.setValue( iddict.getFieldIndex( "barrel" ), 0 );
475
476
477 expId.setValue( iddict.getFieldIndex( "layer" ), layer.getGeometry().getPath().getLeafVolume()
478 .getCopyNumber() );
479
480
481 expId.setValue( iddict.getFieldIndex( "module" ), ( ( SiTrackerModule ) module ).getModuleId() );
482
483
484 expId.setValue( iddict.getFieldIndex( "sensor" ), sensorId );
485
486
487
488 IIdentifier id = iddict.pack( expId );
489
490
491
492
493 String sensorPath = modulePath.toString() + "/" + pv.getName();
494
495
496
497 String sensorName = subdet.getName() + "_layer" + layer.getGeometry().getPhysicalVolume()
498 .getCopyNumber() + "_module" + ( ( SiTrackerModule ) module ).getModuleId() + "_sensor" + sensorId;
499
500 SiSensor sensor = new SiSensor( sensorId, sensorName, module, sensorPath, id );
501 sensor.setIdentifier( id );
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570 ++sensorId;
571
572
573
574
575
576
577
578
579
580
581
582
583 }
584 }
585
586 ++moduleId;
587 }
588 }
589 }
590 }