def _rectangular_pixel_row_column(pix_x, pix_y): """ Get the row and column of rectangular pixels of a camera that are arranged in a grid The cameras in CTA with rectangular pixels have a curved focal plane surface. Pixels on a curved focal surface do not have consistent x and y coordinates along a single row or column. Therefore, a somewhat reliable technique to obtain the row and column is to define bin edges which the pixels are presumed to be within. This function first finds a row and column of the camera which contains a full set of pixels. The coordinates of these pixels are then used to define the bin edges for the entire camera. Parameters ---------- pix_x : ndarray X coordinates of camera pixels pix_y : ndarray Y coordinates of camera pixels Returns ------- row : ndarray Row for each camera pixel column : ndarray Column for each camera pixel """ # Estimate the maximum number of rows and columns of pixels dist = _get_min_pixel_seperation(pix_x, pix_y) max_nrow = int(np.ceil((pix_y.max() - pix_y.min()) / dist)) + 1 max_ncol = int(np.ceil((pix_x.max() - pix_x.min()) / dist)) + 1 # Bin the pixel positions on a 2D grid hist_x = np.histogram2d(pix_x, pix_y, weights=pix_x, bins=[max_ncol, max_nrow])[0] hist_y = np.histogram2d(pix_x, pix_y, weights=pix_y, bins=[max_ncol, max_nrow])[0] hist_xc = np.histogram2d(pix_x, pix_y, bins=[max_ncol, max_nrow])[0] hist_yc = np.histogram2d(pix_x, pix_y, bins=[max_ncol, max_nrow])[0] # Find row and col with a complete number of pixels along them full_col = np.bincount(hist_x.nonzero()[0]).argmax() full_row = np.bincount(hist_y.nonzero()[0]).argmax() # Obtain coordinates of the pixels along this row and column full_x = hist_x[:, full_col][hist_xc[:, full_col].nonzero()] full_y = hist_y[full_row, :][hist_yc[full_row, :].nonzero()] # Define pixel bin edges based on full row and column of pixels mid_dist = _get_min_pixel_seperation(full_x, full_y) / 2 edges_x = np.array([*(full_x - mid_dist), full_x[-1] + mid_dist]) edges_y = np.array([*(full_y - mid_dist), full_y[-1] + mid_dist]) # Obtain the corresponding row and column bin for each pixel column = np.digitize(pix_x, edges_x) - 1 row = np.digitize(pix_y, edges_y) - 1 return row, column
def get_pixel_2d(x_pix, y_pix, values=None): n_pix = x_pix.size if values is None: # By default, fill with pixel id values = np.arange(n_pix) gx = np.histogram2d(x_pix, y_pix, weights=x_pix, bins=[53, 53])[0] gy = np.histogram2d(x_pix, y_pix, weights=y_pix, bins=[53, 53])[0] i = np.bincount(gx.nonzero()[0]).argmax() j = np.bincount(gy.nonzero()[0]).argmax() xc = gx[:, i][gx[:, i].nonzero()] yc = gy[j, :][gy[j, :].nonzero()] dist = _get_min_pixel_seperation(xc, yc) edges_x = np.zeros(xc.size + 1) edges_x[0:xc.size] = xc - dist / 2 edges_x[-1] = xc[-1] + dist / 2 edges_y = np.zeros(yc.size + 1) edges_y[0:yc.size] = yc - dist / 2 edges_y[-1] = yc[-1] + dist / 2 camera = np.histogram2d(-y_pix, x_pix, bins=[-edges_y[::-1], edges_x], weights=values + 1)[0] camera[camera == 0] = np.nan camera -= 1 return camera
def fit(self, x, y, data): minsep = _get_min_pixel_seperation(x, y) p0 = (data.max(), x.mean(), y.mean(), minsep, np.median(data)) bounds = ([0, x.min(), y.min(), 0, -np.inf], [np.inf, x.max(), y.max(), np.inf, np.inf]) popt, pcov = optimize.curve_fit(self._fit_function, (x, y), data, p0=p0, bounds=bounds) coeff = popt return coeff
def test_get_min_pixel_seperation(): x, y = np.meshgrid(np.linspace(-5, 5, 5), np.linspace(-5, 5, 5)) pixsep = _get_min_pixel_seperation(x.ravel(), y.ravel()) assert pixsep == 2.5
def create(self, coords, data, coeff, fitter, axis): di = coords.get_gridded_data(data) df = fitter.get_curve(coords.xi_mg, coords.yi_mg, coeff) di_1d = di.max(axis=axis) df_1d = df.max(axis=axis) if axis == 0: x_pixels = coords.pix_x_u x_plot = coords.xi axis_txt = 'X' else: x_pixels = coords.pix_y_u x_plot = coords.yi axis_txt = 'Y' minsep = _get_min_pixel_seperation(coords.pix_x, coords.pix_y) hx = [] hy =[] for x, y in zip(x_pixels, di_1d): hx.extend([x - minsep/2, x - minsep/2, x + minsep/2, x + minsep/2]) hy.extend([0, y, y, 0]) self.ax.plot(hx, hy, color='grey', linewidth=0.7, antialiased=False) self.ax.axhline(0, color='grey', linewidth=0.7, antialiased=False) self.ax.plot(x_plot, df_1d, color='blue', linewidth=0.7, antialiased=False) self.fig.suptitle("Fit Comparison, {} Projection".format(axis_txt)) # self.ax.axis('off') self.ax.set_xlabel("{} (degrees)".format(axis_txt)) self.ax.set_ylabel("Residual RMS (p.e.)") amplitude, x0, y0, sigma, offset = coeff radius = fitter.find_containment_radius(coords, coeff, 0.8) if axis == 0: x0 = x0 else: x0 = y0 xl = x0 - radius xr = x0 + radius self.ax.axvline(xl, color='green') self.ax.axvline(xr, color='green') self.ax.text(0.99, 0.99, "80% Volume Containment", color='green', transform=self.ax.transAxes, ha='right', va='top') # xl = x0 - sigma # xr = x0 + sigma # self.ax.axvline(xl, color='red') # self.ax.axvline(xr, color='red') # # sep = np.diff(coords.pix_x_u).min()/2 # xl = x0 - sep # xr = x0 + sep # self.ax.axvline(xl, color='blue') # self.ax.axvline(xr, color='blue') minor_locator = AutoMinorLocator(10) self.ax.xaxis.set_minor_locator(minor_locator) # self.ax.yaxis.set_minor_locator(minor_locator) self.ax.axes.set_xlim(-0.8, 0.8)
def test_get_min_pixel_seperation(): x, y = np.meshgrid(np.linspace(-5, 5, 5), np.linspace(-5, 5, 5)) pixsep = _get_min_pixel_seperation(x.ravel(), y.ravel()) assert(pixsep == 2.5)