def run(self) -> None: """ Run method of the module. Locates the position of a binary star (or some other point source) which rotates across the stack of images due to parallactic rotation. The approximate position of the binary star is calculated by taking into account the parallactic angle of each image separately. The brightest pixel is then selected as center around which the image is cropped. Returns ------- NoneType None """ pixscale = self.m_image_in_port.get_attribute('PIXSCALE') parang = self.m_image_in_port.get_attribute('PARANG') positions = np.zeros((parang.shape[0], 2), dtype=np.int) for i, item in enumerate(parang): # rotates in counterclockwise direction, hence the minus sign in angle positions[i, :] = rotate_coordinates(center=self.m_pos_center, position=self.m_pos_binary, angle=item - parang[0]) self.m_image_size = int(math.ceil(self.m_image_size / pixscale)) self.m_search_size = int(math.ceil(self.m_search_size / pixscale)) if self.m_filter_size is not None: self.m_filter_size = int(math.ceil(self.m_filter_size / pixscale)) def _crop_rotating_star(image, position, im_size, filter_size): starpos = locate_star(image=image, center=position, width=self.m_search_size, fwhm=filter_size) return crop_image(image=image, center=starpos, size=im_size) self.apply_function_to_images(_crop_rotating_star, self.m_image_in_port, self.m_image_out_port, 'Running ExtractBinaryModule', func_args=(positions, self.m_image_size, self.m_filter_size)) history = f'filter [pix] = {self.m_filter_size}' self.m_image_out_port.copy_attributes(self.m_image_in_port) self.m_image_out_port.add_history('ExtractBinaryModule', history) self.m_image_out_port.close_port()
def _objective(arg): sys.stdout.write('.') sys.stdout.flush() pos_y = arg[0] pos_x = arg[1] mag = arg[2] sep = math.sqrt((pos_y - center[0])**2 + (pos_x - center[1])**2) ang = math.atan2(pos_y - center[0], pos_x - center[1]) * 180. / math.pi - 90. fake = fake_planet(images=images, psf=psf, parang=parang, position=(sep, ang), magnitude=mag, psf_scaling=self.m_psf_scaling) im_shape = (fake.shape[-2], fake.shape[-1]) mask = create_mask(im_shape, [self.m_cent_size, self.m_edge_size]) _, im_res = pca_psf_subtraction(images=fake * mask, angles=-1. * parang + self.m_extra_rot, pca_number=self.m_pca_number) stack = combine_residuals(method=self.m_residuals, res_rot=im_res) self.m_res_out_port.append(stack, data_dim=3) merit = merit_function(residuals=stack, function=self.m_merit, variance="poisson", aperture=self.m_aperture, sigma=self.m_sigma) position = rotate_coordinates(center, (pos_y, pos_x), -self.m_extra_rot) res = np.asarray((position[1], position[0], sep * pixscale, (ang - self.m_extra_rot) % 360., mag, merit)) self.m_flux_position_port.append(res, data_dim=2) return merit
def run(self): """ Run method of the module. The position and flux of a planet are measured by injecting negative fake companions and applying a simplex method (Nelder-Mead) for minimization of a function of merit at the planet location. The default function of merit is the image curvature which is calculated as the sum of the absolute values of the determinant of the Hessian matrix. :return: None """ self.m_res_out_port.del_all_data() self.m_res_out_port.del_all_attributes() self.m_flux_position_port.del_all_data() self.m_flux_position_port.del_all_attributes() parang = self.m_image_in_port.get_attribute("PARANG") pixscale = self.m_image_in_port.get_attribute("PIXSCALE") if isinstance(self.m_aperture, float): self.m_aperture = { 'type': 'circular', 'pos_x': self.m_position[0], 'pos_y': self.m_position[1], 'radius': self.m_aperture / pixscale } elif isinstance(self.m_aperture, dict): if self.m_aperture['type'] == 'circular': self.m_aperture['radius'] /= pixscale elif self.m_aperture['type'] == 'elliptical': self.m_aperture['semimajor'] /= pixscale self.m_aperture['semiminor'] /= pixscale self.m_sigma /= pixscale if self.m_cent_size is not None: self.m_cent_size /= pixscale if self.m_edge_size is not None: self.m_edge_size /= pixscale psf = self.m_psf_in_port.get_all() center = (psf.shape[-2] / 2., psf.shape[-1] / 2.) images = self.m_image_in_port.get_all() if psf.ndim == 3 and psf.shape[0] != images.shape[0]: raise ValueError( 'The number of frames in psf_in_tag does not match with the number ' 'of frames in image_in_tag. The DerotateAndStackModule can be ' 'used to average the PSF frames (without derotating) before applying ' 'the SimplexMinimizationModule.') def _objective(arg): sys.stdout.write('.') sys.stdout.flush() pos_y = arg[0] pos_x = arg[1] mag = arg[2] sep = math.sqrt((pos_y - center[0])**2 + (pos_x - center[1])**2) ang = math.atan2(pos_y - center[0], pos_x - center[1]) * 180. / math.pi - 90. fake = fake_planet(images=images, psf=psf, parang=parang, position=(sep, ang), magnitude=mag, psf_scaling=self.m_psf_scaling) im_shape = (fake.shape[-2], fake.shape[-1]) mask = create_mask(im_shape, [self.m_cent_size, self.m_edge_size]) _, im_res = pca_psf_subtraction(images=fake * mask, angles=-1. * parang + self.m_extra_rot, pca_number=self.m_pca_number) stack = combine_residuals(method=self.m_residuals, res_rot=im_res) self.m_res_out_port.append(stack, data_dim=3) merit = merit_function(residuals=stack, function=self.m_merit, variance="poisson", aperture=self.m_aperture, sigma=self.m_sigma) position = rotate_coordinates(center, (pos_y, pos_x), -self.m_extra_rot) res = np.asarray((position[1], position[0], sep * pixscale, (ang - self.m_extra_rot) % 360., mag, merit)) self.m_flux_position_port.append(res, data_dim=2) return merit sys.stdout.write("Running SimplexMinimizationModule") sys.stdout.flush() pos_init = rotate_coordinates(center, (self.m_position[1], self.m_position[0]), self.m_extra_rot) # Change integer to float? pos_init = (int(pos_init[0]), int(pos_init[1])) # (y, x) minimize(fun=_objective, x0=[pos_init[0], pos_init[1], self.m_magnitude], method="Nelder-Mead", tol=None, options={ 'xatol': self.m_tolerance, 'fatol': float("inf") }) sys.stdout.write(" [DONE]\n") sys.stdout.flush() self.m_res_out_port.add_history_information( "SimplexMinimizationModule", "Merit function = " + str(self.m_merit)) self.m_flux_position_port.add_history_information( "SimplexMinimizationModule", "Merit function = " + str(self.m_merit)) self.m_res_out_port.copy_attributes_from_input_port( self.m_image_in_port) self.m_flux_position_port.copy_attributes_from_input_port( self.m_image_in_port) self.m_res_out_port.close_port()