1 package org.lcsim.geometry.segmentation;
2
3 import static java.lang.Math.PI;
4 import static java.lang.Math.tan;
5
6 import org.jdom.DataConversionException;
7 import org.jdom.Element;
8 import org.lcsim.geometry.layer.Layer;
9 import org.lcsim.geometry.layer.LayerStack;
10 import org.lcsim.geometry.util.IDDescriptor;
11 import org.lcsim.geometry.util.IDEncoder;
12
13
14
15
16
17
18
19 public class ProjectiveZPlane extends SegmentationBase
20 {
21 private int thetaBins;
22 private int phiBins;
23
24 private int thetaIndex;
25 private int phiIndex;
26 private int systemIndex = -1;
27 private int barrelIndex = -1;
28
29 private double thetaDim = 0;
30 private double phiDim = 0;
31
32 private static final String fieldNames[] = {"phi", "theta"};
33
34 ProjectiveZPlane(Element node) throws DataConversionException
35 {
36 super(node);
37 thetaBins = node.getAttribute("thetaBins").getIntValue();
38 phiBins = node.getAttribute("phiBins").getIntValue();
39 }
40
41 public String[] getSegmentationFieldNames() {
42 return fieldNames;
43 }
44
45 public double getCellSizeU()
46 {
47 return thetaDim;
48 }
49
50 public double getCellSizeV()
51 {
52 return phiDim;
53 }
54
55 public int getThetaBins()
56 {
57 return thetaBins;
58 }
59
60 public int getPhiBins()
61 {
62 return phiBins;
63 }
64
65 public double getPhi()
66 {
67 double phi = 2 * PI * ((getValue(phiIndex) + 0.5) / phiBins);
68 return phi;
69 }
70
71 public double getTheta()
72 {
73 return PI * ((getValue(thetaIndex) + 0.5) / thetaBins);
74 }
75
76 public double getX()
77 {
78 return getSphericalRadius() * Math.cos(getPhi());
79 }
80
81 public double getY()
82 {
83 return getSphericalRadius() * Math.sin(getPhi());
84 }
85
86 public double getZ()
87 {
88 return -Math.signum(getTheta() - PI / 2) * getDistanceToSensitive(getLayer());
89 }
90
91 private double getSphericalRadius()
92 {
93 return getZ() * tan(getTheta());
94 }
95
96 public void setIDDescription(IDDescriptor id)
97 {
98 super.setIDDescription(id);
99
100 phiIndex = id.indexOf("phi");
101 thetaIndex = id.indexOf("theta");
102 barrelIndex = id.indexOf("barrel");
103 systemIndex = id.indexOf("system");
104 }
105
106 public long[] getNeighbourIDs(int deltaLayer, int deltaTheta, int deltaPhi)
107 {
108 IDEncoder encoder = new IDEncoder(descriptor);
109 encoder.setValues(values);
110
111 int nMax = (2 * deltaLayer + 1) * (2 * deltaTheta + 1) * (2 * deltaPhi + 1) - 1;
112 int size = 0;
113 long[] result = new long[nMax];
114 for (int i = -deltaLayer; i <= deltaLayer; i++)
115 {
116 int l = values[layerIndex] + i;
117
118 if (l < 0 || l >= getNumberOfLayers())
119 continue;
120 encoder.setValue(layerIndex, l);
121
122 for (int j = -deltaTheta; j <= deltaTheta; j++)
123 {
124 int t = values[thetaIndex] + j;
125
126 if (t < 0 || t >= thetaBins)
127 continue;
128 encoder.setValue(thetaIndex, t);
129
130 for (int k = -deltaPhi; k <= deltaPhi; k++)
131 {
132 if (i == 0 && j == 0 && k == 0)
133 continue;
134
135 int p = values[phiIndex] + k;
136 if(p<0) p+=phiBins;
137 if(p>=phiBins) p-=phiBins;
138
139 result[size++] = encoder.setValue(phiIndex, p);
140 }
141 }
142 }
143 if (size < result.length)
144 {
145 long[] temp = new long[size];
146 System.arraycopy(result, 0, temp, 0, size);
147 result = temp;
148 }
149 return result;
150 }
151
152 public boolean supportsNeighbours()
153 {
154 return true;
155 }
156
157
158
159
160
161
162
163
164
165
166
167 public long findCellContainingXYZ(double x, double y, double z)
168 {
169
170
171 if(Math.abs(z) < getZMin()) return 0;
172 if(Math.abs(z) > getZMax()) return 0;
173 double rho = Math.sqrt(x * x + y * y);
174 if(rho < getRMin()) return 0;
175 if(rho > getRMax()) return 0;
176
177
178 int ilay = getLayerBin(z);
179
180 double phi = Math.atan2(y, x);
181 if(phi < 0) phi += 2 * PI;
182 int iphi = (int) ((phi * phiBins)/(2*PI) - 0.5);
183
184 double theta = Math.atan2(rho, z);
185 if(theta < 0)
186 {
187
188 System.out.println("ProjCylinder: Is this really needed?!?");
189 theta += 2. * PI;
190 }
191 int itheta = (int) ((theta * thetaBins)/PI - 0.5);
192 int ibar = ( z<0 ? 2 : 1 );
193 int system = detector.getSystemID();
194
195 IDEncoder enc = new IDEncoder(descriptor);
196 enc.setValue(layerIndex, ilay);
197 enc.setValue(thetaIndex, itheta);
198 enc.setValue(phiIndex, iphi);
199 enc.setValue(barrelIndex, ibar);
200 enc.setValue(systemIndex, system);
201 long resultID = enc.getID();
202
203 return resultID;
204 }
205
206
207
208
209
210
211
212
213
214
215
216 public int getLayerBin(double z)
217 {
218
219
220
221
222 double depth = Math.abs(z) - getZMin();
223 if (depth < 0)
224 throw new RuntimeException("ProjectiveZPlane: Error: z < zMin, z=" + z + ", zMin=" + this.getZMin());
225
226 double mean_t = (getZMax() - getZMin()) / getNumberOfLayers();
227
228 int ilay = (int) Math.floor(depth / mean_t);
229 LayerStack stack = getLayering().getLayers();
230 Layer layer = stack.getLayer(ilay);
231 double depHi = stack.getThicknessToLayerBack(ilay);
232 double depLo = depHi - layer.getThickness();
233 for (;;)
234 {
235 if (depth > depLo && depth <= depHi)
236 return ilay;
237 if (depth <= depLo)
238 {
239 --ilay;
240 depHi = depLo;
241 layer = stack.getLayer(ilay);
242 depLo -= layer.getThickness();
243 }
244 if (depth > depHi)
245 {
246 ++ilay;
247 depLo = depHi;
248 layer = stack.getLayer(ilay);
249 depHi += layer.getThickness();
250 }
251 }
252 }
253 }