コード例 #1
0
    def run(self) -> None:
        """
        Run method of the module. Selects the pixel values in the column and row at each pixel
        position, computes the mean or median value while excluding pixels within the radius of
        the mask, and subtracts the mean or median value from each pixel separately.

        Returns
        -------
        NoneType
            None
        """

        pixscale = self.m_image_in_port.get_attribute('PIXSCALE')
        im_shape = self.m_image_in_port.get_shape()[-2:]

        def _subtract_line(image_in, mask):
            image_tmp = np.copy(image_in)
            image_tmp[mask == 0.] = np.nan

            if self.m_combine == 'mean':
                row_mean = np.nanmean(image_tmp, axis=1)
                col_mean = np.nanmean(image_tmp, axis=0)

                x_grid, y_grid = np.meshgrid(col_mean, row_mean)
                subtract = (x_grid+y_grid)/2.

            elif self.m_combine == 'median':
                subtract = np.zeros(im_shape)

                col_median = np.nanmedian(image_tmp, axis=0)
                col_2d = np.tile(col_median, (im_shape[1], 1))

                image_tmp -= col_2d
                image_tmp[mask == 0.] = np.nan

                row_median = np.nanmedian(image_tmp, axis=1)
                row_2d = np.tile(row_median, (im_shape[0], 1))
                row_2d = np.rot90(row_2d)  # 90 deg rotation in clockwise direction

                subtract = col_2d + row_2d

            return image_in - subtract

        if self.m_mask:
            size = (self.m_mask/pixscale, None)
        else:
            size = (None, None)

        mask = create_mask(im_shape, size)

        self.apply_function_to_images(_subtract_line,
                                      self.m_image_in_port,
                                      self.m_image_out_port,
                                      'Running LineSubtractionModule',
                                      func_args=(mask, ))

        history = f'combine = {self.m_combine}'
        self.m_image_out_port.copy_attributes(self.m_image_in_port)
        self.m_image_out_port.add_history('LineSubtractionModule', history)
        self.m_image_out_port.close_port()
コード例 #2
0
ファイル: background.py プロジェクト: tomasstolker/PynPoint
    def run(self) -> None:
        """
        Run method of the module. Selects the pixel values in the column and row at each pixel
        position, computes the mean or median value while excluding pixels within the radius of
        the mask, and subtracts the mean or median value from each pixel separately.

        Returns
        -------
        NoneType
            None
        """

        pixscale = self.m_image_in_port.get_attribute('PIXSCALE')
        im_shape = self.m_image_in_port.get_shape()[-2:]

        if self.m_mask:
            size = (self.m_mask/pixscale, None)
        else:
            size = (None, None)

        mask = create_mask(im_shape, size)

        self.apply_function_to_images(subtract_line,
                                      self.m_image_in_port,
                                      self.m_image_out_port,
                                      'Background subtraction',
                                      func_args=(mask,
                                                 self.m_combine,
                                                 im_shape))

        history = f'combine = {self.m_combine}'
        self.m_image_out_port.copy_attributes(self.m_image_in_port)
        self.m_image_out_port.add_history('LineSubtractionModule', history)
        self.m_image_out_port.close_port()
コード例 #3
0
        def _objective(arg):
            sys.stdout.write('.')
            sys.stdout.flush()

            pos_y = arg[0]
            pos_x = arg[1]
            mag = arg[2]

            sep_ang = cartesian_to_polar(center, pos_y, pos_x)

            fake = fake_planet(images=images,
                               psf=psf,
                               parang=parang,
                               position=(sep_ang[0], sep_ang[1]),
                               magnitude=mag,
                               psf_scaling=self.m_psf_scaling)

            mask = create_mask(fake.shape[-2:], (self.m_cent_size, self.m_edge_size))

            if self.m_reference_in_port is None:
                _, im_res = pca_psf_subtraction(images=fake*mask,
                                                angles=-1.*parang+self.m_extra_rot,
                                                pca_number=self.m_pca_number,
                                                pca_sklearn=None,
                                                im_shape=None,
                                                indices=None)

            else:
                im_reshape = np.reshape(fake*mask, (im_shape[0], im_shape[1]*im_shape[2]))

                _, im_res = pca_psf_subtraction(images=im_reshape,
                                                angles=-1.*parang+self.m_extra_rot,
                                                pca_number=self.m_pca_number,
                                                pca_sklearn=sklearn_pca,
                                                im_shape=im_shape,
                                                indices=None)

            res_stack = combine_residuals(method=self.m_residuals, res_rot=im_res)

            self.m_res_out_port.append(res_stack, data_dim=3)

            chi_square = merit_function(residuals=res_stack[0, ],
                                        merit=self.m_merit,
                                        aperture=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_ang[0]*pixscale,
                              (sep_ang[1]-self.m_extra_rot) % 360.,
                              mag,
                              chi_square])

            self.m_flux_position_port.append(res, data_dim=2)

            return chi_square
コード例 #4
0
ファイル: fluxposition.py プロジェクト: 18alex96/PynPoint
        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
コード例 #5
0
    def run(self) -> None:
        """
        Run method of the module. Computes the similarity between frames based on the Mean Squared
        Error (MSE), the Pearson Correlation Coefficient (PCC), or the Structural Similarity (SSIM).

        Returns
        -------
        NoneType
            None
        """

        # get image number and image shapes
        nimages = self.m_image_in_port.get_shape()[0]
        im_shape = self.m_image_in_port.get_shape()[1:]

        cpu = self._m_config_port.get_attribute('CPU')
        pixscale = self.m_image_in_port.get_attribute('PIXSCALE')

        # convert arcsecs to pixels
        self.m_mask_radii = (math.floor(self.m_mask_radii[0] / pixscale),
                             math.floor(self.m_mask_radii[1] / pixscale))
        self.m_window_size = int(self.m_window_size / pixscale)

        # overlay the same mask over all images
        mask = create_mask(im_shape, self.m_mask_radii)
        images = self.m_image_in_port.get_all()

        # close the port during the calculations
        self.m_image_out_port.close_port()

        if self.m_temporal_median == 'constant':
            temporal_median = np.median(images, axis=0)
        else:
            temporal_median = False

        if self.m_method == 'SSIM':
            images = crop_image(images, None, int(self.m_mask_radii[1]))
            temporal_median = crop_image(temporal_median, None, int(self.m_mask_radii[1]))
        else:
            images *= mask

        # compare images and store similarity
        similarities = np.zeros(nimages)

        pool = mp.Pool(cpu)
        async_results = []

        for i in range(nimages):
            async_results.append(pool.apply_async(FrameSimilarityModule._similarity,
                                                  args=(images,
                                                        i,
                                                        self.m_method,
                                                        self.m_window_size,
                                                        temporal_median)))

        pool.close()

        start_time = time.time()

        # wait for all processes to finish
        while mp.active_children():
            # number of finished processes
            nfinished = sum([i.ready() for i in async_results])

            progress(nfinished, nimages, 'Running FrameSimilarityModule', start_time)

            # check if new processes have finished every 5 seconds
            time.sleep(5)

        # get the results for every async_result object
        for async_result in async_results:
            reference, similarity = async_result.get()
            similarities[reference] = similarity

        pool.terminate()

        # reopen the port after the calculation
        self.m_image_out_port.open_port()
        self.m_image_out_port.add_attribute(f'{self.m_method}', similarities, static=False)
        self.m_image_out_port.close_port()
コード例 #6
0
ファイル: limits.py プロジェクト: nenasedk/PynPoint
    def PCArun(self) -> None:
        """
        Run method of the module. An artificial planet is injected (based on the noise level) at a
        given separation and position angle. The amount of self-subtraction is then determined and
        the contrast limit is calculated for a given sigma level or false positive fraction. A
        correction for small sample statistics is applied for both cases. Note that if the sigma
        level is fixed, the false positive fraction changes with separation, following the
        Student's t-distribution (see Mawet et al. 2014 for details).

        Returns
        -------
        NoneType
            None
        """

        images = self.m_image_in_port.get_all()
        psf = self.m_psf_in_port.get_all()

        if psf.shape[0] != 1 and psf.shape[0] != images.shape[0]:
            raise ValueError(
                f'The number of frames in psf_in_tag {psf.shape} does not match with '
                f'the number of frames in image_in_tag {images.shape}. The '
                f'DerotateAndStackModule can be used to average the PSF frames '
                f'(without derotating) before applying the ContrastCurveModule.'
            )

        cpu = self._m_config_port.get_attribute('CPU')
        working_place = self._m_config_port.get_attribute('WORKING_PLACE')

        parang = self.m_image_in_port.get_attribute('PARANG')
        pixscale = self.m_image_in_port.get_attribute('PIXSCALE')

        self.m_image_in_port.close_port()
        self.m_psf_in_port.close_port()

        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

        self.m_aperture /= pixscale

        pos_r = np.arange(self.m_separation[0] / pixscale,
                          self.m_separation[1] / pixscale,
                          self.m_separation[2] / pixscale)

        pos_t = np.arange(self.m_angle[0] + self.m_extra_rot,
                          self.m_angle[1] + self.m_extra_rot, self.m_angle[2])

        if self.m_cent_size is None:
            index_del = np.argwhere(pos_r - self.m_aperture <= 0.)
        else:
            index_del = np.argwhere(
                pos_r - self.m_aperture <= self.m_cent_size)

        pos_r = np.delete(pos_r, index_del)

        if self.m_edge_size is None or self.m_edge_size > images.shape[1] / 2.:
            index_del = np.argwhere(
                pos_r + self.m_aperture >= images.shape[1] / 2.)
        else:
            index_del = np.argwhere(
                pos_r + self.m_aperture >= self.m_edge_size)

        pos_r = np.delete(pos_r, index_del)

        positions = []
        for sep in pos_r:
            for ang in pos_t:
                positions.append((sep, ang))

        result = []
        async_results = []

        # Create temporary files
        tmp_im_str = os.path.join(working_place, 'tmp_images.npy')
        tmp_psf_str = os.path.join(working_place, 'tmp_psf.npy')

        np.save(tmp_im_str, images)
        np.save(tmp_psf_str, psf)

        mask = create_mask(images.shape[-2:],
                           (self.m_cent_size, self.m_edge_size))

        _, im_res = pca_psf_subtraction(images=images * mask,
                                        angles=-1. * parang + self.m_extra_rot,
                                        pca_number=self.m_pca_number)

        noise = combine_residuals(method=self.m_residuals, res_rot=im_res)

        pool = mp.Pool(cpu)

        for pos in positions:
            async_results.append(
                pool.apply_async(
                    contrast_limit,
                    args=(tmp_im_str, tmp_psf_str, noise, mask, parang,
                          self.m_psf_scaling, self.m_extra_rot,
                          self.m_pca_number, self.m_threshold, self.m_aperture,
                          self.m_residuals, self.m_snr_inject, pos)))

        pool.close()

        start_time = time.time()

        # wait for all processes to finish
        while mp.active_children():
            # number of finished processes
            nfinished = sum([i.ready() for i in async_results])

            progress(nfinished, len(positions),
                     'Calculating detection limits...', start_time)

            # check if new processes have finished every 5 seconds
            time.sleep(5)

        if nfinished != len(positions):
            sys.stdout.write(
                '\r                                                      ')
            sys.stdout.write('\rCalculating detection limits... [DONE]\n')
            sys.stdout.flush()

        # get the results for every async_result object
        for item in async_results:
            result.append(item.get())

        pool.terminate()

        os.remove(tmp_im_str)
        os.remove(tmp_psf_str)

        result = np.asarray(result)

        # Sort the results first by separation and then by angle
        indices = np.lexsort((result[:, 1], result[:, 0]))
        result = result[indices]

        result = result.reshape((pos_r.size, pos_t.size, 4))

        mag_mean = np.nanmean(result, axis=1)[:, 2]
        mag_var = np.nanvar(result, axis=1)[:, 2]
        res_fpf = result[:, 0, 3]

        limits = np.column_stack(
            (pos_r * pixscale, mag_mean, mag_var, res_fpf))

        self.m_image_in_port._check_status_and_activate()
        self.m_contrast_out_port._check_status_and_activate()

        self.m_contrast_out_port.set_all(limits, data_dim=2)

        history = f'{self.m_threshold[0]} = {self.m_threshold[1]}'
        self.m_contrast_out_port.add_history('ContrastCurveModule', history)
        self.m_contrast_out_port.copy_attributes(self.m_image_in_port)
        self.m_contrast_out_port.close_port()
コード例 #7
0
    def run(self):
        """
        Run method of the module. Masks and normalizes the images.

        Returns
        -------
        NoneType
            None
        """

        self.m_image_out_port.del_all_data()
        self.m_image_out_port.del_all_attributes()

        if self.m_mask_out_port is not None:
            self.m_mask_out_port.del_all_data()
            self.m_mask_out_port.del_all_attributes()

        # Get PIXSCALE and MEMORY attributes
        pixscale = self.m_image_in_port.get_attribute("PIXSCALE")
        memory = self._m_config_port.get_attribute("MEMORY")

        # Get the number of images and split into batches to comply with memory constraints
        im_shape = self.m_image_in_port.get_shape()
        nimages = im_shape[0]
        frames = memory_frames(memory, nimages)

        # Convert m_cent_size and m_edge_size from arcseconds to pixels
        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

        # Create 2D disk mask which will be applied to every frame
        mask = create_mask((int(im_shape[-2]), int(im_shape[-1])),
                           [self.m_cent_size, self.m_edge_size]).astype(bool)

        # Keep track of the normalization vectors in case we are normalizing the images (if
        # we are not normalizing, this list will remain empty)
        norms = list()

        # Run the PSFpreparationModule for each subset of frames
        for i, _ in enumerate(frames[:-1]):

            # Print progress to command line
            progress(i, len(frames[:-1]), "Running PSFpreparationModule...")

            # Get the images and ensure they have the correct 3D shape with the following
            # three dimensions: (batch_size, height, width)
            images = self.m_image_in_port[frames[i]:frames[i + 1], ]

            if images.ndim == 2:
                warnings.warn(
                    "The input data has 2 dimensions whereas 3 dimensions are required. "
                    "An extra dimension has been added.")

                images = images[np.newaxis, ...]

            # Apply the mask, i.e., set all pixels to 0 where the mask is False
            images[:, ~mask] = 0.

            # If desired, normalize the images using the Frobenius norm
            if self.m_norm:
                im_norm = np.linalg.norm(images, ord="fro", axis=(1, 2))
                images /= im_norm[:, np.newaxis, np.newaxis]
                norms.append(im_norm)

            # Write processed images to output port
            self.m_image_out_port.append(images, data_dim=3)

        # Store information about mask
        if self.m_mask_out_port is not None:
            self.m_mask_out_port.set_all(mask)
            self.m_mask_out_port.copy_attributes(self.m_image_in_port)

        # Copy attributes from input port
        self.m_image_out_port.copy_attributes(self.m_image_in_port)

        # If the norms list is not empty (i.e., if we have computed the norm for every image),
        # we can also save the corresponding norm vector as an additional attribute
        if norms:
            self.m_image_out_port.add_attribute(name="norm",
                                                value=np.hstack(norms),
                                                static=False)

        # Save cent_size and edge_size as attributes to the output port
        if self.m_cent_size is not None:
            self.m_image_out_port.add_attribute(name="cent_size",
                                                value=self.m_cent_size *
                                                pixscale,
                                                static=True)
        if self.m_edge_size is not None:
            self.m_image_out_port.add_attribute(name="edge_size",
                                                value=self.m_edge_size *
                                                pixscale,
                                                static=True)

        sys.stdout.write("Running PSFpreparationModule... [DONE]\n")
        sys.stdout.flush()
コード例 #8
0
    def run(self) -> None:
        """
        Run method of the module. The posterior distributions of the separation, position angle,
        and flux contrast are sampled with the affine invariant Markov chain Monte Carlo (MCMC)
        ensemble sampler emcee. At each step, a negative copy of the PSF template is injected
        and the likelihood function is evaluated at the approximate position of the planet.

        Returns
        -------
        NoneType
            None
        """

        ndim = 3

        cpu = self._m_config_port.get_attribute('CPU')
        pixscale = self.m_image_in_port.get_attribute('PIXSCALE')
        parang = self.m_image_in_port.get_attribute('PARANG')

        images = self.m_image_in_port.get_all()
        psf = self.m_psf_in_port.get_all()

        im_shape = self.m_image_in_port.get_shape()[-2:]

        self.m_image_in_port.close_port()
        self.m_psf_in_port.close_port()

        if psf.shape[0] != 1 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 '
                             'MCMCsamplingModule.')

        if self.m_mask[0] is not None:
            self.m_mask = (self.m_mask[0]/pixscale, self.m_mask[1])

        if self.m_mask[1] is not None:
            self.m_mask = (self.m_mask[0], self.m_mask[1]/pixscale)

        # create the mask and get the unmasked image indices
        mask = create_mask(im_shape[-2:], self.m_mask)
        indices = np.where(mask.reshape(-1) != 0.)[0]

        if isinstance(self.m_aperture, float):
            yx_pos = polar_to_cartesian(images, self.m_param[0]/pixscale, self.m_param[1])
            aperture = (int(round(yx_pos[0])), int(round(yx_pos[1])), self.m_aperture/pixscale)

        elif isinstance(self.m_aperture, tuple):
            aperture = (self.m_aperture[1], self.m_aperture[0], self.m_aperture[2]/pixscale)

        initial = np.zeros((self.m_nwalkers, ndim))

        initial[:, 0] = self.m_param[0] + np.random.normal(0, self.m_sigma[0], self.m_nwalkers)
        initial[:, 1] = self.m_param[1] + np.random.normal(0, self.m_sigma[1], self.m_nwalkers)
        initial[:, 2] = self.m_param[2] + np.random.normal(0, self.m_sigma[2], self.m_nwalkers)

        print('Sampling the posterior distributions with MCMC...')

        with Pool(processes=cpu) as pool:
            sampler = emcee.EnsembleSampler(self.m_nwalkers,
                                            ndim,
                                            lnprob,
                                            pool=pool,
                                            args=([self.m_bounds,
                                                   images,
                                                   psf,
                                                   mask,
                                                   parang,
                                                   self.m_psf_scaling,
                                                   pixscale,
                                                   self.m_pca_number,
                                                   self.m_extra_rot,
                                                   aperture,
                                                   indices,
                                                   self.m_merit,
                                                   self.m_residuals]))

            sampler.run_mcmc(initial, self.m_nsteps, progress=True)

        self.m_image_in_port._check_status_and_activate()
        self.m_chain_out_port._check_status_and_activate()

        self.m_chain_out_port.set_all(sampler.get_chain())

        history = f'walkers = {self.m_nwalkers}, steps = {self.m_nsteps}'
        self.m_chain_out_port.copy_attributes(self.m_image_in_port)
        self.m_chain_out_port.add_history('MCMCsamplingModule', history)

        mean_accept = np.mean(sampler.acceptance_fraction)
        print(f'Mean acceptance fraction: {mean_accept:.3f}')
        self.m_chain_out_port.add_attribute('ACCEPTANCE', mean_accept, static=True)

        try:
            autocorr = emcee.autocorr.integrated_time(sampler.get_chain())
            print(f'Integrated autocorrelation time ={autocorr}')

        except emcee.autocorr.AutocorrError:
            autocorr = [np.nan, np.nan, np.nan]
            print('The chain is too short to reliably estimate the autocorrelation time. [WARNING]')

        self.m_chain_out_port.add_attribute('AUTOCORR_0', autocorr[0], static=True)
        self.m_chain_out_port.add_attribute('AUTOCORR_1', autocorr[1], static=True)
        self.m_chain_out_port.add_attribute('AUTOCORR_2', autocorr[2], static=True)

        self.m_chain_out_port.close_port()
コード例 #9
0
def pixel_variance(var_type: str, images: np.ndarray, parang: np.ndarray,
                   cent_size: Optional[float], edge_size: Optional[float],
                   pca_number: int, residuals: str,
                   aperture: Tuple[int, int, float], sigma: float) -> float:
    """
    Function to calculate the variance of the noise. After the PSF subtraction, images are rotated
    in opposite direction of the regular derotation, therefore dispersing any companion or disk
    signal. The noise is measured within an annulus.

    Parameters
    ----------
    var_type : str
        Variance type ('gaussian' or 'hessian').
    images : numpy.ndarray
        Input images (3D).
    parang : numpy.ndarray
        Parallactic angles.
    cent_size : float, None
        Radius of the central mask (pix). No mask is used when set to None.
    edge_size : float, None
        Outer radius (pix) beyond which pixels are masked. No outer mask is used when set to
        None.
    pca_number : int
        Number of principal components (PCs) used for the PSF subtraction.
    residuals : str
        Method for combining the residuals ('mean', 'median', 'weighted', or 'clipped').
    aperture : tuple(int, int, float)
        Aperture position (y, x) and radius (pix).
    sigma : float, None
        Standard deviation (pix) of the Gaussian kernel which is used to smooth the images.

    Returns
    -------
    float
        Variance of the pixel values. Either the variance of the pixel values ('gaussian') or
        the variance of the determinant of the Hessian ('hessian').
    """

    mask = create_mask(images.shape[-2:], (cent_size, edge_size))

    _, im_res_derot = pca_psf_subtraction(images * mask, parang, pca_number)

    res_noise = combine_residuals(residuals, im_res_derot)

    sep_ang = cartesian_to_polar(center_subpixel(res_noise), aperture[0],
                                 aperture[1])

    if var_type == 'gaussian':
        selected = select_annulus(res_noise[0, ], sep_ang[0] - aperture[2],
                                  sep_ang[0] + aperture[2])

    elif var_type == 'hessian':
        hessian_rr, hessian_rc, hessian_cc = hessian_matrix(
            image=res_noise[0, ],
            sigma=sigma,
            mode='constant',
            cval=0.,
            order='rc')

        hes_det = (hessian_rr * hessian_cc) - (hessian_rc * hessian_rc)

        selected = select_annulus(hes_det, sep_ang[0] - aperture[2],
                                  sep_ang[0] + aperture[2])

    return float(np.var(selected))
コード例 #10
0
    def run(self) -> None:
        """
        Run method of the module. The posterior distributions of the separation, position angle,
        and flux contrast are sampled with the affine invariant Markov chain Monte Carlo (MCMC)
        ensemble sampler emcee. At each step, a negative copy of the PSF template is injected
        and the likelihood function is evaluated at the approximate position of the planet.

        Returns
        -------
        NoneType
            None
        """

        ndim = 3

        cpu = self._m_config_port.get_attribute('CPU')
        pixscale = self.m_image_in_port.get_attribute('PIXSCALE')
        parang = self.m_image_in_port.get_attribute('PARANG')

        images = self.m_image_in_port.get_all()
        psf = self.m_psf_in_port.get_all()

        if psf.shape[0] != 1 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 '
                             'MCMCsamplingModule.')

        im_shape = self.m_image_in_port.get_shape()[-2:]

        if self.m_mask[0] is not None:
            self.m_mask = (self.m_mask[0]/pixscale, self.m_mask[1])

        if self.m_mask[1] is not None:
            self.m_mask = (self.m_mask[0], self.m_mask[1]/pixscale)

        # create the mask and get the unmasked image indices
        mask = create_mask(im_shape[-2:], self.m_mask)
        indices = np.where(mask.reshape(-1) != 0.)[0]

        if isinstance(self.m_aperture, float):
            yx_pos = polar_to_cartesian(images, self.m_param[0]/pixscale, self.m_param[1])
            aperture = (int(round(yx_pos[0])), int(round(yx_pos[1])), self.m_aperture/pixscale)

        elif isinstance(self.m_aperture, tuple):
            aperture = (self.m_aperture[1], self.m_aperture[0], self.m_aperture[2]/pixscale)

        initial = np.zeros((self.m_nwalkers, ndim))

        initial[:, 0] = self.m_param[0] + np.random.normal(0, self.m_sigma[0], self.m_nwalkers)
        initial[:, 1] = self.m_param[1] + np.random.normal(0, self.m_sigma[1], self.m_nwalkers)
        initial[:, 2] = self.m_param[2] + np.random.normal(0, self.m_sigma[2], self.m_nwalkers)

        # if self.m_merit == 'gaussian':
        #     variance = self.gaussian_variance(images*mask, psf, parang, aperture)
        # else:
        #     variance = None

        sampler = emcee.EnsembleSampler(nwalkers=self.m_nwalkers,
                                        dim=ndim,
                                        lnpostfn=lnprob,
                                        a=self.m_scale,
                                        args=([self.m_bounds,
                                               images,
                                               psf,
                                               mask,
                                               parang,
                                               self.m_psf_scaling,
                                               pixscale,
                                               self.m_pca_number,
                                               self.m_extra_rot,
                                               aperture,
                                               indices,
                                               self.m_merit,
                                               self.m_residuals]),
                                        threads=cpu)

        start_time = time.time()
        for i, _ in enumerate(sampler.sample(p0=initial, iterations=self.m_nsteps)):
            progress(i, self.m_nsteps, 'Running MCMCsamplingModule...', start_time)

        sys.stdout.write('Running MCMCsamplingModule... [DONE]\n')
        sys.stdout.flush()

        self.m_chain_out_port.set_all(sampler.chain)

        history = f'walkers = {self.m_nwalkers}, steps = {self.m_nsteps}'
        self.m_chain_out_port.copy_attributes(self.m_image_in_port)
        self.m_chain_out_port.add_history('MCMCsamplingModule', history)
        self.m_chain_out_port.close_port()

        print(f'Mean acceptance fraction: {np.mean(sampler.acceptance_fraction):.3f}')

        try:
            autocorr = emcee.autocorr.integrated_time(sampler.flatchain,
                                                      low=10,
                                                      high=None,
                                                      step=1,
                                                      c=10,
                                                      full_output=False,
                                                      axis=0,
                                                      fast=False)

            print('Integrated autocorrelation time =', autocorr)

        except emcee.autocorr.AutocorrError:
            print('The chain is too short to reliably estimate the autocorrelation time. [WARNING]')
コード例 #11
0
    def run(self) -> None:
        """
        Run method of the module. Masks and normalizes the images.
        Returns
        -------
        NoneType
            None
        """

        # Get the PIXSCALE and MEMORY attributes
        pixscale = self.m_image_in_port.get_attribute('PIXSCALE')
        memory = self._m_config_port.get_attribute('MEMORY')

        # Get the numnber of dimensions and shape
        ndim = self.m_image_in_port.get_ndim()
        im_shape = self.m_image_in_port.get_shape()

        if ndim == 3:
            # Number of images
            nimages = im_shape[-3]

            # Split into batches to comply with memory constraints
            frames = memory_frames(memory, nimages)

        elif ndim == 4:
            # Process all wavelengths per exposure at once
            frames = np.linspace(0, im_shape[-3], im_shape[-3] + 1)

        if self.m_norm and ndim == 4:
            warnings.warn(
                'The \'norm\' parameter does not support 4D datasets and will therefore '
                'be ignored.')

        # Convert m_cent_size and m_edge_size from arcseconds to pixels

        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

        # Create 2D disk mask which will be applied to every frame
        mask = create_mask((int(im_shape[-2]), int(im_shape[-1])),
                           (self.m_cent_size, self.m_edge_size)).astype(bool)

        # Keep track of the normalization vectors in case we are normalizing the images (if
        # we are not normalizing, this list will remain empty)
        norms = list()

        start_time = time.time()

        # Run the PSFpreparationModule for each subset of frames
        for i in range(frames[:-1].size):
            # Print progress to command line
            progress(i, len(frames[:-1]),
                     'Preparing images for PSF subtraction...', start_time)

            if ndim == 3:
                # Get the images and ensure they have the correct 3D shape with the following
                # three dimensions: (batch_size, height, width)
                images = self.m_image_in_port[frames[i]:frames[i + 1], ]

                if images.ndim == 2:
                    warnings.warn(
                        'The input data has 2 dimensions whereas 3 dimensions are '
                        'required. An extra dimension has been added.')

                    images = images[np.newaxis, ...]

            elif ndim == 4:
                # Process all wavelengths per exposure at once
                images = self.m_image_in_port[:, i, ]

            # Apply the mask, i.e., set all pixels to 0 where the mask is False
            images[:, ~mask] = 0.

            # If desired, normalize the images using the Frobenius norm
            if self.m_norm and ndim == 3:
                im_norm = np.linalg.norm(images, ord='fro', axis=(1, 2))
                images /= im_norm[:, np.newaxis, np.newaxis]
                norms.append(im_norm)

            # Write processed images to output port
            if ndim == 3:
                self.m_image_out_port.append(images, data_dim=3)
            elif ndim == 4:
                self.m_image_out_port.append(images, data_dim=4)

        # Store information about mask
        if self.m_mask_out_port is not None:
            self.m_mask_out_port.set_all(mask)
            self.m_mask_out_port.copy_attributes(self.m_image_in_port)

        # Copy attributes from input port
        self.m_image_out_port.copy_attributes(self.m_image_in_port)

        # If the norms list is not empty (i.e., if we have computed the norm for every image),
        # we can also save the corresponding norm vector as an additional attribute
        if norms:
            self.m_image_out_port.add_attribute(name='norm',
                                                value=np.hstack(norms),
                                                static=False)

        # Save cent_size and edge_size as attributes to the output port
        if self.m_cent_size is not None:
            self.m_image_out_port.add_attribute(name='cent_size',
                                                value=self.m_cent_size *
                                                pixscale,
                                                static=True)

        if self.m_edge_size is not None:
            self.m_image_out_port.add_attribute(name='edge_size',
                                                value=self.m_edge_size *
                                                pixscale,
                                                static=True)
コード例 #12
0
ファイル: fluxposition.py プロジェクト: 18alex96/PynPoint
    def run(self):
        """
        Run method of the module. Shifts the reference PSF to the location of the fake planet
        with an additional correction for the parallactic angle and writes the stack with images
        with the injected planet signal.

        :return: None
        """

        if not isinstance(self.m_param, tuple) or len(self.m_param) != 3:
            raise TypeError(
                "The param argument should contain a tuple with the approximate "
                "separation (arcsec), position angle (deg), and contrast (mag)."
            )

        if not isinstance(self.m_bounds, tuple) or len(self.m_bounds) != 3:
            raise TypeError(
                "The bounds argument should contain a tuple with three tuples for "
                "the boundaries of the separation (arcsec), position angle (deg), and "
                "contrast (mag).")

        if not isinstance(self.m_sigma, tuple) or len(self.m_sigma) != 3:
            raise TypeError(
                "The sigma argument should contain a tuple with the standard "
                "deviation of the separation (arcsec), position angle (deg), "
                "and contrast (mag) that is used to sample the starting position "
                "of the walkers.")

        ndim = 3

        cpu = self._m_config_port.get_attribute("CPU")
        pixscale = self.m_image_in_port.get_attribute("PIXSCALE")
        parang = self.m_image_in_port.get_attribute("PARANG")

        images = self.m_image_in_port.get_all()
        psf = self.m_psf_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 '
                'MCMCsamplingModule.')

        im_shape = image_size_port(self.m_image_in_port)

        if self.m_mask[0] is not None:
            self.m_mask[0] /= pixscale

        if self.m_mask[1] is not None:
            self.m_mask[1] /= pixscale

        # create the mask and get the unmasked image indices
        mask = create_mask(im_shape[-2:], self.m_mask)
        indices = np.where(mask.reshape(-1) != 0.)[0]

        self.aperture_dict(images)

        initial = np.zeros((self.m_nwalkers, ndim))

        initial[:, 0] = self.m_param[0] + np.random.normal(
            0, self.m_sigma[0], self.m_nwalkers)
        initial[:, 1] = self.m_param[1] + np.random.normal(
            0, self.m_sigma[1], self.m_nwalkers)
        initial[:, 2] = self.m_param[2] + np.random.normal(
            0, self.m_sigma[2], self.m_nwalkers)

        if self.m_variance == "gaussian":
            student_t = self.gaussian_noise(images * mask, psf, parang,
                                            self.m_aperture)
            variance = (self.m_variance, student_t)

        else:
            variance = (self.m_variance, None)

        sampler = emcee.EnsembleSampler(
            nwalkers=self.m_nwalkers,
            dim=ndim,
            lnpostfn=lnprob,
            a=self.m_scale,
            args=([
                self.m_bounds, images, psf, mask, parang, self.m_psf_scaling,
                pixscale, self.m_pca_number, self.m_extra_rot, self.m_aperture,
                indices, self.m_prior, variance, self.m_residuals
            ]),
            threads=cpu)

        for i, _ in enumerate(
                sampler.sample(p0=initial, iterations=self.m_nsteps)):
            progress(i, self.m_nsteps, "Running MCMCsamplingModule...")

        sys.stdout.write("Running MCMCsamplingModule... [DONE]\n")
        sys.stdout.flush()

        self.m_chain_out_port.set_all(sampler.chain)
        history = "walkers = " + str(self.m_nwalkers) + ", steps = " + str(
            self.m_nsteps)
        self.m_chain_out_port.add_history_information("MCMCsamplingModule",
                                                      history)
        self.m_chain_out_port.copy_attributes_from_input_port(
            self.m_image_in_port)
        self.m_chain_out_port.close_port()

        print("Mean acceptance fraction: {0:.3f}".format(
            np.mean(sampler.acceptance_fraction)))

        try:
            autocorr = emcee.autocorr.integrated_time(sampler.flatchain,
                                                      low=10,
                                                      high=None,
                                                      step=1,
                                                      c=10,
                                                      full_output=False,
                                                      axis=0,
                                                      fast=False)

            print("Integrated autocorrelation time =", autocorr)

        except emcee.autocorr.AutocorrError:
            print(
                "The chain is too short to reliably estimate the autocorrelation time. [WARNING]"
            )
コード例 #13
0
    def run(self):
        """
        Run method of the module. An artificial planet is injected (based on the noise level) at a
        given separation and position angle. The amount of self-subtraction is then determined and
        the contrast limit is calculated for a given sigma level or false positive fraction. A
        correction for small sample statistics is applied for both cases. Note that if the sigma
        level is fixed, the false positive fraction changes with separation, following the
        Student's t-distribution (see Mawet et al. 2014 for details).

        Returns
        -------
        NoneType
            None
        """

        images = self.m_image_in_port.get_all()
        psf = self.m_psf_in_port.get_all()

        if psf.shape[0] != 1 and psf.shape[0] != images.shape[0]:
            raise ValueError('The number of frames in psf_in_tag {0} does not match with the '
                             'number of frames in image_in_tag {1}. The DerotateAndStackModule can '
                             'be used to average the PSF frames (without derotating) before '
                             'applying the ContrastCurveModule.'.format(psf.shape, images.shape))

        cpu = self._m_config_port.get_attribute("CPU")
        parang = self.m_image_in_port.get_attribute("PARANG")
        pixscale = self.m_image_in_port.get_attribute("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

        self.m_aperture /= pixscale

        pos_r = np.arange(self.m_separation[0]/pixscale,
                          self.m_separation[1]/pixscale,
                          self.m_separation[2]/pixscale)

        pos_t = np.arange(self.m_angle[0]+self.m_extra_rot,
                          self.m_angle[1]+self.m_extra_rot,
                          self.m_angle[2])

        if self.m_cent_size is None:
            index_del = np.argwhere(pos_r-self.m_aperture <= 0.)
        else:
            index_del = np.argwhere(pos_r-self.m_aperture <= self.m_cent_size)

        pos_r = np.delete(pos_r, index_del)

        if self.m_edge_size is None or self.m_edge_size > images.shape[1]/2.:
            index_del = np.argwhere(pos_r+self.m_aperture >= images.shape[1]/2.)
        else:
            index_del = np.argwhere(pos_r+self.m_aperture >= self.m_edge_size)

        pos_r = np.delete(pos_r, index_del)

        sys.stdout.write("Running ContrastCurveModule...\r")
        sys.stdout.flush()

        positions = []
        for sep in pos_r:
            for ang in pos_t:
                positions.append((sep, ang))

        # Create a queue object which will contain the results
        queue = mp.Queue()

        result = []
        jobs = []

        working_place = self._m_config_port.get_attribute("WORKING_PLACE")

        # Create temporary files
        tmp_im_str = os.path.join(working_place, "tmp_images.npy")
        tmp_psf_str = os.path.join(working_place, "tmp_psf.npy")

        np.save(tmp_im_str, images)
        np.save(tmp_psf_str, psf)

        mask = create_mask(images.shape[-2:], [self.m_cent_size, self.m_edge_size])

        _, im_res = pca_psf_subtraction(images=images*mask,
                                        angles=-1.*parang+self.m_extra_rot,
                                        pca_number=self.m_pca_number)

        noise = combine_residuals(method=self.m_residuals, res_rot=im_res)

        for i, pos in enumerate(positions):
            process = mp.Process(target=contrast_limit,
                                 args=(tmp_im_str,
                                       tmp_psf_str,
                                       noise,
                                       mask,
                                       parang,
                                       self.m_psf_scaling,
                                       self.m_extra_rot,
                                       self.m_pca_number,
                                       self.m_threshold,
                                       self.m_aperture,
                                       self.m_residuals,
                                       self.m_snr_inject,
                                       pos,
                                       queue),
                                 name=(str(os.path.basename(__file__)) + '_radius=' +
                                       str(np.round(pos[0]*pixscale, 1)) + '_angle=' +
                                       str(np.round(pos[1], 1))))

            jobs.append(process)

        for i, job in enumerate(jobs):
            job.start()

            if (i+1)%cpu == 0:
                # Start *cpu* number of processes. Wait for them to finish and start again *cpu*
                # number of processes.

                for k in jobs[i+1-cpu:(i+1)]:
                    k.join()

            elif (i+1) == len(jobs) and (i+1)%cpu != 0:
                # Wait for the last processes to finish if number of processes is not a multiple
                # of *cpu*

                for k in jobs[(i + 1 - (i+1)%cpu):]:
                    k.join()

            progress(i, len(jobs), "Running ContrastCurveModule...")

        # Send termination sentinel to queue
        queue.put(None)

        while True:
            item = queue.get()

            if item is None:
                break
            else:
                result.append(item)

        os.remove(tmp_im_str)
        os.remove(tmp_psf_str)

        result = np.asarray(result)

        # Sort the results first by separation and then by angle
        indices = np.lexsort((result[:, 1], result[:, 0]))
        result = result[indices]

        result = result.reshape((pos_r.size, pos_t.size, 4))

        mag_mean = np.nanmean(result, axis=1)[:, 2]
        mag_var = np.nanvar(result, axis=1)[:, 2]
        res_fpf = result[:, 0, 3]

        limits = np.column_stack((pos_r*pixscale, mag_mean, mag_var, res_fpf))

        self.m_contrast_out_port.set_all(limits, data_dim=2)

        sys.stdout.write("\rRunning ContrastCurveModule... [DONE]\n")
        sys.stdout.flush()

        history = str(self.m_threshold[0])+" = "+str(self.m_threshold[1])

        self.m_contrast_out_port.add_history("ContrastCurveModule", history)
        self.m_contrast_out_port.copy_attributes(self.m_image_in_port)
        self.m_contrast_out_port.close_port()