1 package org.lcsim.detector.tracker.silicon;
2
3
4
5
6
7
8
9
10
11
12
13 import org.lcsim.detector.IDetectorElement;
14 import org.lcsim.detector.ITransform3D;
15 import org.lcsim.detector.Transform3D;
16 import hep.physics.vec.Hep3Vector;
17 import hep.physics.vec.BasicHep3Vector;
18 import hep.physics.vec.VecOp;
19 import java.util.ArrayList;
20 import java.util.SortedMap;
21 import java.util.TreeMap;
22 import java.util.Set;
23 import java.util.HashSet;
24 import java.util.List;
25 import org.lcsim.detector.solids.GeomOp2D;
26 import org.lcsim.detector.solids.GeomOp3D;
27 import org.lcsim.detector.solids.Line3D;
28 import org.lcsim.detector.solids.LineSegment3D;
29 import org.lcsim.detector.solids.Point3D;
30 import org.lcsim.detector.solids.Polygon3D;
31
32
33
34
35
36 public class SiStrips implements SiSensorElectrodes
37 {
38
39
40
41
42 private ChargeCarrier _carrier;
43 private int _nstrips;
44 private double _pitch;
45 private IDetectorElement _detector;
46 private ITransform3D _parent_to_local;
47 private ITransform3D _local_to_global;
48 private ITransform3D _global_to_local;
49 private Polygon3D _geometry;
50 private double _capacitance_intercept = 10.;
51 private double _capacitance_slope = 0.1;
52
53
54 private double _strip_offset;
55
56 public SiStrips(){
57
58 };
59
60
61 public SiStrips(ChargeCarrier carrier, double pitch, IDetectorElement detector, ITransform3D parent_to_local)
62 {
63
64
65
66
67
68 setCarrier(carrier);
69 setPitch(pitch);
70 setGeometry(((SiSensor)detector).getBiasSurface(carrier).transformed(parent_to_local));
71 setStripNumbering();
72 setDetectorElement(detector);
73 setParentToLocal(parent_to_local);
74 setGlobalToLocal(Transform3D.multiply(parent_to_local,detector.getGeometry().getGlobalToLocal()));
75 setLocalToGlobal(getGlobalToLocal().inverse());
76 }
77
78 public SiStrips(ChargeCarrier carrier, double pitch, int nstrips, IDetectorElement detector, ITransform3D parent_to_local)
79 {
80 setCarrier(carrier);
81 setPitch(pitch);
82 setGeometry(((SiSensor)detector).getBiasSurface(carrier).transformed(parent_to_local));
83 setNStrips(nstrips);
84 setDetectorElement(detector);
85 setParentToLocal(parent_to_local);
86 setGlobalToLocal(Transform3D.multiply(parent_to_local,detector.getGeometry().getGlobalToLocal()));
87 setLocalToGlobal(getGlobalToLocal().inverse());
88 }
89
90 public SiStrips(ChargeCarrier carrier, double pitch, int nstrips, IDetectorElement detector, ITransform3D parent_to_local ,ITransform3D misalignment){
91
92 }
93
94 public SiStrips(ChargeCarrier carrier, double pitch, IDetectorElement detector, ITransform3D parent_to_local ,ITransform3D misalignment){
95
96 }
97
98
99
100
101
102 public int getNAxes()
103 {
104 return 1;
105 }
106
107 public IDetectorElement getDetectorElement()
108 {
109 return _detector;
110 }
111
112 public ITransform3D getParentToLocal()
113 {
114 return _parent_to_local;
115 }
116
117 public ITransform3D getLocalToGlobal()
118 {
119 return _local_to_global;
120 }
121
122 public ITransform3D getGlobalToLocal()
123 {
124 return _global_to_local;
125 }
126
127 public Polygon3D getGeometry()
128 {
129 return _geometry;
130 }
131
132 public Hep3Vector getMeasuredCoordinate(int axis)
133 {
134 if (axis == 0) return new BasicHep3Vector(1.0,0.0,0.0);
135 else return null;
136 }
137
138 public Hep3Vector getUnmeasuredCoordinate(int axis)
139 {
140 if (axis == 0) return new BasicHep3Vector(0.0,1.0,0.0);
141 else return null;
142 }
143
144 public int getNeighborCell(int cell, int ncells_0, int ncells_1)
145 {
146 int neighbor_cell = cell + ncells_0;
147 if (isValidCell(neighbor_cell)) return neighbor_cell;
148 else return -1;
149 }
150
151 public Set<Integer> getNearestNeighborCells(int cell)
152 {
153 Set<Integer> neighbors = new HashSet<Integer>();
154 for (int ineigh = -1 ; ineigh <= 1; ineigh=ineigh+2)
155 {
156 int neighbor_cell = getNeighborCell(cell,ineigh,0);
157 if (isValidCell(neighbor_cell)) neighbors.add(neighbor_cell);
158 }
159 return neighbors;
160 }
161
162 public boolean isValidCell(int cell)
163 {
164 return (cell >= 0 && cell < getNCells());
165 }
166
167 public int getNCells()
168 {
169 return _nstrips;
170 }
171
172 public int getNCells(int axis)
173 {
174 if (axis == 0)
175 {
176 return _nstrips;
177 }
178 else return 1;
179 }
180
181 public double getPitch(int axis)
182 {
183 if (axis == 0)
184 {
185 return _pitch;
186 }
187 else return 0;
188 }
189 public int getCellID(Hep3Vector position)
190 {
191 return (int)Math.round((position.x()+_strip_offset)/_pitch);
192 }
193
194
195 public int getRowNumber(Hep3Vector position)
196 {
197 return 0;
198 }
199
200 public int getColumnNumber(Hep3Vector position)
201 {
202 return getCellID(position);
203 }
204
205 public int getCellID(int row_number, int column_number)
206 {
207 return column_number;
208 }
209
210 public int getRowNumber(int cell_id)
211 {
212 return 0;
213 }
214
215 public int getColumnNumber(int cell_id)
216 {
217 return cell_id;
218 }
219
220 public Hep3Vector getPositionInCell(Hep3Vector position)
221 {
222 return VecOp.sub(position,getCellPosition(getCellID(position)));
223 }
224
225 public Hep3Vector getCellPosition(int strip_number)
226 {
227 return new BasicHep3Vector(strip_number*_pitch-_strip_offset,0.0,0.0);
228 }
229
230
231
232
233
234
235
236
237
238
239
240 public void setCapacitanceIntercept(double capacitance_intercept) {
241 _capacitance_intercept = capacitance_intercept;
242 }
243
244
245
246
247
248
249 public void setCapacitanceSlope(double capacitance_slope) {
250 _capacitance_slope = capacitance_slope;
251 }
252
253 public ChargeCarrier getChargeCarrier()
254 {
255 return _carrier;
256 }
257
258
259
260
261
262
263
264 public double getCapacitance(int cell_id)
265 {
266 return _capacitance_intercept + _capacitance_slope*getStripLength(cell_id);
267 }
268
269
270
271
272
273
274
275 public double getCapacitance() {
276 return getCapacitance(getNCells(0) / 2);
277 }
278
279 public SortedMap<Integer,Integer> computeElectrodeData(ChargeDistribution distribution)
280 {
281 SortedMap<Integer,Integer> electrode_data = new TreeMap<Integer,Integer>();
282
283 int base_strip = getCellID(distribution.getMean());
284
285
286 int axis = 0;
287 int window_size = (int)Math.ceil(3.0*distribution.sigma1D(getMeasuredCoordinate(axis))/getPitch(axis));
288
289 double integral_lower = distribution.getNormalization();
290 double integral_upper = distribution.getNormalization();
291
292 for (int istrip = base_strip-window_size; istrip <= base_strip+window_size; istrip++)
293 {
294 double cell_edge_upper = getCellPosition(istrip).x() + getPitch(axis)/2.0;
295
296
297
298 double integration_limit = cell_edge_upper;
299
300
301
302 integral_upper = distribution.upperIntegral1D(getMeasuredCoordinate(axis),integration_limit);
303
304
305
306 if (integral_lower<integral_upper)
307 {
308 throw new RuntimeException("Error in integrating Gaussian charge distribution!");
309 }
310
311 int strip_charge = (int)Math.round(integral_lower-integral_upper);
312
313
314
315 if (strip_charge != 0)
316 {
317 electrode_data.put(istrip,strip_charge);
318 }
319
320 integral_lower = integral_upper;
321 }
322
323 return electrode_data;
324
325 }
326
327
328
329
330 public double getStripLength(int cell_id)
331 {
332
333 return getStrip(cell_id).getLength();
334 }
335
336
337 public Hep3Vector getStripCenter(int cell_id)
338 {
339 LineSegment3D strip = getStrip(cell_id);
340 return strip.getEndPoint(strip.getLength()/2);
341 }
342
343
344 public LineSegment3D getStrip(int cell_id)
345 {
346 Line3D strip_line = new Line3D(new Point3D(getCellPosition(cell_id)),getUnmeasuredCoordinate(0));
347
348
349
350
351
352
353
354
355 List<Point3D> intersections = new ArrayList<Point3D>();
356
357
358 for (LineSegment3D edge : _geometry.getEdges())
359 {
360
361
362
363 if (GeomOp2D.intersects(strip_line,edge))
364 {
365 intersections.add(GeomOp3D.lineBetween(strip_line,edge).getStartPoint());
366 }
367 }
368
369
370 List<Point3D> strip_ends = new ArrayList<Point3D>(intersections);
371 if (intersections.size() > 2)
372 {
373 for (int ipoint1 = 0; ipoint1 < intersections.size(); ipoint1++)
374 {
375 Point3D point1 = intersections.get(ipoint1);
376 for (int ipoint2 = ipoint1+1; ipoint2 < intersections.size(); ipoint2++)
377 {
378 Point3D point2 = intersections.get(ipoint2);
379 if (GeomOp3D.intersects(point1,point2))
380 {
381 strip_ends.remove(point2);
382 if (strip_ends.size() == 2) break;
383 }
384 }
385 }
386 }
387
388 return new LineSegment3D(strip_ends.get(0),strip_ends.get(1));
389 }
390
391
392
393 public void setCarrier(ChargeCarrier carrier)
394 {
395 _carrier = carrier;
396 }
397
398 public void setGeometry(Polygon3D geometry)
399 {
400
401
402
403
404
405
406
407
408 if (GeomOp3D.equals(geometry.getPlane(),GeomOp2D.PLANE))
409 {
410 _geometry = geometry;
411 }
412 else
413 {
414 throw new RuntimeException("Electrode geometry must be defined in x-y plane!!");
415 }
416 }
417
418 private void setStripNumbering()
419 {
420 double xmin = Double.MAX_VALUE;
421 double xmax = Double.MIN_VALUE;
422 for (Point3D vertex : _geometry.getVertices())
423 {
424 xmin = Math.min(xmin,vertex.x());
425 xmax = Math.max(xmax,vertex.x());
426 }
427
428
429
430
431
432
433
434 setNStrips( (int)Math.ceil((xmax-xmin)/getPitch(0)) ) ;
435 }
436
437 private void setNStrips(int nstrips)
438 {
439 _nstrips = nstrips;
440 setStripOffset();
441
442 }
443
444 private void setStripOffset()
445 {
446 double xmin = Double.MAX_VALUE;
447 double xmax = Double.MIN_VALUE;
448 for (Point3D vertex : _geometry.getVertices())
449 {
450 xmin = Math.min(xmin,vertex.x());
451 xmax = Math.max(xmax,vertex.x());
452 }
453
454 double strips_center = (xmin+xmax)/2;
455
456 _strip_offset = ((_nstrips-1)*_pitch)/2 - strips_center;
457
458 }
459
460 private void setPitch(double pitch)
461 {
462 _pitch = pitch;
463 }
464
465 private void setDetectorElement(IDetectorElement detector)
466 {
467 _detector = detector;
468 }
469
470 private void setParentToLocal(ITransform3D parent_to_local)
471 {
472 _parent_to_local = parent_to_local;
473 }
474
475 private void setLocalToGlobal(ITransform3D local_to_global)
476 {
477 _local_to_global = local_to_global;
478 }
479
480 private void setGlobalToLocal(ITransform3D global_to_local)
481 {
482 _global_to_local = global_to_local;
483 }
484
485 }
486
487