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