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