1
2
3
4
5
6
7
8
9 package org.lcsim.recon.tracking.digitization.sisim;
10
11 import hep.physics.matrix.SymmetricMatrix;
12 import hep.physics.vec.BasicHep3Vector;
13 import hep.physics.vec.Hep3Vector;
14 import hep.physics.vec.VecOp;
15
16 import java.util.ArrayList;
17 import java.util.HashMap;
18 import java.util.HashSet;
19 import java.util.List;
20 import java.util.Map;
21 import java.util.Set;
22 import java.util.Map.Entry;
23
24 import org.lcsim.detector.IDetectorElement;
25 import org.lcsim.detector.IReadout;
26 import org.lcsim.detector.identifier.IIdentifier;
27 import org.lcsim.detector.tracker.silicon.ChargeCarrier;
28 import org.lcsim.detector.tracker.silicon.DopedSilicon;
29 import org.lcsim.detector.tracker.silicon.SiPixels;
30 import org.lcsim.detector.tracker.silicon.SiSensor;
31 import org.lcsim.detector.tracker.silicon.SiSensorElectrodes;
32 import org.lcsim.detector.tracker.silicon.SiTrackerIdentifierHelper;
33 import org.lcsim.event.RawTrackerHit;
34 import org.lcsim.event.SimTrackerHit;
35
36
37
38
39
40
41
42 public class PixelHitMaker implements Clusterer {
43
44 private static String _NAME = "PixelClusterer";
45
46 ClusteringAlgorithm _clustering;
47
48
49 int _max_cluster_npixels = 10;
50
51 ReadoutChip _readout_chip;
52
53 SiSensorSim _simulation;
54
55 SiTrackerIdentifierHelper _sid_helper;
56
57 Map<RawTrackerHit, Integer> _pixel_map = new HashMap<RawTrackerHit, Integer>();
58 double _oneClusterErr = 1 / Math.sqrt(12);
59 double _twoClusterErr = 1 / 5;
60 double _threeClusterErr = 1 / 3;
61 double _fourClusterErr = 1 / 2;
62 double _fiveClusterErr = 1;
63
64
65
66
67
68
69
70 public PixelHitMaker(SiSensorSim simulation, ReadoutChip readout_chip) {
71 this(simulation, readout_chip, new NearestNeighbor());
72 }
73
74
75
76
77
78
79
80
81 public PixelHitMaker(SiSensorSim simulation, ReadoutChip readout_chip, ClusteringAlgorithm clustering) {
82 _simulation = simulation;
83 _readout_chip = readout_chip;
84 _clustering = clustering;
85 }
86
87 public void setClusteringAlgorithm(ClusteringAlgorithm clustering_algorithm) {
88 _clustering = clustering_algorithm;
89 }
90
91 public void setMaxClusterSize(int max_cluster_npixels) {
92 _max_cluster_npixels = max_cluster_npixels;
93 }
94
95 public String getName() {
96 return _NAME;
97 }
98
99 public void SetOneClusterErr(double err) {
100 _oneClusterErr = err;
101 }
102
103 public void SetTwoClusterErr(double err) {
104 _twoClusterErr = err;
105 }
106
107 public void SetThreeClusterErr(double err) {
108 _threeClusterErr = err;
109 }
110
111 public void SetFourClusterErr(double err) {
112 _fourClusterErr = err;
113 }
114
115 public void SetFiveClusterErr(double err) {
116 _fiveClusterErr = err;
117 }
118
119
120 public List<SiTrackerHit> makeHits(IDetectorElement detector) {
121 System.out.println("makeHits(IDetectorElement): " + detector.getName());
122 List<SiTrackerHit> hits = new ArrayList<SiTrackerHit>();
123 List<SiSensor> sensors = detector.findDescendants(SiSensor.class);
124
125
126 for (SiSensor sensor : sensors) {
127 if (sensor.hasPixels()) {
128 hits.addAll(makeHits(sensor));
129 }
130 }
131
132
133 return hits;
134 }
135
136
137 public List<SiTrackerHit> makeHits(SiSensor sensor) {
138
139
140
141 List<SiTrackerHit> hits = new ArrayList<SiTrackerHit>();
142
143
144 _sid_helper = (SiTrackerIdentifierHelper) sensor.getIdentifierHelper();
145 _pixel_map.clear();
146
147
148 IReadout ro = sensor.getReadout();
149 List<RawTrackerHit> raw_hits = ro.getHits(RawTrackerHit.class);
150
151 Map<SiSensorElectrodes, List<RawTrackerHit>> electrode_hits = new HashMap<SiSensorElectrodes, List<RawTrackerHit>>();
152
153 for (RawTrackerHit raw_hit : raw_hits) {
154
155
156 IIdentifier id = raw_hit.getIdentifier();
157 int pixel_number = _sid_helper.getElectrodeValue(id);
158
159
160 _pixel_map.put(raw_hit, pixel_number);
161
162
163
164 ChargeCarrier carrier = ChargeCarrier.getCarrier(_sid_helper.getSideValue(id));
165 SiSensorElectrodes electrodes = ((SiSensor) raw_hit.getDetectorElement()).getReadoutElectrodes(carrier);
166 if (!(electrodes instanceof SiPixels)) {
167 continue;
168 }
169
170 if (electrode_hits.get(electrodes) == null) {
171 electrode_hits.put(electrodes, new ArrayList<RawTrackerHit>());
172 }
173
174 electrode_hits.get(electrodes).add(raw_hit);
175 }
176
177 for (Entry entry : electrode_hits.entrySet()) {
178 hits.addAll(makeHits(sensor, (SiPixels) entry.getKey(), (List<RawTrackerHit>) entry.getValue()));
179 }
180
181 return hits;
182 }
183
184
185
186
187 public List<SiTrackerHit> makeHits(SiSensor sensor, SiSensorElectrodes electrodes, List<RawTrackerHit> raw_hits) {
188
189
190 List<List<RawTrackerHit>> cluster_list = _clustering.findClusters(electrodes, _readout_chip, raw_hits);
191
192
193 List<SiTrackerHit> hits = new ArrayList<SiTrackerHit>();
194
195
196 for (List<RawTrackerHit> cluster : cluster_list) {
197
198
199 if (cluster.size() <= _max_cluster_npixels) {
200 SiTrackerHitPixel hit = makeTrackerHit(cluster, electrodes);
201
202
203 ((SiSensor) electrodes.getDetectorElement()).getReadout().addHit(hit);
204 hits.add(hit);
205 }
206 }
207
208 return hits;
209 }
210
211
212 private SiTrackerHitPixel makeTrackerHit(List<RawTrackerHit> cluster, SiSensorElectrodes electrodes) {
213 Hep3Vector position = getPosition(cluster, electrodes);
214 SymmetricMatrix covariance = getCovariance(cluster, electrodes);
215 double time = getTime(cluster);
216 double energy = getEnergy(cluster);
217 TrackerHitType type = new TrackerHitType(TrackerHitType.CoordinateSystem.GLOBAL, TrackerHitType.MeasurementType.PIXEL);
218
219 SiTrackerHitPixel hit = new SiTrackerHitPixel(position, covariance, energy, time, cluster, type);
220 return hit;
221 }
222
223 private List<SimTrackerHit> getSimulatedHits(List<RawTrackerHit> cluster) {
224 Set<SimTrackerHit> simulated_hits = new HashSet<SimTrackerHit>();
225 for (RawTrackerHit hit : cluster) {
226 simulated_hits.addAll(hit.getSimTrackerHits());
227 }
228 return new ArrayList<SimTrackerHit>(simulated_hits);
229 }
230
231 private Hep3Vector getPosition(List<RawTrackerHit> cluster, SiSensorElectrodes electrodes) {
232 List<Double> signals = new ArrayList<Double>();
233 List<Hep3Vector> positions = new ArrayList<Hep3Vector>();
234
235 for (RawTrackerHit hit : cluster) {
236 signals.add(_readout_chip.decodeCharge(hit));
237 positions.add(electrodes.getCellPosition(_pixel_map.get(hit)));
238 }
239
240 double total_charge = 0;
241 Hep3Vector position = new BasicHep3Vector(0, 0, 0);
242
243 for (int ipixel = 0; ipixel < signals.size(); ipixel++) {
244 double signal = signals.get(ipixel);
245
246 total_charge += signal;
247 position = VecOp.add(position, VecOp.mult(signal, positions.get(ipixel)));
248 }
249 position = VecOp.mult(1 / total_charge, position);
250
251
252 electrodes.getParentToLocal().inverse().transform(position);
253
254
255
256
257 _simulation.setSensor((SiSensor) electrodes.getDetectorElement());
258 _simulation.lorentzCorrect(position, electrodes.getChargeCarrier());
259
260
261
262
263 return ((SiSensor) electrodes.getDetectorElement()).getGeometry().getLocalToGlobal().transformed(position);
264
265 }
266
267 private double getTime(List<RawTrackerHit> cluster) {
268 int time_sum = 0;
269 int signal_sum = 0;
270
271 for (RawTrackerHit hit : cluster) {
272
273 int pixel_number = _pixel_map.get(hit);
274 double signal = _readout_chip.decodeCharge(hit);
275 double time = _readout_chip.decodeTime(hit);
276
277 time_sum += time * signal;
278 signal_sum += signal;
279
280 }
281 return (double) time_sum / (double) signal_sum;
282 }
283
284 private SymmetricMatrix getCovariance(List<RawTrackerHit> cluster, SiSensorElectrodes electrodes) {
285
286 SymmetricMatrix covariance = new SymmetricMatrix(3);
287 covariance.setElement(0, 0, Math.pow(getXResolution(cluster, electrodes), 2));
288 covariance.setElement(1, 1, Math.pow(getYResolution(cluster, electrodes), 2));
289 covariance.setElement(2, 2, 0.0);
290
291 SymmetricMatrix covariance_global = electrodes.getLocalToGlobal().transformed(covariance);
292
293
294
295 return covariance_global;
296
297 }
298
299 private double getXResolution(List<RawTrackerHit> cluster, SiSensorElectrodes electrodes) {
300
301 double measured_resolution;
302
303 Set<Integer> rows = new HashSet<Integer>();
304 for (RawTrackerHit hit : cluster) {
305 rows.add(electrodes.getRowNumber(_pixel_map.get(hit)));
306 }
307
308 int cluster_width = rows.size();
309 double sense_pitch = ((SiSensor) electrodes.getDetectorElement()).getSenseElectrodes(electrodes.getChargeCarrier()).getPitch(0);
310
311 if (cluster_width == 1) {
312 measured_resolution = sense_pitch * _oneClusterErr;
313 } else if (cluster_width == 2) {
314 measured_resolution = sense_pitch * _twoClusterErr;
315 } else if (cluster_width == 3) {
316 measured_resolution = sense_pitch * _threeClusterErr;
317 } else if (cluster_width == 4) {
318 measured_resolution = sense_pitch * _fourClusterErr;
319 } else {
320 measured_resolution = sense_pitch * _fiveClusterErr;
321 }
322
323 return measured_resolution;
324
325 }
326
327 private double getYResolution(List<RawTrackerHit> cluster, SiSensorElectrodes electrodes) {
328
329 double measured_resolution;
330
331 Set<Integer> columns = new HashSet<Integer>();
332 for (RawTrackerHit hit : cluster) {
333 columns.add(electrodes.getColumnNumber(_pixel_map.get(hit)));
334 }
335
336 int cluster_width = columns.size();
337 double sense_pitch = ((SiSensor) electrodes.getDetectorElement()).getSenseElectrodes(electrodes.getChargeCarrier()).getPitch(1);
338
339 if (cluster_width == 1) {
340 measured_resolution = sense_pitch * _oneClusterErr;
341 } else if (cluster_width == 2) {
342 measured_resolution = sense_pitch * _twoClusterErr;
343 } else if (cluster_width == 3) {
344 measured_resolution = sense_pitch * _threeClusterErr;
345 } else if (cluster_width == 4) {
346 measured_resolution = sense_pitch * _fourClusterErr;
347 } else {
348 measured_resolution = sense_pitch * _fiveClusterErr;
349 }
350
351 return measured_resolution;
352
353 }
354
355 private double getEnergy(List<RawTrackerHit> cluster) {
356 double total_charge = 0.0;
357 for (RawTrackerHit hit : cluster) {
358
359 int pixel_number = _pixel_map.get(hit);
360 double signal = _readout_chip.decodeCharge(hit);
361
362 total_charge += signal;
363 }
364 return total_charge * DopedSilicon.ENERGY_EHPAIR;
365 }
366 }