Пример #1
0
    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()
Пример #2
0
        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
Пример #3
0
    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()