1 package org.lcsim.geometry.segmentation;
2
3 import java.util.ArrayList;
4 import java.util.List;
5
6 import org.jdom.DataConversionException;
7 import org.jdom.Element;
8 import org.lcsim.detector.IDetectorElement;
9 import org.lcsim.detector.IDetectorElementContainer;
10 import org.lcsim.detector.identifier.IExpandedIdentifier;
11 import org.lcsim.detector.identifier.ExpandedIdentifier;
12 import org.lcsim.detector.identifier.IIdentifier;
13 import org.lcsim.detector.identifier.IIdentifierHelper;
14 import org.lcsim.detector.identifier.Identifier;
15 import org.lcsim.detector.solids.Box;
16 import org.lcsim.geometry.util.IDDescriptor;
17 import org.lcsim.geometry.util.BaseIDDecoder;
18 import org.lcsim.geometry.util.IDEncoder;
19 import org.lcsim.geometry.subdetector.AbstractPolyhedraCalorimeter;
20
21
22
23
24
25
26 public class EcalBarrelCartesianGridXY extends CartesianGridXY
27 {
28 private double gridSizeX = 0;
29 private double gridSizeY = 0;
30
31 private int xIndex = -1;
32 private int yIndex = -1;
33 private int moduleIndex = -1;
34 private int nmodules = 12;
35
36 private int[] validXplusG;
37 private int[] validXminusG;
38 private int[] validXplusP;
39 private int[] validXminusP;
40 private int validZplus;
41 private int validZminus;
42
43 private double xc0 = 0.;
44 private double[] yc;
45
46 private double sinth = 0.;
47 private double costh = 0.;
48 private double tanth = 0.;
49 private double cotth = 0.;
50 private double secth = 0.;
51 private double cscth = 0.;
52
53 private int nlayers = 0;
54
55 private static final String[] fieldNames = {"x", "y"};
56
57 public EcalBarrelCartesianGridXY(Element node) throws DataConversionException
58 {
59 super(node);
60
61 if (node.getAttribute("gridSizeX") != null)
62 {
63 gridSizeX = node.getAttribute("gridSizeX").getDoubleValue();
64 cellSizes.add(0, gridSizeX);
65 }
66 else
67 {
68 throw new RuntimeException("Missing gridSizeX parameter.");
69 }
70
71 if (node.getAttribute("gridSizeY") != null)
72 {
73 gridSizeY = node.getAttribute("gridSizeY").getDoubleValue();
74 cellSizes.add(1, gridSizeY);
75 }
76 else
77 {
78 throw new RuntimeException("Missing gridSizeY parameter.");
79 }
80 }
81
82 public String[] getSegmentationFieldNames() {
83 return fieldNames;
84 }
85
86 public long[] getNeighbourIDs(int layerRange, int xRange, int yRange)
87 {
88 if (this.getDecoder().getID() == 0)
89 throw new RuntimeException("No current ID is set.");
90 if (sensitiveSlices == null)
91 initSensitiveSlices();
92 IDEncoder gnEncoder = new IDEncoder(descriptor);
93 BaseIDDecoder gnDecoder = new BaseIDDecoder(descriptor);
94 gnEncoder.setValues(values);
95 gnDecoder.setID(gnEncoder.getID());
96
97
98 if (validXplusP == null)
99 {
100 initializeMappings();
101 }
102
103 int currLayer = gnDecoder.getValue(layerIndex);
104 int currX = gnDecoder.getValue(xIndex);
105 int currY = gnDecoder.getValue(yIndex);
106 int currModule = gnDecoder.getValue(moduleIndex);
107
108
109 List<Long> nl = getNeighbourIDs(layerRange, xRange, yRange, gnEncoder, currLayer, currX, currY);
110
111 boolean bp1 = false;
112 boolean bp2 = false;
113
114
115
116 if (((currLayer - layerRange) < 1) && ((currX + xRange) > validXplusP[0]))
117 bp1 = true;
118
119
120
121 else if ((currX - xRange) <= validXminusG[Math.min(currLayer + layerRange, nlayers - 1)])
122 bp2 = true;
123
124
125 else
126 {
127 long result[] = new long[nl.size()];
128 int i = 0;
129 for (Long id : nl)
130 {
131 result[i] = id;
132 i++;
133 }
134 return result;
135 }
136 if (bp1)
137 {
138
139
140
141
142
143
144
145
146 double lsep = yc[1] - yc[0];
147
148
149 double ycmax = yc[0] + lsep / 2.;
150
151
152
153 double ycmin = yc[0] - lsep / 2. + lsep * (currLayer - layerRange);
154
155
156 double xcmax = xc0 + gridSizeX * (currX + xRange + .5);
157 double xcmin = xc0 + gridSizeX * (currX - xRange - .5);
158
159
160 double minyp = ycmin * costh + xcmin * sinth;
161 double maxyp = ycmax * costh + xcmax * sinth;
162 int minl = 0;
163 int maxl = 0;
164 for (int il = 0; il < nlayers; il++)
165 {
166 if (yc[il] < minyp)
167 minl++;
168 if (yc[il] > maxyp)
169 break;
170 maxl++;
171 }
172
173 int neighborModule = (currModule + 1) % nmodules;
174 gnEncoder.setValue(moduleIndex, neighborModule);
175
176 for (int neighborLayer = minl; neighborLayer < maxl; neighborLayer++)
177 {
178 gnEncoder.setValue(layerIndex, neighborLayer);
179
180
181
182 double xpmax = Math
183 .min(xcmax * secth - yc[neighborLayer] * tanth, yc[neighborLayer] * cotth - ycmin * cscth);
184 double xpmin = Math
185 .max(xcmin * secth - yc[neighborLayer] * tanth, yc[neighborLayer] * cotth - ycmax * cscth);
186
187 int xbmin = (int) ((xpmin - xc0 + gridSizeX * .5) / gridSizeX);
188 int xbmax = (int) ((xpmax - xc0 - gridSizeX * .5) / gridSizeX);
189
190 for (int neighborX = xbmin; neighborX <= xbmax; neighborX++)
191 {
192 gnEncoder.setValue(xIndex, neighborX);
193
194 for (int iy = -yRange; iy <= yRange; iy++)
195 {
196
197 int neighborY = currY + iy;
198 gnEncoder.setValue(yIndex, neighborY);
199 if (sliceIndex >= 0)
200 {
201
202 for (int is = 0; is < sensitiveSlices[neighborLayer].size(); is++)
203 {
204
205 gnEncoder.setValue(sliceIndex, ((Integer) (sensitiveSlices[neighborLayer].get(is)))
206 .intValue());
207 ;
208
209 nl.add(gnEncoder.getID());
210 }
211 }
212 else
213 nl.add(gnEncoder.getID());
214
215 }
216 }
217 }
218 long result[] = new long[nl.size()];
219 int i = 0;
220 for (Long id : nl)
221 {
222 result[i] = id;
223 i++;
224 }
225 return result;
226 }
227
228
229 int neighborModule = (nmodules + currModule - 1) % nmodules;
230 gnEncoder.setValue(moduleIndex, neighborModule);
231 double ycmax = 0.;
232 double ycmin = 0.;
233
234 if (currLayer - layerRange < 1)
235 {
236 double lsep = yc[1] - yc[0];
237 ycmin = yc[0] + (currLayer - layerRange) * lsep - lsep / 2.;
238 }
239 else
240 {
241 double lsep = yc[currLayer - layerRange] - yc[currLayer - layerRange - 1];
242 ycmin = yc[currLayer - layerRange] - lsep / 2.;
243 }
244 if (currLayer + layerRange > nlayers - 2)
245 {
246 double lsep = yc[nlayers - 1] - yc[nlayers - 2];
247 ycmax = yc[nlayers - 1] + lsep / 2.;
248 }
249 else
250 {
251 double lsep = yc[currLayer + layerRange + 1] - yc[currLayer + layerRange];
252 ycmax = yc[currLayer + layerRange] + lsep / 2.;
253 }
254
255 double xcmax = xc0 + gridSizeX * (currX + xRange + .5);
256 double xcmin = xc0 + gridSizeX * (currX - xRange - .5);
257 double minyp = ycmin * costh - xcmax * sinth;
258 double maxyp = ycmax * costh - xcmin * sinth;
259 int minl = 0;
260 int maxl = 0;
261 for (int il = 0; il < nlayers; il++)
262 {
263 if (yc[il] < minyp)
264 minl++;
265 if (yc[il] > maxyp)
266 break;
267 maxl++;
268 }
269
270 for (int neighborLayer = minl; neighborLayer < maxl; neighborLayer++)
271 {
272 gnEncoder.setValue(layerIndex, neighborLayer);
273
274
275 double xpmax = Math
276 .min(xcmax * secth + yc[neighborLayer] * tanth, -yc[neighborLayer] * cotth + ycmax * cscth);
277 double xpmin = Math
278 .max(xcmin * secth + yc[neighborLayer] * tanth, -yc[neighborLayer] * cotth + ycmin * cscth);
279 int xbmin = (int) ((xpmin - xc0 + gridSizeX * .5) / gridSizeX);
280 int xbmax = (int) ((xpmax - xc0 - gridSizeX * .5) / gridSizeX);
281 xbmax = Math.min(xbmax, validXplusG[neighborLayer]);
282
283 for (int neighborX = xbmin; neighborX <= xbmax; neighborX++)
284 {
285 gnEncoder.setValue(xIndex, neighborX);
286 for (int neighborY = Math.max(validZminus, currY - yRange); neighborY <= Math
287 .min(validZplus, currY + yRange); neighborY++)
288 {
289 gnEncoder.setValue(yIndex, neighborY);
290 if (sliceIndex >= 0)
291 {
292
293 for (int is = 0; is < sensitiveSlices[neighborLayer].size(); is++)
294 {
295
296 gnEncoder.setValue(sliceIndex, ((Integer) (sensitiveSlices[neighborLayer].get(is)))
297 .intValue());
298 ;
299 nl.add(gnEncoder.getID());
300 }
301 }
302 else
303 nl.add(gnEncoder.getID());
304 }
305 }
306 }
307 long result[] = new long[nl.size()];
308 int i = 0;
309 for (Long id : nl)
310 {
311 result[i] = id;
312 i++;
313 }
314 return result;
315 }
316
317 protected List<Long> getNeighbourIDs(int layerRange, int xRange, int yRange, IDEncoder gnEncoder, int currLayer, int currX, int currY)
318 {
319
320 List<Long> rl = new ArrayList<Long>();
321 for (int neighborLayer = Math.max(0, currLayer - layerRange); neighborLayer <= Math
322 .min(nlayers - 1, currLayer + layerRange); neighborLayer++)
323 {
324 gnEncoder.setValue(layerIndex, neighborLayer);
325 for (int neighborX = Math.max(validXminusG[neighborLayer], currX - xRange); neighborX <= Math
326 .min(validXplusG[neighborLayer], currX + xRange); neighborX++)
327 {
328 gnEncoder.setValue(xIndex, neighborX);
329 for (int neighborY = Math.max(validZminus, currY - yRange); neighborY <= Math
330 .min(validZplus, currY + yRange); neighborY++)
331 {
332 gnEncoder.setValue(yIndex, neighborY);
333 if (sliceIndex >= 0)
334 {
335
336 for (int is = 0; is < sensitiveSlices[neighborLayer].size(); is++)
337 {
338
339 gnEncoder.setValue(sliceIndex, ((Integer) (sensitiveSlices[neighborLayer].get(is)))
340 .intValue());
341 ;
342 if (this.getDecoder().getID() != gnEncoder.getID())
343 rl.add(gnEncoder.getID());
344 }
345 }
346 else if (this.getDecoder().getID() != gnEncoder.getID())
347 rl.add(gnEncoder.getID());
348 }
349 }
350 }
351 return rl;
352 }
353
354 public void setupGeomFields(IDDescriptor id)
355 {
356 super.setupGeomFields(id);
357 xIndex = id.indexOf("x");
358 yIndex = id.indexOf("y");
359 moduleIndex = id.indexOf("module");
360 layerIndex = id.indexOf("layer");
361 }
362
363 protected void initializeMappings()
364 {
365 nmodules = ((AbstractPolyhedraCalorimeter) getSubdetector()).getNumberOfSides();
366
367
368
369 nlayers = this.getNumberOfLayers();
370
371 validXplusP = new int[this.getNumberOfLayers()];
372 validXminusP = new int[this.getNumberOfLayers()];
373 validXplusG = new int[this.getNumberOfLayers()];
374 validXminusG = new int[this.getNumberOfLayers()];
375
376 sinth = Math.sin(2. * Math.PI / nmodules);
377 costh = Math.cos(2. * Math.PI / nmodules);
378 tanth = sinth / costh;
379 cotth = costh / sinth;
380 secth = 1. / costh;
381 cscth = 1. / sinth;
382
383 IIdentifierHelper helper = detector.getDetectorElement().getIdentifierHelper();
384 IIdentifier currId = new Identifier(this.getDecoder().getID());
385 IExpandedIdentifier thisId = helper.unpack(currId);
386 ExpandedIdentifier pseudoId = new ExpandedIdentifier(thisId);
387
388 pseudoId.setValue(moduleIndex, 0);
389 pseudoId.setValue(xIndex, 0);
390 pseudoId.setValue(layerIndex, 0);
391 pseudoId.setValue(sliceIndex, 0);
392
393 long save = this.getDecoder().getID();
394 this.getDecoder().setID(helper.pack(pseudoId).getValue());
395 this.computeGlobalPosition();
396
397 xc0 = this.globalPosition[0] - gridSizeX / 2.;
398
399 yc = new double[nlayers];
400
401 double[] xhlp = new double[nlayers];
402 for (int i = 0; i < nlayers; i++)
403 {
404
405 pseudoId.setValue(layerIndex, i);
406 if (i == 1)
407 pseudoId.setValue(sliceIndex, 2);
408 this.getDecoder().setID(helper.pack(pseudoId).getValue());
409 this.computeGlobalPosition();
410 yc[i] = this.globalPosition[1];
411
412 IIdentifier geomId = makeGeometryIdentifier(helper.pack(pseudoId).getValue());
413 IDetectorElementContainer deSrch = getSubdetector().getDetectorElement().findDetectorElement(geomId);
414 IDetectorElement de = deSrch.get(0);
415 if (de.getGeometry().getLogicalVolume().getSolid() instanceof Box)
416 {
417 Box sensorBox = (Box) de.getGeometry().getLogicalVolume().getSolid();
418
419 if (i == 0)
420 {
421 double yhl = sensorBox.getYHalfLength();
422
423 int nvalidy = (int) (yhl / gridSizeY) + 1;
424 validZplus = nvalidy - 1;
425 validZminus = -nvalidy;
426 }
427
428 double xhl = sensorBox.getXHalfLength();
429 int nvalidx = (int) (xhl / gridSizeX) + 1;
430 validXplusG[i] = nvalidx - 1;
431 validXminusG[i] = -nvalidx;
432
433
434 xhlp[i] = yc[i] * Math.tan(Math.PI / nmodules);
435 validXplusP[i] = (int) ((xhlp[i] - xc0) / gridSizeX);
436 validXminusP[i] = -(int) ((xhlp[i] + xc0) / gridSizeX) - 1;
437 }
438 else
439 {
440 throw new RuntimeException("Don't know how to bounds check solid " + de.getGeometry()
441 .getLogicalVolume().getSolid().getName() + ".");
442 }
443 }
444
445 this.getDecoder().setID(save);
446 this.computeGlobalPosition();
447 }
448
449 public int getVLayer()
450 {
451 if (validXplusP == null)
452 {
453 initializeMappings();
454 }
455
456 IIdentifierHelper helper = detector.getDetectorElement().getIdentifierHelper();
457 IIdentifier currId = new Identifier(this.getDecoder().getID());
458 IExpandedIdentifier thisId = helper.unpack(currId);
459 int xbin = thisId.getValue(xIndex);
460 int layer = thisId.getValue(layerIndex);
461 if (xbin > validXplusP[layer])
462 {
463 double xc = xc0 + gridSizeX * (xbin + .5);
464 double yp = yc[layer] * costh + xc * sinth;
465 double dely = yp - yc[layer];
466 int vl = layer;
467 for (int il = layer; il < nlayers - 1; il++)
468 {
469 if (dely < (yc[il + 1] - yc[il]) / 2.)
470 break;
471 vl++;
472 dely -= yc[il + 1] - yc[il];
473 }
474 return vl;
475 }
476 return layer;
477 }
478 }