1 package org.lcsim.detector.converter.compact;
2
3 import java.io.IOException;
4 import java.lang.reflect.Modifier;
5 import java.util.HashMap;
6 import java.util.Map;
7 import java.util.Set;
8
9 import org.jdom.Document;
10 import org.jdom.Element;
11 import org.jdom.JDOMException;
12 import org.lcsim.detector.DetectorElement;
13 import org.lcsim.detector.DetectorIdentifierHelper.SystemMap;
14 import org.lcsim.detector.DetectorStore;
15 import org.lcsim.detector.IDetectorElement;
16 import org.lcsim.detector.ILogicalVolume;
17 import org.lcsim.detector.IPhysicalVolume;
18 import org.lcsim.detector.LogicalVolume;
19 import org.lcsim.detector.ParametersStore;
20 import org.lcsim.detector.PhysicalVolume;
21 import org.lcsim.detector.PhysicalVolumeNavigatorStore;
22 import org.lcsim.detector.converter.lcdd.MaterialElementConverter;
23 import org.lcsim.detector.converter.lcdd.MaterialMixtureConverter;
24 import org.lcsim.detector.converter.lcdd.MaterialsConverter;
25 import org.lcsim.detector.identifier.IIdentifierHelper;
26 import org.lcsim.detector.material.IMaterial;
27 import org.lcsim.detector.material.MaterialStore;
28 import org.lcsim.detector.solids.Box;
29 import org.lcsim.detector.solids.Tube;
30 import org.lcsim.geometry.Detector;
31 import org.lcsim.geometry.compact.Constant;
32 import org.lcsim.geometry.compact.Subdetector;
33 import org.lcsim.geometry.subdetector.PolyconeSupport;
34 import org.reflections.Reflections;
35
36 public class DetectorConverter implements IDetectorConverter {
37
38 Map<Class, ISubdetectorConverter> subdetectorConverters = new HashMap<Class, ISubdetectorConverter>();
39
40
41 ParametersConverter paramCnv = new ParametersConverter();
42
43
44 MaterialsConverter materialCnv = new MaterialsConverter();
45 MaterialElementConverter elemCnv = new MaterialElementConverter();
46 MaterialMixtureConverter matCnv = new MaterialMixtureConverter();
47
48
49 SystemMap sysMap;
50
51 public IPhysicalVolume convert(Detector detector, Document doc) throws JDOMException, IOException {
52
53 DetectorStore.getInstance().clear();
54
55
56 convertMaterials("/org/lcsim/material/elements.xml");
57 convertMaterials("/org/lcsim/material/materials.xml");
58 convertMaterials(doc);
59
60
61 IPhysicalVolume pvWorld = buildWorldVolume(detector);
62
63
64 PhysicalVolumeNavigatorStore.getInstance().reset();
65 PhysicalVolumeNavigatorStore.getInstance().createDefault(pvWorld);
66
67
68 IDetectorElement deDet = new DeDetector(detector);
69 detector.setDetectorElement(deDet);
70
71
72 buildTrackingVolume(pvWorld.getLogicalVolume(), detector);
73
74
75 detector.setWorldVolume(pvWorld);
76
77
78 sysMap = makeSystemMap(detector);
79
80
81 convertSubdetectors(detector);
82
83
84 return pvWorld;
85 }
86
87 public DetectorConverter() {
88 }
89
90 public void registerSubdetectorConverters() {
91 Reflections reflect = new Reflections("org.lcsim.detector.converter.compact");
92 Set<Class<? extends AbstractSubdetectorConverter>> converters = reflect
93 .getSubTypesOf(AbstractSubdetectorConverter.class);
94
95 if (converters.size() == 0) {
96 throw new RuntimeException("No subdetector converter classes were found.");
97 }
98
99 for (Class<? extends AbstractSubdetectorConverter> converter : converters) {
100 try {
101 if (!Modifier.isAbstract(converter.getModifiers())) {
102 this.addSubdetectorConverter(converter.newInstance());
103 }
104 } catch (InstantiationException | IllegalAccessException e) {
105 throw new RuntimeException(e);
106 }
107 }
108 }
109
110 private void addSubdetectorConverter(ISubdetectorConverter s) {
111
112
113
114
115 subdetectorConverters.put(s.getSubdetectorType(), s);
116 }
117
118 private ISubdetectorConverter getSubdetectorConverter(Class klass) {
119 return subdetectorConverters.get(klass);
120 }
121
122 public IPhysicalVolume convert(Detector detector, String resource) throws JDOMException, IOException {
123 return convert(detector, CompactDocumentBuilder.build(resource));
124 }
125
126 private void convertMaterials(Document doc) throws JDOMException {
127 materialCnv.convert(doc);
128 }
129
130 private void convertMaterials(String resource) throws JDOMException, IOException {
131 Document doc = CompactDocumentBuilder.build(resource);
132
133 for (Object obj : doc.getRootElement().getChildren()) {
134 Element e = (Element) obj;
135 if (e.getName().equals("element")) {
136 elemCnv.convert(e);
137 } else if (e.getName().equals("material")) {
138 matCnv.convert(e);
139 }
140 }
141 }
142
143 private void convertSubdetectors(Detector detector) {
144
145 for (Subdetector subdetector : detector.getSubdetectors().values()) {
146
147
148 ISubdetectorConverter cnv = getSubdetectorConverter(subdetector.getClass());
149
150 if (cnv != null) {
151
152
153 DetectorElement subdetectorDE = (DetectorElement) cnv.makeSubdetectorDetectorElement(detector, subdetector);
154
155
156 IIdentifierHelper helper = cnv.makeIdentifierHelper(subdetector, sysMap);
157
158
159 try {
160 paramCnv.convert(subdetector.getNode());
161 } catch (JDOMException x) {
162 throw new RuntimeException(x);
163 }
164
165 if (subdetectorDE != null) {
166 subdetectorDE.setIdentifierHelper(helper);
167 }
168
169
170
171 cnv.convert(subdetector, detector);
172
173
174 DetectorElement subdetDE = (DetectorElement) subdetector.getDetectorElement();
175
176
177
178
179
180
181 if (subdetDE != null) {
182
183
184 subdetDE.setParameters(ParametersStore.getInstance().get(subdetector.getName()));
185
186
187
188 if (helper != null && subdetectorDE.getIdentifierHelper() == null) {
189 subdetDE.setIdentifierHelper(helper);
190 }
191
192
193 cnv.makeIdentifiers(subdetector);
194 }
195
196
197 subdetectorDE.initialize();
198 }
199 }
200 }
201
202 private void buildTrackingVolume(ILogicalVolume world, Detector detector) {
203 Map<String, Constant> constants = detector.getConstants();
204
205 if (constants.get("tracking_region_zmax") == null || constants.get("tracking_region_radius") == null) {
206 throw new RuntimeException("Missing parameters for defining tracking region!");
207 }
208
209 double zmax = constants.get("tracking_region_zmax").getValue();
210 double radius = constants.get("tracking_region_radius").getValue();
211
212 Tube trackingTube = new Tube("tracking_region_tube", 0, radius, zmax);
213
214 LogicalVolume trackingLV = new LogicalVolume("tracking_region", trackingTube, MaterialStore.getInstance().get(
215 "Air"));
216
217 new PhysicalVolume(null, "tracking_region", trackingLV, world, 0);
218 }
219
220 private IPhysicalVolume buildWorldVolume(Detector detector) {
221 Map<String, Constant> constants = detector.getConstants();
222
223 if (constants.get("world_x") == null || constants.get("world_y") == null || constants.get("world_z") == null) {
224 throw new RuntimeException("Missing world_x, world_y, or world_z!");
225 }
226
227 double x = constants.get("world_x").getValue();
228 double y = constants.get("world_y").getValue();
229 double z = constants.get("world_z").getValue();
230
231 IMaterial air = MaterialStore.getInstance().get("Air");
232
233 Box boxWorld = new Box("world_box", x, y, z);
234
235 LogicalVolume lvWorld = new LogicalVolume("world", boxWorld, air);
236
237 PhysicalVolume pvWorld = new PhysicalVolume(null, "world", lvWorld, null, 0);
238
239 return pvWorld;
240 }
241
242
243
244
245
246 public static final SystemMap makeSystemMap(Detector d) {
247 SystemMap m = new SystemMap();
248
249 for (Subdetector subdet : d.getSubdetectors().values()) {
250 String name = subdet.getName();
251
252 int sys = subdet.getSystemID();
253
254
255 if (!name.contains("Support") && !(subdet instanceof PolyconeSupport)) {
256 if (name.contains("VertexBarrel")) {
257 m.put("vtxBarrel", sys);
258 } else if (name.contains("VertexEndcap")) {
259 m.put("vtxEndcap", sys);
260 } else if (name.contains("TrackerBarrel")) {
261 m.put("sitBarrel", sys);
262 } else if (name.contains("TrackerEndcap")) {
263 m.put("sitEndcap", sys);
264 } else if (name.contains("TrackerForward")) {
265 m.put("sitForward", sys);
266 } else if (name.contains("TPC")) {
267 m.put("tpc", sys);
268 } else if (name.contains("EMBarrel")) {
269 m.put("ecalBarrel", sys);
270 } else if (name.contains("EMEndcap") && !name.contains("Forward")) {
271 m.put("ecalEndcap", sys);
272 } else if (name.contains("HADBarrel")) {
273 m.put("hcalBarrel", sys);
274 } else if (name.contains("HADEndcap")) {
275 m.put("hcalEndcap", sys);
276 } else if (name.contains("MuonBarrel")) {
277 m.put("muonBarrel", sys);
278 } else if (name.contains("MuonEndcap")) {
279 m.put("muonEndcap", sys);
280 } else if (name.contains("LuminosityMonitor") || name.contains("LumiCal")) {
281 m.put("lumi", sys);
282 } else if (name.contains("ForwardEMEndcap")) {
283 m.put("ecalForward", sys);
284 }
285 }
286 }
287
288 return m;
289 }
290 }