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.Trd;
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 RegularNgonCartesianGridXZ extends CartesianGridXZ
27 {
28 private double gridSizeX = 0;
29 private double gridSizeZ = 0;
30 private int nmodules = 12;
31
32 private int xIndex = -1;
33 private int zIndex = -1;
34 private int moduleIndex = -1;
35 private int barrelIndex = -1;
36
37 private int nzbins = 0;
38 private int zbinmax = 0;
39 private int zbinmin = 0;
40 private int[] nvalidx;
41 private boolean[] borderCellIsDuplicate;
42
43 private double xhl0 = 0.;
44 private double xslope = 0.;
45
46 private int ecsign = -1;
47
48 private static final String fieldNames[] = {"x", "z"};
49
50 public RegularNgonCartesianGridXZ(Element node) throws DataConversionException
51 {
52 super(node);
53
54 if (node.getAttribute("gridSizeX") != null)
55 {
56 gridSizeX = node.getAttribute("gridSizeX").getDoubleValue();
57 cellSizes.add(0, gridSizeX);
58 }
59 else
60 {
61 throw new RuntimeException("Missing gridSizeX parameter.");
62 }
63
64 if (node.getAttribute("gridSizeZ") != null)
65 {
66 gridSizeZ = node.getAttribute("gridSizeZ").getDoubleValue();
67 cellSizes.add(1, gridSizeZ);
68 }
69 else
70 {
71 throw new RuntimeException("Missing gridSizeZ parameter.");
72 }
73 }
74
75 public String[] getSegmentationFieldNames() {
76 return fieldNames;
77 }
78
79 public long[] getNeighbourIDs(int layerRange, int xRange, int zRange)
80 {
81 if (this.getDecoder().getID() == 0)
82 throw new RuntimeException("No current ID is set.");
83 if (sensitiveSlices == null)
84 initSensitiveSlices();
85 IDEncoder gnEncoder = new IDEncoder(descriptor);
86 BaseIDDecoder gnDecoder = new BaseIDDecoder(descriptor);
87 gnEncoder.setValues(values);
88 gnDecoder.setID(gnEncoder.getID());
89 IDEncoder dupEncoder = new IDEncoder(descriptor);
90 BaseIDDecoder dupDecoder = new BaseIDDecoder(descriptor);
91 dupEncoder.setValues(values);
92 dupDecoder.setID(dupEncoder.getID());
93
94
95 int nlayers = this.getNumberOfLayers();
96
97
98 if (nvalidx == null)
99 {
100 initializeBorders();
101 }
102
103 int currLayer = gnDecoder.getValue(layerIndex);
104 int currX = gnDecoder.getValue(xIndex);
105 int currZ = gnDecoder.getValue(zIndex);
106 int currModule = gnDecoder.getValue(moduleIndex);
107
108 List<Long> neighbors = new ArrayList<Long>();
109
110
111 for (int iz = -zRange; iz <= zRange; iz++)
112 {
113
114 int neighborZ = currZ + iz;
115 if (neighborZ >= zbinmin && neighborZ <= zbinmax)
116 {
117 gnEncoder.setValue(zIndex, neighborZ);
118 int Zindex = neighborZ + nzbins / 2;
119
120 for (int ix = -xRange; ix <= xRange; ix++)
121 {
122
123 int neighborX = currX + ix;
124 int neighborModule = currModule;
125 int dupX = neighborX;
126 int dupModule = neighborModule;
127 boolean dup = false;
128 if (neighborX < -nvalidx[Zindex] + 1)
129 {
130 if (neighborX == -nvalidx[Zindex])
131 {
132 if (borderCellIsDuplicate[Zindex])
133 {
134 dup = true;
135 dupX = -neighborX - 1;
136 dupModule = (nmodules + neighborModule - ecsign) % nmodules;
137 }
138 }
139 else
140 {
141 neighborModule = (nmodules + neighborModule - ecsign) % nmodules;
142 neighborX = 2 * nvalidx[Zindex] + neighborX;
143 if (borderCellIsDuplicate[Zindex])
144 neighborX--;
145 }
146 }
147 else if (neighborX > nvalidx[Zindex] - 2)
148 {
149 if (neighborX == nvalidx[Zindex] - 1)
150 {
151 if (borderCellIsDuplicate[Zindex])
152 {
153 dup = true;
154 dupX = -neighborX - 1;
155 dupModule = (nmodules + neighborModule + ecsign) % nmodules;
156 }
157 }
158 else
159 {
160 neighborModule = (nmodules + neighborModule + ecsign) % nmodules;
161 neighborX = -2 * nvalidx[Zindex] + neighborX;
162 if (borderCellIsDuplicate[Zindex])
163 neighborX++;
164 }
165 }
166 gnEncoder.setValue(xIndex, neighborX);
167 gnEncoder.setValue(moduleIndex, neighborModule);
168
169 for (int ilayer = -layerRange; ilayer <= layerRange; ilayer++)
170 {
171
172 int neighborLayer = currLayer + ilayer;
173
174 if (neighborLayer >= 0 && neighborLayer < nlayers)
175 {
176
177
178 gnEncoder.setValue(layerIndex, neighborLayer);
179
180 if (sliceIndex >= 0)
181 {
182
183 for (int is = 0; is < sensitiveSlices[neighborLayer].size(); is++)
184 {
185
186 gnEncoder.setValue(sliceIndex, ((Integer) (sensitiveSlices[neighborLayer].get(is)))
187 .intValue());
188
189 if (this.getDecoder().getID() != gnEncoder.getID())
190 neighbors.add(gnEncoder.getID());
191
192 if (dup)
193 {
194 dupEncoder.setValue(zIndex, neighborZ);
195 dupEncoder.setValue(xIndex, dupX);
196 dupEncoder.setValue(layerIndex, neighborLayer);
197 dupEncoder.setValue(moduleIndex, dupModule);
198 dupEncoder.setValue(sliceIndex, ((Integer) (sensitiveSlices[neighborLayer]
199 .get(is))).intValue());
200 neighbors.add(dupEncoder.getID());
201 }
202 }
203 }
204 else
205 {
206 if (this.getDecoder().getID() != gnEncoder.getID())
207 neighbors.add(gnEncoder.getID());
208
209 if (dup)
210 {
211 dupEncoder.setValue(zIndex, neighborZ);
212 dupEncoder.setValue(xIndex, dupX);
213 dupEncoder.setValue(layerIndex, neighborLayer);
214 dupEncoder.setValue(moduleIndex, dupModule);
215 neighbors.add(dupEncoder.getID());
216 }
217
218 }
219 }
220 }
221 }
222 }
223 }
224
225 long result[] = new long[neighbors.size()];
226 int i = 0;
227 for (Long id : neighbors)
228 {
229 result[i] = id;
230 i++;
231 }
232 return result;
233 }
234
235 protected void initializeBorders()
236 {
237 nmodules = ((AbstractPolyhedraCalorimeter) getSubdetector()).getNumberOfSides();
238 IIdentifierHelper helper = detector.getDetectorElement().getIdentifierHelper();
239
240 IIdentifier currId = new Identifier(this.getDecoder().getID());
241
242 IExpandedIdentifier thisId = helper.unpack(currId);
243 IIdentifier id = new Identifier(this.getDecoder().getID());
244 ExpandedIdentifier testId = new ExpandedIdentifier(thisId);
245 int barrelVal = helper.getValue(id, barrelIndex);
246 ecsign = 1;
247 if (barrelVal == 2)
248 ecsign = -1;
249 testId.setValue(xIndex, 0);
250 IIdentifier geomId = makeGeometryIdentifier(helper.pack(testId).getValue());
251 IDetectorElementContainer deSrch = getSubdetector().getDetectorElement().findDetectorElement(geomId);
252 IDetectorElement de = deSrch.get(0);
253 if (de.getGeometry().getLogicalVolume().getSolid() instanceof Trd)
254 {
255 Trd sensorTrd = (Trd) de.getGeometry().getLogicalVolume().getSolid();
256 double zhl = sensorTrd.getZHalfLength();
257 double xhl1 = sensorTrd.getXHalfLength1();
258 double xhl2 = sensorTrd.getXHalfLength2();
259 xhl0 = (xhl1 + xhl2) / 2.;
260 xslope = (xhl2 - xhl0) * gridSizeZ / zhl;
261 nzbins = 2 * ((int) (zhl / gridSizeZ) + 1);
262 zbinmax = nzbins / 2 - 1;
263 zbinmin = -nzbins / 2;
264 nvalidx = new int[nzbins];
265 borderCellIsDuplicate = new boolean[nzbins];
266 for (int zi = 0; zi < nzbins; zi++)
267 {
268 int zbin = zi - nzbins / 2;
269 double xhl = xhl0 + xslope * (zbin + .5);
270 nvalidx[zi] = (int) (xhl / gridSizeX) + 1;
271 double bcw = (nvalidx[zi] * gridSizeX - xhl) / gridSizeX;
272 borderCellIsDuplicate[zi] = false;
273 if (bcw < .5)
274 borderCellIsDuplicate[zi] = true;
275 }
276 }
277 else
278 {
279 throw new RuntimeException("Don't know how to bounds check solid " + de.getGeometry().getLogicalVolume()
280 .getSolid().getName() + ".");
281 }
282 }
283
284 protected void setupGeomFields(IDDescriptor id)
285 {
286 super.setupGeomFields(id);
287 xIndex = id.indexOf("x");
288 zIndex = id.indexOf("z");
289 moduleIndex = id.indexOf("module");
290 layerIndex = id.indexOf("layer");
291 barrelIndex = id.indexOf("barrel");
292
293 }
294
295 }