SND@LHC Software
Loading...
Searching...
No Matches
shipPatRec.py
Go to the documentation of this file.
1from __future__ import print_function
2from __future__ import division
3__author__ = 'Mikhail Hushchyn'
4
5import numpy as np
6import global_variables
7
8# Globals
9ReconstructibleMCTracks = []
10theTracks = []
11
12r_scale = global_variables.ShipGeo.strawtubes.InnerStrawDiameter / 1.975
13
14def initialize(fgeo):
15 pass
16
17
18def execute(smeared_hits, ship_geo, method=''):
19 """
20 Main function of track pattern recognition.
21
22 Parameters:
23 -----------
24 SmearedHits : list
25 Smeared hits. SmearedHits = [{'digiHit': key,
26 'xtop': xtop, 'ytop': ytop, 'z': ztop,
27 'xbot': xbot, 'ybot': ybot,
28 'dist': dist2wire, 'detID': detID}, {...}, ...]
29 """
30
31 recognized_tracks = {}
32
33 if method == "TemplateMatching":
34 recognized_tracks = template_matching_pattern_recognition(smeared_hits, ship_geo)
35 elif method == "FH":
36 recognized_tracks = fast_hough_transform_pattern_recognition(smeared_hits, ship_geo)
37 elif method == "AR":
38 recognized_tracks = artificial_retina_pattern_recognition(smeared_hits, ship_geo)
39 else:
40 hits_y12, hits_stereo12, hits_y34, hits_stereo34 = hits_split(smeared_hits)
41 atrack = {'y12': hits_y12, 'stereo12': hits_stereo12, 'y34': hits_y34, 'stereo34': hits_stereo34}
42 recognized_tracks[0] = atrack
43
44 # print "track_hits.keys(): ", recognized_tracks.keys()
45
46 return recognized_tracks
47
48
50 pass
51
52
57
58def template_matching_pattern_recognition(SmearedHits, ShipGeo):
59 """
60 Main function of track pattern recognition.
61
62 Parameters:
63 -----------
64 SmearedHits : list
65 Smeared hits. SmearedHits = [{'digiHit': key,
66 'xtop': xtop, 'ytop': ytop, 'z': ztop,
67 'xbot': xbot, 'ybot': ybot,
68 'dist': dist2wire, 'detID': detID}, {...}, ...]
69 """
70
71 recognized_tracks = {}
72
73 if len(SmearedHits) > 500:
74 print("Too large hits in the event!")
75 return recognized_tracks
76
77 min_hits = 3
78
79
80 SmearedHits_12y, SmearedHits_12stereo, SmearedHits_34y, SmearedHits_34stereo = hits_split(SmearedHits)
81
82
83 recognized_tracks_y12 = pat_rec_view(SmearedHits_12y, min_hits)
84 # recognized_tracks_y12 = [{'hits_y': [hit1, hit2, ...], 'k_y': float, 'b_y': float}, {...}, ...]
85
86
87 recognized_tracks_12 = pat_rec_stereo_views(SmearedHits_12stereo, recognized_tracks_y12, min_hits)
88 # recognized_tracks_12 = [{'hits_y': [hit1, hit2, ...], 'hits_stereo': [hit1, hit2, ...], 'k_y': float, 'b_y': float}, {...}, ...]
89
90
91 recognized_tracks_y34 = pat_rec_view(SmearedHits_34y, min_hits)
92 # recognized_tracks_y34 = [{'hits_y': [hit1, hit2, ...], 'k_y': float, 'b_y': float}, {...}, ...]
93
94
95 recognized_tracks_34 = pat_rec_stereo_views(SmearedHits_34stereo, recognized_tracks_y34, min_hits)
96 # recognized_tracks_34 = [{'hits_y': [hit1, hit2, ...], 'hits_stereo': [hit1, hit2, ...], 'k_y': float, 'b_y': float}, {...}, ...]
97
98
99 recognized_tracks_combo = tracks_combination_using_extrapolation(recognized_tracks_12, recognized_tracks_34, ShipGeo.Bfield.z)
100 # recognized_tracks_combo = [{'hits_y12': [hit1, hit2, ...], 'hits_stereo12': [hit1, hit2, ...],
101 # 'hits_y34': [hit1, hit2, ...], 'hits_stereo34': [hit1, hit2, ...]}, {..}, ..]
102
103 # Prepare output of PatRec
104 recognized_tracks = {}
105 i_track = 0
106 for atrack_combo in recognized_tracks_combo:
107
108 hits_y12 = atrack_combo['hits_y12']
109 hits_stereo12 = atrack_combo['hits_stereo12']
110 hits_y34 = atrack_combo['hits_y34']
111 hits_stereo34 = atrack_combo['hits_stereo34']
112
113
114 if len(hits_y12) >= min_hits and len(hits_stereo12) >= min_hits and len(hits_y34) >= min_hits and len(hits_stereo34) >= min_hits:
115 atrack = {'y12': hits_y12, 'stereo12': hits_stereo12, 'y34': hits_y34, 'stereo34': hits_stereo34}
116 recognized_tracks[i_track] = atrack
117 i_track += 1
118
119
120
121 return recognized_tracks
122
123
124def pat_rec_view(SmearedHits, min_hits):
125 """
126 Main function of track pattern recognition.
127
128 Parameters:
129 -----------
130 SmearedHits : list
131 Smeared hits. SmearedHits = [{'digiHit': key,
132 'xtop': xtop, 'ytop': ytop, 'z': ztop,
133 'xbot': xbot, 'ybot': ybot,
134 'dist': dist2wire, 'detID': detID}, {...}, ...]
135 """
136
137 long_recognized_tracks = []
138
139 # Take 2 hits as a track seed
140 for ahit1 in SmearedHits:
141 for ahit2 in SmearedHits:
142
143 if ahit1['z'] >= ahit2['z']:
144 continue
145 if ahit1['detID'] == ahit2['detID']:
146 continue
147
148 k_seed = 1. * (ahit2['ytop'] - ahit1['ytop']) / (ahit2['z'] - ahit1['z'])
149 b_seed = ahit1['ytop'] - k_seed * ahit1['z']
150
151 if abs(k_seed) > 1:
152 continue
153
154 atrack = {}
155 atrack['hits_y'] = [ahit1, ahit2]
156 atrack_layers = [ahit1['detID'] // 10000, ahit2['detID'] // 10000]
157
158 # Add new hits to the seed
159 for ahit3 in SmearedHits:
160
161 if ahit3['detID'] == ahit1['detID'] or ahit3['detID'] == ahit2['detID']:
162 continue
163
164 layer3 = ahit3['detID'] // 10000
165 if layer3 in atrack_layers:
166 continue
167
168 in_bin = hit_in_window(ahit3['z'], ahit3['ytop'], k_seed, b_seed, window_width=1.4 * r_scale)
169 if in_bin:
170 atrack['hits_y'].append(ahit3)
171 atrack_layers.append(layer3)
172
173 if len(atrack['hits_y']) >= min_hits:
174 long_recognized_tracks.append(atrack)
175
176 # Remove clones
177 recognized_tracks = reduce_clones_using_one_track_per_hit(long_recognized_tracks, min_hits)
178
179 # Track fit
180 for atrack in recognized_tracks:
181 z_coords = [ahit['z'] for ahit in atrack['hits_y']]
182 y_coords = [ahit['ytop'] for ahit in atrack['hits_y']]
183 [atrack['k_y'], atrack['b_y']] = np.polyfit(z_coords, y_coords, deg=1)
184
185 return recognized_tracks
186
187
188
193
195 """
196 Main function of track pattern recognition.
197
198 Parameters:
199 -----------
200 SmearedHits : list
201 Smeared hits. SmearedHits = [{'digiHit': key,
202 'xtop': xtop, 'ytop': ytop, 'z': ztop,
203 'xbot': xbot, 'ybot': ybot,
204 'dist': dist2wire, 'detID': detID}, {...}, ...]
205 """
206
207 recognized_tracks = {}
208
209 if len(SmearedHits) > 500:
210 print("Too large hits in the event!")
211 return recognized_tracks
212
213 min_hits = 3
214
215
216 SmearedHits_12y, SmearedHits_12stereo, SmearedHits_34y, SmearedHits_34stereo = hits_split(SmearedHits)
217
218
219 recognized_tracks_y12 = fast_hough_pat_rec_y_view(SmearedHits_12y, min_hits)
220 # recognized_tracks_y12 = [{'hits_y': [hit1, hit2, ...], 'k_y': float, 'b_y': float}, {...}, ...]
221
222
224 recognized_tracks_12 = fast_hough_pat_rec_stereo_views(SmearedHits_12stereo, recognized_tracks_y12, min_hits)
225 # recognized_tracks_12 = [{'hits_y': [hit1, hit2, ...], 'hits_stereo': [hit1, hit2, ...], 'k_y': float, 'b_y': float}, {...}, ...]
226
227
228 recognized_tracks_y34 = fast_hough_pat_rec_y_view(SmearedHits_34y, min_hits)
229 # recognized_tracks_y34 = [{'hits_y': [hit1, hit2, ...], 'k_y': float, 'b_y': float}, {...}, ...]
230
231
233 recognized_tracks_34 = fast_hough_pat_rec_stereo_views(SmearedHits_34stereo, recognized_tracks_y34, min_hits)
234 # recognized_tracks_34 = [{'hits_y': [hit1, hit2, ...], 'hits_stereo': [hit1, hit2, ...], 'k_y': float, 'b_y': float}, {...}, ...]
235
236
237 recognized_tracks_combo = tracks_combination_using_extrapolation(recognized_tracks_12, recognized_tracks_34, ShipGeo.Bfield.z)
238 # recognized_tracks_combo = [{'hits_y12': [hit1, hit2, ...], 'hits_stereo12': [hit1, hit2, ...],
239 # 'hits_y34': [hit1, hit2, ...], 'hits_stereo34': [hit1, hit2, ...]}, {..}, ..]
240
241 # Prepare output of PatRec
242 recognized_tracks = {}
243 i_track = 0
244 for atrack_combo in recognized_tracks_combo:
245
246 hits_y12 = atrack_combo['hits_y12']
247 hits_stereo12 = atrack_combo['hits_stereo12']
248 hits_y34 = atrack_combo['hits_y34']
249 hits_stereo34 = atrack_combo['hits_stereo34']
250
251
252 if len(hits_y12) >= min_hits and len(hits_stereo12) >= min_hits and len(hits_y34) >= min_hits and len(hits_stereo34) >= min_hits:
253 atrack = {'y12': hits_y12, 'stereo12': hits_stereo12, 'y34': hits_y34, 'stereo34': hits_stereo34}
254 recognized_tracks[i_track] = atrack
255 i_track += 1
256
257
258
259 return recognized_tracks
260
261
262def fast_hough_pat_rec_y_view(SmearedHits, min_hits):
263 """
264 Main function of track pattern recognition.
265
266 Parameters:
267 -----------
268 SmearedHits : list
269 Smeared hits. SmearedHits = [{'digiHit': key,
270 'xtop': xtop, 'ytop': ytop, 'z': ztop,
271 'xbot': xbot, 'ybot': ybot,
272 'dist': dist2wire, 'detID': detID}, {...}, ...]
273 """
274
275 long_recognized_tracks = []
276
277 # Take 2 hits as a track seed
278 for ahit1 in SmearedHits:
279 for ahit2 in SmearedHits:
280
281 if ahit1['z'] >= ahit2['z']:
282 continue
283 if ahit1['detID'] == ahit2['detID']:
284 continue
285
286 k_seed = 1. * (ahit2['ytop'] - ahit1['ytop']) / (ahit2['z'] - ahit1['z'])
287 b_seed = ahit1['ytop'] - k_seed * ahit1['z']
288
289 if abs(k_seed) > 1:
290 continue
291
292 atrack = {}
293 atrack['hits_y'] = [ahit1, ahit2]
294 atrack_layers = [ahit1['detID'] // 10000, ahit2['detID'] // 10000]
295
296 # Add new hits to the seed
297 for ahit3 in SmearedHits:
298
299 if ahit3['detID'] == ahit1['detID'] or ahit3['detID'] == ahit2['detID']:
300 continue
301
302 layer3 = ahit3['detID'] // 10000
303 if layer3 in atrack_layers:
304 continue
305
306 in_bin = hit_in_bin(ahit3['z'], ahit3['ytop'], k_seed, b_seed, k_size=0.7/2000 * r_scale, b_size=1700./1000 * r_scale)
307 if in_bin:
308 atrack['hits_y'].append(ahit3)
309 atrack_layers.append(layer3)
310
311 if len(atrack['hits_y']) >= min_hits:
312 long_recognized_tracks.append(atrack)
313
314 # Remove clones
315 recognized_tracks = reduce_clones_using_one_track_per_hit(long_recognized_tracks, min_hits)
316
317 # Track fit
318 for atrack in recognized_tracks:
319 z_coords = [ahit['z'] for ahit in atrack['hits_y']]
320 y_coords = [ahit['ytop'] for ahit in atrack['hits_y']]
321 [atrack['k_y'], atrack['b_y']] = np.polyfit(z_coords, y_coords, deg=1)
322
323 return recognized_tracks
324
325
326
327def fast_hough_pat_rec_stereo_views(SmearedHits_stereo, recognized_tracks_y, min_hits):
328
329
330 recognized_tracks_stereo = []
331 used_hits = []
332
333 for atrack_y in recognized_tracks_y:
334
335 k_y = atrack_y['k_y']
336 b_y = atrack_y['b_y']
337
338 # Get hit zx projections
339 for ahit in SmearedHits_stereo:
340 x_center = get_zy_projection(ahit['z'], ahit['ytop'], ahit['xtop'],ahit['ybot'], ahit['xbot'], k_y, b_y)
341 ahit['zx_projection'] = x_center
342
343 long_recognized_tracks_stereo = []
344
345 for ahit1 in SmearedHits_stereo:
346 for ahit2 in SmearedHits_stereo:
347
348 if ahit1['z'] >= ahit2['z']:
349 continue
350 if ahit1['detID'] == ahit2['detID']:
351 continue
352 if ahit1['digiHit'] in used_hits:
353 continue
354 if ahit2['digiHit'] in used_hits:
355 continue
356
357 if abs(ahit1['zx_projection']) > 300 or abs(ahit2['zx_projection']) > 300:
358 continue
359
360 k_seed = 1. * (ahit2['zx_projection'] - ahit1['zx_projection']) / (ahit2['z'] - ahit1['z'])
361 b_seed = ahit1['zx_projection'] - k_seed * ahit1['z']
362
363 atrack_stereo = {}
364 atrack_stereo['hits_stereo'] = [ahit1, ahit2]
365 atrack_stereo_layers = [ahit1['detID'] // 10000, ahit2['detID'] // 10000]
366
367 for ahit3 in SmearedHits_stereo:
368
369 if ahit3['digiHit'] == ahit1['digiHit'] or ahit3['digiHit'] == ahit2['digiHit']:
370 continue
371 if ahit3['digiHit'] in used_hits:
372 continue
373
374 if abs(ahit3['zx_projection']) > 300:
375 continue
376
377 layer3 = ahit3['detID'] // 10000
378 if layer3 in atrack_stereo_layers:
379 continue
380
381 in_bin = hit_in_bin(ahit3['z'], ahit3['zx_projection'], k_seed, b_seed, k_size=0.6/200 * r_scale, b_size=1000./70 * r_scale)
382 if in_bin:
383 atrack_stereo['hits_stereo'].append(ahit3)
384 atrack_stereo_layers.append(layer3)
385
386 if len(atrack_stereo['hits_stereo']) >= min_hits:
387 long_recognized_tracks_stereo.append(atrack_stereo)
388
389
390 # Remove clones
391 max_track = None
392 max_n_hits = -999
393
394 for atrack_stereo in long_recognized_tracks_stereo:
395 if len(atrack_stereo['hits_stereo']) > max_n_hits:
396 max_track = atrack_stereo
397 max_n_hits = len(atrack_stereo['hits_stereo'])
398
399 atrack = {}
400 atrack['hits_y'] = atrack_y['hits_y']
401 atrack['k_y'] = atrack_y['k_y']
402 atrack['b_y'] = atrack_y['b_y']
403 atrack['hits_stereo'] = []
404
405 if max_track is not None:
406 atrack['hits_stereo'] = max_track['hits_stereo']
407 for ahit in max_track['hits_stereo']:
408 used_hits.append(ahit['digiHit'])
409
410 recognized_tracks_stereo.append(atrack)
411
412 return recognized_tracks_stereo
413
414
415
416def hit_in_bin(x, y, k_bin, b_bin, k_size, b_size):
417 """
418 Counts hits in a bin of track parameter space (b, k).
419
420 Parameters
421 ---------
422 x : array-like
423 Array of x coordinates of hits.
424 y : array-like
425 Array of x coordinates of hits.
426 k_bin : float
427 Track parameter: y = k_bin * x + b_bin
428 b_bin : float
429 Track parameter: y = k_bin * x + b_bin
430
431 Return
432 ------
433 track_inds : array-like
434 Hit indexes of a track: [ind1, ind2, ...]
435 """
436
437
438 b_left = y - (k_bin - 0.5 * k_size) * x
439 b_right = y - (k_bin + 0.5 * k_size) * x
440
441 sel = (b_left >= b_bin - 0.5 * b_size) * (b_right <= b_bin + 0.5 * b_size) + \
442 (b_left <= b_bin + 0.5 * b_size) * (b_right >= b_bin - 0.5 * b_size)
443
444 return sel
445
446
447
452
453from scipy.optimize import minimize
454
456 """
457 Main function of track pattern recognition.
458
459 Parameters:
460 -----------
461 SmearedHits : list
462 Smeared hits. SmearedHits = [{'digiHit': key,
463 'xtop': xtop, 'ytop': ytop, 'z': ztop,
464 'xbot': xbot, 'ybot': ybot,
465 'dist': dist2wire, 'detID': detID}, {...}, ...]
466 """
467
468 recognized_tracks = {}
469
470 if len(SmearedHits) > 500:
471 print("Too large hits in the event!")
472 return recognized_tracks
473
474 min_hits = 3
475
476
477 SmearedHits_12y, SmearedHits_12stereo, SmearedHits_34y, SmearedHits_34stereo = hits_split(SmearedHits)
478
479
480 recognized_tracks_y12 = artificial_retina_pat_rec_y_view(SmearedHits_12y, min_hits)
481 # recognized_tracks_y12 = [{'hits_y': [hit1, hit2, ...], 'k_y': float, 'b_y': float}, {...}, ...]
482
483
485 recognized_tracks_12 = artificial_retina_pat_rec_stereo_views(SmearedHits_12stereo, recognized_tracks_y12, min_hits)
486 # recognized_tracks_12 = [{'hits_y': [hit1, hit2, ...], 'hits_stereo': [hit1, hit2, ...], 'k_y': float, 'b_y': float}, {...}, ...]
487
488
489 recognized_tracks_y34 = artificial_retina_pat_rec_y_view(SmearedHits_34y, min_hits)
490 # recognized_tracks_y34 = [{'hits_y': [hit1, hit2, ...], 'k_y': float, 'b_y': float}, {...}, ...]
491
492
494 recognized_tracks_34 = artificial_retina_pat_rec_stereo_views(SmearedHits_34stereo, recognized_tracks_y34, min_hits)
495 # recognized_tracks_34 = [{'hits_y': [hit1, hit2, ...], 'hits_stereo': [hit1, hit2, ...], 'k_y': float, 'b_y': float}, {...}, ...]
496
497
498 recognized_tracks_combo = tracks_combination_using_extrapolation(recognized_tracks_12, recognized_tracks_34, ShipGeo.Bfield.z)
499 # recognized_tracks_combo = [{'hits_y12': [hit1, hit2, ...], 'hits_stereo12': [hit1, hit2, ...],
500 # 'hits_y34': [hit1, hit2, ...], 'hits_stereo34': [hit1, hit2, ...]}, {..}, ..]
501
502 # Prepare output of PatRec
503 recognized_tracks = {}
504 i_track = 0
505 for atrack_combo in recognized_tracks_combo:
506
507 hits_y12 = atrack_combo['hits_y12']
508 hits_stereo12 = atrack_combo['hits_stereo12']
509 hits_y34 = atrack_combo['hits_y34']
510 hits_stereo34 = atrack_combo['hits_stereo34']
511
512
513 if len(hits_y12) >= min_hits and len(hits_stereo12) >= min_hits and len(hits_y34) >= min_hits and len(hits_stereo34) >= min_hits:
514 atrack = {'y12': hits_y12, 'stereo12': hits_stereo12, 'y34': hits_y34, 'stereo34': hits_stereo34}
515 recognized_tracks[i_track] = atrack
516 i_track += 1
517
518
519
520 return recognized_tracks
521
522
523def artificial_retina_pat_rec_y_view(SmearedHits, min_hits):
524 """
525 Main function of track pattern recognition.
526
527 Parameters:
528 -----------
529 SmearedHits : list
530 Smeared hits. SmearedHits = [{'digiHit': key,
531 'xtop': xtop, 'ytop': ytop, 'z': ztop,
532 'xbot': xbot, 'ybot': ybot,
533 'dist': dist2wire, 'detID': detID}, {...}, ...]
534 """
535
536 long_recognized_tracks = []
537 used_hits = np.zeros(len(SmearedHits))
538
539 hits_z = np.array([ahit['z'] for ahit in SmearedHits])
540 hits_y = np.array([ahit['ytop'] for ahit in SmearedHits])
541
542 for i in range(len(SmearedHits)):
543
544 hits_z_unused = hits_z[used_hits == 0]
545 hits_y_unused = hits_y[used_hits == 0]
546
547 sigma=1. * r_scale
548 best_seed_params = get_best_seed(hits_z_unused, hits_y_unused, sigma, sample_weight=None)
549
550 res = minimize(retina_func, best_seed_params, args = (hits_z_unused, hits_y_unused, sigma, None), method='BFGS',
551 jac=retina_grad, options={'gtol': 1e-6, 'disp': False, 'maxiter': 5})
552 [k_seed_upd, b_seed_upd] = res.x
553
554 atrack = {}
555 atrack['hits_y'] = []
556 atrack_layers = []
557 hit_ids = []
558
559 # Add new hits to the seed
560 for i_hit3 in range(len(SmearedHits)):
561
562 if used_hits[i_hit3] == 1:
563 continue
564
565 ahit3 = SmearedHits[i_hit3]
566 layer3 = ahit3['detID'] // 10000
567 if layer3 in atrack_layers:
568 continue
569
570 in_bin = hit_in_window(ahit3['z'], ahit3['ytop'], k_seed_upd, b_seed_upd, window_width=1.4 * r_scale)
571 if in_bin:
572 atrack['hits_y'].append(ahit3)
573 atrack_layers.append(layer3)
574 hit_ids.append(i_hit3)
575
576 if len(atrack['hits_y']) >= min_hits:
577 long_recognized_tracks.append(atrack)
578 used_hits[hit_ids] = 1
579 else:
580 break
581
582 # Remove clones
583 recognized_tracks = reduce_clones_using_one_track_per_hit(long_recognized_tracks, min_hits)
584
585 # Track fit
586 for atrack in recognized_tracks:
587 z_coords = [ahit['z'] for ahit in atrack['hits_y']]
588 y_coords = [ahit['ytop'] for ahit in atrack['hits_y']]
589 [atrack['k_y'], atrack['b_y']] = np.polyfit(z_coords, y_coords, deg=1)
590
591 return recognized_tracks
592
593
594
595def artificial_retina_pat_rec_stereo_views(SmearedHits_stereo, recognized_tracks_y, min_hits):
596
597
598 recognized_tracks_stereo = []
599 used_hits = []
600
601 for atrack_y in recognized_tracks_y:
602
603 k_y = atrack_y['k_y']
604 b_y = atrack_y['b_y']
605
606 # Get hit zx projections
607 for ahit in SmearedHits_stereo:
608 x_center = get_zy_projection(ahit['z'], ahit['ytop'], ahit['xtop'],ahit['ybot'], ahit['xbot'], k_y, b_y)
609 ahit['zx_projection'] = x_center
610
611 long_recognized_tracks_stereo = []
612 hits_z = []
613 hits_x = []
614
615 for ahit in SmearedHits_stereo:
616 if ahit['digiHit'] in used_hits:
617 continue
618 if abs(ahit['zx_projection']) > 300:
619 continue
620 hits_z.append(ahit['z'])
621 hits_x.append(ahit['zx_projection'])
622 hits_z = np.array(hits_z)
623 hits_x = np.array(hits_x)
624
625 sigma=15. * r_scale
626 best_seed_params = get_best_seed(hits_z, hits_x, sigma, sample_weight=None)
627
628 res = minimize(retina_func, best_seed_params, args = (hits_z, hits_x, sigma, None), method='BFGS',
629 jac=retina_grad, options={'gtol': 1e-6, 'disp': False, 'maxiter': 5})
630 [k_seed_upd, b_seed_upd] = res.x
631
632 atrack_stereo = {}
633 atrack_stereo['hits_stereo'] = []
634 atrack_stereo_layers = []
635
636 for ahit3 in SmearedHits_stereo:
637
638 if ahit3['digiHit'] in used_hits:
639 continue
640
641 if abs(ahit3['zx_projection']) > 300:
642 continue
643
644 layer3 = ahit3['detID'] // 10000
645 if layer3 in atrack_stereo_layers:
646 continue
647
648 in_bin = hit_in_window(ahit3['z'], ahit3['zx_projection'], k_seed_upd, b_seed_upd, window_width=15. * r_scale)
649 if in_bin:
650 atrack_stereo['hits_stereo'].append(ahit3)
651 atrack_stereo_layers.append(layer3)
652
653 if len(atrack_stereo['hits_stereo']) >= min_hits:
654 long_recognized_tracks_stereo.append(atrack_stereo)
655
656
657 # Remove clones
658 max_track = None
659 max_n_hits = -999
660
661 for atrack_stereo in long_recognized_tracks_stereo:
662 if len(atrack_stereo['hits_stereo']) > max_n_hits:
663 max_track = atrack_stereo
664 max_n_hits = len(atrack_stereo['hits_stereo'])
665
666 atrack = {}
667 atrack['hits_y'] = atrack_y['hits_y']
668 atrack['k_y'] = atrack_y['k_y']
669 atrack['b_y'] = atrack_y['b_y']
670 atrack['hits_stereo'] = []
671
672 if max_track is not None:
673 atrack['hits_stereo'] = max_track['hits_stereo']
674 for ahit in max_track['hits_stereo']:
675 used_hits.append(ahit['digiHit'])
676
677 recognized_tracks_stereo.append(atrack)
678
679 return recognized_tracks_stereo
680
681
682def get_best_seed(x, y, sigma, sample_weight=None):
683
684 best_retina_val = 0
685 best_seed_params = [0, 0]
686
687 for i_1 in range(len(x)-1):
688 for i_2 in range(i_1+1, len(x)):
689
690 if x[i_1] >= x[i_2]:
691 continue
692
693 seed_k = (y[i_2] - y[i_1]) / (x[i_2] - x[i_1] + 10**-6)
694 seed_b = y[i_1] - seed_k * x[i_1]
695
696 retina_val = retina_func([seed_k, seed_b], x, y, sigma, sample_weight)
697
698 if retina_val < best_retina_val:
699 best_retina_val = retina_val
700 best_seed_params = [seed_k, seed_b]
701
702 return best_seed_params
703
704
705def retina_func(track_prams, x, y, sigma, sample_weight=None):
706 """
707 Calculates the artificial retina function value.
708 Parameters
709 ----------
710 track_prams : array-like
711 Track parameters [k, b].
712 x : array-like
713 Array of x coordinates of hits.
714 y : array-like
715 Array of x coordinates of hits.
716 sigma : float
717 Standard deviation of hit form a track.
718 sample_weight : array-like
719 Hit weights used during the track fit.
720 Retunrs
721 -------
722 retina : float
723 Negative value of the artificial retina function.
724 """
725
726 rs = track_prams[0] * x + track_prams[1] - y
727
728 if sample_weight == None:
729 exps = np.exp(- (rs/sigma)**2)
730 else:
731 exps = np.exp(- (rs/sigma)**2) * sample_weight
732
733 retina = exps.sum()
734
735 return -retina
736
737
738
739def retina_grad(track_prams, x, y, sigma, sample_weight=None):
740 """
741 Calculates the artificial retina gradient.
742 Parameters
743 ----------
744 track_prams : array-like
745 Track parameters [k, b].
746 x : array-like
747 Array of x coordinates of hits.
748 y : array-like
749 Array of x coordinates of hits.
750 sigma : float
751 Standard deviation of hit form a track.
752 sample_weight : array-like
753 Hit weights used during the track fit.
754 Retunrs
755 -------
756 retina : float
757 Negative value of the artificial retina gradient.
758 """
759
760 rs = track_prams[0] * x + track_prams[1] - y
761
762 if sample_weight == None:
763 exps = np.exp(- (rs/sigma)**2)
764 else:
765 exps = np.exp(- (rs/sigma)**2) * sample_weight
766
767 dks = - 2.*rs / sigma**2 * exps * x
768 dbs = - 2.*rs / sigma**2 * exps
769
770 return -np.array([dks.sum(), dbs.sum()])
771
772
773
778
779
780
781def hits_split(smeared_hits):
782 """
783 Split hits into groups of station views.
784
785 Parameters:
786 -----------
787 SmearedHits : list
788 Smeared hits. SmearedHits = [{'digiHit': key,
789 'xtop': xtop, 'ytop': ytop, 'z': ztop,
790 'xbot': xbot, 'ybot': ybot,
791 'dist': dist2wire, 'detID': detID}, {...}, ...]
792 """
793
794 smeared_hits_12y = []
795 smeared_hits_12stereo = []
796 smeared_hits_34y = []
797 smeared_hits_34stereo = []
798
799 for i_hit in range(len(smeared_hits)):
800
801 ahit = smeared_hits[i_hit]
802
803 detID = ahit['detID']
804 statnb, vnb, pnb, lnb, snb = decodeDetectorID(detID)
805 is_y12 = ((statnb == 1) + (statnb == 2)) * ((vnb == 0) + (vnb == 3))
806 is_stereo12 = ((statnb == 1) + (statnb == 2)) * ((vnb == 1) + (vnb == 2))
807 is_y34 = ((statnb == 3) + (statnb == 4)) * ((vnb == 0) + (vnb == 3))
808 is_stereo34 = ((statnb == 3) + (statnb == 4)) * ((vnb == 1) + (vnb == 2))
809
810 if is_y12:
811 smeared_hits_12y.append(ahit)
812 if is_stereo12:
813 smeared_hits_12stereo.append(ahit)
814 if is_y34:
815 smeared_hits_34y.append(ahit)
816 if is_stereo34:
817 smeared_hits_34stereo.append(ahit)
818
819 return smeared_hits_12y, smeared_hits_12stereo, smeared_hits_34y, smeared_hits_34stereo
820
821
822def reduce_clones_using_one_track_per_hit(recognized_tracks, min_hits=3):
823 """
824 Split hits into groups of station views.
825
826 Parameters:
827 -----------
828 recognized_tracks : list
829 Track hits. Tracks = [{'hits_y': [hit1, hit2, hit3, ...]}, {...}, ...]
830 min_hits : int
831 Minimal number of hits per track.
832 """
833
834 used_hits = []
835 tracks_no_clones = []
836 n_hits = [len(atrack['hits_y']) for atrack in recognized_tracks]
837
838 for i_track in np.argsort(n_hits)[::-1]:
839
840 atrack = recognized_tracks[i_track]
841 new_track = {}
842 new_track['hits_y'] = []
843
844 for i_hit in range(len(atrack['hits_y'])):
845 ahit = atrack['hits_y'][i_hit]
846 if ahit['digiHit'] not in used_hits:
847 new_track['hits_y'].append(ahit)
848
849 if len(new_track['hits_y']) >= min_hits:
850 tracks_no_clones.append(new_track)
851 for ahit in new_track['hits_y']:
852 used_hits.append(ahit['digiHit'])
853
854 return tracks_no_clones
855
856
857def tracks_combination_using_extrapolation(recognized_tracks_12, recognized_tracks_34, z_magnet):
858
859 recognized_tracks_combo = []
860
861 i_track_y12 = []
862 i_track_y34 = []
863 deltas_y = []
864
865 for i_12 in range(len(recognized_tracks_12)):
866
867 atrack_12 = recognized_tracks_12[i_12]
868 y_center_y12 = atrack_12['k_y'] * z_magnet + atrack_12['b_y']
869
870 for i_34 in range(len(recognized_tracks_34)):
871
872 atrack_34 = recognized_tracks_34[i_34]
873 y_center_y34 = atrack_34['k_y'] * z_magnet + atrack_34['b_y']
874
875 i_track_y12.append(i_12)
876 i_track_y34.append(i_34)
877 deltas_y.append(abs(y_center_y12 - y_center_y34))
878
879 max_dy = 50
880 used_y12 = []
881 used_y34 = []
882
883 for i in np.argsort(deltas_y):
884
885 dy = deltas_y[i]
886 i_12 = i_track_y12[i]
887 i_34 = i_track_y34[i]
888
889 if (dy < max_dy) and (i_12 not in used_y12) and (i_34 not in used_y34):
890 atrack = {}
891 atrack['hits_y12'] = recognized_tracks_12[i_12]['hits_y']
892 atrack['hits_stereo12'] = recognized_tracks_12[i_12]['hits_stereo']
893 atrack['hits_y34'] = recognized_tracks_34[i_34]['hits_y']
894 atrack['hits_stereo34'] = recognized_tracks_34[i_34]['hits_stereo']
895 recognized_tracks_combo.append(atrack)
896 used_y12.append(i_12)
897 used_y34.append(i_34)
898
899 for i_12 in range(len(recognized_tracks_12)):
900 if i_12 not in used_y12:
901 atrack = {}
902 atrack['hits_y12'] = recognized_tracks_12[i_12]['hits_y']
903 atrack['hits_stereo12'] = recognized_tracks_12[i_12]['hits_stereo']
904 atrack['hits_y34'] = []
905 atrack['hits_stereo34'] = []
906 recognized_tracks_combo.append(atrack)
907
908 for i_34 in range(len(recognized_tracks_34)):
909 if i_34 not in used_y34:
910 atrack = {}
911 atrack['hits_y12'] = []
912 atrack['hits_stereo12'] = []
913 atrack['hits_y34'] = recognized_tracks_34[i_34]['hits_y']
914 atrack['hits_stereo34'] = recognized_tracks_34[i_34]['hits_stereo']
915 recognized_tracks_combo.append(atrack)
916 recognized_tracks_combo.append(atrack)
917
918 return recognized_tracks_combo
919
920
921
923 """
924 Decodes detector ID.
925
926 Parameters
927 ----------
928 detID : int or array-like
929 Detector ID values.
930
931 Returns
932 -------
933 statnb : int or array-like
934 Station numbers.
935 vnb : int or array-like
936 View numbers.
937 pnb : int or array-like
938 Plane numbers.
939 lnb : int or array-like
940 Layer numbers.
941 snb : int or array-like
942 Straw tube numbers.
943 """
944
945 statnb = detID // 10000000
946 vnb = (detID - statnb * 10000000) // 1000000
947 pnb = (detID - statnb * 10000000 - vnb * 1000000) // 100000
948 lnb = (detID - statnb * 10000000 - vnb * 1000000 - pnb * 100000) // 10000
949 snb = detID - statnb * 10000000 - vnb * 1000000 - pnb * 100000 - lnb * 10000 - 2000
950
951 return statnb, vnb, pnb, lnb, snb
952
953
954
955def hit_in_window(x, y, k_bin, b_bin, window_width=1.):
956 """
957 Counts hits in a bin of track parameter space (b, k).
958
959 Parameters
960 ---------
961 x : array-like
962 Array of x coordinates of hits.
963 y : array-like
964 Array of x coordinates of hits.
965 k_bin : float
966 Track parameter: y = k_bin * x + b_bin
967 b_bin : float
968 Track parameter: y = k_bin * x + b_bin
969
970 Return
971 ------
972 track_inds : array-like
973 Hit indexes of a track: [ind1, ind2, ...]
974 """
975
976
977 y_approx = k_bin * x + b_bin
978
979 flag = False
980 if np.abs(y_approx - y) <= window_width:
981 flag = True
982
983 return flag
984
985
986def get_zy_projection(z, xtop, ytop, xbot, ybot, k_y, b_y):
987
988 x = k_y * z + b_y
989 k = (ytop - ybot) / (xtop - xbot + 10**-6)
990 b = ytop - k * xtop
991 y = k * x + b
992
993 return y
994
995
996def pat_rec_stereo_views(SmearedHits_stereo, recognized_tracks_y, min_hits):
997
998
999 recognized_tracks_stereo = []
1000 used_hits = []
1001
1002 for atrack_y in recognized_tracks_y:
1003
1004 k_y = atrack_y['k_y']
1005 b_y = atrack_y['b_y']
1006
1007 # Get hit zx projections
1008 for ahit in SmearedHits_stereo:
1009 x_center = get_zy_projection(ahit['z'], ahit['ytop'], ahit['xtop'],ahit['ybot'], ahit['xbot'], k_y, b_y)
1010 ahit['zx_projection'] = x_center
1011
1012 long_recognized_tracks_stereo = []
1013
1014 for ahit1 in SmearedHits_stereo:
1015 for ahit2 in SmearedHits_stereo:
1016
1017 if ahit1['z'] >= ahit2['z']:
1018 continue
1019 if ahit1['detID'] == ahit2['detID']:
1020 continue
1021 if ahit1['digiHit'] in used_hits:
1022 continue
1023 if ahit2['digiHit'] in used_hits:
1024 continue
1025
1026 if abs(ahit1['zx_projection']) > 300 or abs(ahit2['zx_projection']) > 300:
1027 continue
1028
1029 k_seed = 1. * (ahit2['zx_projection'] - ahit1['zx_projection']) / (ahit2['z'] - ahit1['z'])
1030 b_seed = ahit1['zx_projection'] - k_seed * ahit1['z']
1031
1032 atrack_stereo = {}
1033 atrack_stereo['hits_stereo'] = [ahit1, ahit2]
1034 atrack_stereo_layers = [ahit1['detID'] // 10000, ahit2['detID'] // 10000]
1035
1036 for ahit3 in SmearedHits_stereo:
1037
1038 if ahit3['digiHit'] == ahit1['digiHit'] or ahit3['digiHit'] == ahit2['digiHit']:
1039 continue
1040 if ahit3['digiHit'] in used_hits:
1041 continue
1042
1043 if abs(ahit3['zx_projection']) > 300:
1044 continue
1045
1046 layer3 = ahit3['detID'] // 10000
1047 if layer3 in atrack_stereo_layers:
1048 continue
1049
1050 in_bin = hit_in_window(ahit3['z'], ahit3['zx_projection'], k_seed, b_seed, window_width=15. * r_scale)
1051 if in_bin:
1052 atrack_stereo['hits_stereo'].append(ahit3)
1053 atrack_stereo_layers.append(layer3)
1054
1055 if len(atrack_stereo['hits_stereo']) >= min_hits:
1056 long_recognized_tracks_stereo.append(atrack_stereo)
1057
1058
1059 # Remove clones
1060 max_track = None
1061 max_n_hits = -999
1062
1063 for atrack_stereo in long_recognized_tracks_stereo:
1064 if len(atrack_stereo['hits_stereo']) > max_n_hits:
1065 max_track = atrack_stereo
1066 max_n_hits = len(atrack_stereo['hits_stereo'])
1067
1068 atrack = {}
1069 atrack['hits_y'] = atrack_y['hits_y']
1070 atrack['k_y'] = atrack_y['k_y']
1071 atrack['b_y'] = atrack_y['b_y']
1072 atrack['hits_stereo'] = []
1073
1074 if max_track is not None:
1075 atrack['hits_stereo'] = max_track['hits_stereo']
1076 for ahit in max_track['hits_stereo']:
1077 used_hits.append(ahit['digiHit'])
1078
1079 recognized_tracks_stereo.append(atrack)
1080
1081 return recognized_tracks_stereo
pat_rec_stereo_views(SmearedHits_stereo, recognized_tracks_y, min_hits)
fast_hough_pat_rec_stereo_views(SmearedHits_stereo, recognized_tracks_y, min_hits)
artificial_retina_pat_rec_stereo_views(SmearedHits_stereo, recognized_tracks_y, min_hits)
hit_in_window(x, y, k_bin, b_bin, window_width=1.)
fast_hough_transform_pattern_recognition(SmearedHits, ShipGeo)
Fast Hough Transform.
get_zy_projection(z, xtop, ytop, xbot, ybot, k_y, b_y)
pat_rec_view(SmearedHits, min_hits)
artificial_retina_pat_rec_y_view(SmearedHits, min_hits)
hits_split(smeared_hits)
The End of the PatRec Methods.
fast_hough_pat_rec_y_view(SmearedHits, min_hits)
template_matching_pattern_recognition(SmearedHits, ShipGeo)
Template Matching.
Definition shipPatRec.py:58
artificial_retina_pattern_recognition(SmearedHits, ShipGeo)
initialize(fgeo)
Definition shipPatRec.py:14
hit_in_bin(x, y, k_bin, b_bin, k_size, b_size)
get_best_seed(x, y, sigma, sample_weight=None)
retina_grad(track_prams, x, y, sigma, sample_weight=None)
tracks_combination_using_extrapolation(recognized_tracks_12, recognized_tracks_34, z_magnet)
retina_func(track_prams, x, y, sigma, sample_weight=None)
reduce_clones_using_one_track_per_hit(recognized_tracks, min_hits=3)
execute(smeared_hits, ship_geo, method='')
Definition shipPatRec.py:18
decodeDetectorID(detID)