View Javadoc

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.Element;
10  import org.lcsim.detector.DetectorElement;
11  import org.lcsim.detector.IDetectorElement;
12  import org.lcsim.detector.ILogicalVolume;
13  import org.lcsim.detector.IPhysicalVolume;
14  import org.lcsim.detector.IRotation3D;
15  import org.lcsim.detector.ITransform3D;
16  import org.lcsim.detector.ITranslation3D;
17  import org.lcsim.detector.LogicalVolume;
18  import org.lcsim.detector.PhysicalVolume;
19  import org.lcsim.detector.RotationPassiveXYZ;
20  import org.lcsim.detector.Transform3D;
21  import org.lcsim.detector.Translation3D;
22  import org.lcsim.detector.identifier.ExpandedIdentifier;
23  import org.lcsim.detector.identifier.IExpandedIdentifier;
24  import org.lcsim.detector.identifier.IIdentifier;
25  import org.lcsim.detector.identifier.IIdentifierHelper;
26  import org.lcsim.detector.material.IMaterial;
27  import org.lcsim.detector.material.MaterialStore;
28  import org.lcsim.detector.solids.Box;
29  import org.lcsim.detector.solids.Trd;
30  import org.lcsim.geometry.compact.Detector;
31  import org.lcsim.geometry.compact.Subdetector;
32  import org.lcsim.geometry.layer.Layer;
33  import org.lcsim.geometry.layer.Layering;
34  import org.lcsim.geometry.subdetector.PolyhedraBarrelCalorimeter;
35  
36  public class PolyhedraBarrelCalorimeterConverter extends AbstractSubdetectorConverter
37  {
38      public void convert( Subdetector subdet, Detector detector )
39      {
40          // subdetector parameters
41          int sysId = subdet.getSystemID();
42          String subdetName = subdet.getName();
43          PolyhedraBarrelCalorimeter cal = ( PolyhedraBarrelCalorimeter ) subdet;
44          int nsides = cal.getNumberOfSides();
45          double innerR = cal.getInnerRadius();
46          Layering layering = cal.getLayering();
47          double thickness = layering.getThickness();
48          double z = cal.getZLength();
49  
50          // parameters for trapezoid section
51          double innerAngle = Math.PI * 2 / nsides;
52          double halfInnerAngle = innerAngle / 2;
53          double innerFaceLength = innerR * tan( halfInnerAngle ) * 2;
54          double rmax = innerR + thickness;
55          double outerFaceLength = rmax * tan( halfInnerAngle ) * 2;
56          double sectCenter = innerR + thickness / 2;
57          double layerOuterAngle = ( PI - innerAngle ) / 2;
58          double layerInnerAngle = ( PI / 2 - layerOuterAngle );
59  
60          Trd sectTrd = new Trd( subdet.getName() + "_stave_trapezoid",
61                                 innerFaceLength / 2,
62                                 outerFaceLength / 2,
63                                 z / 2,
64                                 z / 2,
65                                 thickness / 2 );
66          IMaterial air = MaterialStore.getInstance().get( "Air" );
67          ILogicalVolume sectLV = new LogicalVolume( subdetName + "_stave", sectTrd, air );
68  
69          double stave_thickness = thickness;
70  
71          int layer_number = 0;
72          double layer_position_z = -( stave_thickness / 2 );
73  
74          double layer_dim_x = innerFaceLength;
75  
76          for ( Iterator i = subdet.getNode().getChildren( "layer" ).iterator(); i.hasNext(); )
77          {
78              Element layer_element = ( Element ) i.next();
79  
80              // Get the layer from the layering engine.
81              Layer layer = layering.getLayer( layer_number );
82  
83              // Get number of times to repeat this layer.
84              int repeat;
85  
86              try
87              {
88                  repeat = ( int ) layer_element.getAttribute( "repeat" ).getDoubleValue();
89              }
90              catch ( Exception x )
91              {
92                  throw new RuntimeException( x );
93              }
94  
95              // Loop over repeats for this layer.
96              for ( int j = 0; j < repeat; j++ )
97              {
98                  // Name of the layer.
99                  String layer_name = subdetName + "_stave_layer" + layer_number;
100 
101                 // Layer thickness.
102                 double layer_thickness = layer.getThickness();
103 
104                 int nslices = layer_element.getChildren( "slices" ).size();
105 
106                 // Layer position in Z within the stave.
107                 layer_position_z += layer_thickness / 2;
108 
109                 // Position of layer.
110                 ITranslation3D layer_position = new Translation3D( 0, 0, layer_position_z );
111 
112                 // Layer box.
113                 Box layer_box = new Box( layer_name + "_box", layer_dim_x / 2, z / 2, layer_thickness / 2 );
114 
115                 ILogicalVolume layer_volume = new LogicalVolume( layer_name, layer_box, air );
116 
117                 // Create the slices (sublayers) within the layer.
118                 double slice_position_z = -( layer_thickness / 2 );
119 
120                 int slice_number = 0;
121                 for ( Iterator k = layer_element.getChildren( "slice" ).iterator(); k.hasNext(); )
122                 {
123                     Element slice_element = ( Element ) k.next();
124 
125                     String slice_name = layer_name + "_slice" + slice_number;
126 
127                     boolean sensitive = false;
128                     try
129                     {
130                         if ( slice_element.getAttribute( "sensitive" ) != null )
131                         {
132                             Attribute s = slice_element.getAttribute( "sensitive" );
133                             sensitive = s != null && s.getBooleanValue();
134                         }
135                     }
136                     catch ( Exception x )
137                     {
138                         throw new RuntimeException( x );
139                     }
140 
141                     double slice_thickness;
142                     try
143                     {
144                         slice_thickness = slice_element.getAttribute( "thickness" ).getDoubleValue();
145                     }
146                     catch ( Exception x )
147                     {
148                         throw new RuntimeException( x );
149                     }
150 
151                     slice_position_z += slice_thickness / 2;
152 
153                     IMaterial slice_material = MaterialStore.getInstance().get(
154                             slice_element.getAttributeValue( "material" ) );
155 
156                     ITranslation3D slice_position = new Translation3D( 0, 0, slice_position_z );
157                     Box slice_box = new Box( slice_name + "_box", layer_dim_x / 2, z / 2, slice_thickness / 2 );
158                     ILogicalVolume slice_volume = new LogicalVolume( slice_name, slice_box, slice_material );
159                     ITransform3D sliceTrans = new Transform3D( slice_position );
160                     PhysicalVolume slice_physvol = new PhysicalVolume( sliceTrans,
161                                                                        slice_name,
162                                                                        slice_volume,
163                                                                        layer_volume,
164                                                                        slice_number );
165                     if ( sensitive )
166                         slice_physvol.setSensitive( true );
167 
168                     slice_position_z += slice_thickness / 2;
169                     ++slice_number;
170                 }
171 
172                 // Layer PhysicalVolume.
173                 new PhysicalVolume( new Transform3D( layer_position ), layer_name, layer_volume, sectLV, layer_number );
174 
175                 // Increment the layer X dimension.
176                 layer_dim_x += layer_thickness * tan( layerInnerAngle ) * 2;
177 
178                 // Increment the layer Z position.
179                 layer_position_z += layer_thickness / 2;
180 
181                 // Increment the layer number.
182                 ++layer_number;
183             }
184         }
185 
186         // Create DetectorElements for modules.
187         for ( int i = 0; i < nsides; i++ )
188         {
189             double phi = -( 2 * Math.PI * ( ( double ) i ) / nsides - Math.PI / 2 );
190             double zc = -phi + Math.PI / 2;
191             double x = sectCenter * Math.cos( phi );
192             double y = sectCenter * Math.sin( phi );
193 
194             ITranslation3D trans = new Translation3D( x, y, 0 );
195             IRotation3D rotate = new RotationPassiveXYZ( Math.PI / 2, 0, zc );
196 
197             ITransform3D transform = new Transform3D( trans, rotate );
198 
199             String name = subdetName + "_module" + i;
200             new PhysicalVolume( transform,
201                                 name,
202                                 sectLV,
203                                 detector.getDetectorElement().getGeometry().getLogicalVolume(),
204                                 i );
205             new DetectorElement( subdet.getName() + "_module" + i, subdet.getDetectorElement(), "/" + name );
206         }
207 
208         IIdentifierHelper helper = cal.getDetectorElement().getIdentifierHelper();
209 
210         // Create DetectorElements for sensitive slices.
211         for ( IDetectorElement section : subdet.getDetectorElement().getChildren() )
212         {
213             int sectNum = section.getGeometry().getPhysicalVolume().getCopyNumber();
214             for ( IPhysicalVolume layer : section.getGeometry().getLogicalVolume().getDaughters() )
215             {
216                 for ( IPhysicalVolume slice : layer.getLogicalVolume().getDaughters() )
217                 {
218                     IExpandedIdentifier expId = new ExpandedIdentifier( helper.getIdentifierDictionary()
219                             .getNumberOfFields() );
220 
221                     expId.setValue( helper.getFieldIndex( "system" ), sysId );
222                     expId.setValue( helper.getFieldIndex( "barrel" ), 0 );
223                     expId.setValue( helper.getFieldIndex( "module" ), section.getGeometry().getPhysicalVolume()
224                             .getCopyNumber() );
225                     expId.setValue( helper.getFieldIndex( "layer" ), layer.getCopyNumber() );
226                     expId.setValue( helper.getFieldIndex( "slice" ), slice.getCopyNumber() );
227                     IIdentifier id = helper.pack( expId );
228 
229                     if ( slice.isSensitive() )
230                     {
231                         new DetectorElement( subdetName + "_module" + sectNum + "_layer" + layer.getCopyNumber() + "_slice" + slice
232                                                      .getCopyNumber(),
233                                              section,
234                                              "/" + section.getGeometry().getPhysicalVolume().getName() + "/" + layer
235                                                      .getName() + "/" + slice.getName(),
236                                              id );
237                     }
238                 }
239             }
240         }
241 
242     }
243 
244     public Class getSubdetectorType()
245     {
246         return PolyhedraBarrelCalorimeter.class;
247     }
248 }