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