Source code for psfsubtraction.fitpsf.optregion

# Licensed under a MIT licence - see file `license`
'''Function to construct the "optimization region" for a region.

The "optimization region" is the region used in the fitting to find the best
PSF for a region. The "optimization region" can (but usually will not) be
identical to the region.
For example, if the base PSF is flat, and the region we are looking at
contains some flat area and also a source, then the fit might tell us to
subtract a constant so that the mean of the subtracted data is zero.
Instead, if we look for the best fit for the source and we use only the
surrounding flat region, then we will be left with the source after the
subtraction - exactly what we want.

These functions meant to be included into a `PSFFitter` object and this they
all take the ``self`` argument.

All functions here take three arguments:

- ``self``
- ``region``: See `region` for a description
- ``indpsf``: See `findbase`.

and return a "optimization region" which has the same format as `region`.

'''
from warnings import warn

import numpy as np
from scipy.ndimage import binary_dilation

from .utils import OptionalAttributeError

__all__ = ['identity', 'all_unmasked', 'dilated_region',
           'around_region', 'wrapper_optmask', 'wrapper_ignore_all_masked']


[docs]def identity(self, region, indpsf): '''Return a input region as optimization region.''' return region
[docs]def all_unmasked(self, region, indpsf): '''Here we select the maximal region. The region is maximal in the sense that it includes all pixels that are not masked in the data or any of the bases. Returns ------- optregion : np.array of type bool True for those pixels that should be included in the fit ''' psfmask = np.max(np.ma.getmaskarray(self.psfbase1d[:, indpsf]), axis=1) datamask = np.ma.getmaskarray(self.image1d) optregion = ~psfmask & ~datamask if optregion.sum() <= np.asarray(indpsf).sum(): warn('Fit underdetermined. Choose larger optimization region or smaller base.') return optregion
[docs]def dilated_region(self, region, indpsf): '''Specify a optimization region that extends around the ``region``. This requires that the fitter has an attribute ``dilatation_region``, which can be - an int: In this case a square matrix of size 2 * n + 1 is used. - a matrix (see `scipy.ndimage.binary_dilation` for details. Examples -------- >>> from psfsubtraction.fitpsf import fitters >>> from psfsubtraction.fitpsf import optregion >>> region = np.array([[True, False, False], \ [False, False, False], \ [False, False, False]]) >>> class DilationFitter(fitters.SimpleSubtraction): ... optregion = optregion.dilated_region ... dilation_region = 1 >>> dummy_image = np.ones((3, 3)) # boring image, but good enough for the example >>> dummy_psfs = np.ones((3,3,4)) # even more boring psf array. >>> myfitter = DilationFitter(dummy_psfs, dummy_image) >>> myfitter.optregion(region, [0]).reshape((3, 3)) array([[ True, True, False], [ True, True, False], [False, False, False]]) ''' if not hasattr(self, 'dilation_region'): raise OptionalAttributeError('Fitter must speficy the `self.dilation_region`\n' + 'which is either and int or a square matrix.') if np.isscalar(self.dilation_region): selem = np.ones((2 * self.dilation_region + 1, 2 * self.dilation_region + 1)) else: selem = self.dilation_region return self.dim2to1(binary_dilation(self.dim1to2(region), selem))
[docs]def around_region(self, region, indpsf): '''similar to `dilated_region`, but exclude all pixels in ``region`` itself. See `dilated_region` for options. Examples -------- >>> from psfsubtraction.fitpsf import fitters >>> from psfsubtraction.fitpsf import optregion >>> region = np.array([[True, False, False], \ [False, False, False], \ [False, False, False]]) >>> dummy_image = np.ones((3, 3)) # boring image, but good enough for the example >>> dummy_psfs = np.ones((3,3,4)) # even more boring psf array. >>> class AroundFitter(fitters.SimpleSubtraction): ... optregion = optregion.around_region ... dilation_region = 1 >>> myfitter = AroundFitter(dummy_psfs, dummy_image) >>> myfitter.optregion(region.ravel(), [0]).reshape((3, 3)) array([[False, True, False], [ True, True, False], [False, False, False]]) ''' fitreg = dilated_region(self, region, indpsf) return fitreg & ~np.asarray(region)
[docs]def wrapper_optmask(func): '''Wrap an optregion function to apply an additional global mask. This function wraps the optregion function ``func``. Optimization regions are determined by that function, but are then additionally filtered such that points that are masked as ``True`` in ``self.optmask`` are not included in the optimization region. One use case is an image with a source hidden in the PSF. Assume that this source is already known. We want to include it in ``region`` to make sure that the PSF is removed under it, but we do not want to include when optimize the PSF. (A better alternative might be to fit its PSF at the same time, but that is beyond the scope of this module.) Parameters ---------- func : callable function to be wrapped. Returns ------- func_and_optmask : function wrapped ``func`` ''' def func_and_optmask(self, region, indpsf): if not hasattr(self, "optmask"): raise OptionalAttributeError('Fit object needs to define a boolean array optmask.') if not hasattr(self.optmask, "shape") or \ not ((self.optmask.shape == self.image.shape) or (self.optmask.shape == self.image1d.shape)): raise OptionalAttributeError('"optmask" must have same shape as image.') optregion = func(self, region, indpsf) optregion_and_optmask = optregion & ~self.optmask.flatten() if optregion_and_optmask.sum() <= np.asarray(indpsf).sum(): warn('Fit underdetermined. Ignoring fitmask.') return optregion else: return optregion_and_optmask return func_and_optmask
[docs]def wrapper_ignore_all_masked(func): '''Wrap a optregion function to remove all masked pixels from optregion. This function wraps the optregion function ``func``. Optimization regions are determined by that function, but are then additionally filtered such that points that are masked in either the image or and used psfbase are not part of the returned ``optregion``. Parameters ---------- func : callable function to be wrapped. Returns ------- func_and_fitmask : function wrapped ``func`` ''' def func_unmasked(self, region, indpsf): optregion = self.anyreg_to_mask(func(self, region, indpsf)) psfmask = np.max(np.ma.getmaskarray(self.psfbase1d[:, indpsf]), axis=1) datamask = np.ma.getmaskarray(self.image1d) optregion = optregion & ~psfmask & ~datamask if optregion.sum() <= np.asarray(indpsf).sum(): warn('Fit underdetermined. Choose larger optimization region or smaller base.') return optregion return func_unmasked