View Javadoc

1   package org.lcsim.detector.converter.compact;
2   
3   import org.lcsim.detector.DetectorElement;
4   import org.lcsim.detector.ILogicalVolume;
5   import org.lcsim.detector.IPhysicalVolume;
6   import org.lcsim.detector.IRotation3D;
7   import org.lcsim.detector.LogicalVolume;
8   import org.lcsim.detector.PhysicalVolume;
9   import org.lcsim.detector.RotationPassiveXYZ;
10  import org.lcsim.detector.Transform3D;
11  import org.lcsim.detector.Translation3D;
12  import org.lcsim.detector.identifier.ExpandedIdentifier;
13  import org.lcsim.detector.identifier.IExpandedIdentifier;
14  import org.lcsim.detector.identifier.IIdentifier;
15  import org.lcsim.detector.identifier.IIdentifierHelper;
16  import org.lcsim.detector.material.IMaterial;
17  import org.lcsim.detector.material.MaterialStore;
18  import org.lcsim.detector.solids.Tube;
19  import org.lcsim.geometry.compact.Detector;
20  import org.lcsim.geometry.compact.Subdetector;
21  import org.lcsim.geometry.layer.Layer;
22  import org.lcsim.geometry.layer.LayerSlice;
23  import org.lcsim.geometry.layer.Layering;
24  import org.lcsim.geometry.subdetector.BarrelEndcapFlag;
25  import org.lcsim.geometry.subdetector.CylindricalEndcapCalorimeter;
26  
27  public class CylindricalEndcapCalorimeterConverter extends AbstractSubdetectorConverter implements
28          ISubdetectorConverter
29  {
30      public void convert( Subdetector subdet, Detector detector )
31      {
32          CylindricalEndcapCalorimeter cal = ( CylindricalEndcapCalorimeter ) subdet;
33  
34          IPhysicalVolume world = detector.getWorldVolume();
35  
36          ILogicalVolume envelope = buildEnvelope( cal, world.getLogicalVolume().getMaterial() );
37  
38          double width = ( cal.getZMax() - cal.getZMin() ) / 2;
39          double zcenter = cal.getZMin() + width;
40  
41          // Positive endcap.
42          IPhysicalVolume pv = new PhysicalVolume( new Transform3D( new Translation3D( 0, 0, zcenter ) ),
43                                                   cal.getName() + "_positive",
44                                                   envelope,
45                                                   world.getLogicalVolume(),
46                                                   subdet.getSystemID() );
47  
48          double negz = -cal.getZMin() - width;
49  
50          // DE for positive endcap.
51          DetectorElement endcap = new DetectorElement( cal.getName() + "_positive", subdet.getDetectorElement() );
52          endcap.setSupport( cal.getName() + "_positive" );
53  
54          // DE for negative endcap.
55          DetectorElement reflectedEndcap = null;
56          if ( cal.getReflect() )
57          {
58              // IRotation3D reflect = new RotationPassiveEuler(Math.PI,0,0);
59              IRotation3D reflect = new RotationPassiveXYZ( 0, Math.PI, 0 );
60  
61              new PhysicalVolume( new Transform3D( new Translation3D( 0, 0, negz ), reflect ),
62                                  cal.getName() + "_negative",
63                                  envelope,
64                                  world.getLogicalVolume(),
65                                  subdet.getSystemID() );
66  
67              reflectedEndcap = new DetectorElement( cal.getName() + "_negative", subdet.getDetectorElement() );
68              reflectedEndcap.setSupport( cal.getName() + "_negative" );
69          }
70  
71          // Build the layers into the logical volume.
72          buildLayers( cal, envelope );
73  
74          // Build the DetectorElements for positive and negative endcaps.
75          buildDetectorElements( cal, endcap, reflectedEndcap );
76      }
77  
78      private void buildDetectorElements( CylindricalEndcapCalorimeter cal,
79              DetectorElement endcap,
80              DetectorElement reflectedEndcap )
81      {
82          IIdentifierHelper helper = cal.getDetectorElement().getIdentifierHelper();
83  
84          int layerNumber = 0;
85  
86          for ( int i = 0; i < cal.getLayering().getNumberOfLayers(); i++ )
87          {
88              Layer layer = cal.getLayering().getLayer( i );
89              String layerName = "layer" + i;
90              int sensorNumber = 0;
91              for ( int j = 0; j < layer.getSlices().size(); j++ )
92              {
93                  String sliceName = "slice" + j;
94                  LayerSlice slice = layer.getSlice( j );
95                  if ( slice.isSensitive() )
96                  {
97                      // FIXME: Hack to fix old detectors like sid02. Remove when these are
98                      // retired.
99                      if ( sensorNumber > 0 && !helper.hasField( "slice" ) )
100                     {
101                         // System.out.println("Not creating second sensor, because id is missing a slice field!");
102                         break;
103                     }
104 
105                     // Create an endcap sensor.
106                     String pathName = "/" + cal.getName() + "_positive" + "/" + layerName + "/" + sliceName;
107 
108                     // Make an id for the endcap north sensor.
109                     if ( helper.hasField( "system" ) )
110                     {
111                         IExpandedIdentifier expid = new ExpandedIdentifier( helper.getIdentifierDictionary()
112                                 .getNumberOfFields() );
113                         if ( helper.hasField( "system" ) )
114                             expid.setValue( helper.getFieldIndex( "system" ), cal.getSystemID() );
115                         expid.setValue( helper.getFieldIndex( "barrel" ), BarrelEndcapFlag.ENDCAP_NORTH.getFlag() );
116                         expid.setValue( helper.getFieldIndex( "layer" ), i );
117                         if ( helper.hasField( "slice" ) )
118                             expid.setValue( helper.getFieldIndex( "slice" ), j );
119                         IIdentifier id = helper.pack( expid );
120 
121                         new DetectorElement( cal.getName() + "_positive_layer" + layerNumber + "_sensor" + sensorNumber,
122                                              endcap,
123                                              pathName,
124                                              id );
125                     }
126 
127                     // Create the reflected endcap sensor.
128                     if ( reflectedEndcap != null )
129                     {
130                         String reflectedPathName = "/" + cal.getName() + "_negative" + "/" + layerName + "/" + sliceName;
131 
132                         // Make an id for the endcap south sensor.
133 
134                         if ( helper.hasField( "system" ) )
135                         {
136                             IExpandedIdentifier reflectedExpid = new ExpandedIdentifier( helper
137                                     .getIdentifierDictionary().getNumberOfFields() );
138                             if ( helper.hasField( "system" ) )
139                                 reflectedExpid.setValue( helper.getFieldIndex( "system" ), cal.getSystemID() );
140                             reflectedExpid.setValue( helper.getFieldIndex( "barrel" ), BarrelEndcapFlag.ENDCAP_SOUTH
141                                     .getFlag() );
142                             reflectedExpid.setValue( helper.getFieldIndex( "layer" ), i );
143                             if ( helper.hasField( "slice" ) )
144                                 reflectedExpid.setValue( helper.getFieldIndex( "slice" ), j );
145                             IIdentifier idReflect = helper.pack( reflectedExpid );
146 
147                             new DetectorElement( cal.getName() + "_negative_layer" + layerNumber + "_sensor" + sensorNumber,
148                                                  reflectedEndcap,
149                                                  reflectedPathName,
150                                                  idReflect );
151                         }
152                     }
153 
154                     // Increment the sensor number.
155                     ++sensorNumber;
156                 }
157             }
158 
159             // Increment the layer number.
160             ++layerNumber;
161         }
162     }
163 
164     private ILogicalVolume buildEnvelope( CylindricalEndcapCalorimeter cal, IMaterial material )
165     {
166         String name = cal.getName();
167         Tube tube = new Tube( name + "envelope_tube", cal.getInnerRadius(), cal.getOuterRadius(), ( cal.getZMax() - cal
168                 .getZMin() ) / 2 );
169 
170         ILogicalVolume lv = new LogicalVolume( name + "_envelope", tube, material );
171 
172         return lv;
173     }
174 
175     private void buildLayers( CylindricalEndcapCalorimeter cal, ILogicalVolume envelope )
176     {
177         Layering layering = cal.getLayering();
178 
179         double innerRadius = cal.getInnerRadius();
180         double outerRadius = cal.getOuterRadius();
181 
182         String name = cal.getName();
183 
184         double totalThickness = cal.getZMax() - cal.getZMin();
185         totalThickness = -totalThickness;
186         double zLayer = totalThickness / 2;
187 
188         for ( int i = 0; i < layering.getNumberOfLayers(); i++ )
189         {
190             Layer layer = layering.getLayer( i );
191 
192             Tube tubeLayer = new Tube( name + "layer" + i + "_tube", innerRadius, outerRadius, layer.getThickness() / 2 );
193 
194             ILogicalVolume lvLayer = new LogicalVolume( name + "_layer" + i, tubeLayer, envelope.getMaterial() );
195 
196             new PhysicalVolume( new Transform3D( new Translation3D( 0, 0, zLayer + layer.getThickness() / 2 ) ),
197                                 "layer" + i,
198                                 lvLayer,
199                                 envelope,
200                                 i );
201 
202             // double zSlice = zLayer;
203             double zSlice = -layer.getThickness() / 2;
204 
205             for ( int j = 0; j < layer.getNumberOfSlices(); j++ )
206             {
207                 LayerSlice slice = layer.getSlice( j );
208 
209                 Tube tubeSlice = new Tube( cal.getName() + "_layer" + i + "_slice" + j, cal.getInnerRadius(), cal
210                         .getOuterRadius(), slice.getThickness() / 2 );
211 
212                 ILogicalVolume lvSlice = new LogicalVolume( cal.getName() + "_layer" + i + "_slice" + j,
213                                                             tubeSlice,
214                                                             MaterialStore.getInstance().get(
215                                                                     slice.getMaterial().getName() ) );
216 
217                 zSlice += slice.getThickness() / 2;
218 
219                 PhysicalVolume pvSlice = new PhysicalVolume( new Transform3D( new Translation3D( 0, 0, zSlice ) ),
220                                                              "slice" + j,
221                                                              lvSlice,
222                                                              lvLayer,
223                                                              j );
224 
225                 if ( slice.isSensitive() )
226                 {
227                     pvSlice.setSensitive( true );
228                 }
229 
230                 zSlice += slice.getThickness() / 2;
231             }
232 
233             zLayer += layer.getThickness();
234         }
235     }
236 
237     public Class getSubdetectorType()
238     {
239         return CylindricalEndcapCalorimeter.class;
240     }
241 }