View Javadoc

1   /*
2    * ForwardDetector.java
3    *
4    * Created on June 16, 2005, 1:54 PM
5    */
6   
7   package org.lcsim.geometry.compact.converter.lcdd;
8   
9   import org.jdom.JDOMException;
10  import org.jdom.Element;
11  import org.jdom.Attribute;
12  import org.lcsim.geometry.compact.converter.lcdd.util.Define;
13  import org.lcsim.geometry.compact.converter.lcdd.util.LCDD;
14  import org.lcsim.geometry.compact.converter.lcdd.util.Material;
15  import org.lcsim.geometry.compact.converter.lcdd.util.PhysVol;
16  import org.lcsim.geometry.compact.converter.lcdd.util.SensitiveDetector;
17  import org.lcsim.geometry.compact.converter.lcdd.util.Solids;
18  import org.lcsim.geometry.compact.converter.lcdd.util.Structure;
19  import org.lcsim.geometry.compact.converter.lcdd.util.Volume;
20  import org.lcsim.geometry.compact.converter.lcdd.util.SubtractionSolid;
21  import org.lcsim.geometry.compact.converter.lcdd.util.Tube;
22  import org.lcsim.geometry.compact.converter.lcdd.util.Position;
23  import org.lcsim.geometry.compact.converter.lcdd.util.Rotation;
24  import org.lcsim.geometry.layer.LayerFromCompactCnv;
25  
26  /**
27   *
28   * @author jeremym
29   */
30  public class ForwardDetector extends LCDDSubdetector
31  {
32      
33      /** Creates a new instance of ForwardDetector */
34      public ForwardDetector(Element node) throws JDOMException
35      {
36          super(node);
37      }
38      
39      /** FIXME: This method is horrible spaghetti code.  --JM */
40      public void addToLCDD(LCDD lcdd, SensitiveDetector sens) throws JDOMException
41      {
42          int id = -1;
43          if (node.getAttribute("id") != null)
44              id = node.getAttribute("id").getIntValue();
45          String detectorName = node.getAttributeValue("name");        
46          
47          Material air = lcdd.getMaterial("Air");
48          Solids solids = lcdd.getSolids();
49          Structure structure = lcdd.getStructure();
50          Volume motherVolume = lcdd.pickMotherVolume(this);
51          
52          Define defines = lcdd.getDefine();
53          Rotation reflection = lcdd.getDefine().getRotation("reflect_rot");
54          
55          boolean reflect = node.getAttribute("reflect").getBooleanValue();
56          
57          /** Dimension parameters. */
58          Element dimensions = node.getChild("dimensions");
59          double zinner = dimensions.getAttribute("inner_z").getDoubleValue();
60          double rmax = dimensions.getAttribute("outer_r").getDoubleValue();
61          double rmin = dimensions.getAttribute("inner_r").getDoubleValue();
62          
63          /** Beampipe parameters. */
64          Element beam = node.getChild("beampipe");
65          double outgoingR = beam.getAttribute("outgoing_r").getDoubleValue();
66          double incomingR = beam.getAttribute("incoming_r").getDoubleValue();
67          double xangle = beam.getAttribute("crossing_angle").getDoubleValue();
68          double xangleHalf = xangle / 2;
69          
70          /** Computed z values. */
71          double thickness = layers.getLayerStack().getTotalThickness();
72          double zpos = zinner + (thickness / 2);
73          double zouter = zinner + thickness;
74          
75          /** Beampipe position in envelope. */
76          double beamPosX = Math.tan(xangleHalf) * zpos;
77          //System.out.println("xangleHalf: " + xangleHalf);
78          //System.out.println("thickness: " + thickness);
79          //System.out.println("zpos: " + zpos);
80          //System.out.println("beamPosX: " + beamPosX);
81          
82          /** Detector envelope solid. */
83          Tube envelopeTube = new Tube(detectorName + "_tube");
84          envelopeTube.setRMax(rmax);
85          envelopeTube.setRMin(rmin);
86          envelopeTube.setZ(thickness);
87          solids.addSolid(envelopeTube);
88          
89          /** Incoming beampipe solid. */
90          Tube beamInTube = new Tube(detectorName + "_beampipe_incoming_tube");
91          beamInTube.setZ(thickness * 2);
92          beamInTube.setRMin(0);
93          beamInTube.setRMax(outgoingR);
94          solids.addSolid(beamInTube);
95          
96          /** Outgoing beampipe solid. */
97          Tube beamOutTube = new Tube(detectorName + "_beampipe_outgoing_tube");
98          beamOutTube.setZ(thickness * 2);
99          beamOutTube.setRMin(0);
100         beamOutTube.setRMax(incomingR);
101         solids.addSolid(beamOutTube);
102         
103         /** /\/\/\/\ First envelope boolean subtraction of incoming beampipe. /\/\/\/\ */
104         SubtractionSolid envelopeSubtraction1 =
105                 new SubtractionSolid(detectorName + "_subtraction1_tube");
106         envelopeSubtraction1.setFirstSolid(envelopeTube);
107         envelopeSubtraction1.setSecondSolid(beamInTube);
108         solids.addSolid(envelopeSubtraction1);
109         
110         /** Position of incoming beampipe. */
111         Position beamInPos = new Position(detectorName + "_subtraction1_tube_pos");
112         defines.addPosition(beamInPos);
113         beamInPos.setX(beamPosX);
114         envelopeSubtraction1.setPosition(beamInPos);
115         
116         /** Rotation of incoming beampipe. */
117         Rotation beamInRot = new Rotation(detectorName + "_subtraction1_tube_rot");
118         defines.addRotation(beamInRot);
119         beamInRot.setY(xangleHalf);
120         envelopeSubtraction1.setRotation(beamInRot);
121         
122         /** /\/\/\/\ Second envelope boolean subtracion of outgoing beampipe. /\/\/\/\ */
123         SubtractionSolid envelopeSubtraction2 =
124                 new SubtractionSolid(detectorName + "_subtraction2_tube");
125         envelopeSubtraction2.setFirstSolid(envelopeSubtraction1);
126         envelopeSubtraction2.setSecondSolid(beamOutTube);
127         solids.addSolid(envelopeSubtraction2);
128         
129         /** Position of outgoing beampipe. */
130         Position beamOutPos = new Position(detectorName + "_subtraction2_tube_pos");
131         defines.addPosition(beamOutPos);
132         beamOutPos.setX(-beamPosX);
133         envelopeSubtraction2.setPosition(beamOutPos);
134         
135         /** Rotation of outgoing beampipe. */
136         Rotation beamOutRot = new Rotation(detectorName + "_subtraction2_tube_rot");
137         defines.addRotation(beamOutRot);
138         beamOutRot.setY(-xangleHalf);
139         envelopeSubtraction2.setRotation(beamOutRot);
140         
141         /** Final envelope boolean volume. */
142         Volume envelopeVolume = new Volume(detectorName + "_envelope_volume");
143         envelopeVolume.setSolid(envelopeSubtraction2);
144         envelopeVolume.setMaterial(air);
145         
146         /** Process each layer element. */
147         double layerPosZ = -thickness / 2;
148         double layerDisplZ = 0;
149         for (Object o : node.getChildren("layer") )
150         {
151             Element layerElem = (Element) o;
152             
153             int repeat = layerElem.getAttribute("repeat").getIntValue();
154             
155             double layerThickness = LayerFromCompactCnv.computeSingleLayerThickness(layerElem);
156             
157             /**
158              * Create tube envelope for this layer, which can be reused in boolean definition
159              * in the repeat loop below.
160              */
161             Tube layerTube = new Tube(detectorName + "_layer_tube");
162             layerTube.setRMin(rmin);
163             layerTube.setRMax(rmax);
164             layerTube.setZ(layerThickness);
165             solids.addSolid(layerTube);
166             
167             /** Layer x repeat loop. */
168             for (int i=0; i < repeat; i++)
169             {
170                 //System.out.println("proc layer repeat: " + i);
171                 
172                 String layerBasename = detectorName + "_layer" + i;
173                 
174                 /** Increment to new layer position. */
175                 layerDisplZ += layerThickness / 2;
176                 layerPosZ += layerThickness / 2;
177                 
178                 //System.out.println("layerPosZ: " + layerPosZ);
179                 
180                 /** First layer subtraction solid. */
181                 SubtractionSolid layerSubtraction1 =
182                         new SubtractionSolid(layerBasename + "_subtraction1");
183                 layerSubtraction1.setFirstSolid(layerTube);
184                 layerSubtraction1.setSecondSolid(beamInTube);
185                 solids.addSolid(layerSubtraction1);
186                 
187                 Position layerSubtraction1Pos = new Position(layerBasename + "_subtraction1_pos");
188                 
189                 double layerGlobalZ = zinner + layerDisplZ;
190 //                System.out.println("layerGlobalZ: " + layerGlobalZ);
191                 double layerPosX = Math.tan(xangleHalf) * layerGlobalZ;
192 //                System.out.println("layerPosX: " + layerPosX);
193                 layerSubtraction1Pos.setX(layerPosX);
194                 defines.addPosition(layerSubtraction1Pos);
195                 
196                 layerSubtraction1.setPosition(layerSubtraction1Pos);
197                 layerSubtraction1.setRotation(beamInRot);
198                 
199                 /** Second layer subtraction solid. */
200                 SubtractionSolid layerSubtraction2 =
201                         new SubtractionSolid(layerBasename + "_subtraction2");
202                 layerSubtraction2.setFirstSolid(layerSubtraction1);
203                 layerSubtraction2.setSecondSolid(beamOutTube);
204                 solids.addSolid(layerSubtraction2);
205                 
206                 Position layerSubtraction2Pos = new Position(layerBasename + "_subtraction2_pos");
207                 layerSubtraction2Pos.setX(-layerPosX);
208                 defines.addPosition(layerSubtraction2Pos);
209                 
210                 layerSubtraction2.setPosition(layerSubtraction2Pos);
211                 layerSubtraction2.setRotation(beamOutRot);
212                 
213                 /** Layer LV. */
214                 Volume layerVolume = new Volume(layerBasename + "_volume");
215                 layerVolume.setMaterial(air);
216                 layerVolume.setSolid(layerSubtraction2);
217                 
218                 /** Slice loop. */
219                 double slicePosZ = -layerThickness / 2;
220                 double sliceDisplZ = 0;
221                 int sliceCount = 0;
222                 for ( Object oo : layerElem.getChildren("slice"))
223                 {
224                     Element sliceElem = (Element) oo;
225                     
226                     String sliceBasename = layerBasename + "_slice" + sliceCount;
227                     
228                     /** Get slice parameters. */
229                     double sliceThickness = sliceElem.getAttribute("thickness").getDoubleValue();
230                     Attribute s = sliceElem.getAttribute("sensitive");
231                     boolean sensitive = ( s != null && s.getBooleanValue() );
232                     String materialName = sliceElem.getAttributeValue("material");
233                     
234                     /** Go to mid of this slice. */
235                     sliceDisplZ += sliceThickness / 2;
236                     slicePosZ += sliceThickness / 2;
237 //                    System.out.println("sliceDisplZ: " + sliceDisplZ );
238 //                    System.out.println("slicePosZ: " + slicePosZ );
239                     
240                     /** Slice's basic tube. */
241                     Tube sliceTube = new Tube(sliceBasename + "_tube");
242                     sliceTube.setRMin(rmin);
243                     sliceTube.setRMax(rmax);
244                     sliceTube.setZ(sliceThickness);
245                     solids.addSolid(sliceTube);
246                     
247                     /** First slice subtraction solid. */
248                     SubtractionSolid sliceSubtraction1 =
249                             new SubtractionSolid(sliceBasename + "_subtraction1");
250                     sliceSubtraction1.setFirstSolid(sliceTube);
251                     sliceSubtraction1.setSecondSolid(beamInTube);
252                     solids.addSolid(sliceSubtraction1);
253                     
254                     Position sliceSubtraction1Pos = new Position(sliceBasename + "_subtraction1_pos");
255                     double sliceGlobalZ = zinner + (layerDisplZ - layerThickness / 2) + sliceDisplZ;
256                     
257 //                    System.out.println("sliceGlobalZ: " + sliceGlobalZ);
258                     
259                     double slicePosX = Math.tan(xangleHalf) * sliceGlobalZ;
260                     
261 //                    System.out.println("slicePosX: " + slicePosX);
262                     
263                     sliceSubtraction1Pos.setX(slicePosX);
264                     defines.addPosition(sliceSubtraction1Pos);
265                     
266                     sliceSubtraction1.setPosition(sliceSubtraction1Pos);
267                     sliceSubtraction1.setRotation(beamInRot);
268                     
269                     /** Second slice subtraction solid. */
270                     SubtractionSolid sliceSubtraction2 =
271                             new SubtractionSolid(sliceBasename + "_subtraction2");
272                     sliceSubtraction2.setFirstSolid(sliceSubtraction1);
273                     sliceSubtraction2.setSecondSolid(beamOutTube);
274                     solids.addSolid(sliceSubtraction2);
275                     
276                     Position sliceSubtraction2Pos = new Position(sliceBasename + "_subtraction2_pos");
277                     sliceSubtraction2Pos.setX(-slicePosX);
278                     defines.addPosition(sliceSubtraction2Pos);
279                     
280                     sliceSubtraction2.setPosition(sliceSubtraction2Pos);
281                     sliceSubtraction2.setRotation(beamOutRot);
282                     
283                     /** Slice LV. */
284                     Volume sliceVolume = new Volume(sliceBasename + "_volume");
285                     sliceVolume.setMaterial(lcdd.getMaterial(sliceElem.getAttributeValue("material")));
286                     sliceVolume.setSolid(sliceSubtraction2);
287                     
288                     if ( sensitive )
289                     {
290                         sliceVolume.setSensitiveDetector(sens);
291                     }
292                     
293                     /* FIXME: these need to be called automatically whenever a new volume is created --JM */
294                     setRegion(lcdd, sliceElem, sliceVolume);
295                     setLimitSet(lcdd, sliceElem, sliceVolume);                    
296                     
297                     setVisAttributes(lcdd, node, sliceVolume);
298                     
299                     structure.addVolume(sliceVolume);
300                     
301                     /** Slice PV. */
302                     PhysVol slicePV = new PhysVol(sliceVolume);
303                     slicePV.setZ(slicePosZ);
304                     layerVolume.addPhysVol(slicePV);
305                     
306                     /** Start of next slice. */
307                     sliceDisplZ += sliceThickness / 2;
308                     slicePosZ += sliceThickness / 2;
309                     ++sliceCount;
310                 }
311                 
312                 setVisAttributes(lcdd, node, layerVolume);
313                 
314                 structure.addVolume(layerVolume);
315                 
316                 /** Layer PV. */
317                 PhysVol layerPV = new PhysVol(layerVolume);
318                 layerPV.setZ(layerPosZ);
319                 layerPV.addPhysVolID("layer", i);
320                 envelopeVolume.addPhysVol(layerPV);
321                 
322                 /** Increment to start of next layer. */
323                 layerDisplZ += layerThickness / 2;
324                 layerPosZ += layerThickness / 2;
325             }
326         }
327         
328         setVisAttributes(lcdd, node, envelopeVolume);
329         
330         /** Add envelope LV. */
331         structure.addVolume(envelopeVolume);
332                 
333         /** Add envelope PV. */
334         PhysVol envelopePV = new PhysVol(envelopeVolume);
335         envelopePV.setZ(zpos);
336         envelopePV.addPhysVolID("system", id);
337         envelopePV.addPhysVolID("barrel", 1);
338         motherVolume.addPhysVol(envelopePV);
339         
340         /** Reflect it. */
341         if ( reflect )
342         {
343             PhysVol envelopePV2 = new PhysVol(envelopeVolume);
344             envelopePV2.setZ(-zpos);
345             envelopePV2.setRotation(reflection);
346             envelopePV2.addPhysVolID("system", id);
347             envelopePV2.addPhysVolID("barrel", 2);
348             motherVolume.addPhysVol(envelopePV2);
349         }
350     }
351     
352     public boolean isCalorimeter()
353     {
354         return true;
355     }
356 }