1 package org.lcsim.geometry.compact.converter.lcdd;
2
3 import java.io.FileInputStream;
4 import java.io.FileNotFoundException;
5 import java.io.IOException;
6 import java.io.OutputStream;
7 import java.net.URL;
8 import java.util.HashMap;
9 import java.util.Iterator;
10 import java.util.Map;
11 import java.util.zip.CRC32;
12 import java.util.zip.CheckedOutputStream;
13
14 import org.jdom.Document;
15 import org.jdom.Element;
16 import org.jdom.JDOMException;
17 import org.jdom.filter.ContentFilter;
18 import org.jdom.output.Format;
19 import org.jdom.output.XMLOutputter;
20 import org.lcsim.geometry.compact.Field;
21 import org.lcsim.geometry.compact.Readout;
22 import org.lcsim.geometry.compact.Subdetector;
23 import org.lcsim.geometry.compact.converter.lcdd.util.Author;
24 import org.lcsim.geometry.compact.converter.lcdd.util.Calorimeter;
25 import org.lcsim.geometry.compact.converter.lcdd.util.Constant;
26 import org.lcsim.geometry.compact.converter.lcdd.util.Define;
27 import org.lcsim.geometry.compact.converter.lcdd.util.Detector;
28 import org.lcsim.geometry.compact.converter.lcdd.util.Generator;
29 import org.lcsim.geometry.compact.converter.lcdd.util.HitProcessor;
30 import org.lcsim.geometry.compact.converter.lcdd.util.HitsCollection;
31 import org.lcsim.geometry.compact.converter.lcdd.util.IDField;
32 import org.lcsim.geometry.compact.converter.lcdd.util.IDSpec;
33 import org.lcsim.geometry.compact.converter.lcdd.util.LCDD;
34 import org.lcsim.geometry.compact.converter.lcdd.util.LCDDMaterialHelper;
35 import org.lcsim.geometry.compact.converter.lcdd.util.Limit;
36 import org.lcsim.geometry.compact.converter.lcdd.util.LimitSet;
37 import org.lcsim.geometry.compact.converter.lcdd.util.Position;
38 import org.lcsim.geometry.compact.converter.lcdd.util.Region;
39 import org.lcsim.geometry.compact.converter.lcdd.util.Rotation;
40 import org.lcsim.geometry.compact.converter.lcdd.util.SensitiveDetector;
41 import org.lcsim.geometry.compact.converter.lcdd.util.Tracker;
42 import org.lcsim.geometry.compact.converter.lcdd.util.UnsegmentedCalorimeter;
43 import org.lcsim.geometry.compact.converter.lcdd.util.VisAttributes;
44 import org.lcsim.geometry.util.IDDescriptor;
45 import org.lcsim.util.cache.FileCache;
46
47 import Jama.Matrix;
48
49
50
51
52
53 class LCDDDetector extends org.lcsim.geometry.compact.Detector {
54
55
56 private Element compact;
57
58
59 private long checksum;
60
61 LCDDDetector(Element node) {
62 super(node);
63 this.compact = node;
64 }
65
66 Document writeLCDD(String filename) throws IOException, JDOMException {
67 LCDD lcdd = new LCDD();
68
69 checksum = calculateChecksum(compact);
70
71 Detector detector = lcdd.getHeader().getDetector();
72 detector.setTitle(getHeader().getDetectorName());
73 lcdd.getHeader().setComment(getHeader().getComment());
74
75 Generator generator = lcdd.getHeader().getGenerator();
76 generator.setTitle(getName());
77 generator.setVersion(getVersion());
78 generator.setFile(filename);
79 generator.setChecksum(getChecksum());
80
81 Author author = lcdd.getHeader().getAuthor();
82 author.setAuthorName(getHeader().getAuthor());
83
84
85 Define define = lcdd.getDefine();
86 Rotation rotation = new Rotation("identity_rot");
87 define.addRotation(rotation);
88
89 Rotation reflect = new Rotation("reflect_rot");
90 reflect.setX(Math.PI);
91 define.addRotation(reflect);
92
93 Position position = new Position("identity_pos");
94 define.addPosition(position);
95
96
97 for (org.lcsim.geometry.compact.Constant c : getConstants().values()) {
98 define.addConstant(new Constant(c.getName(), String.valueOf(c.getValue())));
99 }
100
101
102 writeMatrices(lcdd);
103
104
105 setupMaterials(lcdd);
106
107
108 Map<Readout, IDSpec> idMap = writeReadouts(lcdd);
109
110
111 writeRegions(lcdd);
112
113
114 writeLimits(lcdd);
115
116
117 writeVisAttribs(lcdd);
118
119
120 writeSubdetectors(lcdd, idMap);
121
122
123 writeFields(lcdd);
124
125
126 writeGDMLRefs(lcdd);
127
128 lcdd.cleanUp();
129
130
131 Document doc = new Document();
132 doc.setRootElement(lcdd);
133
134 return doc;
135 }
136
137 private void writeGDMLRefs(LCDD lcdd) throws IOException, FileNotFoundException {
138 FileCache cache = new FileCache();
139 for (URL gdmlFile : getGDMLReferences()) {
140 lcdd.mergeGDML(new FileInputStream(cache.getCachedFile(gdmlFile)));
141 }
142 }
143
144 private void writeFields(LCDD lcdd) throws JDOMException {
145 for (Field field : getFields().values()) {
146 ((LCDDField) field).addToLCDD(lcdd);
147 }
148 }
149
150 private void writeSubdetectors(LCDD lcdd, Map<Readout, IDSpec> idMap) throws JDOMException {
151 for (Subdetector sub : getSubdetectors().values()) {
152 SensitiveDetector sensitiveDetector = null;
153 Readout readout = sub.getReadout();
154 if (readout != null) {
155 if (sub.isTracker()) {
156 sensitiveDetector = new Tracker(sub.getName());
157 } else if (sub.isCalorimeter()) {
158 if (readout.getSegmentation() != null && readout.getSegmentation().useForHitPosition()) {
159
160 sensitiveDetector = new Calorimeter(sub.getName());
161 } else {
162
163
164 sensitiveDetector = new UnsegmentedCalorimeter(sub.getName());
165 }
166 }
167
168 if (sensitiveDetector != null) {
169 sensitiveDetector.setIDSpec(idMap.get(readout));
170 sensitiveDetector.setHitsCollection(readout.getName());
171 lcdd.addSensitiveDetector(sensitiveDetector);
172 }
173
174
175
176 for (String processorName : readout.getProcessorNames()) {
177 sensitiveDetector.addContent(new HitProcessor(processorName));
178 }
179
180
181 for (String collectionName : readout.getCollectionNames()) {
182 sensitiveDetector.addContent(new HitsCollection(collectionName));
183 }
184
185 if (sub.isCalorimeter()) {
186 try {
187 if (readout.getSegmentation() != null) {
188 LCDDSegmentation seg = (LCDDSegmentation) readout.getSegmentation();
189 seg.setSegmentation((Calorimeter) sensitiveDetector);
190 }
191 } catch (Throwable x) {
192 throw new RuntimeException("Readout " + readout.getName() + " is not a valid Segmentation object.", x);
193 }
194 }
195
196 }
197
198
199
200 if (sub instanceof LCDDSubdetector) {
201 ((LCDDSubdetector) sub).addToLCDD(lcdd, sensitiveDetector);
202 } else {
203 throw new RuntimeException("Subdetector is not an instanceof LCDDSubdetector.");
204 }
205 }
206 }
207
208 private void writeVisAttribs(LCDD lcdd) {
209
210 for (org.lcsim.geometry.compact.VisAttributes vis : getVisAttributes().values()) {
211 VisAttributes lcddvis = new VisAttributes(vis.getName());
212
213 float rgba[] = vis.getRGBA();
214 lcddvis.setColor(rgba[0], rgba[1], rgba[2], rgba[3]);
215 lcddvis.setDrawingStyle(vis.getDrawingStyle());
216 lcddvis.setLineStyle(vis.getLineStyle());
217 lcddvis.setVisible(vis.getVisible());
218 lcddvis.setShowDaughters(vis.getShowDaughters());
219
220 lcdd.add(lcddvis);
221 }
222 }
223
224 private void writeLimits(LCDD lcdd) {
225 for (org.lcsim.geometry.compact.LimitSet limitset : getLimits().values()) {
226 LimitSet lcddLimitSet = new LimitSet(limitset.getName());
227 for (org.lcsim.geometry.compact.Limit limit : limitset.getLimits().values()) {
228 Limit lcddLimit = new Limit(limit.getName());
229
230 lcddLimit.setParticles(limit.getParticles());
231 lcddLimit.setUnit(limit.getUnit());
232 lcddLimit.setValue(limit.getValue());
233
234 lcddLimitSet.addLimit(lcddLimit);
235 }
236 lcdd.addLimitSet(lcddLimitSet);
237 }
238 }
239
240 private void writeRegions(LCDD lcdd) {
241 for (org.lcsim.geometry.compact.Region region : getRegions().values()) {
242 Region lcddRegion = new Region(region.getName());
243 lcddRegion.setStoreSecondaries(region.getStoreSecondaries());
244 lcddRegion.setKillTracks(region.getKillTracks());
245 lcddRegion.setThreshold(region.getEnergyThreshold());
246 lcddRegion.setEnergyUnit(region.getEnergyUnit());
247 lcddRegion.setLengthUnit(region.getLengthUnit());
248 lcddRegion.setCut(region.getRangeCut());
249 lcdd.addRegion(lcddRegion);
250 }
251 }
252
253 private void writeMatrices(LCDD lcdd) {
254 for (String name : this.getMatrices().keySet()) {
255 Matrix matrix = this.getMatrix(name);
256 int coldim = matrix.getColumnDimension();
257 org.lcsim.geometry.compact.converter.lcdd.util.Matrix lcddMatrix =
258 new org.lcsim.geometry.compact.converter.lcdd.util.Matrix(name, coldim);
259 String values = "";
260 for (int i=0, n=matrix.getRowDimension(); i<n; i++) {
261 String row = "";
262 for (int j=0; j<coldim; j++) {
263 row += matrix.get(i, j) + " ";
264 }
265 values += row.trim() + '\n';
266 }
267 values = values.trim();
268 lcddMatrix.setValues(values);
269 lcdd.add(lcddMatrix);
270 }
271 }
272
273 private Map<Readout, IDSpec> writeReadouts(LCDD lcdd) {
274
275 Map<Readout, IDSpec> idMap = new HashMap<Readout, IDSpec>();
276 for (Readout readout : getReadouts().values()) {
277
278 setupIdSpec(lcdd, idMap, readout);
279 }
280 return idMap;
281 }
282
283 private void setupIdSpec(LCDD lcdd, Map<Readout, IDSpec> idMap, Readout readout) {
284 IDDescriptor id = readout.getIDDescriptor();
285 IDSpec idspec = new IDSpec(readout.getName());
286 idspec.setLength(id.getMaxBit());
287
288 for (int i = 0; i < id.fieldCount(); i++) {
289 IDField field = new IDField();
290 field.setLabel(id.fieldName(i));
291 field.setLength(id.fieldLength(i));
292 field.setStart(id.fieldStart(i));
293 field.setSigned(id.isSigned(i));
294 idspec.addIDField(field);
295 }
296 lcdd.addIDSpec(idspec);
297 idMap.put(readout, idspec);
298 }
299
300 private void setupMaterials(LCDD lcdd) throws JDOMException {
301 LCDDMaterialHelper helper = new LCDDMaterialHelper(getXMLMaterialManager());
302 helper.copyToLCDD(compact, lcdd);
303 }
304
305 public String getName() {
306 return "GeomConverter";
307 }
308
309 private String getVersion() {
310 return "1.0";
311 }
312
313 private long getChecksum() {
314 return checksum;
315 }
316
317 private long calculateChecksum(Element top) throws IOException {
318
319
320 Iterator iter = top.getDescendants(new ContentFilter(ContentFilter.COMMENT));
321 while (iter.hasNext()) {
322 iter.next();
323 iter.remove();
324 }
325
326 CRC32 check = new CRC32();
327 OutputStream out = new CheckedOutputStream(new NullOutputStream(), check);
328
329 XMLOutputter outputter = new XMLOutputter();
330 outputter.setFormat(Format.getCompactFormat());
331 outputter.output(top, out);
332 out.close();
333 return check.getValue();
334 }
335
336 private static class NullOutputStream extends OutputStream {
337 public void write(byte[] b, int off, int len) throws IOException {
338 }
339
340 public void write(byte[] b) throws IOException {
341 }
342
343 public void write(int b) throws IOException {
344 }
345 }
346 }