1
2
3
4
5
6 package org.lcsim.geometry.segmentation;
7
8 import static java.lang.Math.atan;
9 import static java.lang.Math.cos;
10 import static java.lang.Math.sin;
11 import static java.lang.Math.sqrt;
12 import static java.lang.Math.floor;
13 import static java.lang.Math.PI;
14 import org.jdom.DataConversionException;
15 import org.jdom.Element;
16 import org.lcsim.geometry.layer.Layer;
17 import org.lcsim.geometry.layer.LayerStack;
18 import org.lcsim.geometry.util.BaseIDDecoder;
19 import org.lcsim.geometry.util.IDDescriptor;
20 import org.lcsim.geometry.util.IDEncoder;
21
22
23
24
25
26
27
28 public class NonprojectiveCylinder extends BarrelCylinderSegmentationBase
29 {
30 private double gridSizePhi;
31 private double gridSizeZ;
32
33 private int zIndex;
34 private int phiIndex;
35 private int systemIndex;
36 private int barrelIndex;
37
38 private static final String fieldNames[] = {"gridSizePhi", "gridSizeZ"};
39
40
41 public NonprojectiveCylinder(Element node) throws DataConversionException
42 {
43 super(node);
44
45 gridSizePhi = node.getAttribute("gridSizePhi").getDoubleValue();
46 gridSizeZ = node.getAttribute("gridSizeZ").getDoubleValue();
47
48 this.cellSizes.add(0, gridSizePhi);
49 this.cellSizes.add(1, gridSizeZ);
50 }
51
52 public String[] getSegmentationFieldNames() {
53 return fieldNames;
54 }
55
56 public double getCellSizeU()
57 {
58 return gridSizeZ;
59 }
60
61 public double getCellSizeV()
62 {
63 return gridSizeZ;
64 }
65
66 void setGridSizePhi(double gsp)
67 {
68 gridSizePhi = gsp;
69 }
70
71 void setGridSizeZ(double gsz)
72 {
73 gridSizeZ = gsz;
74 }
75
76 public double getGridSizePhi()
77 {
78 return gridSizePhi;
79 }
80
81 public double getGridSizeZ()
82 {
83 return gridSizeZ;
84 }
85
86 public double getPhi()
87 {
88 return (((double) getValue(phiIndex)) + 0.5) * computeDeltaPhiForLayer();
89 }
90
91 public double getTheta()
92 {
93 double x = this.getX();
94 double y = this.getY();
95 double theta = atan(sqrt(x * x + y * y) / getZ());
96
97
98 if (theta < 0)
99 {
100 theta += PI;
101 }
102
103 return theta;
104 }
105
106 public double getX()
107 {
108 return getDistanceToSensitive( getLayer() ) * cos( getPhi() );
109 }
110
111 public double getY()
112 {
113 return getDistanceToSensitive(getLayer()) * sin(getPhi());
114 }
115
116 public double getZ()
117 {
118 return ((double) getValue(zIndex) + 0.5) * gridSizeZ;
119 }
120
121 public double computeDeltaPhiForLayer(int layer)
122 {
123 double circ = getDistanceToSensitive(layer) * (2 * PI);
124 int nphi = (int) Math.floor(circ / gridSizePhi);
125 double deltaPhi = (2 * PI) / nphi;
126 return deltaPhi;
127 }
128
129 public double computeDeltaPhiForLayer()
130 {
131 return computeDeltaPhiForLayer(getLayer());
132 }
133
134 public void setIDDescription(IDDescriptor id)
135 {
136 super.setIDDescription(id);
137 phiIndex = id.indexOf("phi");
138 zIndex = id.indexOf("z");
139 systemIndex = id.indexOf("system");
140 barrelIndex = id.indexOf("barrel");
141 }
142
143 public boolean supportsNeighbours()
144 {
145 return true;
146 }
147
148
149
150
151
152
153
154
155 public long[] getNeighbourIDs(int layerRange, int zRange, int phiRange)
156 {
157 IDEncoder gnEncoder = new IDEncoder(descriptor);
158 BaseIDDecoder gnDecoder = new BaseIDDecoder(descriptor);
159 gnEncoder.setValues(values);
160 long origID = gnEncoder.getID();
161 gnDecoder.setID(gnEncoder.getID());
162
163 int nMax = (2*layerRange + 1)*(2*zRange + 1)*(2*phiRange + 1) - 1;
164 long[] result = new long[nMax];
165
166
167 double theta = getTheta();
168 double phi = getPhi();
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203 int zBins = 2 * (int) Math.round( (getZMax()-getZMin())/(2.0*getGridSizeZ()) );
204
205 int size = 0;
206 for (int i = -layerRange; i <= layerRange; ++i)
207 {
208 int ilay = values[layerIndex] + i;
209
210 if (ilay < 0 || ilay >= getNumberOfLayers())
211 continue;
212 gnEncoder.setValue(layerIndex, ilay);
213
214 double dphi = this.computeDeltaPhiForLayer(ilay);
215 int phiBins = (int) Math.round(2 * Math.PI / dphi);
216
217 if (i != 0) {
218 double cylR = getRadiusSensitiveMid(ilay);
219 double x = cylR * Math.cos(phi);
220 double y = cylR * Math.sin(phi);
221 double z = cylR / Math.tan(theta);
222
223 long id = this.findCellContainingXYZ(x,y,z);
224 if(id==0) continue;
225
226 gnDecoder.setID(id);
227 } else {
228
229 gnDecoder.setID(origID);
230 }
231
232 for (int j = -zRange; j <= zRange; ++j)
233 {
234 int iz = gnDecoder.getValue(zIndex) + j;
235
236 if (iz < -zBins / 2 || iz >= zBins / 2) {
237
238
239
240
241 continue;
242 }
243 gnEncoder.setValue(zIndex, iz);
244
245 for (int k = -phiRange; k <= phiRange; ++k)
246 {
247
248 if (i==0 && j==0 && k==0) continue;
249
250 int iphi = gnDecoder.getValue(phiIndex) + k;
251
252 if (iphi < 0) iphi += phiBins;
253 if (iphi >= phiBins) iphi -= phiBins;
254
255 if (iphi < 0 || iphi >= phiBins) continue;
256 gnEncoder.setValue(phiIndex, iphi);
257 result[size++] = gnEncoder.getID();
258 }
259 }
260 }
261
262
263 if (size < result.length)
264 {
265 long[] temp = new long[size];
266 System.arraycopy(result, 0, temp, 0, size);
267 result = temp;
268 }
269
270 return result;
271 }
272
273
274
275
276
277
278
279
280
281
282
283 public long findCellContainingXYZ(double x, double y, double z)
284 {
285
286
287 if (z < getZMin()) return 0;
288 if (z > getZMax()) return 0;
289 double rho = Math.sqrt(x * x + y * y);
290 if (rho < getRMin()) return 0;
291 if (rho > getRMax()) return 0;
292
293
294 int ilay = getLayerBin(rho);
295 int iz = getZBin(z);
296
297 double phi = Math.atan2(y, x);
298 if (phi < 0) phi += 2 * Math.PI;
299 int iphi = getPhiBin(ilay, phi);
300
301 IDEncoder enc = new IDEncoder(descriptor);
302 enc.setValues(values);
303 enc.setValue(layerIndex, ilay);
304 enc.setValue(zIndex, iz);
305 enc.setValue(phiIndex, iphi);
306 enc.setValue(barrelIndex,0);
307 enc.setValue(systemIndex, detector.getSystemID());
308 long resultID = enc.getID();
309
310 return resultID;
311 }
312
313 public int getPhiBin(int ilay, double phi)
314 {
315
316 double deltaPhi = this.computeDeltaPhiForLayer(ilay);
317 double phic = deltaPhi / 2;
318 int iphi = (int) Math.floor((phi - phic) / deltaPhi + 0.5);
319 return iphi;
320 }
321
322 public int getZBin(double z)
323 {
324
325 int numz = (int) Math.floor((getZMax() - getZMin()) / gridSizeZ);
326
327
328 double zc = gridSizeZ / 2;
329 int iz = (int) Math.floor((z - zc) / gridSizeZ + 0.5);
330 return iz;
331 }
332
333
334
335
336
337
338
339 private double getRadiusSensitiveMid(int ilay)
340 {
341 LayerStack stack = getLayering().getLayers();
342 Layer layer = stack.getLayer(ilay);
343
344 double preLayers = 0;
345 if (ilay > 0)
346 preLayers = stack.getSectionThickness(0, ilay - 1);
347
348 return this.getRMin() + preLayers + layer.getThicknessToSensitiveMid();
349 }
350 }