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