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
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
51 DetectorElement endcap = new DetectorElement( cal.getName() + "_positive", subdet.getDetectorElement() );
52 endcap.setSupport( cal.getName() + "_positive" );
53
54
55 DetectorElement reflectedEndcap = null;
56 if ( cal.getReflect() )
57 {
58
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
72 buildLayers( cal, envelope );
73
74
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
98
99 if ( sensorNumber > 0 && !helper.hasField( "slice" ) )
100 {
101
102 break;
103 }
104
105
106 String pathName = "/" + cal.getName() + "_positive" + "/" + layerName + "/" + sliceName;
107
108
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
128 if ( reflectedEndcap != null )
129 {
130 String reflectedPathName = "/" + cal.getName() + "_negative" + "/" + layerName + "/" + sliceName;
131
132
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
155 ++sensorNumber;
156 }
157 }
158
159
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
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 }