View Javadoc

1   package org.lcsim.detector.converter.compact;
2   
3   import static java.lang.Math.cos;
4   import static java.lang.Math.sin;
5   
6   import java.util.HashMap;
7   import java.util.Iterator;
8   import java.util.Map;
9   
10  import org.jdom.DataConversionException;
11  import org.jdom.Element;
12  import org.lcsim.detector.IDetectorElement;
13  import org.lcsim.detector.ILogicalVolume;
14  import org.lcsim.detector.IPhysicalVolume;
15  import org.lcsim.detector.IPhysicalVolumePath;
16  import org.lcsim.detector.IRotation3D;
17  import org.lcsim.detector.ITranslation3D;
18  import org.lcsim.detector.LogicalVolume;
19  import org.lcsim.detector.PhysicalVolume;
20  import org.lcsim.detector.RotationPassiveXYZ;
21  import org.lcsim.detector.Transform3D;
22  import org.lcsim.detector.Translation3D;
23  import org.lcsim.detector.DetectorIdentifierHelper.SystemMap;
24  import org.lcsim.detector.RotationGeant;
25  import org.lcsim.detector.identifier.ExpandedIdentifier;
26  import org.lcsim.detector.identifier.IIdentifier;
27  import org.lcsim.detector.identifier.IIdentifierDictionary;
28  import org.lcsim.detector.identifier.IIdentifierHelper;
29  import org.lcsim.detector.identifier.IdentifierDictionaryManager;
30  import org.lcsim.detector.identifier.IdentifierUtil;
31  import org.lcsim.detector.material.IMaterial;
32  import org.lcsim.detector.material.MaterialStore;
33  import org.lcsim.detector.solids.Box;
34  import org.lcsim.detector.solids.ISolid;
35  import org.lcsim.detector.solids.Trd;
36  import org.lcsim.detector.solids.Tube;
37  import org.lcsim.detector.tracker.silicon.SiSensor;
38  import org.lcsim.detector.tracker.silicon.SiTrackerIdentifierHelper;
39  import org.lcsim.detector.tracker.silicon.SiTrackerLayer;
40  import org.lcsim.detector.tracker.silicon.SiTrackerModule;
41  import org.lcsim.geometry.compact.Detector;
42  import org.lcsim.geometry.compact.Subdetector;
43  import org.lcsim.geometry.subdetector.SiTrackerBarrel;
44  
45  public class SiTrackerFixedTarget2ConverterBarrel extends AbstractSubdetectorConverter implements ISubdetectorConverter
46  {
47  
48      public IIdentifierHelper makeIdentifierHelper( Subdetector subdetector, SystemMap systemMap )
49      {
50          return new SiTrackerIdentifierHelper( subdetector.getDetectorElement(),
51                                                makeIdentifierDictionary( subdetector ),
52                                                systemMap );
53      }
54  
55      public void convert( Subdetector subdet, Detector detector )
56      {
57          Map< String, ILogicalVolume > modules = buildModules( subdet );
58  
59          try
60          {
61              buildLayers( detector, subdet, modules );
62          }
63          catch ( DataConversionException x )
64          {
65              throw new RuntimeException( x );
66          }
67  
68          setupSensorDetectorElements( subdet );
69      }
70  
71      private Map< String, ILogicalVolume > buildModules( Subdetector subdet )
72      {
73          Map< String, ILogicalVolume > modules = new HashMap< String, ILogicalVolume >();
74  
75          Element subdetElement = subdet.getNode();
76  
77          for ( Iterator i = subdetElement.getChildren( "module" ).iterator(); i.hasNext(); )
78          {
79              Element module = ( Element ) i.next();
80              String module_name = module.getAttributeValue( "name" );
81              ILogicalVolume module_envelope;
82              try
83              {
84                  module_envelope = buildModule( subdetElement, module_name );
85                  modules.put( module_name, module_envelope );
86              }
87              catch ( Exception x )
88              {
89                  throw new RuntimeException( x );
90              }
91          }
92  
93          return modules;
94      }
95  
96      private ILogicalVolume buildModule( Element subdetElement, String module_name ) throws Exception
97      {
98          String subdetName = subdetElement.getAttributeValue( "name" );
99          ILogicalVolume moduleLogVol = null;
100 
101         Element moduleElement = null;
102         for ( Iterator i = subdetElement.getChildren( "module" ).iterator(); i.hasNext(); )
103         {
104             Element moduleCheck = ( Element ) i.next();
105             if ( moduleCheck.getAttributeValue( "name" ).compareTo( module_name ) == 0 )
106             {
107                 moduleElement = moduleCheck;
108             }
109         }
110         if ( moduleElement == null )
111         {
112             throw new RuntimeException( "module <" + module_name + " was not found" );
113         }
114 
115         Element moduleEnvelopeElement = moduleElement.getChild( "module_envelope" );
116 
117         // Create the module box.
118         double moduleLength = moduleEnvelopeElement.getAttribute( "length" ).getDoubleValue();
119         double moduleWidth = moduleEnvelopeElement.getAttribute( "width" ).getDoubleValue();
120         double moduleThickness = moduleEnvelopeElement.getAttribute( "thickness" ).getDoubleValue();
121         ISolid moduleBox = new Box( module_name + "_box", moduleWidth / 2, moduleLength / 2, moduleThickness / 2 );
122 
123         // Create the module logical volume.
124         IMaterial air = MaterialStore.getInstance().get( "Air" );
125         moduleLogVol = new LogicalVolume( module_name, moduleBox, air );
126 
127         int componentNumber = 0;
128         for ( Iterator j = moduleElement.getChildren( "module_component" ).iterator(); j.hasNext(); ++componentNumber )
129         {
130             Element componentElement = ( Element ) j.next();
131 
132             boolean sensitive = ( ( componentElement.getAttribute( "sensitive" ) == null ) ? false : componentElement
133                     .getAttribute( "sensitive" ).getBooleanValue() );
134 
135             String componentName = module_name + "_component" + componentNumber;
136 
137             // Create the box solid for the module component.
138             double componentLength = componentElement.getAttribute( "length" ).getDoubleValue();
139             double componentWidth = componentElement.getAttribute( "width" ).getDoubleValue();
140             double componentThickness = componentElement.getAttribute( "thickness" ).getDoubleValue();
141             ISolid componentBox = new Box( componentName,
142                                            componentWidth / 2,
143                                            componentLength / 2,
144                                            componentThickness / 2 );
145 
146             IMaterial componentMaterial = MaterialStore.getInstance().get(
147                     componentElement.getAttributeValue( "material" ) );
148 
149             // Create the volume for the module component.
150             ILogicalVolume componentLogVol = new LogicalVolume( componentName, componentBox, componentMaterial );
151 
152             // Set component position.
153             double px = 0, py = 0, pz = 0;
154 
155             if ( componentElement.getChild( "position" ) != null )
156             {
157                 Element pos_elem = componentElement.getChild( "position" );
158 
159                 if ( pos_elem.getAttribute( "x" ) != null )
160                 {
161                     px = pos_elem.getAttribute( "x" ).getDoubleValue();
162                 }
163 
164                 if ( pos_elem.getAttribute( "y" ) != null )
165                 {
166                     py = pos_elem.getAttribute( "y" ).getDoubleValue();
167                 }
168 
169                 if ( pos_elem.getAttribute( "z" ) != null )
170                 {
171                     pz = pos_elem.getAttribute( "z" ).getDoubleValue();
172                 }
173             }
174 
175             ITranslation3D pos = new Translation3D( px, py, pz );
176 
177             // Set component rotation.
178             double rx = 0, ry = 0, rz = 0;
179 
180             if ( componentElement.getChild( "rotation" ) != null )
181             {
182                 Element rot_elem = componentElement.getChild( "rotation" );
183 
184                 if ( rot_elem.getAttribute( "x" ) != null )
185                 {
186                     rx = rot_elem.getAttribute( "x" ).getDoubleValue();
187                 }
188 
189                 if ( rot_elem.getAttribute( "y" ) != null )
190                 {
191                     ry = rot_elem.getAttribute( "y" ).getDoubleValue();
192                 }
193 
194                 if ( rot_elem.getAttribute( "z" ) != null )
195                 {
196                     rz = rot_elem.getAttribute( "z" ).getDoubleValue();
197                 }
198             }
199 
200             IRotation3D rot = new RotationPassiveXYZ( rx, ry, rz );
201 
202             // Make transform
203             Transform3D componentTransform = new Transform3D( pos, rot );
204 
205             PhysicalVolume componentPhysVol = new PhysicalVolume( componentTransform,
206                                                                   componentName,
207                                                                   componentLogVol,
208                                                                   moduleLogVol,
209                                                                   componentNumber );
210 
211             if ( sensitive )
212             {
213                 componentPhysVol.setSensitive( true );
214             }
215 
216             ++componentNumber;
217         }
218 
219         return moduleLogVol;
220     }
221 
222     private void buildLayers( Detector detector, Subdetector subdet, Map< String, ILogicalVolume > modules ) throws DataConversionException
223     {
224         Element node = subdet.getNode();
225         String detector_name = subdet.getName();
226 
227         // Build the layers.
228         // int nlayer = 0;
229         for ( Iterator i = node.getChildren( "layer" ).iterator(); i.hasNext(); )
230         {
231             // Get the next layer element.
232             Element layer_element = ( Element ) i.next();
233 
234             int layern = layer_element.getAttribute( "id" ).getIntValue();
235 
236             // Get the reference to the module from the layer.
237             String module_name = layer_element.getAttributeValue( "module" );
238 
239             // Get the logical volume for the module.
240             ILogicalVolume moduleEnvelope = modules.get( module_name );
241 
242             // Get the barrel_envelope for this layer.
243             Element barrel_envelope = layer_element.getChild( "barrel_envelope" );
244 
245             // Inner radius of layer.
246             double ir = barrel_envelope.getAttribute( "inner_x" ).getDoubleValue();
247 
248             // Outer radius of layer.
249             double or = barrel_envelope.getAttribute( "outer_x" ).getDoubleValue();
250 
251             // Full length in z of layer.
252             double oz = barrel_envelope.getAttribute( "z_length" ).getDoubleValue();
253             double oy = barrel_envelope.getAttribute( "y_length" ).getDoubleValue();
254 
255             // Name of this layer including layer number.
256             String layer_name = detector_name + "_layer" + layern;
257 
258             // System.out.println("layer_name=" + layer_name);
259             // make the trapazoid...
260             double dx1, dx2;
261             dx1 = dx2 = ( or - ir ) / 2;
262             Trd layer_trd = new Trd( layer_name + "_trd", dx1, dx2, oy, oy, oz );
263             Translation3D p = new Translation3D( ir, 0, 0 );
264             RotationGeant rot = new RotationGeant( 0, 0, -Math.PI / 2 );
265             Transform3D trans = new Transform3D( p, rot );
266             Tube layer_tube = new Tube( layer_name + "_tube", ir, or, oz / 2 );
267 
268             // Create the layer envelope volume.
269             IMaterial air = MaterialStore.getInstance().get( "Air" );
270             ILogicalVolume layer_volume = new LogicalVolume( layer_name, layer_trd, air );
271 
272             // Layer PhysicalVolume.
273             IPhysicalVolume layer_envelope_physvol = new PhysicalVolume( trans, layer_name, layer_volume, detector
274                     .getTrackingVolume().getLogicalVolume(), layern );
275 
276             // Layer DE.
277             String layerPath = "/tracking_region/" + layer_name;
278             IDetectorElement layerDE = new SiTrackerLayer( layer_name, subdet.getDetectorElement(), layerPath, layern );
279 
280             // Get the layout element.
281             Element layout = layer_element.getChild( "layout" );
282 
283             // angle with respect to x (beam) axis of first module.
284             double xTilt = layout.getAttribute( "xTilt" ).getDoubleValue();
285 
286             // Number of modules in y.
287             int ny = layout.getAttribute( "ny" ).getIntValue();
288             assert ( ny > 0 );
289             // Number of modules in z.
290             int nz = layout.getAttribute( "nz" ).getIntValue();
291             assert ( nz > 0 );
292 
293             // Radius of the module center.
294             double xCent = layout.getAttribute( "xCent" ).getDoubleValue();
295 
296             // Radius of the module center.
297             double zGap = layout.getAttribute( "zgap" ).getDoubleValue();
298 
299             // The delta radius of every other module.
300             double dx = 0.0;
301             if ( layout.getAttribute( "dx" ) != null )
302             {
303                 dx = layout.getAttribute( "dx" ).getDoubleValue();
304             }
305 
306             // y increment for one module.
307             // double phi_incr = (Math.PI * 2) / nphi;
308 
309             // Phi of the module center.
310             double phic = 0;
311             // phic += phi0;
312 
313             // Z increment for module placement along Z axis.
314             // Adjust for z0 at center of module rather than
315             // the end of cylindrical envelope.
316             // double z_incr = (2.0 * z0) / (nz - 1);
317 
318             // Starting z for module placement along Z axis.
319             // double module_z = -z0;
320 
321             // DEBUG
322             // System.out.println("layer ir=" + ir);
323             // System.out.println("layer or=" + or);
324             // System.out.println("layer oz=" + oz);
325             // System.out.println("phi_tilt=" + phi_tilt);
326             // System.out.println("rc=" + rc);
327             // System.out.println("phi0=" + phi0);
328             // System.out.println("module z_incr=" + z_incr);
329             // System.out.println("module z0=" + z0);
330             // System.out.println("module nz=" + nz);
331             // System.out.println("module dr=" + dr);
332             //
333 
334             // String module_lkp_name = layer.getAttributeValue("module");
335 
336             int moduleId = 0;
337 
338             // Loop over the number of modules in phi.
339             // for (int phicount = 0; phicount < nphi; phicount++) {
340             // Delta x of module position.
341             // / double dx = z_dr * cos(phic + phi_tilt);
342 
343             // Delta y of module position.
344             // double dy = z_dr * sin(phic + phi_tilt);
345 
346             // Basic x module position.
347             // double x = rc * cos(phic);
348 
349             // Basic y module position.
350             // double y = rc * sin(phic);
351 
352             // Loop over the number of modules in z.
353             for ( int zcount = 0; zcount < nz; zcount++ )
354             {
355                 // Create a unique name for the module in this logical volume, layer, phi,
356                 // and z.
357                 // String module_place_name = detector_name + "_layer" + layern + "_phi" +
358                 // phicount + "_z" + zcount;
359 
360                 // double z = module_z;
361 
362                 // DEBUG
363                 // System.out.println("module build...");
364                 // System.out.println("module nphi=" + ii);
365                 // System.out.println("module nz" + j);
366                 // System.out.println("module x=" + x);
367                 // System.out.println("module y=" + y);
368                 // System.out.println("module z=" + z);
369                 // DEBUG
370                 /*
371                  * // Position of module. //Position module_position = new
372                  * Position(module_place_name + "_position"); ITranslation3D
373                  * module_position = new Translation3D(x, y, z);
374                  * 
375                  * /* from the LCDD converter
376                  * 
377                  * double rotx = Math.PI / 2; double roty = -((Math.PI / 2) - phic -
378                  * phi_tilt); double rotz = 0;
379                  * 
380                  * /*
381                  * 
382                  * // Rotation of module.
383                  * 
384                  * // FIXME: The Y and Z rotations are switched around from // the LCDD /
385                  * Geant4 convention. Seems like an // active versus passive problem.
386                  * double rotx = Math.PI / 2; double roty = 0; double rotz = ((Math.PI /
387                  * 2) - phic - phi_tilt);
388                  * 
389                  * 
390                  * IRotation3D module_rotation = new RotationPassiveXYZ(rotx, roty, rotz);
391                  * 
392                  * //System.out.println("module rotx=" + rotx);
393                  * //System.out.println("module roty=" + roty);
394                  * //System.out.println("module rotz=" + rotz);
395                  * 
396                  * Transform3D moduleTransform = new Transform3D(module_position,
397                  * module_rotation);
398                  * 
399                  * // Module PhysicalVolume. IPhysicalVolume module_physvol = new
400                  * PhysicalVolume( moduleTransform, module_place_name, moduleEnvelope,
401                  * layer_volume, moduleId);
402                  * 
403                  * String modulePath = "/tracking_region/" + layer_name + "/" +
404                  * module_place_name;
405                  * 
406                  * new SiTrackerModule( module_place_name, layerDE, modulePath, moduleId);
407                  * 
408                  * // Increment the by-layer module number. ++moduleId;
409                  * 
410                  * // Adjust the x and y coordinates of the module. x += dx; y += dy;
411                  * 
412                  * // Flip sign of x and y adjustments. dx *= -1; dy *= -1;
413                  * 
414                  * // Add z increment to get next z placement pos. module_z += z_incr;
415                  * 
416                  * //System.out.println(); }
417                  * 
418                  * // Increment the phi placement of module. phic += phi_incr;
419                  * 
420                  * // Increment the center radius according to dr parameter. rc +=
421                  * rphi_dr;
422                  * 
423                  * // Flip sign of dr parameter. rphi_dr *= -1;
424                  * 
425                  * // Reset the Z placement parameter for module. module_z = -z0;
426                  */
427             }
428         }
429     }
430 
431     public Class getSubdetectorType()
432     {
433         return SiTrackerFixedTarget2ConverterBarrel.class;
434     }
435 
436     private void setupSensorDetectorElements( Subdetector subdet )
437     {
438         int moduleId = 0;
439         for ( IDetectorElement layer : subdet.getDetectorElement().getChildren() )
440         {
441             for ( IDetectorElement module : layer.getChildren() )
442             {
443                 IPhysicalVolumePath modulePath = module.getGeometry().getPath();
444 
445                 IPhysicalVolume modulePhysVol = modulePath.getLeafVolume();
446 
447                 int sensorId = 0;
448                 for ( IPhysicalVolume pv : modulePhysVol.getLogicalVolume().getDaughters() )
449                 {
450                     // Create the identifier for this sensor.
451                     if ( pv.isSensitive() )
452                     {
453                         IIdentifierDictionary iddict = IdentifierDictionaryManager.getInstance()
454                                 .getIdentifierDictionary( subdet.getReadout().getName() );
455 
456                         ExpandedIdentifier expId = new ExpandedIdentifier( iddict.getNumberOfFields() );
457 
458                         // Set the System ID.
459                         expId.setValue( iddict.getFieldIndex( "system" ), subdet.getSystemID() );
460 
461                         // Set the barrel-endcap flag.
462                         expId.setValue( iddict.getFieldIndex( "barrel" ), 0 );
463 
464                         // Set the layer number.
465                         expId.setValue( iddict.getFieldIndex( "layer" ), layer.getGeometry().getPath().getLeafVolume()
466                                 .getCopyNumber() );
467 
468                         // Set the module id from the DetectorElement.
469                         expId.setValue( iddict.getFieldIndex( "module" ), ( ( SiTrackerModule ) module ).getModuleId() );
470 
471                         // Set the sensor id for double-sided.
472                         expId.setValue( iddict.getFieldIndex( "sensor" ), sensorId );
473 
474                         // Create the packed id using util method.
475                         // No IdentifierHelper is available yet.
476                         IIdentifier id = iddict.pack( expId );
477 
478                         // System.out.println(pv.getName() + " is sens");
479                         // System.out.println("path : " + modulePath.toString() + "/" +
480                         // pv.getName());
481                         String sensorPath = modulePath.toString() + "/" + pv.getName();
482                         // String sensorName = subdet.getName() + "_layer" +
483                         // layer.getGeometry().getPhysicalVolume().getCopyNumber() +
484                         // "_module" + moduleId + "_sensor" + sensorId;
485                         String sensorName = subdet.getName() + "_layer" + layer.getGeometry().getPhysicalVolume()
486                                 .getCopyNumber() + "_module" + ( ( SiTrackerModule ) module ).getModuleId() + "_sensor" + sensorId;
487 
488                         SiSensor sensor = new SiSensor( sensorId, sensorName, module, sensorPath, id );
489                         sensor.setIdentifier( id );
490 
491                         /*
492                          * 
493                          * Comment out sensor setup and use lcsim Driver.
494                          * 
495                          * // Set up SiStrips for the sensors IPolyhedron sensor_solid =
496                          * (IPolyhedron
497                          * )sensor.getGeometry().getLogicalVolume().getSolid();
498                          * 
499                          * // Bias the sensor Polygon3D p_side =
500                          * sensor_solid.getFacesNormalTo(new
501                          * BasicHep3Vector(0,0,1)).get(0); //
502                          * System.out.println("Plane of p_side polygon has... "); //
503                          * System
504                          * .out.println("                        normal: "+p_side.getNormal
505                          * ()); //
506                          * System.out.println("                        distance: "+
507                          * p_side.getDistance()); // for (Point3D point :
508                          * p_side.getClosedVertices()) // { //
509                          * System.out.println("      Vertex: "+point); // }
510                          * 
511                          * 
512                          * Polygon3D n_side = sensor_solid.getFacesNormalTo(new
513                          * BasicHep3Vector(0,0,-1)).get(0); //
514                          * System.out.println("Plane of n_side polygon has... "); //
515                          * System
516                          * .out.println("                        normal: "+n_side.getNormal
517                          * ()); //
518                          * System.out.println("                        distance: "+
519                          * n_side.getDistance());
520                          * 
521                          * sensor.setBiasSurface(ChargeCarrier.HOLE,p_side);
522                          * sensor.setBiasSurface(ChargeCarrier.ELECTRON,n_side);
523                          * 
524                          * // Add sense and readout electrodes ITranslation3D
525                          * electrodes_position = new
526                          * Translation3D(VecOp.mult(-p_side.getDistance
527                          * (),p_side.getNormal())); // translate to p_side IRotation3D
528                          * electrodes_rotation = new RotationPassiveXYZ(0.0,0.0,0.0); //
529                          * no rotation (global x-y = local x-y for axial strips)
530                          * Transform3D electrodes_transform = new
531                          * Transform3D(electrodes_position, electrodes_rotation);
532                          * 
533                          * // Free calculation of readout electrodes, sense electrodes
534                          * determined thereon SiSensorElectrodes readout_electrodes = new
535                          * SiStrips(ChargeCarrier.HOLE,0.050,sensor,electrodes_transform);
536                          * SiSensorElectrodes sense_electrodes = new
537                          * SiStrips(ChargeCarrier
538                          * .HOLE,0.025,(readout_electrodes.getNCells(
539                          * )*2-1),sensor,electrodes_transform);
540                          * 
541                          * // Free calculation of sense electrodes, readout electrodes
542                          * determined thereon // SiSensorElectrodes sense_electrodes = new
543                          * SiStrips(ChargeCarrier.HOLE,0.025,sensor,electrodes_transform);
544                          * // SiSensorElectrodes readout_electrodes = new
545                          * SiStrips(ChargeCarrier
546                          * .HOLE,0.050,(sense_electrodes.getNCells()+
547                          * 1)/2,sensor,electrodes_transform);
548                          * 
549                          * sensor.setSenseElectrodes(sense_electrodes);
550                          * sensor.setReadoutElectrodes(readout_electrodes);
551                          * 
552                          * double[][] transfer_efficiencies = { {0.986,0.419} };
553                          * sensor.setTransferEfficiencies(ChargeCarrier.HOLE,new
554                          * BasicMatrix(transfer_efficiencies));
555                          */
556 
557                         // Incremenet sensorID for double-sided.
558                         ++sensorId;
559 
560                         // SiSensorElectrodes sense_electrodes = new
561                         // SiStrips(3679,0.025,sensor,electrodes_transform);
562                         // SiSensorElectrodes readout_electrodes = new
563                         // SiStrips(1840,0.050,sensor,electrodes_transform);
564                         //
565                         // double[][] transfer_efficiencies = { {0.986,0.419} };
566                         // sensor.setSenseElectrodes(ChargeCarrier.HOLE,sense_electrodes);
567                         // sensor.setReadoutElectrodes(ChargeCarrier.HOLE,readout_electrodes);
568                         // sensor.setTransferEfficiencies(ChargeCarrier.HOLE,new
569                         // BasicMatrix(transfer_efficiencies));
570 
571                     }
572                 }
573 
574                 ++moduleId;
575             }
576         }
577     }
578 }