1 package org.lcsim.geometry.subdetector;
2
3 import hep.graphics.heprep.HepRep;
4 import hep.graphics.heprep.HepRepFactory;
5
6 import java.util.ArrayList;
7 import java.util.Comparator;
8 import java.util.HashMap;
9 import java.util.HashSet;
10 import java.util.List;
11 import java.util.Set;
12
13 import org.jdom.Element;
14 import org.jdom.JDOMException;
15 import org.lcsim.detector.converter.heprep.DetectorElementToHepRepConverter;
16 import org.lcsim.detector.identifier.IIdentifierHelper;
17 import org.lcsim.detector.identifier.Identifier;
18 import org.lcsim.geometry.IDDecoder;
19 import org.lcsim.geometry.util.IDEncoder;
20
21
22
23
24
25
26
27
28 public class HPSEcal3 extends AbstractSubdetector {
29 private int nx;
30 private int ny;
31
32
33 private boolean oddX;
34 List<CrystalRange> removeCrystals = new ArrayList<CrystalRange>();
35
36 public static class NeighborMap extends HashMap<Long, Set<Long>> {
37 IIdentifierHelper helper;
38
39 public NeighborMap(IIdentifierHelper helper) {
40 this.helper = helper;
41 }
42
43 public String toString() {
44 System.out.println("NeighborMap has " + this.size() + " entries.");
45 StringBuffer buff = new StringBuffer();
46 for (long id : this.keySet()) {
47 buff.append(helper.unpack(new Identifier(id))).append("\n");
48 Set<Long> nei = this.get(id);
49 for (long nid : nei) {
50 buff.append(" " + helper.unpack(new Identifier(nid))).append("\n");
51 }
52 }
53 return buff.toString();
54 }
55 }
56
57 private NeighborMap neighborMap = null;
58
59 HPSEcal3(Element node) throws JDOMException {
60 super(node);
61
62 Element layout = node.getChild("layout");
63
64 nx = layout.getAttribute("nx").getIntValue();
65 ny = layout.getAttribute("ny").getIntValue();
66
67
68
69 if (nx % 2 != 0)
70 oddX = true;
71
72
73 for (Object obj : layout.getChildren("remove")) {
74 Element remove = (Element) obj;
75 try {
76 removeCrystals.add(new CrystalRange(remove));
77 } catch (Exception x) {
78 throw new RuntimeException(x);
79 }
80 }
81
82
83
84
85 }
86
87 private static class CrystalRange {
88 int ixmin;
89 int ixmax;
90 int iymin;
91 int iymax;
92
93 CrystalRange(Element elem) throws Exception {
94 ixmin = ixmax = iymin = iymax = 0;
95
96 if (elem.getAttribute("ixmin") != null) {
97 ixmin = elem.getAttribute("ixmin").getIntValue();
98 } else {
99 throw new RuntimeException("Missing ixmin parameter.");
100 }
101
102 if (elem.getAttribute("ixmax") != null) {
103 ixmax = elem.getAttribute("ixmax").getIntValue();
104 } else {
105 throw new RuntimeException("Missing ixmax parameter.");
106 }
107
108 if (elem.getAttribute("iymin") != null) {
109 iymin = elem.getAttribute("iymin").getIntValue();
110 } else {
111 throw new RuntimeException("Missing ixmax parameter.");
112 }
113
114 if (elem.getAttribute("iymax") != null) {
115 iymax = elem.getAttribute("iymax").getIntValue();
116 } else {
117 throw new RuntimeException("Missing iymax parameter.");
118 }
119 }
120 }
121
122 private boolean isValidXY(int ix, int iy) {
123 if (!isValidX(ix))
124 return false;
125 if (!isValidY(iy))
126 return false;
127 return checkRange(ix, iy, this.removeCrystals);
128 }
129
130 private boolean checkRange(int ix, int iy, List<CrystalRange> ranges) {
131 if (ranges.size() == 0)
132 return true;
133 for (CrystalRange range : ranges) {
134 if ((ix >= range.ixmin && ix <= range.ixmax) && ((iy >= range.iymin) && (iy <= range.iymax))) {
135 return false;
136 }
137
138 }
139 return true;
140 }
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155 public double nx() {
156 return nx;
157 }
158
159
160
161
162
163
164 public double ny() {
165 return ny;
166 }
167
168
169 static class XY implements Comparator<XY> {
170 int x;
171 int y;
172
173 public XY(int x, int y) {
174 this.x = x;
175 this.y = y;
176 }
177
178 public int x() {
179 return x;
180 }
181
182 public int y() {
183 return y;
184 }
185
186 public boolean equals(Object o) {
187 XY xy = (XY) o;
188 return xy.x() == x && xy.y() == y;
189 }
190
191 public int compare(XY o1, XY o2) {
192 if (o1.equals(o2)) {
193 return 0;
194 } else {
195 return -1;
196 }
197 }
198 }
199
200
201
202
203
204
205 Set<Long> getNeighbors(Long id) {
206
207 IDDecoder dec = getIDDecoder();
208
209
210 dec.setID(id);
211
212
213 int x = dec.getValue("ix");
214 int y = dec.getValue("iy");
215
216
217 int ix = dec.getFieldIndex("ix");
218 int iy = dec.getFieldIndex("iy");
219
220
221 Set<XY> neighbors = getNeighbors(x, y);
222
223
224 int[] buffer = new int[dec.getFieldCount()];
225 dec.getValues(buffer);
226
227
228 IDEncoder enc = new IDEncoder(dec.getIDDescription());
229
230
231 Set<Long> ids = new HashSet<Long>();
232
233
234 for (XY xyside : neighbors) {
235 buffer[ix] = xyside.x;
236 buffer[iy] = xyside.y;
237 long nId = enc.setValues(buffer);
238 ids.add(nId);
239 }
240
241 return ids;
242 }
243
244 Set<XY> getNeighbors(int ix, int iy) {
245 Set<Integer> xneighbors = getXNeighbors(ix);
246 Set<Integer> yneighbors = getYNeighbors(iy);
247
248 Set<XY> neighbors = new HashSet<XY>();
249
250 for (Integer jx : xneighbors) {
251 for (Integer jy : yneighbors) {
252
253 if (jx == ix && jy == iy) {
254 continue;
255 }
256
257
258
259 if (!isValidXY(jx, jy))
260 continue;
261
262 neighbors.add(new XY(jx, jy));
263 }
264 }
265
266 return neighbors;
267 }
268
269 Set<Integer> getXNeighbors(int ix) {
270 Set<Integer> neighbors = new HashSet<Integer>();
271
272
273 neighbors.add(ix);
274
275
276 if (isValidX(ix - 1)) {
277 neighbors.add(ix - 1);
278 } else if (isValidX(ix - 2)) {
279 neighbors.add(ix - 2);
280 }
281
282
283 if (isValidX(ix + 1)) {
284 neighbors.add(ix + 1);
285 } else if (isValidX(ix + 2)) {
286 neighbors.add(ix + 2);
287 }
288
289 return neighbors;
290 }
291
292 Set<Integer> getYNeighbors(int iy) {
293 Set<Integer> neighbors = new HashSet<Integer>();
294
295
296 neighbors.add(iy);
297
298
299 if (isValidY(iy - 1)) {
300 neighbors.add(iy - 1);
301 }
302
303
304 if (isValidY(iy + 1)) {
305 neighbors.add(iy + 1);
306 }
307
308 return neighbors;
309 }
310
311 boolean isValidY(int iy) {
312
313 return iy >= -ny && iy <= ny && iy != 0;
314 }
315
316 boolean isValidX(int ix) {
317
318 if (!oddX) {
319 return ix >= -nx / 2 && ix <= nx / 2 && ix != 0;
320 }
321
322 else {
323 return ix >= (-nx - 1) / 2 && ix <= (nx + 1) / 2;
324 }
325 }
326
327
328
329
330
331
332 public NeighborMap getNeighborMap() {
333 if (neighborMap != null) {
334 return neighborMap;
335 }
336
337
338 neighborMap = new NeighborMap(this.getDetectorElement().getIdentifierHelper());
339
340 IDDecoder dec = getIDDecoder();
341 IDEncoder enc = new IDEncoder(dec.getIDDescription());
342
343 int nfields = dec.getFieldCount();
344 int[] vals = new int[nfields];
345
346 vals[dec.getFieldIndex("system")] = getSystemID();
347
348 int idxx = dec.getFieldIndex("ix");
349 int idxy = dec.getFieldIndex("iy");
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364 for (int iy = -ny; iy <= ny; iy++) {
365 int loopx = (int) Math.floor(nx / 2);
366
367 for (int ix = -loopx; ix <= loopx; ix++) {
368 if (!isValidXY(ix, iy))
369 continue;
370
371 vals[idxx] = ix;
372 vals[idxy] = iy;
373
374 Long id = enc.setValues(vals);
375 Set<Long> neighbors = getNeighbors(id);
376
377 neighborMap.put(id, neighbors);
378 }
379 }
380
381 return neighborMap;
382 }
383
384 public void appendHepRep(HepRepFactory factory, HepRep heprep) {
385 DetectorElementToHepRepConverter.convert(getDetectorElement(), factory, heprep, -1, false, getVisAttributes().getColor());
386 }
387 }