4__author__ =
"Mikhail Hushchyn"
11logger = logging.getLogger(__name__)
14ReconstructibleMCTracks = []
18max_x = global_variables.ShipGeo.strawtubes_geo.width
25def execute(smeared_hits, ship_geo, method: str =
""):
27 Main function of track pattern recognition.
32 Smeared hits. SmearedHits = [{'digiHit': key,
33 'xtop': xtop,
'ytop': ytop,
'z': ztop,
34 'xbot': xbot,
'ybot': ybot,
35 'dist': dist2wire,
'detID': detID}, {...}, ...]
38 recognized_tracks = {}
40 logger.debug("PatRec input: %d smeared hits, method=%s", len(smeared_hits), method
or "none")
42 if method ==
"TemplateMatching":
49 hits_y12, hits_stereo12, hits_y34, hits_stereo34 =
hits_split(smeared_hits)
50 atrack = {
"y12": hits_y12,
"stereo12": hits_stereo12,
"y34": hits_y34,
"stereo34": hits_stereo34}
51 recognized_tracks[0] = atrack
53 logger.debug(
"PatRec output: %d tracks", len(recognized_tracks))
55 return recognized_tracks
71 Main function of track pattern recognition.
76 Smeared hits. SmearedHits = [{'digiHit': key,
77 'xtop': xtop,
'ytop': ytop,
'z': ztop,
78 'xbot': xbot,
'ybot': ybot,
79 'dist': dist2wire,
'detID': detID}, {...}, ...]
82 recognized_tracks = {}
84 if len(SmearedHits) > 500:
85 print(
"Too large hits in the event!")
86 return recognized_tracks
91 SmearedHits_12y, SmearedHits_12stereo, SmearedHits_34y, SmearedHits_34stereo =
hits_split(SmearedHits)
94 recognized_tracks_y12 =
pat_rec_view(SmearedHits_12y, min_hits)
98 recognized_tracks_12 =
pat_rec_stereo_views(SmearedHits_12stereo, recognized_tracks_y12, min_hits)
102 recognized_tracks_y34 =
pat_rec_view(SmearedHits_34y, min_hits)
106 recognized_tracks_34 =
pat_rec_stereo_views(SmearedHits_34stereo, recognized_tracks_y34, min_hits)
111 recognized_tracks_12, recognized_tracks_34, ShipGeo.Bfield.z
117 return recognized_tracks
122 Main function of track pattern recognition.
127 Smeared hits. SmearedHits = [{'digiHit': key,
128 'xtop': xtop,
'ytop': ytop,
'z': ztop,
129 'xbot': xbot,
'ybot': ybot,
130 'dist': dist2wire,
'detID': detID}, {...}, ...]
133 long_recognized_tracks = []
135 n_seeds_slope_cut = 0
138 for ahit1
in SmearedHits:
139 for ahit2
in SmearedHits:
140 if ahit1[
"z"] >= ahit2[
"z"]:
142 if ahit1[
"detID"] == ahit2[
"detID"]:
146 k_seed = 1.0 * (ahit2[
"ytop"] - ahit1[
"ytop"]) / (ahit2[
"z"] - ahit1[
"z"])
147 b_seed = ahit1[
"ytop"] - k_seed * ahit1[
"z"]
150 n_seeds_slope_cut += 1
154 atrack[
"hits_y"] = [ahit1, ahit2]
155 atrack_layers = [ahit1[
"detID"] // 10000, ahit2[
"detID"] // 10000]
158 for ahit3
in SmearedHits:
159 if ahit3[
"detID"] == ahit1[
"detID"]
or ahit3[
"detID"] == ahit2[
"detID"]:
162 layer3 = ahit3[
"detID"] // 10000
163 if layer3
in atrack_layers:
166 in_bin =
hit_in_window(ahit3[
"z"], ahit3[
"ytop"], k_seed, b_seed, window_width=1.4 * r_scale)
168 atrack[
"hits_y"].append(ahit3)
169 atrack_layers.append(layer3)
171 if len(atrack[
"hits_y"]) >= min_hits:
172 long_recognized_tracks.append(atrack)
178 "pat_rec_view: %d hits, %d seeds tried, %d cut by slope, %d tracks before clone removal, %d after",
182 len(long_recognized_tracks),
183 len(recognized_tracks),
187 for atrack
in recognized_tracks:
188 z_coords = [ahit[
"z"]
for ahit
in atrack[
"hits_y"]]
189 y_coords = [ahit[
"ytop"]
for ahit
in atrack[
"hits_y"]]
190 [atrack[
"k_y"], atrack[
"b_y"]] = np.polyfit(z_coords, y_coords, deg=1)
192 return recognized_tracks
204 Main function of track pattern recognition.
209 Smeared hits. SmearedHits = [{'digiHit': key,
210 'xtop': xtop,
'ytop': ytop,
'z': ztop,
211 'xbot': xbot,
'ybot': ybot,
212 'dist': dist2wire,
'detID': detID}, {...}, ...]
215 recognized_tracks = {}
217 if len(SmearedHits) > 500:
218 print(
"Too large hits in the event!")
219 return recognized_tracks
224 SmearedHits_12y, SmearedHits_12stereo, SmearedHits_34y, SmearedHits_34stereo =
hits_split(SmearedHits)
240 recognized_tracks_12, recognized_tracks_34, ShipGeo.Bfield.z
246 return recognized_tracks
251 Main function of track pattern recognition.
256 Smeared hits. SmearedHits = [{'digiHit': key,
257 'xtop': xtop,
'ytop': ytop,
'z': ztop,
258 'xbot': xbot,
'ybot': ybot,
259 'dist': dist2wire,
'detID': detID}, {...}, ...]
262 long_recognized_tracks = []
264 n_seeds_slope_cut = 0
267 for ahit1
in SmearedHits:
268 for ahit2
in SmearedHits:
269 if ahit1[
"z"] >= ahit2[
"z"]:
271 if ahit1[
"detID"] == ahit2[
"detID"]:
275 k_seed = 1.0 * (ahit2[
"ytop"] - ahit1[
"ytop"]) / (ahit2[
"z"] - ahit1[
"z"])
276 b_seed = ahit1[
"ytop"] - k_seed * ahit1[
"z"]
279 n_seeds_slope_cut += 1
283 atrack[
"hits_y"] = [ahit1, ahit2]
284 atrack_layers = [ahit1[
"detID"] // 10000, ahit2[
"detID"] // 10000]
287 for ahit3
in SmearedHits:
288 if ahit3[
"detID"] == ahit1[
"detID"]
or ahit3[
"detID"] == ahit2[
"detID"]:
291 layer3 = ahit3[
"detID"] // 10000
292 if layer3
in atrack_layers:
300 k_size=0.7 / 2000 * r_scale,
301 b_size=1700.0 / 1000 * r_scale,
304 atrack[
"hits_y"].append(ahit3)
305 atrack_layers.append(layer3)
307 if len(atrack[
"hits_y"]) >= min_hits:
308 long_recognized_tracks.append(atrack)
314 "fast_hough_y_view: %d hits, %d seeds tried, %d cut by slope, %d tracks before clone removal, %d after",
318 len(long_recognized_tracks),
319 len(recognized_tracks),
323 for atrack
in recognized_tracks:
324 z_coords = [ahit[
"z"]
for ahit
in atrack[
"hits_y"]]
325 y_coords = [ahit[
"ytop"]
for ahit
in atrack[
"hits_y"]]
326 [atrack[
"k_y"], atrack[
"b_y"]] = np.polyfit(z_coords, y_coords, deg=1)
328 return recognized_tracks
333 recognized_tracks_stereo = []
335 n_y_tracks_with_stereo = 0
337 for atrack_y
in recognized_tracks_y:
338 k_y = atrack_y[
"k_y"]
339 b_y = atrack_y[
"b_y"]
342 for ahit
in SmearedHits_stereo:
343 x_center =
get_zy_projection(ahit[
"z"], ahit[
"ytop"], ahit[
"xtop"], ahit[
"ybot"], ahit[
"xbot"], k_y, b_y)
344 ahit[
"zx_projection"] = x_center
346 long_recognized_tracks_stereo = []
348 for ahit1
in SmearedHits_stereo:
349 for ahit2
in SmearedHits_stereo:
350 if ahit1[
"z"] >= ahit2[
"z"]:
352 if ahit1[
"detID"] == ahit2[
"detID"]:
354 if ahit1[
"digiHit"]
in used_hits:
356 if ahit2[
"digiHit"]
in used_hits:
359 if abs(ahit1[
"zx_projection"]) > max_x
or abs(ahit2[
"zx_projection"]) > max_x:
362 k_seed = 1.0 * (ahit2[
"zx_projection"] - ahit1[
"zx_projection"]) / (ahit2[
"z"] - ahit1[
"z"])
363 b_seed = ahit1[
"zx_projection"] - k_seed * ahit1[
"z"]
366 atrack_stereo[
"hits_stereo"] = [ahit1, ahit2]
367 atrack_stereo_layers = [ahit1[
"detID"] // 10000, ahit2[
"detID"] // 10000]
369 for ahit3
in SmearedHits_stereo:
370 if ahit3[
"digiHit"] == ahit1[
"digiHit"]
or ahit3[
"digiHit"] == ahit2[
"digiHit"]:
372 if ahit3[
"digiHit"]
in used_hits:
375 if abs(ahit3[
"zx_projection"]) > max_x:
378 layer3 = ahit3[
"detID"] // 10000
379 if layer3
in atrack_stereo_layers:
384 ahit3[
"zx_projection"],
387 k_size=0.6 / 200 * r_scale,
388 b_size=1000.0 / 70 * r_scale,
391 atrack_stereo[
"hits_stereo"].append(ahit3)
392 atrack_stereo_layers.append(layer3)
394 if len(atrack_stereo[
"hits_stereo"]) >= min_hits:
395 long_recognized_tracks_stereo.append(atrack_stereo)
401 for atrack_stereo
in long_recognized_tracks_stereo:
402 if len(atrack_stereo[
"hits_stereo"]) > max_n_hits:
403 max_track = atrack_stereo
404 max_n_hits = len(atrack_stereo[
"hits_stereo"])
407 atrack[
"hits_y"] = atrack_y[
"hits_y"]
408 atrack[
"k_y"] = atrack_y[
"k_y"]
409 atrack[
"b_y"] = atrack_y[
"b_y"]
410 atrack[
"hits_stereo"] = []
412 if max_track
is not None:
413 atrack[
"hits_stereo"] = max_track[
"hits_stereo"]
414 n_y_tracks_with_stereo += 1
415 for ahit
in max_track[
"hits_stereo"]:
416 used_hits.append(ahit[
"digiHit"])
418 recognized_tracks_stereo.append(atrack)
421 "fast_hough_stereo: %d stereo hits, %d y-tracks, %d matched with stereo",
422 len(SmearedHits_stereo),
423 len(recognized_tracks_y),
424 n_y_tracks_with_stereo,
427 return recognized_tracks_stereo
432 Counts hits in a bin of track parameter space (b, k).
437 Array of x coordinates of hits.
439 Array of x coordinates of hits.
441 Track parameter: y = k_bin * x + b_bin
443 Track parameter: y = k_bin * x + b_bin
447 track_inds : array-like
448 Hit indexes of a track: [ind1, ind2, ...]
451 b_left = y - (k_bin - 0.5 * k_size) * x
452 b_right = y - (k_bin + 0.5 * k_size) * x
454 sel = (b_left >= b_bin - 0.5 * b_size) * (b_right <= b_bin + 0.5 * b_size) + (b_left <= b_bin + 0.5 * b_size) * (
455 b_right >= b_bin - 0.5 * b_size
467from scipy.optimize
import minimize
472 Main function of track pattern recognition.
477 Smeared hits. SmearedHits = [{'digiHit': key,
478 'xtop': xtop,
'ytop': ytop,
'z': ztop,
479 'xbot': xbot,
'ybot': ybot,
480 'dist': dist2wire,
'detID': detID}, {...}, ...]
483 recognized_tracks = {}
485 if len(SmearedHits) > 500:
486 print(
"Too large hits in the event!")
487 return recognized_tracks
492 SmearedHits_12y, SmearedHits_12stereo, SmearedHits_34y, SmearedHits_34stereo =
hits_split(SmearedHits)
508 recognized_tracks_12, recognized_tracks_34, ShipGeo.Bfield.z
514 return recognized_tracks
519 Main function of track pattern recognition.
524 Smeared hits. SmearedHits = [{'digiHit': key,
525 'xtop': xtop,
'ytop': ytop,
'z': ztop,
526 'xbot': xbot,
'ybot': ybot,
527 'dist': dist2wire,
'detID': detID}, {...}, ...]
530 long_recognized_tracks = []
531 used_hits = np.zeros(len(SmearedHits))
533 hits_z = np.array([ahit["z"]
for ahit
in SmearedHits])
534 hits_y = np.array([ahit[
"ytop"]
for ahit
in SmearedHits])
536 for i
in range(len(SmearedHits)):
537 hits_z_unused = hits_z[used_hits == 0]
538 hits_y_unused = hits_y[used_hits == 0]
540 sigma = 1.0 * r_scale
541 best_seed_params =
get_best_seed(hits_z_unused, hits_y_unused, sigma, sample_weight=
None)
546 args=(hits_z_unused, hits_y_unused, sigma,
None),
549 options={
"gtol": 1e-6,
"disp":
False,
"maxiter": 5},
551 [k_seed_upd, b_seed_upd] = res.x
554 atrack[
"hits_y"] = []
559 for i_hit3
in range(len(SmearedHits)):
560 if used_hits[i_hit3] == 1:
563 ahit3 = SmearedHits[i_hit3]
564 layer3 = ahit3[
"detID"] // 10000
565 if layer3
in atrack_layers:
568 in_bin =
hit_in_window(ahit3[
"z"], ahit3[
"ytop"], k_seed_upd, b_seed_upd, window_width=1.4 * r_scale)
570 atrack[
"hits_y"].append(ahit3)
571 atrack_layers.append(layer3)
572 hit_ids.append(i_hit3)
574 if len(atrack[
"hits_y"]) >= min_hits:
575 long_recognized_tracks.append(atrack)
576 used_hits[hit_ids] = 1
584 "ar_y_view: %d hits, %d tracks before clone removal, %d after",
586 len(long_recognized_tracks),
587 len(recognized_tracks),
591 for atrack
in recognized_tracks:
592 z_coords = [ahit[
"z"]
for ahit
in atrack[
"hits_y"]]
593 y_coords = [ahit[
"ytop"]
for ahit
in atrack[
"hits_y"]]
594 [atrack[
"k_y"], atrack[
"b_y"]] = np.polyfit(z_coords, y_coords, deg=1)
596 return recognized_tracks
601 recognized_tracks_stereo = []
603 n_y_tracks_with_stereo = 0
605 for atrack_y
in recognized_tracks_y:
606 k_y = atrack_y[
"k_y"]
607 b_y = atrack_y[
"b_y"]
610 for ahit
in SmearedHits_stereo:
611 x_center =
get_zy_projection(ahit[
"z"], ahit[
"ytop"], ahit[
"xtop"], ahit[
"ybot"], ahit[
"xbot"], k_y, b_y)
612 ahit[
"zx_projection"] = x_center
614 long_recognized_tracks_stereo = []
618 for ahit
in SmearedHits_stereo:
619 if ahit[
"digiHit"]
in used_hits:
621 if abs(ahit[
"zx_projection"]) > max_x:
623 hits_z.append(ahit[
"z"])
624 hits_x.append(ahit[
"zx_projection"])
625 hits_z = np.array(hits_z)
626 hits_x = np.array(hits_x)
628 sigma = 15.0 * r_scale
629 best_seed_params =
get_best_seed(hits_z, hits_x, sigma, sample_weight=
None)
634 args=(hits_z, hits_x, sigma,
None),
637 options={
"gtol": 1e-6,
"disp":
False,
"maxiter": 5},
639 [k_seed_upd, b_seed_upd] = res.x
642 atrack_stereo[
"hits_stereo"] = []
643 atrack_stereo_layers = []
645 for ahit3
in SmearedHits_stereo:
646 if ahit3[
"digiHit"]
in used_hits:
649 if abs(ahit3[
"zx_projection"]) > max_x:
652 layer3 = ahit3[
"detID"] // 10000
653 if layer3
in atrack_stereo_layers:
657 ahit3[
"z"], ahit3[
"zx_projection"], k_seed_upd, b_seed_upd, window_width=15.0 * r_scale
660 atrack_stereo[
"hits_stereo"].append(ahit3)
661 atrack_stereo_layers.append(layer3)
663 if len(atrack_stereo[
"hits_stereo"]) >= min_hits:
664 long_recognized_tracks_stereo.append(atrack_stereo)
670 for atrack_stereo
in long_recognized_tracks_stereo:
671 if len(atrack_stereo[
"hits_stereo"]) > max_n_hits:
672 max_track = atrack_stereo
673 max_n_hits = len(atrack_stereo[
"hits_stereo"])
676 atrack[
"hits_y"] = atrack_y[
"hits_y"]
677 atrack[
"k_y"] = atrack_y[
"k_y"]
678 atrack[
"b_y"] = atrack_y[
"b_y"]
679 atrack[
"hits_stereo"] = []
681 if max_track
is not None:
682 atrack[
"hits_stereo"] = max_track[
"hits_stereo"]
683 n_y_tracks_with_stereo += 1
684 for ahit
in max_track[
"hits_stereo"]:
685 used_hits.append(ahit[
"digiHit"])
687 recognized_tracks_stereo.append(atrack)
690 "ar_stereo: %d stereo hits, %d y-tracks, %d matched with stereo",
691 len(SmearedHits_stereo),
692 len(recognized_tracks_y),
693 n_y_tracks_with_stereo,
696 return recognized_tracks_stereo
701 best_seed_params = [0, 0]
703 for i_1
in range(len(x) - 1):
704 for i_2
in range(i_1 + 1, len(x)):
708 seed_k = (y[i_2] - y[i_1]) / (x[i_2] - x[i_1] + 10**-6)
709 seed_b = y[i_1] - seed_k * x[i_1]
711 retina_val =
retina_func([seed_k, seed_b], x, y, sigma, sample_weight)
713 if retina_val < best_retina_val:
714 best_retina_val = retina_val
715 best_seed_params = [seed_k, seed_b]
717 return best_seed_params
722 Calculates the artificial retina function value.
725 track_prams : array-like
726 Track parameters [k, b].
728 Array of x coordinates of hits.
730 Array of x coordinates of hits.
732 Standard deviation of hit form a track.
733 sample_weight : array-like
734 Hit weights used during the track fit.
738 Negative value of the artificial retina function.
741 rs = track_prams[0] * x + track_prams[1] - y
743 if sample_weight
is None:
744 exps = np.exp(-((rs / sigma) ** 2))
746 exps = np.exp(-((rs / sigma) ** 2)) * sample_weight
755 Calculates the artificial retina gradient.
758 track_prams : array-like
759 Track parameters [k, b].
761 Array of x coordinates of hits.
763 Array of x coordinates of hits.
765 Standard deviation of hit form a track.
766 sample_weight : array-like
767 Hit weights used during the track fit.
771 Negative value of the artificial retina gradient.
774 rs = track_prams[0] * x + track_prams[1] - y
776 if sample_weight
is None:
777 exps = np.exp(-((rs / sigma) ** 2))
779 exps = np.exp(-((rs / sigma) ** 2)) * sample_weight
781 dks = -2.0 * rs / sigma**2 * exps * x
782 dbs = -2.0 * rs / sigma**2 * exps
784 return -np.array([dks.sum(), dbs.sum()])
796 Split hits into groups of station views.
801 Smeared hits. SmearedHits = [{'digiHit': key,
802 'xtop': xtop,
'ytop': ytop,
'z': ztop,
803 'xbot': xbot,
'ybot': ybot,
804 'dist': dist2wire,
'detID': detID}, {...}, ...]
807 smeared_hits_12y = []
808 smeared_hits_12stereo = []
809 smeared_hits_34y = []
810 smeared_hits_34stereo = []
812 for i_hit
in range(len(smeared_hits)):
813 ahit = smeared_hits[i_hit]
815 detID = ahit[
"detID"]
816 decode = global_variables.modules[
"strawtubes"].StrawDecode(detID)
818 is_y12 = ((decode[0] == 1) + (decode[0] == 2)) * ((decode[1] == 0) + (decode[1] == 3))
819 is_stereo12 = ((decode[0] == 1) + (decode[0] == 2)) * ((decode[1] == 1) + (decode[1] == 2))
820 is_y34 = ((decode[0] == 3) + (decode[0] == 4)) * ((decode[1] == 0) + (decode[1] == 3))
821 is_stereo34 = ((decode[0] == 3) + (decode[0] == 4)) * ((decode[1] == 1) + (decode[1] == 2))
824 smeared_hits_12y.append(ahit)
826 smeared_hits_12stereo.append(ahit)
828 smeared_hits_34y.append(ahit)
830 smeared_hits_34stereo.append(ahit)
833 "hits_split: y12=%d, stereo12=%d, y34=%d, stereo34=%d",
834 len(smeared_hits_12y),
835 len(smeared_hits_12stereo),
836 len(smeared_hits_34y),
837 len(smeared_hits_34stereo),
840 return smeared_hits_12y, smeared_hits_12stereo, smeared_hits_34y, smeared_hits_34stereo
845 Split hits into groups of station views.
849 recognized_tracks : list
850 Track hits. Tracks = [{'hits_y': [hit1, hit2, hit3, ...]}, {...}, ...]
852 Minimal number of hits per track.
856 tracks_no_clones = []
857 n_hits = [len(atrack["hits_y"])
for atrack
in recognized_tracks]
859 for i_track
in np.argsort(n_hits)[::-1]:
860 atrack = recognized_tracks[i_track]
862 new_track[
"hits_y"] = []
864 for i_hit
in range(len(atrack[
"hits_y"])):
865 ahit = atrack[
"hits_y"][i_hit]
866 if ahit[
"digiHit"]
not in used_hits:
867 new_track[
"hits_y"].append(ahit)
869 if len(new_track[
"hits_y"]) >= min_hits:
870 tracks_no_clones.append(new_track)
871 for ahit
in new_track[
"hits_y"]:
872 used_hits.append(ahit[
"digiHit"])
874 return tracks_no_clones
878 recognized_tracks_combo = []
884 for i_12
in range(len(recognized_tracks_12)):
885 atrack_12 = recognized_tracks_12[i_12]
886 y_center_y12 = atrack_12[
"k_y"] * z_magnet + atrack_12[
"b_y"]
888 for i_34
in range(len(recognized_tracks_34)):
889 atrack_34 = recognized_tracks_34[i_34]
890 y_center_y34 = atrack_34[
"k_y"] * z_magnet + atrack_34[
"b_y"]
892 i_track_y12.append(i_12)
893 i_track_y34.append(i_34)
894 deltas_y.append(abs(y_center_y12 - y_center_y34))
900 for i
in np.argsort(deltas_y):
902 i_12 = i_track_y12[i]
903 i_34 = i_track_y34[i]
905 if (dy < max_dy)
and (i_12
not in used_y12)
and (i_34
not in used_y34):
907 atrack[
"hits_y12"] = recognized_tracks_12[i_12][
"hits_y"]
908 atrack[
"hits_stereo12"] = recognized_tracks_12[i_12][
"hits_stereo"]
909 atrack[
"hits_y34"] = recognized_tracks_34[i_34][
"hits_y"]
910 atrack[
"hits_stereo34"] = recognized_tracks_34[i_34][
"hits_stereo"]
911 atrack[
"k_y12"] = recognized_tracks_12[i_12][
"k_y"]
912 atrack[
"b_y12"] = recognized_tracks_12[i_12][
"b_y"]
913 atrack[
"k_y34"] = recognized_tracks_34[i_34][
"k_y"]
914 atrack[
"b_y34"] = recognized_tracks_34[i_34][
"b_y"]
915 recognized_tracks_combo.append(atrack)
916 used_y12.append(i_12)
917 used_y34.append(i_34)
919 for i_12
in range(len(recognized_tracks_12)):
920 if i_12
not in used_y12:
922 atrack[
"hits_y12"] = recognized_tracks_12[i_12][
"hits_y"]
923 atrack[
"hits_stereo12"] = recognized_tracks_12[i_12][
"hits_stereo"]
924 atrack[
"hits_y34"] = []
925 atrack[
"hits_stereo34"] = []
926 atrack[
"k_y12"] = recognized_tracks_12[i_12][
"k_y"]
927 atrack[
"b_y12"] = recognized_tracks_12[i_12][
"b_y"]
928 atrack[
"k_y34"] =
None
929 atrack[
"b_y34"] =
None
930 recognized_tracks_combo.append(atrack)
932 for i_34
in range(len(recognized_tracks_34)):
933 if i_34
not in used_y34:
935 atrack[
"hits_y12"] = []
936 atrack[
"hits_stereo12"] = []
937 atrack[
"hits_y34"] = recognized_tracks_34[i_34][
"hits_y"]
938 atrack[
"hits_stereo34"] = recognized_tracks_34[i_34][
"hits_stereo"]
939 atrack[
"k_y12"] =
None
940 atrack[
"b_y12"] =
None
941 atrack[
"k_y34"] = recognized_tracks_34[i_34][
"k_y"]
942 atrack[
"b_y34"] = recognized_tracks_34[i_34][
"b_y"]
943 recognized_tracks_combo.append(atrack)
946 "tracks_combo: %d 12-tracks, %d 34-tracks, %d matched pairs, %d total combos",
947 len(recognized_tracks_12),
948 len(recognized_tracks_34),
950 len(recognized_tracks_combo),
953 return recognized_tracks_combo
957 """Prepare PatRec output, filtering tracks with too few hits and preserving track parameters."""
958 recognized_tracks = {}
961 for atrack_combo
in recognized_tracks_combo:
962 hits_y12 = atrack_combo[
"hits_y12"]
963 hits_stereo12 = atrack_combo[
"hits_stereo12"]
964 hits_y34 = atrack_combo[
"hits_y34"]
965 hits_stereo34 = atrack_combo[
"hits_stereo34"]
968 len(hits_y12) >= min_hits
969 and len(hits_stereo12) >= min_hits
970 and len(hits_y34) >= min_hits
971 and len(hits_stereo34) >= min_hits
975 "stereo12": hits_stereo12,
977 "stereo34": hits_stereo34,
978 "k_y12": atrack_combo.get(
"k_y12"),
979 "b_y12": atrack_combo.get(
"b_y12"),
980 "k_y34": atrack_combo.get(
"k_y34"),
981 "b_y34": atrack_combo.get(
"b_y34"),
983 recognized_tracks[i_track] = atrack
989 "output: %d tracks accepted, %d rejected by min_hits=%d filter",
995 return recognized_tracks
1000 Check whether a hit falls within a window around a straight-line track.
1005 Z coordinate of the hit.
1007 Y (or projected X) coordinate of the hit.
1009 Track slope: y = k_bin * x + b_bin
1011 Track intercept: y = k_bin * x + b_bin
1012 window_width : float
1013 Half-width of the acceptance window
in the y direction.
1018 True if the hit
is within the window.
1021 y_approx = k_bin * x + b_bin
1024 if np.abs(y_approx - y) <= window_width:
1032 Project a stereo straw hit onto the ZX plane using the Y-view track parameters.
1034 A stereo straw is tilted: its top-end
is at (xtop, ytop)
and bottom-end at
1035 (xbot, ybot), both at the same z. The Y-view track gives the y position at
1036 this z
as y_track = k_y * z + b_y. This function finds the x coordinate
1037 where the straw wire crosses y_track by parameterising the wire
as a line
1038 in the XY plane
and evaluating it at y = y_track.
1040 Note: the caller passes (ytop, xtop, ybot, xbot) — the argument names here
1041 are swapped relative to the geometric meaning because the call sites swap
1042 the x/y coordinates. This
is intentional: the straw wire
is parameterised
1043 as x(y),
not y(x), because the stereo straws are nearly vertical.
1048 Z coordinate of the hit.
1050 First coordinate of wire top-end (actually ytop at call site).
1052 Second coordinate of wire top-end (actually xtop at call site).
1054 First coordinate of wire bottom-end (actually ybot at call site).
1056 Second coordinate of wire bottom-end (actually xbot at call site).
1058 Slope of the Y-view track: y = k_y * z + b_y.
1060 Intercept of the Y-view track.
1065 The projected x coordinate of the hit
in the ZX plane.
1068 k = (ytop - ybot) / (xtop - xbot + 10**-6)
1077 recognized_tracks_stereo = []
1079 n_y_tracks_with_stereo = 0
1081 for atrack_y
in recognized_tracks_y:
1082 k_y = atrack_y[
"k_y"]
1083 b_y = atrack_y[
"b_y"]
1086 for ahit
in SmearedHits_stereo:
1087 x_center =
get_zy_projection(ahit[
"z"], ahit[
"ytop"], ahit[
"xtop"], ahit[
"ybot"], ahit[
"xbot"], k_y, b_y)
1088 ahit[
"zx_projection"] = x_center
1090 long_recognized_tracks_stereo = []
1092 for ahit1
in SmearedHits_stereo:
1093 for ahit2
in SmearedHits_stereo:
1094 if ahit1[
"z"] >= ahit2[
"z"]:
1096 if ahit1[
"detID"] == ahit2[
"detID"]:
1098 if ahit1[
"digiHit"]
in used_hits:
1100 if ahit2[
"digiHit"]
in used_hits:
1103 if abs(ahit1[
"zx_projection"]) > max_x
or abs(ahit2[
"zx_projection"]) > max_x:
1106 k_seed = 1.0 * (ahit2[
"zx_projection"] - ahit1[
"zx_projection"]) / (ahit2[
"z"] - ahit1[
"z"])
1107 b_seed = ahit1[
"zx_projection"] - k_seed * ahit1[
"z"]
1110 atrack_stereo[
"hits_stereo"] = [ahit1, ahit2]
1111 atrack_stereo_layers = [ahit1[
"detID"] // 10000, ahit2[
"detID"] // 10000]
1113 for ahit3
in SmearedHits_stereo:
1114 if ahit3[
"digiHit"] == ahit1[
"digiHit"]
or ahit3[
"digiHit"] == ahit2[
"digiHit"]:
1116 if ahit3[
"digiHit"]
in used_hits:
1119 if abs(ahit3[
"zx_projection"]) > max_x:
1122 layer3 = ahit3[
"detID"] // 10000
1123 if layer3
in atrack_stereo_layers:
1127 ahit3[
"z"], ahit3[
"zx_projection"], k_seed, b_seed, window_width=15.0 * r_scale
1130 atrack_stereo[
"hits_stereo"].append(ahit3)
1131 atrack_stereo_layers.append(layer3)
1133 if len(atrack_stereo[
"hits_stereo"]) >= min_hits:
1134 long_recognized_tracks_stereo.append(atrack_stereo)
1140 for atrack_stereo
in long_recognized_tracks_stereo:
1141 if len(atrack_stereo[
"hits_stereo"]) > max_n_hits:
1142 max_track = atrack_stereo
1143 max_n_hits = len(atrack_stereo[
"hits_stereo"])
1146 atrack[
"hits_y"] = atrack_y[
"hits_y"]
1147 atrack[
"k_y"] = atrack_y[
"k_y"]
1148 atrack[
"b_y"] = atrack_y[
"b_y"]
1149 atrack[
"hits_stereo"] = []
1151 if max_track
is not None:
1152 atrack[
"hits_stereo"] = max_track[
"hits_stereo"]
1153 n_y_tracks_with_stereo += 1
1154 for ahit
in max_track[
"hits_stereo"]:
1155 used_hits.append(ahit[
"digiHit"])
1157 recognized_tracks_stereo.append(atrack)
1160 "pat_rec_stereo: %d stereo hits, %d y-tracks, %d matched with stereo",
1161 len(SmearedHits_stereo),
1162 len(recognized_tracks_y),
1163 n_y_tracks_with_stereo,
1166 return recognized_tracks_stereo
def artificial_retina_pat_rec_y_view(SmearedHits, int min_hits)
def retina_grad(track_prams, x, y, sigma, sample_weight=None)
def execute(smeared_hits, ship_geo, str method="")
def hits_split(smeared_hits)
The End of the PatRec Methods.
def template_matching_pattern_recognition(SmearedHits, ShipGeo)
Template Matching.
def tracks_combination_using_extrapolation(recognized_tracks_12, recognized_tracks_34, z_magnet)
def retina_func(track_prams, x, y, sigma, sample_weight=None)
def get_zy_projection(z, xtop, ytop, xbot, ybot, k_y, b_y)
def fast_hough_pat_rec_stereo_views(SmearedHits_stereo, recognized_tracks_y, int min_hits)
def pat_rec_view(SmearedHits, int min_hits)
def get_best_seed(x, y, float sigma, sample_weight=None)
def fast_hough_transform_pattern_recognition(SmearedHits, ShipGeo)
Fast Hough Transform.
def pat_rec_stereo_views(SmearedHits_stereo, recognized_tracks_y, int min_hits)
def _prepare_output(recognized_tracks_combo, min_hits)
def fast_hough_pat_rec_y_view(SmearedHits, int min_hits)
def reduce_clones_using_one_track_per_hit(recognized_tracks, int min_hits=3)
def hit_in_bin(x, y, k_bin, b_bin, k_size, b_size)
bool hit_in_window(x, y, k_bin, b_bin, window_width=1.0)
def artificial_retina_pattern_recognition(SmearedHits, ShipGeo)
def artificial_retina_pat_rec_stereo_views(SmearedHits_stereo, recognized_tracks_y, int min_hits)