def run(self): """ Run method of the module. Calculates the minimum, maximum, sum, mean, median, and standard deviation of the pixel values of each image separately. NaNs are ignored for each calculation. The values are calculated for either the full images or a circular subsection of the images. Returns ------- NoneType None """ self.m_stat_out_port.del_all_data() self.m_stat_out_port.del_all_attributes() memory = self._m_config_port.get_attribute("MEMORY") pixscale = self.m_image_in_port.get_attribute("PIXSCALE") if self.m_position is not None: self.m_position = ( int(self.m_position[1]), # y position int(self.m_position[0]), # x position self.m_position[2] / pixscale) # radius (pix) nimages = self.m_image_in_port.get_shape()[0] im_shape = self.m_image_in_port.get_shape()[1:] frames = memory_frames(memory, nimages) for i, _ in enumerate(frames[:-1]): progress(i, len(frames[:-1]), "Running ImageStatisticsModule...") images = self.m_image_in_port[frames[i]:frames[i + 1], ] images = np.reshape(images, (images.shape[0], im_shape[0] * im_shape[1])) if self.m_position is not None: rr_grid = pixel_distance(im_shape, self.m_position) indices = np.where(rr_grid <= self.m_position[2])[0] images = images[:, indices] nmin = np.nanmin(images, axis=1) nmax = np.nanmax(images, axis=1) nsum = np.nansum(images, axis=1) mean = np.nanmean(images, axis=1) median = np.nanmedian(images, axis=1) std = np.nanstd(images, axis=1) result = np.column_stack((nmin, nmax, nsum, mean, median, std)) self.m_stat_out_port.append(result) sys.stdout.write("Running ImageStatisticsModule... [DONE]\n") sys.stdout.flush() history = "number of images = " + str(nimages) self.m_stat_out_port.copy_attributes(self.m_image_in_port) self.m_stat_out_port.add_history("ImageStatisticsModule", history) self.m_stat_out_port.close_port()
def run(self) -> None: """ Run method of the module. Applies a frame selection on the derotated residuals from the PSF subtraction. The pixels within an annulus (e.g. at the separation of an expected planet) are selected and the standard deviation is calculated. The chosen percentage of images with the lowest standard deviation are stored as output. Returns ------- NoneType None """ pixscale = self.m_image_in_port.get_attribute('PIXSCALE') nimages = self.m_image_in_port.get_shape()[0] npix = self.m_image_in_port.get_shape()[-1] rr_grid, _, _ = pixel_distance((npix, npix), position=None) pixel_select = np.where((rr_grid > self.m_annulus_radii[0] / pixscale) & (rr_grid < self.m_annulus_radii[1] / pixscale)) start_time = time.time() phot_annulus = np.zeros(nimages) for i in range(nimages): progress(i, nimages, 'Aperture photometry...', start_time) phot_annulus[i] = np.sum( np.abs(self.m_image_in_port[i][pixel_select])) print( f'Minimum, maximum = {np.amin(phot_annulus):.2f}, {np.amax(phot_annulus):.2f}' ) print( f'Mean, median = {np.nanmean(phot_annulus):.2f}, {np.nanmedian(phot_annulus):.2f}' ) print(f'Standard deviation = {np.nanstd(phot_annulus):.2f}') n_select = int(nimages * self.m_percentage / 100.) index_del = np.argsort(phot_annulus)[n_select:] write_selected_data(memory=self._m_config_port.get_attribute('MEMORY'), indices=index_del, image_in_port=self.m_image_in_port, selected_out_port=self.m_selected_out_port, removed_out_port=self.m_removed_out_port) write_selected_attributes(indices=index_del, image_in_port=self.m_image_in_port, selected_out_port=self.m_selected_out_port, removed_out_port=self.m_removed_out_port, module_type='ResidualSelectionModule', history=f'frames removed = {index_del.size}') self.m_image_in_port.close_port()
def run(self) -> None: """ Run method of the module. Calculates the minimum, maximum, sum, mean, median, and standard deviation of the pixel values of each image separately. NaNs are ignored for each calculation. The values are calculated for either the full images or a circular subsection of the images. Returns ------- NoneType None """ pixscale = self.m_image_in_port.get_attribute('PIXSCALE') nimages = self.m_image_in_port.get_shape()[0] im_shape = self.m_image_in_port.get_shape()[1:] if self.m_position is None: indices = None else: if self.m_position[0] is None and self.m_position[1] is None: center = center_pixel(self.m_image_in_port[0, ]) self.m_position = ( center[0], # y position center[1], # x position self.m_position[2] / pixscale) # radius (pix) else: self.m_position = ( int(self.m_position[1]), # y position int(self.m_position[0]), # x position self.m_position[2] / pixscale) # radius (pix) rr_grid, _, _ = pixel_distance(im_shape, position=self.m_position[0:2]) rr_reshape = np.reshape(rr_grid, (rr_grid.shape[0] * rr_grid.shape[1])) indices = np.where(rr_reshape <= self.m_position[2])[0] self.apply_function_to_images(image_stat, self.m_image_in_port, self.m_stat_out_port, 'Calculating image statistics', func_args=(indices, )) history = f'number of images = {nimages}' self.m_stat_out_port.copy_attributes(self.m_image_in_port) self.m_stat_out_port.add_history('ImageStatisticsModule', history) self.m_stat_out_port.close_port()
def merit_function(residuals: np.ndarray, merit: str, aperture: Tuple[int, int, float], sigma: float, var_noise: Optional[float]) -> float: """ Function to calculate the figure of merit at a given position in the image residuals. Parameters ---------- residuals : numpy.ndarray Residuals of the PSF subtraction (2D). merit : str Figure of merit for the chi-square function ('hessian', 'poisson', or 'gaussian'). aperture : tuple(int, int, float) Position (y, x) of the aperture center (pix) and aperture radius (pix). sigma : float Standard deviation (pix) of the Gaussian kernel which is used to smooth the residuals before the chi-square is calculated. var_noise : float, None Variance of the noise which is required when `merit` is set to 'gaussian' or 'hessian'. Returns ------- float Chi-square value. """ rr_grid = pixel_distance(im_shape=residuals.shape, position=(aperture[0], aperture[1])) indices = np.where(rr_grid <= aperture[2]) if merit == 'hessian': hessian_rr, hessian_rc, hessian_cc = hessian_matrix(image=residuals, sigma=sigma, mode='constant', cval=0., order='rc') hes_det = (hessian_rr * hessian_cc) - (hessian_rc * hessian_rc) chi_square = np.sum(hes_det[indices]**2) / var_noise elif merit == 'poisson': if sigma > 0.: residuals = gaussian_filter(input=residuals, sigma=sigma) chi_square = np.sum(np.abs(residuals[indices])) elif merit == 'gaussian': chi_square = np.sum(residuals[indices]**2) / var_noise else: raise ValueError( 'Figure of merit not recognized. Please use \'hessian\', \'poisson\' ' 'or \'gaussian\'. Previous use of \'sum\' should now be set as ' '\'poisson\'.') return chi_square
def merit_function(residuals: np.ndarray, merit: str, aperture: Tuple[int, int, float], sigma: float) -> float: """ Function to calculate the figure of merit at a given position in the image residuals. Parameters ---------- residuals : numpy.ndarray Residuals of the PSF subtraction (2D). merit : str Figure of merit for the chi-square function ('hessian', 'poisson', or 'gaussian'). aperture : tuple(int, int, float) Position (y, x) of the aperture center (pix) and aperture radius (pix). sigma : float Standard deviation (pix) of the Gaussian kernel which is used to smooth the residuals before the chi-square is calculated. Returns ------- float Chi-square ('poisson' and 'gaussian') or sum of the absolute values ('hessian'). """ rr_grid = pixel_distance(im_shape=residuals.shape, position=(aperture[0], aperture[1])) indices = np.where(rr_grid < aperture[2]) if merit == 'hessian': # This is not the chi-square but simply the sum of the absolute values hessian_rr, hessian_rc, hessian_cc = hessian_matrix(image=residuals, sigma=sigma, mode='constant', cval=0., order='rc') hes_det = (hessian_rr * hessian_cc) - (hessian_rc * hessian_rc) chi_square = np.sum(np.abs(hes_det[indices])) elif merit == 'poisson': if sigma > 0.: residuals = gaussian_filter(input=residuals, sigma=sigma) chi_square = np.sum(np.abs(residuals[indices])) elif merit == 'gaussian': # separation (pix) and position angle (deg) sep_ang = cartesian_to_polar(center=center_subpixel(residuals), y_pos=aperture[0], x_pos=aperture[1]) if sigma > 0.: residuals = gaussian_filter(input=residuals, sigma=sigma) selected = select_annulus(image_in=residuals, radius_in=sep_ang[0] - aperture[2], radius_out=sep_ang[0] + aperture[2], mask_position=aperture[0:2], mask_radius=aperture[2]) chi_square = np.sum(residuals[indices]**2) / np.var(selected) else: raise ValueError( 'Figure of merit not recognized. Please use \'hessian\', \'poisson\' ' 'or \'gaussian\'. Previous use of \'sum\' should now be set as ' '\'poisson\'.') return chi_square
def run(self) -> None: """ Run method of the module. Uses a non-linear least squares (Levenberg-Marquardt) method to fit the the individual images or the mean of all images with a 2D Gaussian or Moffat function. The best-fit results and errors are stored and contain zeros in case the algorithm could not converge. The ``fit_out_tag`` can be used as argument of ``shift_xy`` when running the :class:`~pynpoint.processing.centering.ShiftImagesModule`. Returns ------- NoneType None """ memory = self._m_config_port.get_attribute('MEMORY') cpu = self._m_config_port.get_attribute('CPU') pixscale = self.m_image_in_port.get_attribute('PIXSCALE') if cpu > 1 and self.m_mask_out_port is not None: warnings.warn('The mask_out_port can only be used if CPU=1. No data will be ' 'stored to this output port.') del self._m_output_ports[self.m_mask_out_port.tag] self.m_mask_out_port = None if self.m_mask_radii[0] is None: # Convert from arcsec to pixels and change None to 0 self.m_mask_radii = (0., self.m_mask_radii[1]/pixscale) else: # Convert from arcsec to pixels self.m_mask_radii = (self.m_mask_radii[0]/pixscale, self.m_mask_radii[1]/pixscale) if self.m_filter_size: # Convert from arcsec to pixels self.m_filter_size /= pixscale _, xx_grid, yy_grid = pixel_distance(self.m_image_in_port.get_shape()[-2:], position=None) rr_ap = subpixel_distance(self.m_image_in_port.get_shape()[-2:], position=(self.m_guess[1], self.m_guess[0]), shift_center=False) # (y, x) nimages = self.m_image_in_port.get_shape()[0] frames = memory_frames(memory, nimages) if self.m_method == 'full': self.apply_function_to_images(fit_2d_function, self.m_image_in_port, self.m_fit_out_port, 'Fitting the stellar PSF', func_args=(self.m_mask_radii, self.m_sign, self.m_model, self.m_filter_size, self.m_guess, self.m_mask_out_port, xx_grid, yy_grid, rr_ap, pixscale)) elif self.m_method == 'mean': print('Fitting the stellar PSF...', end='') im_mean = np.zeros(self.m_image_in_port.get_shape()[1:3]) for i, _ in enumerate(frames[:-1]): im_mean += np.sum(self.m_image_in_port[frames[i]:frames[i+1], ], axis=0) best_fit = fit_2d_function(im_mean/float(nimages), 0, self.m_mask_radii, self.m_sign, self.m_model, self.m_filter_size, self.m_guess, self.m_mask_out_port, xx_grid, yy_grid, rr_ap, pixscale) best_fit = best_fit[np.newaxis, ...] best_fit = np.repeat(best_fit, nimages, axis=0) self.m_fit_out_port.set_all(best_fit, data_dim=2) print(' [DONE]') history = f'model = {self.m_model}' self.m_fit_out_port.copy_attributes(self.m_image_in_port) self.m_fit_out_port.add_history('FitCenterModule', history) if self.m_mask_out_port: self.m_mask_out_port.copy_attributes(self.m_image_in_port) self.m_mask_out_port.add_history('FitCenterModule', history) self.m_fit_out_port.close_port()
def run(self) -> None: """ Run method of the module. Calculates the minimum, maximum, sum, mean, median, and standard deviation of the pixel values of each image separately. NaNs are ignored for each calculation. The values are calculated for either the full images or a circular subsection of the images. Returns ------- NoneType None """ pixscale = self.m_image_in_port.get_attribute('PIXSCALE') nimages = self.m_image_in_port.get_shape()[0] im_shape = self.m_image_in_port.get_shape()[1:] if self.m_position is None: indices = None else: if self.m_position[0] is None and self.m_position[1] is None: center = center_pixel(self.m_image_in_port[0, ]) self.m_position = (center[0], # y position center[1], # x position self.m_position[2]/pixscale) # radius (pix) else: self.m_position = (int(self.m_position[1]), # y position int(self.m_position[0]), # x position self.m_position[2]/pixscale) # radius (pix) rr_grid = pixel_distance(im_shape, self.m_position[0:2]) rr_reshape = np.reshape(rr_grid, (rr_grid.shape[0]*rr_grid.shape[1])) indices = np.where(rr_reshape <= self.m_position[2])[0] @typechecked def _image_stat(image_in: np.ndarray, indices: Optional[np.ndarray]) -> np.ndarray: if indices is None: image_select = np.copy(image_in) else: image_reshape = np.reshape(image_in, (image_in.shape[0]*image_in.shape[1])) image_select = image_reshape[indices] nmin = np.nanmin(image_select) nmax = np.nanmax(image_select) nsum = np.nansum(image_select) mean = np.nanmean(image_select) median = np.nanmedian(image_select) std = np.nanstd(image_select) return np.asarray([nmin, nmax, nsum, mean, median, std]) self.apply_function_to_images(_image_stat, self.m_image_in_port, self.m_stat_out_port, 'Calculating image statistics', func_args=(indices, )) history = f'number of images = {nimages}' self.m_stat_out_port.copy_attributes(self.m_image_in_port) self.m_stat_out_port.add_history('ImageStatisticsModule', history) self.m_stat_out_port.close_port()