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