SND@LHC Software
Loading...
Searching...
No Matches
SndlhcMuonReco.hough Class Reference

Public Member Functions

 __init__ (self, n_yH, yH_range, n_xH, xH_range, z_offset, Hformat, space_scale, det_Zlen, squaretheta=False, smooth=True)
 
 fit (self, hit_collection, is_scaled, draw, weights=None)
 
 fit_randomize (self, hit_collection, hit_d, n_random, is_scaled, draw, weights=None)
 

Public Attributes

 n_yH
 
 n_xH
 
 yH_range
 
 xH_range
 
 z_offset
 
 HoughSpace_format
 
 space_scale
 
 det_Zlen
 
 smooth
 
 yH_bins
 
 xH_bins
 
 cos_thetas
 
 sin_thetas
 
 xH_i
 
 n_yH_scaled
 
 n_xH_scaled
 
 yH_bins_scaled
 
 xH_bins_scaled
 
 cos_thetas_scaled
 
 sin_thetas_scaled
 
 xH_i_scaled
 
 accumulator
 

Detailed Description

 Hough transform implementation 

Definition at line 25 of file SndlhcMuonReco.py.

Constructor & Destructor Documentation

◆ __init__()

SndlhcMuonReco.hough.__init__ (   self,
  n_yH,
  yH_range,
  n_xH,
  xH_range,
  z_offset,
  Hformat,
  space_scale,
  det_Zlen,
  squaretheta = False,
  smooth = True 
)

Definition at line 28 of file SndlhcMuonReco.py.

28 def __init__(self, n_yH, yH_range, n_xH, xH_range, z_offset, Hformat, space_scale, det_Zlen, squaretheta = False, smooth = True) :
29
30 self.n_yH = n_yH
31 self.n_xH = n_xH
32
33 self.yH_range = yH_range
34 self.xH_range = xH_range
35
36 self.z_offset = z_offset
37 self.HoughSpace_format = Hformat
38 self.space_scale = space_scale
39
40 self.det_Zlen = det_Zlen
41
42 self.smooth = smooth
43
44 self.yH_bins = np.linspace(self.yH_range[0], self.yH_range[1], n_yH)
45 if not squaretheta :
46 self.xH_bins = np.linspace(self.xH_range[0], self.xH_range[1], n_xH)
47 else :
48 self.xH_bins = np.linspace(np.sign(self.xH_range[0])*(self.xH_range[0]**0.5), np.sign(self.xH_range[1])*(self.xH_range[1]**0.5), n_xH)
49 self.xH_bins = np.sign(self.xH_bins)*np.square(self.xH_bins)
50
51 self.cos_thetas = np.cos(self.xH_bins)
52 self.sin_thetas = np.sin(self.xH_bins)
53
54 self.xH_i = np.array(list(range(n_xH)))
55
56 # A back-up Hough space designed to have more/less bins wrt the default one above.
57 # It is useful when fitting some low-E muon tracks, which are curved due to mult. scattering.
58 self.n_yH_scaled = int(n_yH*space_scale)
59 self.n_xH_scaled = int(n_xH*space_scale)
60 self.yH_bins_scaled = np.linspace(self.yH_range[0], self.yH_range[1], self.n_yH_scaled)
61 if not squaretheta :
62 self.xH_bins_scaled= np.linspace(self.xH_range[0], self.xH_range[1], self.n_xH_scaled)
63 else :
64 self.xH_bins_scaled = np.linspace(np.sign(self.xH_range[0])*(self.xH_range[0]**0.5), np.sign(self.xH_range[1])*(self.xH_range[1]**0.5), self.n_xH_scaled)
65 self.xH_bins_scaled = np.sign(self.xH_bins_scaled)*np.square(self.xH_bins_scaled)
66
67 self.cos_thetas_scaled = np.cos(self.xH_bins_scaled)
68 self.sin_thetas_scaled = np.sin(self.xH_bins_scaled)
69
70 self.xH_i_scaled = np.array(list(range(self.n_xH_scaled)))
71

Member Function Documentation

◆ fit()

SndlhcMuonReco.hough.fit (   self,
  hit_collection,
  is_scaled,
  draw,
  weights = None 
)

Definition at line 72 of file SndlhcMuonReco.py.

72 def fit(self, hit_collection, is_scaled, draw, weights = None) :
73
74 if not is_scaled:
75 n_xH = self.n_xH
76 n_yH = self.n_yH
77 cos_thetas = self.cos_thetas
78 sin_thetas = self.sin_thetas
79 xH_bins = self.xH_bins
80 yH_bins = self.yH_bins
81 xH_i = self.xH_i
82 res = self.res
83 else:
84 n_xH = self.n_xH_scaled
85 n_yH = self.n_yH_scaled
86 cos_thetas = self.cos_thetas_scaled
87 sin_thetas = self.sin_thetas_scaled
88 xH_bins = self.xH_bins_scaled
89 yH_bins = self.yH_bins_scaled
90 xH_i = self.xH_i_scaled
91 res = self.res*self.space_scale
92
93 self.accumulator = np.zeros((n_yH, n_xH))
94 for i_hit, hit in enumerate(hit_collection) :
95 shifted_hitZ = hit[0] - self.z_offset
96 if self.HoughSpace_format == 'normal':
97 hit_yH = shifted_hitZ*cos_thetas + hit[1]*sin_thetas
98 elif self.HoughSpace_format == 'linearSlopeIntercept':
99 hit_yH = hit[1] - shifted_hitZ*xH_bins
100 elif self.HoughSpace_format== 'linearIntercepts':
101 hit_yH = (self.det_Zlen*hit[1] - shifted_hitZ*xH_bins)/(self.det_Zlen - shifted_hitZ)
102 out_of_range = np.logical_and(hit_yH > self.yH_range[0], hit_yH < self.yH_range[1])
103 hit_yH_i = np.floor((hit_yH[out_of_range] - self.yH_range[0])/(self.yH_range[1] - self.yH_range[0])*n_yH).astype(np.int_)
104
105 if weights is not None :
106 self.accumulator[hit_yH_i, xH_i[out_of_range]] += weights[i_hit]
107 else :
108 self.accumulator[hit_yH_i, xH_i[out_of_range]] += 1
109
110 # Smooth accumulator
111 if self.smooth_full :
112 self.accumulator = scipy.ndimage.gaussian_filter(self.accumulator, self.sigma, truncate=self.truncate)
113
114 # This might be useful for debugging, but leave out for now.
115 if draw :
116 plt.figure()
117 plt.imshow(self.accumulator, origin = "lower", extent = [self.xH_range[0], self.xH_range[-1], self.yH_range[0], self.yH_range[-1]], aspect = "auto")
118 if self.HoughSpace_format == 'normal':
119 plt.xlabel(r"$\theta$ [rad]")
120 plt.ylabel("r [cm]")
121 elif self.HoughSpace_format == 'linearSlopeIntercept':
122 plt.xlabel("slope")
123 plt.ylabel("intercept @ 1st plane [cm]")
124 elif self.HoughSpace_format == 'linearIntercepts':
125 plt.xlabel("intercept @ last plane [cm]")
126 plt.ylabel("intercept @ 1st plane [cm]")
127 plt.tight_layout()
128 plt.show()
129
130 if self.smooth_full:
131 # In case of multiple occurrences of the maximum values, argmax returns
132 # the indices corresponding to the first occurrence(along 1st axis).
133 i_max = np.unravel_index(self.accumulator.argmax(), self.accumulator.shape)
134 else:
135 # In case there are more than 1 bins with the maximal Nentries, check if the n-th quantile of
136 # found peaks along 'slope' axis(yH axis) enloses <n-th quantile> portion of all maxima 'slope' bins
137 # within a specified range. It is advisable that that range is consistent with
138 # the detector angular resolution.
139 maxima = np.argwhere(self.accumulator == np.amax(self.accumulator))
140 if len(maxima) == 1:
141 i_max = maxima[0]
142 elif len(maxima)==0 or (len(maxima) > 1 and self.HoughSpace_format == 'linearIntercepts'):
143 # if no reasonable way to select btw maxima, force track-build failure
144 # to be decided what to do in 'linearIntercepts' case and multiple maxima
145 return(-999, -999)
146 elif len(maxima) > 1 and abs(min([x[1] for x in maxima]) - max([x[1] for x in maxima])) < res:
147 i_max = maxima[0]
148 else:
149 # FIXME: the next two lines can be a single line command for sure
150 maxima_slopesAxis_list = list([x[1] for x in maxima])
151 maxima_slopesAxis_list = np.asarray(maxima_slopesAxis_list)
152 quantile = np.quantile(maxima_slopesAxis_list, self.n_quantile)
153 Nwithin = 0
154 # FIXME: a more elegant 'hidden' loop is maybe possible here too
155 for item in maxima:
156 if abs(item[1]-quantile)< res:
157 Nwithin += 1
158 if Nwithin/len(maxima) > self.n_quantile:
159 i_x = min([x[1] for x in maxima], key=lambda b: abs(b-quantile))
160 for im in maxima:
161 if im[1] == i_x : i_max = im
162 else:
163 # if no reasonable way to select btw maxima, force track-build failure
164 return(-999, -999)
165
166 found_yH = yH_bins[int(i_max[0])]
167 found_xH = xH_bins[int(i_max[1])]
168
169 if self.HoughSpace_format == 'normal':
170 slope = -1./np.tan(found_xH)
171 interceptShift = found_yH/np.sin(found_xH)
172 intercept = (np.tan(found_xH)*interceptShift + self.z_offset)/np.tan(found_xH)
173 elif self.HoughSpace_format == 'linearSlopeIntercept':
174 slope = found_xH
175 intercept = found_yH - slope*self.z_offset
176 elif self.HoughSpace_format == 'linearIntercepts':
177 slope = (found_xH - found_yH)/self.det_Zlen
178 intercept = found_yH - slope*self.z_offset
179
180 return (slope, intercept)
181

◆ fit_randomize()

SndlhcMuonReco.hough.fit_randomize (   self,
  hit_collection,
  hit_d,
  n_random,
  is_scaled,
  draw,
  weights = None 
)

Definition at line 182 of file SndlhcMuonReco.py.

182 def fit_randomize(self, hit_collection, hit_d, n_random, is_scaled, draw, weights = None) :
183 success = True
184 if not len(hit_collection) :
185 return (-1, -1, [[],[]], [], False)
186
187 # Randomize hits
188 if (n_random > 0) :
189 random_hit_collection = []
190 for i_random in range(n_random) :
191 random_hits = np.random.uniform(size = hit_collection.shape) - 0.5
192 random_hits *= hit_d
193 random_hits += hit_collection
194 random_hit_collection.append(random_hits)
195
196 random_hit_collection = np.concatenate(random_hit_collection)
197 if weights is not None :
198 weights = np.tile(weights, n_random)
199
200 fit = self.fit(random_hit_collection, is_scaled, draw, weights)
201 else :
202 fit = self.fit(hit_collection, is_scaled, draw, weights)
203
204 return fit
205

Member Data Documentation

◆ accumulator

SndlhcMuonReco.hough.accumulator

Definition at line 93 of file SndlhcMuonReco.py.

◆ cos_thetas

SndlhcMuonReco.hough.cos_thetas

Definition at line 51 of file SndlhcMuonReco.py.

◆ cos_thetas_scaled

SndlhcMuonReco.hough.cos_thetas_scaled

Definition at line 67 of file SndlhcMuonReco.py.

◆ det_Zlen

SndlhcMuonReco.hough.det_Zlen

Definition at line 40 of file SndlhcMuonReco.py.

◆ HoughSpace_format

SndlhcMuonReco.hough.HoughSpace_format

Definition at line 37 of file SndlhcMuonReco.py.

◆ n_xH

SndlhcMuonReco.hough.n_xH

Definition at line 31 of file SndlhcMuonReco.py.

◆ n_xH_scaled

SndlhcMuonReco.hough.n_xH_scaled

Definition at line 59 of file SndlhcMuonReco.py.

◆ n_yH

SndlhcMuonReco.hough.n_yH

Definition at line 30 of file SndlhcMuonReco.py.

◆ n_yH_scaled

SndlhcMuonReco.hough.n_yH_scaled

Definition at line 58 of file SndlhcMuonReco.py.

◆ sin_thetas

SndlhcMuonReco.hough.sin_thetas

Definition at line 52 of file SndlhcMuonReco.py.

◆ sin_thetas_scaled

SndlhcMuonReco.hough.sin_thetas_scaled

Definition at line 68 of file SndlhcMuonReco.py.

◆ smooth

SndlhcMuonReco.hough.smooth

Definition at line 42 of file SndlhcMuonReco.py.

◆ space_scale

SndlhcMuonReco.hough.space_scale

Definition at line 38 of file SndlhcMuonReco.py.

◆ xH_bins

SndlhcMuonReco.hough.xH_bins

Definition at line 46 of file SndlhcMuonReco.py.

◆ xH_bins_scaled

SndlhcMuonReco.hough.xH_bins_scaled

Definition at line 62 of file SndlhcMuonReco.py.

◆ xH_i

SndlhcMuonReco.hough.xH_i

Definition at line 54 of file SndlhcMuonReco.py.

◆ xH_i_scaled

SndlhcMuonReco.hough.xH_i_scaled

Definition at line 70 of file SndlhcMuonReco.py.

◆ xH_range

SndlhcMuonReco.hough.xH_range

Definition at line 34 of file SndlhcMuonReco.py.

◆ yH_bins

SndlhcMuonReco.hough.yH_bins

Definition at line 44 of file SndlhcMuonReco.py.

◆ yH_bins_scaled

SndlhcMuonReco.hough.yH_bins_scaled

Definition at line 60 of file SndlhcMuonReco.py.

◆ yH_range

SndlhcMuonReco.hough.yH_range

Definition at line 33 of file SndlhcMuonReco.py.

◆ z_offset

SndlhcMuonReco.hough.z_offset

Definition at line 36 of file SndlhcMuonReco.py.


The documentation for this class was generated from the following file: