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.IPhysicalVolumeNavigator;
7   import org.lcsim.detector.IPhysicalVolumePath;
8   import org.lcsim.detector.LogicalVolume;
9   import org.lcsim.detector.PhysicalVolume;
10  import org.lcsim.detector.PhysicalVolumeNavigatorStore;
11  import org.lcsim.detector.identifier.ExpandedIdentifier;
12  import org.lcsim.detector.identifier.IExpandedIdentifier;
13  import org.lcsim.detector.identifier.IIdentifier;
14  import org.lcsim.detector.identifier.IIdentifierHelper;
15  import org.lcsim.detector.material.IMaterial;
16  import org.lcsim.detector.material.MaterialStore;
17  import org.lcsim.detector.solids.Tube;
18  import org.lcsim.geometry.compact.Detector;
19  import org.lcsim.geometry.compact.Subdetector;
20  import org.lcsim.geometry.layer.Layer;
21  import org.lcsim.geometry.layer.LayerSlice;
22  import org.lcsim.geometry.layer.Layering;
23  import org.lcsim.geometry.subdetector.BarrelEndcapFlag;
24  import org.lcsim.geometry.subdetector.CylindricalBarrelCalorimeter;
25  
26  public class CylindricalBarrelCalorimeterConverter extends AbstractSubdetectorConverter implements
27          ISubdetectorConverter
28  {
29      public void convert( Subdetector subdet, Detector detector )
30      {
31          // Cast to subtype.
32          CylindricalBarrelCalorimeter cal = ( CylindricalBarrelCalorimeter ) subdet;
33  
34          // Get the world volume.
35          IPhysicalVolume world = detector.getWorldVolume();
36  
37          // Get the world volume fill material.
38          IMaterial matWorld = world.getLogicalVolume().getMaterial();
39  
40          // Create the Subdetector's envelope LogicalVolume.
41          ILogicalVolume envelope = buildEnvelope( cal, matWorld );
42  
43          // Create the PhysicalVolume.
44          new PhysicalVolume( null, cal.getName(), envelope, world.getLogicalVolume(), subdet.getSystemID() );
45  
46          // Setup the geometry.
47          IPhysicalVolumeNavigator nav = PhysicalVolumeNavigatorStore.getInstance().getDefaultNavigator();
48          IPhysicalVolumePath path = nav.getPath( cal.getName() );
49  
50          // Create the Subdetector's DetectorElement.
51          ( ( DetectorElement ) cal.getDetectorElement() ).setSupport( path );
52  
53          // Build the layers.
54          buildLayers( cal, envelope );
55      }
56  
57      private ILogicalVolume buildEnvelope( CylindricalBarrelCalorimeter cal, IMaterial material )
58      {
59          Tube tube = new Tube( cal.getName() + "_envelope_tube", cal.getInnerRadius(), cal.getOuterRadius(), cal
60                  .getZMax() );
61  
62          LogicalVolume logvol = new LogicalVolume( cal.getName() + "_envelope", tube, material );
63  
64          return logvol;
65      }
66  
67      private void buildLayers( CylindricalBarrelCalorimeter cal, ILogicalVolume envelope )
68      {
69          IIdentifierHelper helper = cal.getDetectorElement().getIdentifierHelper();
70  
71          Layering layering = cal.getLayering();
72          String name = cal.getName();
73  
74          double zHalfLength = cal.getZMax();
75  
76          int layerNumber = 0;
77  
78          for ( int i = 0; i < layering.getNumberOfLayers(); i++ )
79          {
80              Layer layer = layering.getLayer( i );
81  
82              double layerInnerRadius = layering.getDistanceToLayer( i );
83  
84              String layerName = "layer" + i;
85  
86              Tube tubeLayer = new Tube( name + "_layer" + i + "_tube", layerInnerRadius, layerInnerRadius + layer
87                      .getThickness(), zHalfLength );
88  
89              LogicalVolume lvLayer = new LogicalVolume( name + "_layer" + i, tubeLayer, envelope.getMaterial() );
90  
91              new PhysicalVolume( null, layerName, lvLayer, envelope, i );
92  
93              double sliceInnerRadius = layerInnerRadius;
94  
95              int sensorNumber = 0;
96              for ( int j = 0; j < layer.getSlices().size(); j++ )
97              {
98                  LayerSlice slice = layer.getSlice( j );
99  
100                 double sliceThickness = slice.getThickness();
101 
102                 String materialName = slice.getMaterial().getName();
103                 IMaterial material = MaterialStore.getInstance().get( materialName );
104 
105                 String sliceName = "slice" + j;
106 
107                 Tube sliceLayer = new Tube( name + "_layer" + i + "_slice" + j + "_tube",
108                                             sliceInnerRadius,
109                                             sliceInnerRadius + sliceThickness,
110                                             zHalfLength );
111 
112                 LogicalVolume lvSlice = new LogicalVolume( name + "_layer" + i + "_slice" + j, sliceLayer, material );
113 
114                 PhysicalVolume pvSlice = new PhysicalVolume( null, sliceName, lvSlice, lvLayer, j );
115 
116                 // Setup a DE for each sensitive slice.
117                 // TODO: needs identifier
118                 if ( slice.isSensitive() )
119                 {
120                     // FIXME: Hack to fix old detectors like sid02. Remove when these are
121                     // retired.
122                     if ( sensorNumber > 0 && !helper.hasField( "slice" ) )
123                     {
124                         // System.out.println("Not creating second sensor, because id is missing a slice field!");
125                         break;
126                     }
127 
128                     pvSlice.setSensitive( true );
129 
130                     // Path to the PhysicalVolume of this sensor.
131                     String sensorPath = "/" + cal.getName() + "/" + layerName + "/" + sliceName;
132 
133                     // Make an id for the sensor.
134                     IExpandedIdentifier expid = new ExpandedIdentifier( helper.getIdentifierDictionary()
135                             .getNumberOfFields() );
136                     if ( helper.hasField( "system" ) )
137                     {
138                         expid.setValue( helper.getFieldIndex( "system" ), cal.getSystemID() );
139                         expid.setValue( helper.getFieldIndex( "barrel" ), BarrelEndcapFlag.BARREL.getFlag() );
140                         expid.setValue( helper.getFieldIndex( "layer" ), i );
141                         if ( helper.hasField( "slice" ) )
142                             expid.setValue( helper.getFieldIndex( "slice" ), j );
143                         IIdentifier id = helper.pack( expid );
144 
145                         new DetectorElement( cal.getName() + "_layer" + layerNumber + "_sensor" + sensorNumber, cal
146                                 .getDetectorElement(), sensorPath, id );
147                     }
148                     // Increment the number of sensors.
149                     ++sensorNumber;
150                 }
151 
152                 sliceInnerRadius += sliceThickness;
153             }
154             // Increment layer number..
155             layerNumber += 1;
156         }
157     }
158 
159     public void makeIdentifierContext( Subdetector subdet )
160     {
161         /*
162          * IIdentifierDictionary iddict =
163          * subdet.getDetectorElement().getIdentifierHelper().getIdentifierDictionary();
164          * 
165          * int systemIndex = iddict.getFieldIndex("system"); int barrelIndex =
166          * iddict.getFieldIndex("barrel"); int layerIndex = iddict.getFieldIndex("layer");
167          * 
168          * IdentifierContext systemContext = new IdentifierContext(new int[]
169          * {systemIndex}); IdentifierContext subdetContext = new IdentifierContext(new
170          * int[] {systemIndex,barrelIndex}); IdentifierContext layerContext = new
171          * IdentifierContext(new int[] {systemIndex,barrelIndex,layerIndex});
172          * 
173          * iddict.addIdentifierContext("system", systemContext);
174          * iddict.addIdentifierContext("subdetector", subdetContext);
175          * iddict.addIdentifierContext("layer", layerContext);
176          * 
177          * IDDecoder decoder = subdet.getIDDecoder(); if ( decoder instanceof
178          * SegmentationBase) { if (decoder instanceof NonprojectiveCylinder) { int
179          * phiIndex = iddict.getFieldIndex("phi"); int zIndex = iddict.getFieldIndex("z");
180          * IdentifierContext cellContext = new IdentifierContext(new int[]
181          * {systemIndex,barrelIndex,layerIndex,phiIndex,zIndex});
182          * iddict.addIdentifierContext("cell", cellContext); } else if (decoder instanceof
183          * ProjectiveCylinder) { // TODO } else if (decoder instanceof GridXYZ) { // TODO
184          * } else if (decoder instanceof ProjectiveZPlane) { // TODO } }
185          */
186     }
187 
188     public Class getSubdetectorType()
189     {
190         return CylindricalBarrelCalorimeter.class;
191     }
192 }