Example #1
0
def image_scaling(image_in: np.ndarray,
                  im_index: int,
                  scaling_y: float,
                  scaling_x: float,
                  scaling_flux: float) -> np.ndarray:

    return scaling_flux * scale_image(image_in, scaling_y, scaling_x)
Example #2
0
        def _image_scaling(image_in,
                           scaling_x,
                           scaling_y,
                           scaling_flux):

            tmp_image = scale_image(image_in, scaling_x, scaling_y)

            return scaling_flux * tmp_image
Example #3
0
    def run(self) -> None:
        """
        Run method of the module. Normalizes the images for the different filter widths,
        upscales the images, and crops the images to the initial image shape in order to
        align the PSF patterns.

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

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

        wvl_factor = self.m_line_wvl / self.m_cnt_wvl
        width_factor = self.m_line_width / self.m_cnt_width

        nimages = self.m_image_in_port.get_shape()[0]

        start_time = time.time()
        for i in range(nimages):
            progress(i, nimages, 'Running SDIpreparationModule...', start_time)

            image = self.m_image_in_port[i, ]

            im_scale = width_factor * scale_image(image, wvl_factor,
                                                  wvl_factor)

            if i == 0:
                npix_del = im_scale.shape[-1] - image.shape[-1]

                if npix_del % 2 == 0:
                    npix_del_a = int(npix_del / 2)
                    npix_del_b = int(npix_del / 2)

                else:
                    npix_del_a = int((npix_del - 1) / 2)
                    npix_del_b = int((npix_del + 1) / 2)

            im_crop = im_scale[npix_del_a:-npix_del_b, npix_del_a:-npix_del_b]

            if npix_del % 2 == 1:
                im_crop = shift_image(im_crop, (-0.5, -0.5),
                                      interpolation='spline')

            self.m_image_out_port.append(im_crop, data_dim=3)

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

        history = f'(line, continuum) = ({self.m_line_wvl}, {self.m_cnt_wvl})'
        self.m_image_out_port.copy_attributes(self.m_image_in_port)
        self.m_image_out_port.add_history('SDIpreparationModule', history)
        self.m_image_in_port.close_port()
Example #4
0
def sdi_scaling(image_in: np.ndarray, scaling: np.ndarray) -> np.ndarray:
    """
    Function to rescale the images by their wavelength ratios.

    Parameters
    ----------
    image_in : np.ndarray
        Data to rescale
    scaling : np.ndarray
        Scaling factors.

    Returns
    -------
    np.ndarray
        Rescaled images with the same shape as ``image_in``.
    """

    if image_in.shape[0] != scaling.shape[0]:
        raise ValueError(
            'The number of wavelengths is not equal to the number of available '
            'scaling factors.')

    image_out = np.zeros(image_in.shape)

    for i in range(image_in.shape[0]):
        swaps = scale_image(image_in[i, ], scaling[i], scaling[i])

        npix_del = swaps.shape[-1] - image_out.shape[-1]

        if npix_del == 0:
            image_out[i, ] = swaps

        else:
            if npix_del % 2 == 0:
                npix_del_a = int(npix_del / 2)
                npix_del_b = int(npix_del / 2)

            else:
                npix_del_a = int((npix_del - 1) / 2)
                npix_del_b = int((npix_del + 1) / 2)

            image_out[i, ] = swaps[npix_del_a:-npix_del_b,
                                   npix_del_a:-npix_del_b]

        if npix_del % 2 == 1:
            image_out[i, ] = shift_image(image_out[i, ], (-0.5, -0.5),
                                         interpolation='spline')

    return image_out
Example #5
0
        def _image_scaling(image_in, scaling_x, scaling_y, scaling_flux):

            return scaling_flux * scale_image(image_in, scaling_x, scaling_y)
Example #6
0
def pca_psf_subtraction(
        images: np.ndarray,
        angles: Optional[np.ndarray],
        pca_number: Union[int, np.int64],
        scales: Optional[np.ndarray] = None,
        pca_sklearn: Optional[PCA] = None,
        im_shape: Optional[tuple] = None,
        indices: Optional[np.ndarray] = None) -> Tuple[np.ndarray, np.ndarray]:
    """
    Function for PSF subtraction with PCA.

    Parameters
    ----------
    images : np.ndarray
        Stack of images. Also used as reference images if ```pca_sklearn``` is set to None. The
        data should have the original 3D shape if ``pca_sklearn`` is set to None or it should be
        in a 2D reshaped format if ``pca_sklearn`` is not set to None.
    angles : np.ndarray
        Parallactic angles (deg).
    pca_number : int
        Number of principal components.
    scales : np.ndarray, None
        Scaling factors for SDI. Not used if set to None.
    pca_sklearn : sklearn.decomposition.pca.PCA, None
        PCA object with the principal components.
    im_shape : tuple(int, int, int), None
        The original 3D shape of the stack with images. Only required if ``pca_sklearn`` is not set
        to None.
    indices : np.ndarray, None
        Array with the indices of the pixels that are used for the PSF subtraction. All pixels are
        used if set to None.

    Returns
    -------
    np.ndarray
        Residuals of the PSF subtraction.
    np.ndarray
        Derotated residuals of the PSF subtraction.
    """

    if pca_sklearn is None:
        # Create a PCA object if not provided as argument
        pca_sklearn = PCA(n_components=pca_number, svd_solver='arpack')

        # The 3D shape of the array with images
        im_shape = images.shape

        if indices is None:
            # Select the first image and get the unmasked image indices
            im_star = images[0, ].reshape(-1)
            indices = np.where(im_star != 0.)[0]

        # Reshape the images and select the unmasked pixels
        im_reshape = images.reshape(im_shape[0], im_shape[1] * im_shape[2])
        im_reshape = im_reshape[:, indices]

        # Subtract the mean image
        # This is also done by sklearn.decomposition.PCA.fit()
        im_reshape -= np.mean(im_reshape, axis=0)

        # Fit the principal components
        pca_sklearn.fit(im_reshape)

    else:
        # If the PCA object is already there then so are the reshaped data
        im_reshape = np.copy(images)

    # Project the data on the principal components
    # Note that this is the same as sklearn.decomposition.PCA.transform()
    # It is harcoded because the number of components has been adjusted
    pca_rep = np.matmul(pca_sklearn.components_[:pca_number], im_reshape.T)

    # The zeros are added with vstack to account for the components that have not been used for the
    # transformation to the lower-dimensional space, while they were initiated with the PCA object.
    # Since inverse_transform uses the number of initial components, the zeros are added for
    # components > pca_number. These components do not impact the inverse transformation.
    zeros = np.zeros(
        (pca_sklearn.n_components - pca_number, im_reshape.shape[0]))
    pca_rep = np.vstack((pca_rep, zeros)).T

    # Transform the data back to the original space
    psf_model = pca_sklearn.inverse_transform(pca_rep)

    # Create an array with the original shape
    residuals = np.zeros((im_shape[0], im_shape[1] * im_shape[2]))

    # Select all pixel indices if set to None
    if indices is None:
        indices = np.arange(0, im_reshape.shape[1], 1)

    # Subtract the PSF model
    residuals[:, indices] = im_reshape - psf_model

    # Reshape the residuals to the original shape
    residuals = residuals.reshape(im_shape)

    # ----------- back scale images
    scal_cor = np.zeros(residuals.shape)

    if scales is not None:

        # check if the number of parang is equal to the number of images
        if residuals.shape[0] != scales.shape[0]:
            raise ValueError(
                f'The number of images ({residuals.shape[0]}) is not equal to the '
                f'number of wavelengths ({scales.shape[0]}).')

        for i, _ in enumerate(scales):
            # rescaling the images
            swaps = scale_image(residuals[i, ], 1 / scales[i], 1 / scales[i])

            npix_del = scal_cor.shape[-1] - swaps.shape[-1]

            if npix_del == 0:
                scal_cor[i, ] = swaps

            else:
                if npix_del % 2 == 0:
                    npix_del_a = int(npix_del / 2)
                    npix_del_b = int(npix_del / 2)

                else:
                    npix_del_a = int((npix_del - 1) / 2)
                    npix_del_b = int((npix_del + 1) / 2)

                scal_cor[i, npix_del_a:-npix_del_b,
                         npix_del_a:-npix_del_b] = swaps

                if npix_del % 2 == 1:
                    scal_cor[i, ] = shift_image(scal_cor[i, ], (0.5, 0.5),
                                                interpolation='spline')

    else:
        scal_cor = residuals

    res_rot = np.zeros(residuals.shape)

    if angles is not None:

        # Check if the number of parang is equal to the number of images
        if residuals.shape[0] != angles.shape[0]:
            raise ValueError(
                f'The number of images ({residuals.shape[0]}) is not equal to the '
                f'number of parallactic angles ({angles.shape[0]}).')

        for j, item in enumerate(angles):
            res_rot[j, ] = rotate(scal_cor[j, ], item, reshape=False)

    else:
        res_rot = scal_cor

    return scal_cor, res_rot
Example #7
0
def pca_psf_subtraction(
        images: np.ndarray,
        angles: Optional[np.ndarray],
        pca_number: Union[int, np.int64],
        scales: Optional[np.ndarray] = None,
        pca_sklearn: Optional[PCA] = None,
        im_shape: Optional[tuple] = None,
        indices: Optional[np.ndarray] = None) -> Tuple[np.ndarray, np.ndarray]:
    """
    Function for PSF subtraction with PCA.

    Parameters
    ----------
    images : np.ndarray
        Stack of images. Also used as reference images if `pca_sklearn` is set to None. Should be
        in the original 3D shape if `pca_sklearn` is set to None or in the 2D reshaped format if
        `pca_sklearn` is not set to None.
    angles : np.ndarray, None
        Derotation angles (deg). The images are not derotated (e.g. for SDI) if set to None.
    pca_number : int
        Number of principal components used for the PSF model.
    scales : np.ndarray, None
        Scaling factors for SDI. Not used if set to None.
    pca_sklearn : sklearn.decomposition.pca.PCA, None
        PCA decomposition of the input data.
    im_shape : tuple(int, int, int), None
        Original shape of the stack with images. Required if `pca_sklearn` is not set to None.
    indices : np.ndarray, None
        Non-masked image indices. All pixels are used if set to None.

    Returns
    -------
    np.ndarray
        Residuals of the PSF subtraction.
    np.ndarray
        Derotated residuals of the PSF subtraction.
    """

    if pca_sklearn is None:
        pca_sklearn = PCA(n_components=pca_number, svd_solver='arpack')

        im_shape = images.shape

        if indices is None:
            # select the first image and get the unmasked image indices
            im_star = images[0, ].reshape(-1)
            indices = np.where(im_star != 0.)[0]

        # reshape the images and select the unmasked pixels
        im_reshape = images.reshape(im_shape[0], im_shape[1] * im_shape[2])
        im_reshape = im_reshape[:, indices]

        # subtract mean image
        im_reshape -= np.mean(im_reshape, axis=0)

        # create pca basis
        pca_sklearn.fit(im_reshape)

    else:
        im_reshape = np.copy(images)

    # create pca representation
    zeros = np.zeros(
        (pca_sklearn.n_components - pca_number, im_reshape.shape[0]))
    pca_rep = np.matmul(pca_sklearn.components_[:pca_number], im_reshape.T)
    pca_rep = np.vstack((pca_rep, zeros)).T

    # create psf model
    psf_model = pca_sklearn.inverse_transform(pca_rep)

    # create original array size
    residuals = np.zeros((im_shape[0], im_shape[1] * im_shape[2]))

    # subtract the psf model
    if indices is None:
        indices = np.arange(0, im_reshape.shape[1], 1)

    residuals[:, indices] = im_reshape - psf_model

    # reshape to the original image size
    residuals = residuals.reshape(im_shape)

    # ----------- back scale images
    scal_cor = np.zeros(residuals.shape)

    if scales is not None:

        # check if the number of parang is equal to the number of images
        if residuals.shape[0] != scales.shape[0]:
            raise ValueError(
                f'The number of images ({residuals.shape[0]}) is not equal to the '
                f'number of wavelengths ({scales.shape[0]}).')

        for i, _ in enumerate(scales):
            # rescaling the images
            swaps = scale_image(residuals[i, ], 1 / scales[i], 1 / scales[i])

            npix_del = scal_cor.shape[-1] - swaps.shape[-1]

            if npix_del == 0:
                scal_cor[i, ] = swaps

            else:
                if npix_del % 2 == 0:
                    npix_del_a = int(npix_del / 2)
                    npix_del_b = int(npix_del / 2)

                else:
                    npix_del_a = int((npix_del - 1) / 2)
                    npix_del_b = int((npix_del + 1) / 2)

                scal_cor[i, npix_del_a:-npix_del_b,
                         npix_del_a:-npix_del_b] = swaps

                if npix_del % 2 == 1:
                    scal_cor[i, ] = shift_image(scal_cor[i, ], (0.5, 0.5),
                                                interpolation='spline')

    else:
        scal_cor = residuals

    res_rot = np.zeros(residuals.shape)

    if angles is not None:

        # Check if the number of parang is equal to the number of images
        if residuals.shape[0] != angles.shape[0]:
            raise ValueError(
                f'The number of images ({residuals.shape[0]}) is not equal to the '
                f'number of parallactic angles ({angles.shape[0]}).')

        for j, item in enumerate(angles):
            res_rot[j, ] = rotate(scal_cor[j, ], item, reshape=False)

    else:
        res_rot = scal_cor

    return scal_cor, res_rot