View Javadoc

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;// -LAYER_ENVELOPE_TOLERANCE;
138                 double layerOuterFaceLength = outerFaceLength;// -LAYER_ENVELOPE_TOLERANCE;
139                 double layerRadialThickness = radialThickness;// -LAYER_ENVELOPE_TOLERANCE;
140 
141                 // Layer trapezoid.
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                     // Apply tolerance factor to given slice thickness.
181                     // slice_thickness -= SLICE_TOLERANCE;
182 
183                     slicePositionY -= sliceThickness / 2;
184 
185                     Translation3D slicePosition = new Translation3D( 0, slicePositionY, 0 );
186 
187                     double sliceInnerFaceLength = layerInnerFaceLength;// -
188                     // SLICE_ENVELOPE_TOLERANCE;
189                     double sliceOuterFaceLength = layerOuterFaceLength;// -
190                     // SLICE_ENVELOPE_TOLERANCE;
191                     double sliceRadialThickness = layerRadialThickness;// -
192                     // SLICE_ENVELOPE_TOLERANCE;
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                     // The slice thickness is the original, NOT adjusted for tolerance,
214                     // so that the center of the slice is in the right place with
215                     // tolerance
216                     // gaps on either side.
217                     slicePositionY -= sliceThickness / 2;
218 
219                     // Increment the slice counter.
220                     ++sliceNumber;
221                 }
222 
223                 new PhysicalVolume( new Transform3D( layer_position ), layerName, layerVolume, sectVolume, layerNumber );
224 
225                 layerPositionY -= layerThickness / 2;
226 
227                 // DEBUG
228                 // layer_position_y -= INTER_LAYER_GAP;
229 
230                 ++layerNumber;
231             }
232             // DEBUG - Uncomment to build only one layer.
233             // break;
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             // double phi = 2*Math.PI*((double)i)/numsides;
245             double zc = -phi + Math.PI / 2;
246             // double zc = -phi + Math.PI/2;
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             // System.out.println("endcap: " + endcap.getName());
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                              * IDetectorElement x = sensor;
314                              * System.out.println("---print sensor---"); while (x != null)
315                              * { System.out.println(x.getName()); x = x.getParent(); }
316                              * System.out.println("------------");
317                              */
318 
319                             ++sensorNum;
320                         }
321                     }
322                 }
323             }
324         }
325     }
326 
327     public Class getSubdetectorType()
328     {
329         return PolyhedraEndcapCalorimeter.class;
330     }
331 }