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
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
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
81 Layer layer = layering.getLayer( layer_number );
82
83
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
96 for ( int j = 0; j < repeat; j++ )
97 {
98
99 String layer_name = subdetName + "_stave_layer" + layer_number;
100
101
102 double layer_thickness = layer.getThickness();
103
104 int nslices = layer_element.getChildren( "slices" ).size();
105
106
107 layer_position_z += layer_thickness / 2;
108
109
110 ITranslation3D layer_position = new Translation3D( 0, 0, layer_position_z );
111
112
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
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
173 new PhysicalVolume( new Transform3D( layer_position ), layer_name, layer_volume, sectLV, layer_number );
174
175
176 layer_dim_x += layer_thickness * tan( layerInnerAngle ) * 2;
177
178
179 layer_position_z += layer_thickness / 2;
180
181
182 ++layer_number;
183 }
184 }
185
186
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
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 }