View Javadoc

1   package org.lcsim.detector.converter.compact;
2   
3   import java.util.HashMap;
4   import java.util.Iterator;
5   import java.util.Map;
6   
7   import org.jdom.Element;
8   import org.jdom.JDOMException;
9   import org.lcsim.detector.DetectorElement;
10  import org.lcsim.detector.DetectorIdentifierHelper;
11  import org.lcsim.detector.IDetectorElement;
12  import org.lcsim.detector.IPhysicalVolume;
13  import org.lcsim.detector.IPhysicalVolumePath;
14  import org.lcsim.detector.LogicalVolume;
15  import org.lcsim.detector.PhysicalVolume;
16  import org.lcsim.detector.RotationGeant;
17  import org.lcsim.detector.Transform3D;
18  import org.lcsim.detector.Translation3D;
19  import org.lcsim.detector.DetectorIdentifierHelper.SystemMap;
20  import org.lcsim.detector.identifier.ExpandedIdentifier;
21  import org.lcsim.detector.identifier.IExpandedIdentifier;
22  import org.lcsim.detector.identifier.IIdentifier;
23  import org.lcsim.detector.identifier.IIdentifierDictionary;
24  import org.lcsim.detector.identifier.IIdentifierHelper;
25  import org.lcsim.detector.identifier.IdentifierUtil;
26  import org.lcsim.detector.material.IMaterial;
27  import org.lcsim.detector.material.MaterialStore;
28  import org.lcsim.detector.solids.Trd;
29  import org.lcsim.detector.tracker.silicon.SiSensor;
30  import org.lcsim.detector.tracker.silicon.SiTrackerIdentifierHelper;
31  import org.lcsim.detector.tracker.silicon.SiTrackerModule;
32  import org.lcsim.geometry.compact.Detector;
33  import org.lcsim.geometry.compact.Subdetector;
34  import org.lcsim.geometry.compact.converter.SiTrackerModuleComponentParameters;
35  import org.lcsim.geometry.compact.converter.SiTrackerModuleParameters;
36  import org.lcsim.geometry.subdetector.SiTrackerFixedTarget2;
37  
38  /**
39   * An LCDD converter for a Silicon tracker model for a fixed target...based off of
40   * SiTrackerEndcap2
41   * 
42   * @author mgraham
43   */
44  public class SiTrackerFixedTarget2Converter extends AbstractSubdetectorConverter implements ISubdetectorConverter
45  {
46  
47      Map< String, SiTrackerModuleParameters > moduleParameters = new HashMap< String, SiTrackerModuleParameters >();
48      Map< String, LogicalVolume > modules = new HashMap< String, LogicalVolume >();
49      IMaterial vacuum;
50  
51      public IIdentifierHelper makeIdentifierHelper( Subdetector subdetector, SystemMap systemMap )
52      {
53          return new SiTrackerIdentifierHelper( subdetector.getDetectorElement(),
54                                                makeIdentifierDictionary( subdetector ),
55                                                systemMap );
56      }
57  
58      public void convert( Subdetector subdet, Detector detector )
59      {
60          try
61          {
62              Element node = subdet.getNode();
63              String subdetName = node.getAttributeValue( "name" );
64              vacuum = MaterialStore.getInstance().get( "Air" );
65  
66              boolean reflect=true;
67              if ( node.getAttribute( "reflect" ) != null )
68              {
69                  reflect = node.getAttribute( "reflect" ).getBooleanValue();
70              }
71  
72  
73                boolean flipSA=false;
74              if ( node.getAttribute( "flipSA" ) != null )
75              {
76                  flipSA = node.getAttribute( "flipSA" ).getBooleanValue();
77              }
78  
79              IDetectorElement subdetDetElem = subdet.getDetectorElement();
80              DetectorIdentifierHelper helper = ( DetectorIdentifierHelper ) subdetDetElem.getIdentifierHelper();
81              int nfields = helper.getIdentifierDictionary().getNumberOfFields();
82              IDetectorElement endcapPos = null;
83              IDetectorElement endcapNeg = null;
84              try
85              {
86                  // Positive endcap DE
87                  IExpandedIdentifier endcapPosId = new ExpandedIdentifier( nfields );
88                  endcapPosId.setValue( helper.getFieldIndex( "system" ), subdet.getSystemID() );
89                  endcapPosId.setValue( helper.getFieldIndex( "barrel" ), helper.getBarrelValue() );
90                  endcapPos = new DetectorElement( subdet.getName() + "_positive", subdetDetElem );
91                  endcapPos.setIdentifier( helper.pack( endcapPosId ) );
92                  if ( reflect )
93                  {
94                      IExpandedIdentifier endcapNegId = new ExpandedIdentifier( nfields );
95                      endcapNegId.setValue( helper.getFieldIndex( "system" ), subdet.getSystemID() );
96                      endcapNegId.setValue( helper.getFieldIndex( "barrel" ), helper.getBarrelValue() );
97                      endcapNeg = new DetectorElement( subdet.getName() + "_negative", subdetDetElem );
98                      endcapNeg.setIdentifier( helper.pack( endcapNegId ) );
99                  }
100             }
101             catch ( Exception x )
102             {
103                 throw new RuntimeException( x );
104             }
105 
106             for ( Iterator i = node.getChildren( "module" ).iterator(); i.hasNext(); )
107             {
108                 Element module = ( Element ) i.next();
109                 String moduleName = module.getAttributeValue( "name" );
110                 moduleParameters.put( moduleName, new SiTrackerModuleParameters( module ) );
111                 modules.put( moduleName, makeModule( moduleParameters.get( moduleName ) ) );
112             }
113 
114             for ( Iterator i = node.getChildren( "layer" ).iterator(); i.hasNext(); )
115             {
116                 Element layerElement = ( Element ) i.next();
117 
118                 int layerId = layerElement.getAttribute( "id" ).getIntValue();
119 
120                 // Positive endcap layer.
121                 IExpandedIdentifier layerPosId = new ExpandedIdentifier( nfields );
122                 layerPosId.setValue( helper.getFieldIndex( "system" ), subdet.getSystemID() );
123                 // layerPosId.setValue(helper.getFieldIndex("barrel"),
124                 // helper.getEndcapPositiveValue());
125                 layerPosId.setValue( helper.getFieldIndex( "barrel" ), helper.getBarrelValue() );
126                 layerPosId.setValue( helper.getFieldIndex( "layer" ), layerId );
127                 IDetectorElement layerPos = new DetectorElement( endcapPos.getName() + "_layer" + layerId,
128                                                                  endcapPos,
129                                                                  helper.pack( layerPosId ) );
130 
131                 // Negative endcap layer.
132                 IDetectorElement layerNeg = null;
133                 if ( reflect )
134                 {
135                     IExpandedIdentifier layerNegId = new ExpandedIdentifier( nfields );
136                     layerNegId.setValue( helper.getFieldIndex( "system" ), subdet.getSystemID() );
137                     layerNegId.setValue( helper.getFieldIndex( "barrel" ), helper.getBarrelValue() );
138                     layerNegId.setValue( helper.getFieldIndex( "layer" ), layerId );
139                     layerNeg = new DetectorElement( endcapNeg.getName() + "_layer_reflected" + layerId,
140                                                     endcapNeg,
141                                                     helper.pack( layerNegId ) );
142                 }
143 
144                 int moduleNumber = 0;
145                 for ( Iterator j = layerElement.getChildren( "quadrant" ).iterator(); j.hasNext(); )
146                 {
147                     Element ringElement = ( Element ) j.next();
148                     double xLayer = ringElement.getAttribute( "x" ).getDoubleValue();
149                     double dx = ringElement.getAttribute( "dx" ).getDoubleValue();
150                     double yStart = ringElement.getAttribute( "yStart" ).getDoubleValue();
151                     double yStep = ringElement.getAttribute( "yStep" ).getDoubleValue();
152                     int ny = ringElement.getAttribute( "ny" ).getIntValue();
153                     double zStart = ringElement.getAttribute( "zStart" ).getDoubleValue();
154                     int nz = ringElement.getAttribute( "nz" ).getIntValue();
155                     double zStep = ringElement.getAttribute( "zStep" ).getDoubleValue();
156 
157                     double phi0 = 0;
158                     if ( ringElement.getAttribute( "phi0" ) != null )
159                     {
160                         phi0 = ringElement.getAttribute( "phi0" ).getDoubleValue();
161                     }
162                     String module = ringElement.getAttributeValue( "module" );
163                     LogicalVolume moduleVolume = modules.get( module );
164                     if ( moduleVolume == null )
165                     {
166                         throw new RuntimeException( "Module " + module + " was not found." );
167                     }
168 
169                     SiTrackerModuleParameters modPars = moduleParameters.get( module );
170 
171                     double x, y, z;
172                     x = xLayer;
173                     y = yStart;
174 
175                     for ( int k = 0; k < ny; k++ )
176                     {
177                         z = zStart;
178                         for ( int kk = 0; kk < nz; kk++ )
179                         {
180                             String moduleBaseName = subdetName + "_layer" + layerId + "_module" + moduleNumber;
181 
182                             // Positive endcap module.
183                             Translation3D p = new Translation3D( x + dx, y, z );
184                             RotationGeant rot = new RotationGeant( Math.PI / 2 + phi0, 0, -Math.PI / 2 );
185                             new PhysicalVolume( new Transform3D( p, rot ), moduleBaseName, moduleVolume, detector
186                                     .getTrackingVolume().getLogicalVolume(), 0 );
187                             String path = "/" + detector.getTrackingVolume().getName() + "/" + moduleBaseName;
188                             IDetectorElement modulePos = new SiTrackerModule( moduleBaseName,
189                                                                               layerPos,
190                                                                               path,
191                                                                               moduleNumber );
192                             ++moduleNumber;
193                             //System.out.println( "Making module " + moduleBaseName + "  @ " + layerPos.toString() );
194                             // Negative endcap module.
195                             if ( reflect )
196                             {
197                                 Translation3D pr = new Translation3D( x + dx, y, -z );
198                                 double rphi0=phi0;
199                                 if(flipSA) rphi0=-rphi0;
200                                 RotationGeant rotr = new RotationGeant( Math.PI / 2 + rphi0, 0, -Math.PI / 2 );
201 
202                                 String path2 = "/" + detector.getTrackingVolume().getName() + "/" + moduleBaseName + "_reflected";
203                                 new PhysicalVolume( new Transform3D( pr, rotr ),
204                                                     moduleBaseName + "_reflected",
205                                                     moduleVolume,
206                                                     detector.getTrackingVolume().getLogicalVolume(),
207                                                     k );
208                                 new SiTrackerModule( moduleBaseName + "_reflected", layerNeg, path2, moduleNumber );
209                                 //System.out.println( "Making module " + moduleBaseName + "  @ " + layerNeg.toString() );
210                             }
211 
212                             dx = -dx;
213                             z += zStep;
214                             ++moduleNumber;
215                         }
216                         y += yStep;
217                     }
218                 }
219             }
220         }
221         catch ( JDOMException except )
222         {
223             throw new RuntimeException( except );
224         }
225 
226         // Create DetectorElements for the sensors.
227         setupSensorDetectorElements( subdet );
228     }
229 
230     private LogicalVolume makeModule( SiTrackerModuleParameters params )
231     {
232         double thickness = params.getThickness();
233         double dx1, dx2, dy1, dy2, dz;
234         dy1 = dy2 = thickness / 2;
235         dx1 = params.getDimension( 0 );
236         dx2 = params.getDimension( 1 );
237         dz = params.getDimension( 2 );
238         Trd envelope = new Trd( params.getName() + "Trd", dx1, dx2, dy1, dy2, dz );
239         LogicalVolume volume = new LogicalVolume( params.getName() + "Volume", envelope, vacuum );
240         makeModuleComponents( volume, params );
241         return volume;
242     }
243 
244     private void makeModuleComponents( LogicalVolume moduleVolume, SiTrackerModuleParameters moduleParameters )
245     {
246         Trd trd = ( Trd ) moduleVolume.getSolid();
247 
248         double x1 = trd.getXHalfLength1();
249         double x2 = trd.getXHalfLength2();
250         double y1 = trd.getYHalfLength1();
251         double z = trd.getZHalfLength();
252 
253         double posY = -y1;
254 
255         String moduleName = moduleVolume.getName();
256 
257         int sensor = 0;
258         for ( SiTrackerModuleComponentParameters component : moduleParameters )
259         {
260             double thickness = component.getThickness();
261 
262             IMaterial material = MaterialStore.getInstance().get( component.getMaterialName() );
263             if ( material == null )
264             {
265                 throw new RuntimeException( "The material " + component.getMaterialName() + " does not exist in the materials database." );
266             }
267             boolean sensitive = component.isSensitive();
268             int componentNumber = component.getComponentNumber();
269 
270             posY += thickness / 2;
271 
272             String componentName = moduleName + "_component" + componentNumber;
273 
274             Trd sliceTrd = new Trd( componentName + "_trd", x1, x2, thickness / 2, thickness / 2, z );
275 
276             LogicalVolume volume = new LogicalVolume( componentName, sliceTrd, material );
277 
278             double zrot = 0;
279             if ( sensitive )
280             {
281                 if ( sensor > 1 )
282                 {
283                     throw new RuntimeException( "Exceeded maximum of 2 sensors per module." );
284                 }
285                 // Flip 180 deg for 1st sensor.
286                 if ( sensor == 0 )
287                 {
288                     zrot = Math.PI;
289                 }
290                 ++sensor;
291             }
292             Translation3D position = new Translation3D( 0., posY, 0 );
293             RotationGeant rotation = new RotationGeant( 0, 0, zrot );
294             PhysicalVolume pv = new PhysicalVolume( new Transform3D( position, rotation ),
295                                                     componentName,
296                                                     volume,
297                                                     moduleVolume,
298                                                     componentNumber );
299             pv.setSensitive( sensitive );
300 
301             posY += thickness / 2;
302         }
303     }
304 
305     private void setupSensorDetectorElements( Subdetector subdet )
306     {
307         SiTrackerIdentifierHelper helper = ( SiTrackerIdentifierHelper ) subdet.getDetectorElement()
308                 .getIdentifierHelper();
309 
310         for ( IDetectorElement endcap : subdet.getDetectorElement().getChildren() )
311         {
312             for ( IDetectorElement layer : endcap.getChildren() )
313             {
314                 for ( IDetectorElement module : layer.getChildren() )
315                 {
316                     IPhysicalVolume modulePhysVol = module.getGeometry().getPhysicalVolume();
317                     IPhysicalVolumePath modulePath = module.getGeometry().getPath();
318                     int sensorId = 0;
319                     for ( IPhysicalVolume pv : modulePhysVol.getLogicalVolume().getDaughters() )
320                     {
321                         if ( pv.isSensitive() )
322                         {
323                             IIdentifierDictionary iddict = subdet.getDetectorElement().getIdentifierHelper()
324                                     .getIdentifierDictionary();
325 
326                             ExpandedIdentifier expId = new ExpandedIdentifier( iddict.getNumberOfFields() );
327                             expId.setValue( iddict.getFieldIndex( "system" ), subdet.getSystemID() );
328 
329                             if ( helper.isEndcapPositive( endcap.getIdentifier() ) )
330                             {
331                                 expId.setValue( iddict.getFieldIndex( "barrel" ), helper.getEndcapPositiveValue() );
332                             }
333                             else if ( helper.isEndcapNegative( endcap.getIdentifier() ) )
334                             {
335                                 expId.setValue( iddict.getFieldIndex( "barrel" ), helper.getEndcapNegativeValue() );
336                             }
337                             else if ( helper.isBarrel( endcap.getIdentifier() ) )
338                             {
339                                 expId.setValue( iddict.getFieldIndex( "barrel" ), helper.getBarrelValue() );
340                             }
341                             else
342                             {
343                                 throw new RuntimeException( endcap.getName() + " is not a positive or negative endcap!" );
344                             }
345                             expId.setValue( iddict.getFieldIndex( "layer" ), layer.getIdentifierHelper().getValue(
346                                     layer.getIdentifier(),
347                                     "layer" ) );
348                             expId.setValue( iddict.getFieldIndex( "module" ), ( ( SiTrackerModule ) module )
349                                     .getModuleId() );
350                             expId.setValue( iddict.getFieldIndex( "sensor" ), sensorId );
351 
352                             IIdentifier id = iddict.pack( expId );
353 
354                             String sensorPath = modulePath.toString() + "/" + pv.getName();
355                             String sensorName = module.getName() + "_sensor" + sensorId;
356 
357                             SiSensor sensor = new SiSensor( sensorId, sensorName, module, sensorPath, id );
358 
359                             // Set up SiStrips for the sensors
360                             /*
361                              * Trd sensor_solid =
362                              * (Trd)sensor.getGeometry().getLogicalVolume().getSolid();
363                              * 
364                              * Polygon3D n_side = sensor_solid.getFacesNormalTo(new
365                              * BasicHep3Vector(0,-1,0)).get(0); Polygon3D p_side =
366                              * sensor_solid.getFacesNormalTo(new
367                              * BasicHep3Vector(0,1,0)).get(0);
368                              * 
369                              * //System.out.println("Plane of p_side polygon has... ");
370                              * //System
371                              * .out.println("                        normal: "+p_side
372                              * .getNormal());
373                              * //System.out.println("                        distance: "
374                              * +p_side.getDistance()); //for (Point3D point :
375                              * p_side.getVertices()) //{ //
376                              * System.out.println("      Vertex: "+point); //}
377                              * 
378                              * //System.out.println("Plane of n_side polygon has... ");
379                              * //System
380                              * .out.println("                        normal: "+n_side
381                              * .getNormal());
382                              * //System.out.println("                        distance: "
383                              * +n_side.getDistance());
384                              * 
385                              * // Bias the sensor
386                              * sensor.setBiasSurface(ChargeCarrier.HOLE,p_side);
387                              * sensor.setBiasSurface(ChargeCarrier.ELECTRON,n_side);
388                              * 
389                              * double strip_angle =
390                              * Math.atan2(sensor_solid.getXHalfLength2() -
391                              * sensor_solid.getXHalfLength1(),
392                              * sensor_solid.getZHalfLength() * 2);
393                              * 
394                              * ITranslation3D electrodes_position = new
395                              * Translation3D(VecOp.mult(-p_side.getDistance(),new
396                              * BasicHep3Vector(0,0,1))); // translate to outside of
397                              * polygon IRotation3D electrodes_rotation = new
398                              * RotationPassiveXYZ(-Math.PI/2,0,strip_angle); Transform3D
399                              * electrodes_transform = new Transform3D(electrodes_position,
400                              * electrodes_rotation);
401                              * 
402                              * // Free calculation of readout electrodes, sense electrodes
403                              * determined thereon SiSensorElectrodes readout_electrodes =
404                              * new
405                              * SiStrips(ChargeCarrier.HOLE,0.050,sensor,electrodes_transform
406                              * ); SiSensorElectrodes sense_electrodes = new
407                              * SiStrips(ChargeCarrier
408                              * .HOLE,0.025,(readout_electrodes.getNCells
409                              * ()*2-1),sensor,electrodes_transform);
410                              * 
411                              * sensor.setSenseElectrodes(sense_electrodes);
412                              * sensor.setReadoutElectrodes(readout_electrodes);
413                              * 
414                              * double[][] transfer_efficiencies = { {0.986,0.419} };
415                              * sensor.setTransferEfficiencies(ChargeCarrier.HOLE,new
416                              * BasicMatrix(transfer_efficiencies));
417                              */
418                             ++sensorId;
419                         }
420                     }
421                 }
422             }
423         }
424     }
425 
426     public Class getSubdetectorType()
427     {
428         return SiTrackerFixedTarget2.class;
429     }
430 }