View Javadoc

1   package org.lcsim.detector.converter.compact;
2   
3   import java.util.ArrayList;
4   import java.util.HashMap;
5   import java.util.List;
6   import java.util.Map;
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.DetectorIdentifierHelper;
13  import org.lcsim.detector.IDetectorElement;
14  import org.lcsim.detector.ILogicalVolume;
15  import org.lcsim.detector.IPhysicalVolume;
16  import org.lcsim.detector.IPhysicalVolumePath;
17  import org.lcsim.detector.IRotation3D;
18  import org.lcsim.detector.ITransform3D;
19  import org.lcsim.detector.LogicalVolume;
20  import org.lcsim.detector.PhysicalVolume;
21  import org.lcsim.detector.RotationGeant;
22  import org.lcsim.detector.RotationPassiveXYZ;
23  import org.lcsim.detector.Transform3D;
24  import org.lcsim.detector.Translation3D;
25  import org.lcsim.detector.DetectorIdentifierHelper.SystemMap;
26  import org.lcsim.detector.identifier.ExpandedIdentifier;
27  import org.lcsim.detector.identifier.IExpandedIdentifier;
28  import org.lcsim.detector.identifier.IIdentifier;
29  import org.lcsim.detector.identifier.IIdentifierDictionary;
30  import org.lcsim.detector.identifier.IIdentifierHelper;
31  import org.lcsim.detector.identifier.IdentifierDictionaryManager;
32  import org.lcsim.detector.identifier.IdentifierUtil;
33  import org.lcsim.detector.material.IMaterial;
34  import org.lcsim.detector.material.MaterialStore;
35  import org.lcsim.detector.solids.Box;
36  import org.lcsim.detector.solids.Trap;
37  import org.lcsim.detector.solids.Trd;
38  import org.lcsim.detector.solids.Tube;
39  import org.lcsim.detector.tracker.silicon.SiSensor;
40  import org.lcsim.detector.tracker.silicon.SiTrackerIdentifierHelper;
41  import org.lcsim.detector.tracker.silicon.SiTrackerModule;
42  import org.lcsim.geometry.compact.Detector;
43  import org.lcsim.geometry.compact.Subdetector;
44  import org.lcsim.geometry.compact.converter.SiTrackerModuleComponentParameters;
45  import org.lcsim.geometry.compact.converter.SiTrackerModuleParameters;
46  import org.lcsim.geometry.subdetector.SiTrackerEndcap;
47  
48  /**
49   * Converter for SiTrackerEndcap.
50   * 
51   * @author Jeremy McCormick, Tim Nelson
52   * @version $Id: SiTrackerEndcapConverter.java,v 1.38 2011/02/25 03:09:38 jeremy Exp $
53   */
54  
55  public class SiTrackerEndcapConverter extends AbstractSubdetectorConverter implements ISubdetectorConverter
56  {
57      public SiTrackerEndcapConverter()
58      {
59      }
60  
61      public IIdentifierHelper makeIdentifierHelper( Subdetector subdetector, SystemMap systemMap )
62      {
63          return new SiTrackerIdentifierHelper( subdetector.getDetectorElement(),
64                                                makeIdentifierDictionary( subdetector ),
65                                                systemMap );
66      }
67  
68      public void convert( Subdetector subdet, Detector detector )
69      {
70          Map< String, SiTrackerModuleParameters > moduleParameters = new HashMap< String, SiTrackerModuleParameters >();
71  
72          IPhysicalVolume trackingPV = detector.getTrackingVolume();
73          ILogicalVolume trackingLV = trackingPV.getLogicalVolume();
74  
75          Element node = subdet.getNode();
76  
77          IDetectorElement endcapDE = subdet.getDetectorElement();
78  
79          DetectorIdentifierHelper helper = ( DetectorIdentifierHelper ) endcapDE.getIdentifierHelper();
80          int nfields = helper.getIdentifierDictionary().getNumberOfFields();
81  
82          IDetectorElement endcapPosDE = null;
83          IDetectorElement endcapNegDE = null;
84          try
85          {
86              // Positive endcap DE
87              IExpandedIdentifier endcapPosId = new ExpandedIdentifier( nfields );
88              endcapPosId.setValue( helper.getFieldIndex( "system" ), subdet.getSystemID() );
89              endcapPosId.setValue( helper.getFieldIndex( "barrel" ), helper.getEndcapPositiveValue() );
90              endcapPosDE = new DetectorElement( subdet.getName() + "_positive", endcapDE );
91              endcapPosDE.setIdentifier( helper.pack( endcapPosId ) );
92  
93              // Negative endcap DE.
94              IExpandedIdentifier endcapNegId = new ExpandedIdentifier( nfields );
95              endcapNegId.setValue( helper.getFieldIndex( "system" ), subdet.getSystemID() );
96              endcapNegId.setValue( helper.getFieldIndex( "barrel" ), helper.getEndcapNegativeValue() );
97              endcapNegDE = new DetectorElement( subdet.getName() + "_negative", endcapDE );
98              endcapNegDE.setIdentifier( helper.pack( endcapNegId ) );
99  
100         }
101         catch ( Exception x )
102         {
103             throw new RuntimeException( x );
104         }
105 
106         // Set static module parameters.
107         for ( Object n : node.getChildren( "module" ) )
108         {
109             Element e = ( Element ) n;
110             moduleParameters.put( e.getAttributeValue( "name" ), new SiTrackerModuleParameters( e ) );
111         }
112 
113         for ( Object o : node.getChildren( "layer" ) )
114         {
115             Element layerElement = ( Element ) o;
116 
117             int nwedges;
118             try
119             {
120                 nwedges = layerElement.getAttribute( "nwedges" ).getIntValue();
121             }
122             catch ( DataConversionException x )
123             {
124                 throw new RuntimeException( x );
125             }
126 
127             double innerR, outerR, innerZ, thickness;
128             int layern;
129             try
130             {
131                 layern = layerElement.getAttribute( "id" ).getIntValue();
132                 innerR = layerElement.getAttribute( "inner_r" ).getDoubleValue();
133                 outerR = layerElement.getAttribute( "outer_r" ).getDoubleValue();
134                 innerZ = layerElement.getAttribute( "inner_z" ).getDoubleValue();
135                 thickness = layerElement.getAttribute( "thickness" ).getDoubleValue();
136             }
137             catch ( DataConversionException x )
138             {
139                 throw new RuntimeException( x );
140             }
141 
142             ILogicalVolume layerLV = makeLayer(
143                     detector,
144                     subdet,
145                     innerR,
146                     outerR,
147                     thickness,
148                     nwedges,
149                     layerElement,
150                     moduleParameters );
151 
152             double layerZ = innerZ + thickness / 2;
153 
154             // Positive endcap layer.
155             ITransform3D layerTrans = new Transform3D( new Translation3D( 0, 0, layerZ ) );
156             String layerName = layerLV.getName() + "_positive";
157             new PhysicalVolume( layerTrans, layerName, layerLV, trackingLV, layern );
158             String layerPath = "/" + trackingPV.getName() + "/" + layerName;
159             IDetectorElement layerDE = new DetectorElement( layerLV.getName(), endcapPosDE, detector.getNavigator()
160                     .getPath( layerPath ) );
161 
162             // Negative endcap layer.
163             ITransform3D layerTransReflect = new Transform3D( new Translation3D( 0, 0, -layerZ ),
164                                                               new RotationPassiveXYZ( 0, Math.PI, 0 ) );
165             String layerNameReflect = layerLV.getName() + "_negative";
166             new PhysicalVolume( layerTransReflect, layerNameReflect, layerLV, trackingLV, layern );
167             String layerPathReflect = "/" + trackingPV.getName() + "/" + layerNameReflect;
168             IDetectorElement layerDEReflect = new DetectorElement( layerNameReflect, endcapNegDE, detector
169                     .getNavigator().getPath( layerPathReflect ) );
170 
171             // Wedge DE.
172             for ( IPhysicalVolume wedge : layerLV.getDaughters() )
173             {
174                 // Positive endcap.
175                 String wedgePath = layerPath + "/" + wedge.getName();
176                 String wedgeName = layerName + "_wedge" + wedge.getCopyNumber();
177                 IDetectorElement wedgeDE = new DetectorElement( wedgeName, layerDE, detector.getNavigator().getPath(
178                         wedgePath ) );
179 
180                 // Negative endcap.
181                 String wedgePathReflect = layerPathReflect + "/" + wedge.getName();
182                 String wedgeNameReflect = layerNameReflect + "_wedge" + wedge.getCopyNumber();
183                 IDetectorElement wedgeDEReflect = new DetectorElement( wedgeNameReflect, layerDEReflect, detector
184                         .getNavigator().getPath( wedgePathReflect ) );
185 
186                 // Module DEs.
187                 for ( IPhysicalVolume module : wedge.getLogicalVolume().getDaughters() )
188                 {
189                     // Positive endcap module.
190                     String modulePath = wedgePath + "/" + module.getName();
191                     String moduleName = wedgeName + "_module" + module.getCopyNumber();
192                     IDetectorElement moduleDE = new SiTrackerModule( moduleName, wedgeDE, detector.getNavigator()
193                             .getPath( modulePath ).toString(), module.getCopyNumber() );
194 
195                     // Negative endcap module.
196                     String modulePathReflect = wedgePathReflect + "/" + module.getName();
197                     String moduleNameReflect = wedgeNameReflect + "_module" + module.getCopyNumber();
198                     IDetectorElement moduleDEReflect = new SiTrackerModule( moduleNameReflect, wedgeDEReflect, detector
199                             .getNavigator().getPath( modulePathReflect ).toString(), module.getCopyNumber() );
200                 }
201             }
202         }
203 
204         try
205         {
206             setupSensorDetectorElements( subdet );
207         }
208         catch ( Exception x )
209         {
210             throw new RuntimeException( x );
211         }
212     }
213 
214     private ILogicalVolume makeWedge( Detector detector,
215             Subdetector subdet,
216             double innerR,
217             double outerR,
218             double thickness,
219             int nwedges,
220             int layern )
221     {
222         IMaterial material = detector.getTrackingVolume().getLogicalVolume().getMaterial();
223 
224         String name = subdet.getName() + "_layer" + layern + "_wedge";
225 
226         double wedge_margin = 0.0001;
227         // double wedge_margin = 2.0;
228 
229         double dz = ( outerR - innerR ) / 2;
230         double dy1, dy2;
231         dy1 = dy2 = thickness / 2;
232         double dx1, dx2;
233         double dphi = Math.PI / nwedges;
234         dx1 = innerR * Math.tan( dphi ) - wedge_margin / Math.cos( dphi );
235         dx2 = outerR * Math.tan( dphi ) - wedge_margin / Math.cos( dphi );
236 
237         Trd wedgeTrd = new Trd( name, dx1, dx2, dy1, dy2, dz );
238 
239         ILogicalVolume wedgeLV = new LogicalVolume( name, wedgeTrd, material );
240 
241         return wedgeLV;
242     }
243 
244     private ILogicalVolume makeLayer( Detector detector,
245             Subdetector subdet,
246             double innerR,
247             double outerR,
248             double thickness,
249             int nwedges,
250             Element layerElement,
251             Map< String, SiTrackerModuleParameters > moduleParameters )
252     {
253         int layern;
254         try
255         {
256             layern = layerElement.getAttribute( "id" ).getIntValue();
257         }
258         catch ( DataConversionException x )
259         {
260             throw new RuntimeException( x );
261         }
262 
263         IMaterial material = detector.getTrackingVolume().getLogicalVolume().getMaterial();
264         String layerName = subdet.getName() + "_layer" + layern;
265 
266         double dphi = Math.PI / nwedges;
267 
268         double tubeInnerR, tubeOuterR;
269         tubeInnerR = innerR;
270         tubeOuterR = outerR / Math.cos( dphi );
271 
272         Tube layerTube = new Tube( layerName, tubeInnerR, tubeOuterR, thickness / 2 );
273 
274         // Make the layer LV.
275         ILogicalVolume layerLV = new LogicalVolume( layerName, layerTube, material );
276 
277         // Make the wedge LV.
278         ILogicalVolume wedgeLV = makeWedge( detector, subdet, innerR, outerR, thickness, nwedges, layern );
279 
280         Attribute moduleref = layerElement.getAttribute( "module" );
281 
282         if ( moduleref == null )
283             throw new RuntimeException( "module reference is missing for layer number " + layern );
284 
285         SiTrackerModuleParameters module = moduleParameters.get( moduleref.getValue() );
286 
287         // Make the modules in the wedge.
288         makeModules( subdet, wedgeLV, layerElement.getChild( "module_parameters" ), module, layern );
289 
290         // Place the wedges in the layer.
291         double r = ( innerR + outerR ) / 2;
292 
293         for ( int i = 0; i < nwedges; i++ )
294         {
295             double phi = i * 2 * Math.PI / nwedges;
296             double x = r * Math.cos( phi );
297             double y = r * Math.sin( phi );
298 
299             Translation3D p = new Translation3D( x, y, 0 );
300             IRotation3D rot = new RotationGeant( -Math.PI / 2, -Math.PI / 2 - phi, 0. );
301             Transform3D transform = new Transform3D( p, rot );
302             new PhysicalVolume( transform, "wedge" + i, wedgeLV, layerLV, i );
303         }
304 
305         return layerLV;
306     }
307 
308     private void makeModules( Subdetector subdet,
309             ILogicalVolume wedgeLV,
310             Element moduleElement,
311             SiTrackerModuleParameters module,
312             int layern )
313     {
314         double r_size;
315         try
316         {
317             r_size = moduleElement.getAttribute( "r_size" ).getDoubleValue();
318         }
319         catch ( DataConversionException x )
320         {
321             throw new RuntimeException( x );
322         }
323 
324         double phi_size_max;
325         try
326         {
327             phi_size_max = moduleElement.getAttribute( "phi_size_max" ).getDoubleValue();
328         }
329         catch ( DataConversionException x )
330         {
331             throw new RuntimeException( x );
332         }
333 
334         Trd wedgeTrd = ( Trd ) wedgeLV.getSolid();
335         double dz = ( ( Trd ) wedgeLV.getSolid() ).getZHalfLength();
336         double dx1 = wedgeTrd.getXHalfLength1();
337         double dx2 = wedgeTrd.getXHalfLength2();
338         double dy = wedgeTrd.getYHalfLength1();
339         double deltax = dx2 - dx1;
340         double side_slope = deltax / ( 2 * dz );
341 
342         double module_margin = 0.0001;
343         // double module_margin = 1.0;
344         double box_margin = module_margin;
345         double side_angle = Math.atan( side_slope );
346         double trap_margin_1 = module_margin * ( 1.0 / Math.cos( side_angle ) - Math.sin( side_angle ) );
347         double trap_margin_2 = module_margin * ( 1.0 / Math.cos( side_angle ) + Math.sin( side_angle ) );
348 
349         List< Double > zcenters = new ArrayList< Double >();
350         List< Double > zsizes = new ArrayList< Double >();
351         List< Double > xsizes1 = new ArrayList< Double >();
352         List< Double > xsizes2 = new ArrayList< Double >();
353 
354         {
355             double zcurr = dz;
356             while ( zcurr - r_size > -dz )
357             {
358                 double zmax = zcurr;
359                 double zmin = zcurr - r_size;
360                 zcenters.add( ( zmin + zmax ) / 2 );
361                 zsizes.add( ( zmax - zmin ) / 2 );
362 
363                 double xsize1 = dx1 + side_slope * ( zmin + dz );
364                 double xsize2 = dx1 + side_slope * ( zmax + dz );
365 
366                 xsizes1.add( xsize1 );
367                 xsizes2.add( xsize2 );
368 
369                 zcurr -= r_size;
370             }
371             double zmax = zcurr;
372             double zmin = -dz;
373             zcenters.add( ( zmin + zmax ) / 2 );
374             zsizes.add( ( zmax - zmin ) / 2 );
375             double xsize1 = dx1 + side_slope * ( zmin + dz );
376             double xsize2 = dx1 + side_slope * ( zmax + dz );
377             xsizes1.add( xsize1 );
378             xsizes2.add( xsize2 );
379         }
380 
381         IMaterial sliceMaterial = wedgeLV.getMaterial();
382 
383         double zsize_last = 0.0;
384         double xsize1_min = phi_size_max / 2;
385         double xsize_box = 0.0;
386         int nboxes = 0;
387 
388         int imodule = 0;
389 
390         for ( int i = zcenters.size() - 1; i >= 0; i-- )
391         {
392 
393             if ( zsizes.get( i ) != zsize_last )
394             {
395                 zsize_last = zsizes.get( i );
396                 xsize1_min = phi_size_max / 2;
397                 xsize_box = 0.0;
398                 nboxes = 0;
399             }
400 
401             int ntraps = ( int ) Math.ceil( 2 * ( xsizes1.get( i ) - nboxes * xsize_box ) / phi_size_max );
402 
403             // Squares to fill extra space
404             if ( ntraps > 2 )
405             {
406                 double delta_x = xsizes2.get( i ) - xsizes1.get( i );
407 
408                 if ( phi_size_max > delta_x )
409                 {
410                     xsize_box = delta_x * ( int ) Math.floor( phi_size_max / delta_x );
411                 }
412                 else
413                 {
414                     xsize_box = delta_x / ( int ) Math.floor( delta_x / phi_size_max );
415                 }
416 
417                 if ( xsize_box > 0.0 )
418                 {
419                     nboxes = ( int ) Math.floor( ( xsizes1.get( i ) - 2 * xsize1_min ) / xsize_box );
420                 }
421                 ntraps = 2;
422             }
423 
424             double xmin = -nboxes * xsize_box;
425             double xmax = xmin + 2 * xsize_box;
426 
427             for ( int ibox = 0; ibox < nboxes; ibox++ )
428             {
429 
430                 double xcenter = ( xmin + xmax ) / 2;
431                 xmin += 2 * xsize_box;
432                 xmax += 2 * xsize_box;
433 
434                 String sliceName = "module" + imodule;
435 
436                 Box sliceBox = new Box( sliceName, xsize_box - box_margin, dy, zsizes.get( i ) - box_margin );
437 
438                 ILogicalVolume sliceLV = new LogicalVolume( sliceName, sliceBox, sliceMaterial );
439 
440                 // Build the module substructure.
441                 makeBoxModule( sliceLV, module, imodule );
442 
443                 Transform3D trans = new Transform3D( new Translation3D( xcenter, 0, zcenters.get( i ) ) );
444 
445                 new PhysicalVolume( trans, sliceName, sliceLV, wedgeLV, imodule );
446 
447                 imodule++;
448             }
449 
450             // Small symmetric trapezoids
451             if ( ntraps == 1 )
452             {
453                 String sliceName = "module" + imodule;
454 
455                 Trd sliceTrd = new Trd( sliceName,
456                                         xsizes1.get( i ) - trap_margin_1,
457                                         xsizes2.get( i ) - trap_margin_2,
458                                         dy,
459                                         dy,
460                                         zsizes.get( i ) - box_margin );
461 
462                 ILogicalVolume sliceLV = new LogicalVolume( sliceName, sliceTrd, sliceMaterial );
463 
464                 // Build the module substructure.
465                 makeTrdModule( sliceLV, module, imodule );
466 
467                 Transform3D trans = new Transform3D( new Translation3D( 0, 0, zcenters.get( i ) ) );
468 
469                 new PhysicalVolume( trans, sliceName, sliceLV, wedgeLV, imodule );
470 
471                 imodule++;
472             }
473 
474             // Split trapezoids
475             if ( ntraps == 2 )
476             {
477 
478                 double xoffset = xsize_box * nboxes;
479 
480                 double average_margin_1 = ( box_margin + trap_margin_1 ) / 2;
481                 double average_margin_2 = ( box_margin + trap_margin_2 ) / 2;
482 
483                 double xsize1 = ( xsizes1.get( i ) - xoffset ) / ntraps - average_margin_1;
484                 if ( xsize1_min == 0.0 )
485                     xsize1_min = xsize1;
486                 double xsize2 = ( xsizes2.get( i ) - xoffset ) / ntraps - average_margin_2;
487 
488                 double xcenter = ( xsize1 + xsize2 ) / 2 + xoffset + box_margin;
489                 double theta = Math.abs( Math.atan( side_slope / 2 ) );
490 
491                 for ( int ix = -1; ix <= 1; ix = ix + 2 )
492                 {
493 
494                     String sliceName = "module" + imodule;
495 
496                     Trap sliceTrap = new Trap( sliceName,
497                                                zsizes.get( i ) - box_margin,
498                                                theta * ix,
499                                                0.0,
500                                                dy,
501                                                xsize1,
502                                                xsize1,
503                                                0.0,
504                                                dy,
505                                                xsize2,
506                                                xsize2,
507                                                0.0 );
508 
509                     ILogicalVolume sliceLV = new LogicalVolume( sliceName, sliceTrap, sliceMaterial );
510 
511                     makeTrapModule( sliceLV, module, imodule );
512 
513                     Transform3D trans = new Transform3D( new Translation3D( ix * xcenter, 0, zcenters.get( i ) ) );
514 
515                     new PhysicalVolume( trans, sliceName, sliceLV, wedgeLV, imodule );
516 
517                     imodule++;
518                 }
519             }
520         }
521     }
522 
523     public void makeBoxModule( ILogicalVolume module, SiTrackerModuleParameters moduleParameters, int moduleTypeId )
524     {
525         Box moduleBox = ( Box ) module.getSolid();
526         double posY = -moduleBox.getYHalfLength();
527         double moduleX = moduleBox.getXHalfLength();
528         double moduleZ = moduleBox.getZHalfLength();
529 
530         // pull corners in by 0.5 microns to eliminate overlaps.
531         // moduleX -= 0.0005;
532         // moduleZ -= 0.0005;
533 
534         for ( SiTrackerModuleComponentParameters component : moduleParameters )
535         {
536             double thickness = component.getThickness();
537             IMaterial material = MaterialStore.getInstance().get( component.getMaterialName() );
538             boolean sensitive = component.isSensitive();
539             int componentNumber = component.getComponentNumber();
540 
541             posY += thickness / 2;
542 
543             String componentName = "module" + moduleTypeId + "_component" + componentNumber;
544 
545             Box sliceBox = new Box( componentName + "_box", moduleX, thickness / 2, moduleZ );
546 
547             ILogicalVolume volume = new LogicalVolume( componentName, sliceBox, material );
548 
549             Transform3D trans = new Transform3D( new Translation3D( 0, posY, 0 ) );
550 
551             PhysicalVolume pv = new PhysicalVolume( trans, componentName, volume, module, componentNumber );
552             pv.setSensitive( sensitive );
553 
554             posY += thickness / 2;
555         }
556     }
557 
558     public void makeTrdModule( ILogicalVolume module, SiTrackerModuleParameters moduleParameters, int moduleTypeId )
559     {
560         Trd trd = ( Trd ) module.getSolid();
561         double x1 = trd.getXHalfLength1();
562         double x2 = trd.getXHalfLength2();
563         double y1 = trd.getYHalfLength1();
564         double z = trd.getZHalfLength();
565 
566         // pull corners in by 0.5 microns to eliminate overlaps.
567         // x1 -= 0.0005;
568         // x2 -= 0.0005;
569         // z -= 0.0005;
570 
571         double posY = -y1;
572 
573         for ( SiTrackerModuleComponentParameters component : moduleParameters )
574         {
575             double thickness = component.getThickness();
576             IMaterial material = MaterialStore.getInstance().get( component.getMaterialName() );
577             boolean sensitive = component.isSensitive();
578             int componentNumber = component.getComponentNumber();
579 
580             posY += thickness / 2;
581 
582             String componentName = "module" + moduleTypeId + "_component" + componentNumber;
583 
584             Trd sliceTrd = new Trd( componentName, x1, x2, thickness / 2, thickness / 2, z );
585 
586             ILogicalVolume volume = new LogicalVolume( componentName, sliceTrd, material );
587 
588             Transform3D trans = new Transform3D( new Translation3D( 0, posY, 0 ) );
589 
590             PhysicalVolume pv = new PhysicalVolume( trans, componentName, volume, module, componentNumber );
591             pv.setSensitive( sensitive );
592 
593             posY += thickness / 2;
594         }
595     }
596 
597     public void makeTrapModule( ILogicalVolume module, SiTrackerModuleParameters moduleParameters, int moduleTypeId )
598     {
599         Trap trap = ( Trap ) module.getSolid();
600         double a1 = trap.getAlpha1();
601         double a2 = trap.getAlpha2();
602         double x1 = trap.getXHalfLength1();
603         double x2 = trap.getXHalfLength2();
604         double x3 = trap.getXHalfLength3();
605         double x4 = trap.getXHalfLength4();
606         double y1 = trap.getYHalfLength1();
607         double z = trap.getZHalfLength();
608         double theta = trap.getTheta();
609         double phi = trap.getPhi();
610         double posY = -y1;
611 
612         // pull corners in by 0.5 microns to eliminate overlaps.
613         // x1 -= 0.0005;
614         // x2 -= 0.0005;
615         // x3 -= 0.0005;
616         // x4 -= 0.0005;
617         // z -= 0.0005;
618 
619         for ( SiTrackerModuleComponentParameters component : moduleParameters )
620         {
621             double thickness = component.getThickness();
622             IMaterial material = MaterialStore.getInstance().get( component.getMaterialName() );
623             boolean sensitive = component.isSensitive();
624             int componentNumber = component.getComponentNumber();
625 
626             posY += thickness / 2;
627 
628             String componentName = "module" + moduleTypeId + "_component" + componentNumber;
629 
630             Trap sliceTrap = new Trap( componentName,
631                                        z,
632                                        theta,
633                                        phi,
634                                        thickness / 2,
635                                        x1,
636                                        x2,
637                                        a1,
638                                        thickness / 2,
639                                        x3,
640                                        x4,
641                                        a2 );
642 
643             ILogicalVolume volume = new LogicalVolume( componentName, sliceTrap, material );
644 
645             Transform3D trans = new Transform3D( new Translation3D( 0, posY, 0 ) );
646 
647             PhysicalVolume pv = new PhysicalVolume( trans, componentName, volume, module, componentNumber );
648             pv.setSensitive( sensitive );
649 
650             posY += thickness / 2;
651         }
652     }
653 
654     public Class getSubdetectorType()
655     {
656         return SiTrackerEndcap.class;
657     }
658 
659     // TODO: Need to have SiTrackerIdentifierHelper available before this is called.
660     private void setupSensorDetectorElements( Subdetector subdet ) throws Exception
661     {
662         SiTrackerIdentifierHelper id_helper = ( SiTrackerIdentifierHelper ) subdet.getDetectorElement()
663                 .getIdentifierHelper();
664 
665         if ( id_helper == null )
666             throw new RuntimeException( "helper is null!!!!!!!!!" );
667 
668         int moduleId = 0;
669 
670         for ( IDetectorElement endcap : subdet.getDetectorElement().getChildren() )
671         {
672             for ( IDetectorElement layer : endcap.getChildren() )
673             {
674                 int nwedges = layer.getChildren().size();
675                 for ( IDetectorElement wedge : layer.getChildren() )
676                 {
677                     for ( IDetectorElement module : wedge.getChildren() )
678                     {
679                         IPhysicalVolumePath modulePath = module.getGeometry().getPath();
680 
681                         IPhysicalVolume modulePhysVol = modulePath.getLeafVolume();
682 
683                         int sensorId = 0;
684                         for ( IPhysicalVolume pv : modulePhysVol.getLogicalVolume().getDaughters() )
685                         {
686                             // Create the identifier for this sensor.
687                             if ( pv.isSensitive() )
688                             {
689                                 IIdentifierDictionary iddict = IdentifierDictionaryManager.getInstance()
690                                         .getIdentifierDictionary( subdet.getReadout().getName() );
691 
692                                 ExpandedIdentifier expId = new ExpandedIdentifier( iddict.getNumberOfFields() );
693 
694                                 // Set the System ID.
695                                 expId.setValue( iddict.getFieldIndex( "system" ), subdet.getSystemID() );
696 
697                                 // Set the barrel-endcap flag.
698                                 if ( id_helper.isEndcapPositive( endcap.getIdentifier() ) )
699                                 {
700                                     expId.setValue( iddict.getFieldIndex( "barrel" ), id_helper
701                                             .getEndcapPositiveValue() );
702                                 }
703                                 else if ( id_helper.isEndcapNegative( endcap.getIdentifier() ) )
704                                 {
705                                     expId.setValue( iddict.getFieldIndex( "barrel" ), id_helper
706                                             .getEndcapNegativeValue() );
707                                 }
708                                 else
709                                 {
710                                     throw new RuntimeException( endcap.getName() + " - not pos or neg endcap!" );
711                                 }
712 
713                                 // System.out.println("barrel flag set to " +
714                                 // expId.getValue(iddict.getFieldIndex("barrel")));
715 
716                                 // Set the layer number.
717                                 expId.setValue( iddict.getFieldIndex( "layer" ), layer.getGeometry().getPath()
718                                         .getLeafVolume().getCopyNumber() );
719 
720                                 // Set the wedge number.
721                                 expId.setValue( iddict.getFieldIndex( "wedge" ), wedge.getGeometry().getPath()
722                                         .getLeafVolume().getCopyNumber() );
723 
724                                 // Set the module id from the DetectorElement.
725                                 expId.setValue( iddict.getFieldIndex( "module" ), ( ( SiTrackerModule ) module )
726                                         .getModuleId() );
727 
728                                 // Set the sensor id for double-sided.
729                                 expId.setValue( iddict.getFieldIndex( "sensor" ), sensorId );
730 
731                                 // Create the packed id using util method.
732                                 // No IdentifierHelper is available yet.
733                                 IIdentifier id = iddict.pack( expId );
734 
735                                 String sensorPath = modulePath.toString() + "/" + pv.getName();
736                                 String sensorName = endcap.getName() + "_layer" + layer.getGeometry()
737                                         .getPhysicalVolume().getCopyNumber() + "_wedge" + wedge.getGeometry().getPath()
738                                         .getLeafVolume().getCopyNumber() + "_module" + ( ( SiTrackerModule ) module )
739                                         .getModuleId() + "_sensor" + sensorId;
740 
741                                 // System.out.println(sensorName + " -> " + expId);
742                                 // System.out.println(sensorName + " -> " + id);
743                                 // System.out.println();
744 
745                                 SiSensor sensor = new SiSensor( sensorId, sensorName, module, sensorPath, id );
746 
747                                 /*
748                                  * // Set up SiStrips for the sensors IPolyhedron
749                                  * sensor_solid =
750                                  * (IPolyhedron)sensor.getGeometry().getLogicalVolume
751                                  * ().getSolid();
752                                  * 
753                                  * Polygon3D inner_surface =
754                                  * sensor_solid.getFacesNormalTo(new
755                                  * BasicHep3Vector(0,-1,0)).get(0); Polygon3D
756                                  * outer_surface = sensor_solid.getFacesNormalTo(new
757                                  * BasicHep3Vector(0,1,0)).get(0); // double
758                                  * strip_angle_magnitude = Math.PI/nwedges;
759                                  * 
760                                  * Polygon3D p_side; Polygon3D n_side; int side;
761                                  * 
762                                  * if (sensorId == 0) // inner sensor { p_side =
763                                  * inner_surface; n_side = outer_surface; side = 1; //
764                                  * strip_angle = strip_angle_magnitude; } else // outer
765                                  * sensor { p_side = outer_surface; n_side =
766                                  * inner_surface; side = -1; // strip_angle =
767                                  * -1*strip_angle_magnitude; }
768                                  * 
769                                  * 
770                                  * 
771                                  * 
772                                  * //System.out.println("Plane of p_side polygon has... ");
773                                  * /
774                                  * /System.out.println("                        normal: "+
775                                  * p_side.getNormal());
776                                  * //System.out.println("                        distance: "
777                                  * +p_side.getDistance()); //for (Point3D point :
778                                  * p_side.getVertices()) //{ //
779                                  * System.out.println("      Vertex: "+point); //}
780                                  * 
781                                  * 
782                                  * 
783                                  * 
784                                  * //System.out.println("Plane of n_side polygon has... ");
785                                  * /
786                                  * /System.out.println("                        normal: "+
787                                  * n_side.getNormal());
788                                  * //System.out.println("                        distance: "
789                                  * +n_side.getDistance());
790                                  * 
791                                  * // Bias the sensor
792                                  * sensor.setBiasSurface(ChargeCarrier.HOLE,p_side);
793                                  * sensor.setBiasSurface(ChargeCarrier.ELECTRON,n_side);
794                                  * 
795                                  * double strip_angle = Math.PI/nwedges;
796                                  * 
797                                  * 
798                                  * 
799                                  * 
800                                  * //System.out.println("                        side = : "
801                                  * +side);
802                                  * 
803                                  * ITranslation3D electrodes_position = new
804                                  * Translation3D(VecOp.mult(-p_side.getDistance(),new
805                                  * BasicHep3Vector(0,0,1))); // translate to outside of
806                                  * polygon IRotation3D electrodes_rotation = new
807                                  * RotationPassiveXYZ(side*(Math.PI/2),0,strip_angle); //
808                                  * Transform3D electrodes_transform = new
809                                  * Transform3D(electrodes_position, electrodes_rotation);
810                                  * 
811                                  * // Free calculation of readout electrodes, sense
812                                  * electrodes determined thereon SiSensorElectrodes
813                                  * readout_electrodes = new
814                                  * SiStrips(ChargeCarrier.HOLE,0.050
815                                  * ,sensor,electrodes_transform); SiSensorElectrodes
816                                  * sense_electrodes = new
817                                  * SiStrips(ChargeCarrier.HOLE,0.025
818                                  * ,(readout_electrodes.getNCells
819                                  * ()*2-1),sensor,electrodes_transform);
820                                  * 
821                                  * sensor.setSenseElectrodes(sense_electrodes);
822                                  * sensor.setReadoutElectrodes(readout_electrodes);
823                                  * 
824                                  * double[][] transfer_efficiencies = { {0.986,0.419} };
825                                  * sensor.setTransferEfficiencies(ChargeCarrier.HOLE,new
826                                  * BasicMatrix(transfer_efficiencies));
827                                  */
828 
829                                 // Increment sensorID for double-sided.
830                                 ++sensorId;
831                             }
832                         }
833                         ++moduleId;
834                     }
835                 }
836             }
837         }
838     }
839 
840     /*
841      * public static class ModuleComponentParameters { String materialName; double
842      * thickness; boolean sensitive; int componentNumber;
843      * 
844      * public ModuleComponentParameters(double thickness, String materialName, int
845      * componentNumber, boolean sensitive) { this.thickness = thickness; this.materialName
846      * = materialName; this.sensitive = sensitive; this.componentNumber = componentNumber;
847      * }
848      * 
849      * public double getThickness() { return thickness; }
850      * 
851      * public String getMaterialName() { return materialName; }
852      * 
853      * public boolean isSensitive() { return sensitive; }
854      * 
855      * public int getComponentNumber() { return componentNumber; } }
856      * 
857      * public static class ModuleParameters extends ArrayList<ModuleComponentParameters> {
858      * double thickness=0.; String name; public ModuleParameters(Element element) { name =
859      * element.getAttributeValue("name"); int cntr=0; for (Object o :
860      * element.getChildren("module_component")) { try {
861      * 
862      * Element e = (Element)o;
863      * 
864      * double thickness = e.getAttribute("thickness").getDoubleValue();
865      * 
866      * String materialName = e.getAttributeValue("material");
867      * 
868      * boolean sensitive = false; if (e.getAttribute("sensitive") != null) sensitive =
869      * e.getAttribute("sensitive").getBooleanValue(); add(new
870      * ModuleComponentParameters(thickness, materialName, cntr, sensitive)); } catch
871      * (JDOMException x) { throw new RuntimeException(x); } ++cntr; }
872      * calculateThickness(); }
873      * 
874      * public void calculateThickness() { thickness = 0.; // reset thickness for
875      * (ModuleComponentParameters p : this) { thickness += p.getThickness(); } }
876      * 
877      * public double getThickness() { return thickness; } }
878      */
879 }