1
2
3
4 package org.lcsim.recon.tracking.digitization.sisim;
5
6 import java.util.ArrayList;
7 import java.util.HashMap;
8 import java.util.LinkedList;
9 import java.util.List;
10 import java.util.Map;
11 import java.util.Set;
12 import org.lcsim.detector.identifier.IIdentifier;
13 import org.lcsim.detector.tracker.silicon.SiSensorElectrodes;
14 import org.lcsim.detector.tracker.silicon.SiTrackerIdentifierHelper;
15 import org.lcsim.event.RawTrackerHit;
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 public class NearestNeighborRMS implements ClusteringAlgorithm {
36
37 private static String _NAME = "NearestNeighborRMS";
38 private double _seed_threshold;
39 private double _neighbor_threshold;
40 private double _cluster_threshold;
41
42
43
44
45
46
47
48
49
50
51
52
53 public NearestNeighborRMS(double seed_threshold, double neighbor_threshold, double cluster_threshold) {
54 _seed_threshold = seed_threshold;
55 _neighbor_threshold = neighbor_threshold;
56 _cluster_threshold = cluster_threshold;
57 }
58
59
60
61
62
63
64
65
66 public NearestNeighborRMS() {
67 this(4.0, 3.0, 4.0);
68 }
69
70
71
72
73
74
75 public void setSeedThreshold(double seed_threshold) {
76 _seed_threshold = seed_threshold;
77 }
78
79
80
81
82
83
84 public void setNeighborThreshold(double neighbor_threshold) {
85 _neighbor_threshold = neighbor_threshold;
86 }
87
88
89
90
91
92
93 public void setClusterThreshold(double cluster_threshold) {
94 _cluster_threshold = cluster_threshold;
95 }
96
97
98
99
100
101
102 public double getSeedThreshold() {
103 return _seed_threshold;
104 }
105
106
107
108
109
110
111 public double getNeighborThreshold() {
112 return _neighbor_threshold;
113 }
114
115
116
117
118
119
120 public double getClusterThreshold() {
121 return _cluster_threshold;
122 }
123
124
125
126
127
128
129 public String getName() {
130 return _NAME;
131 }
132
133
134
135
136
137
138
139
140
141 public List<List<RawTrackerHit>> findClusters(SiSensorElectrodes electrodes,
142 ReadoutChip readout_chip, List<RawTrackerHit> raw_hits) {
143
144
145 if (_seed_threshold < _neighbor_threshold) {
146 throw new RuntimeException("Tracker hit clustering error: seed threshold below neighbor threshold");
147 }
148
149
150 int mapsize = 2 * raw_hits.size();
151 Map<Integer, Boolean> clusterable = new HashMap<Integer, Boolean>(mapsize);
152 Map<RawTrackerHit, Integer> hit_to_channel = new HashMap<RawTrackerHit, Integer>(mapsize);
153 Map<Integer, RawTrackerHit> channel_to_hit = new HashMap<Integer, RawTrackerHit>(mapsize);
154
155
156 List<Integer> cluster_seeds = new ArrayList<Integer>();
157
158
159
160 for (RawTrackerHit raw_hit : raw_hits) {
161
162
163 SiTrackerIdentifierHelper sid_helper = (SiTrackerIdentifierHelper) raw_hit.getIdentifierHelper();
164 IIdentifier id = raw_hit.getIdentifier();
165 int channel_number = sid_helper.getElectrodeValue(id);
166
167
168 if (hit_to_channel.containsKey(raw_hit)) {
169 throw new RuntimeException("Duplicate hit: "+id.toString());
170 }
171
172
173 if (channel_to_hit.containsKey(channel_number)) {
174 throw new RuntimeException("Duplicate channel number: "+channel_number);
175 }
176
177
178 hit_to_channel.put(raw_hit, channel_number);
179 channel_to_hit.put(channel_number, raw_hit);
180
181
182 double signal = readout_chip.decodeCharge(raw_hit);
183 double noiseRMS = readout_chip.getChannel(channel_number).computeNoise(electrodes.getCapacitance(channel_number));
184
185
186 clusterable.put(channel_number, signal/noiseRMS >= _neighbor_threshold);
187
188
189 if (signal/noiseRMS >= _seed_threshold) {
190 cluster_seeds.add(channel_number);
191 }
192 }
193
194
195 List<List<RawTrackerHit>> cluster_list = new ArrayList<List<RawTrackerHit>>();
196
197
198 for (int seed_channel : cluster_seeds) {
199
200
201 if (!clusterable.get(seed_channel)) continue;
202
203
204 List<RawTrackerHit> cluster = new ArrayList<RawTrackerHit>();
205 double cluster_signal = 0.;
206 double cluster_noise_squared = 0.;
207
208
209 LinkedList<Integer> unchecked = new LinkedList<Integer>();
210
211
212 unchecked.addLast(seed_channel);
213 clusterable.put(seed_channel, false);
214
215
216 while (unchecked.size() > 0) {
217
218
219 int clustered_cell = unchecked.removeFirst();
220 cluster.add(channel_to_hit.get(clustered_cell));
221 cluster_signal += readout_chip.decodeCharge(channel_to_hit.get(clustered_cell));
222 cluster_noise_squared += Math.pow(readout_chip.getChannel(clustered_cell).computeNoise(electrodes.getCapacitance(clustered_cell)),2);
223
224
225 Set<Integer> neighbor_channels = electrodes.getNearestNeighborCells(clustered_cell);
226
227
228 for (int channel : neighbor_channels) {
229
230
231 Boolean addhit = clusterable.get(channel);
232
233
234 if (addhit == null) continue;
235
236
237 if (!addhit) continue;
238
239
240
241 unchecked.addLast(channel);
242 clusterable.put(channel, false);
243
244 }
245 }
246
247
248 if (cluster.size() > 0 &&
249 cluster_signal/Math.sqrt(cluster_noise_squared) > _cluster_threshold)
250 {
251 cluster_list.add(cluster);
252 }
253
254 }
255
256
257 return cluster_list;
258 }
259 }