Source code for astrophot.models.group_psf_model
from .group_model_object import GroupModel
from ..image import PSFImage
from ..errors import InvalidTarget
from ..param import forward
__all__ = ["PSFGroupModel"]
[docs]
class PSFGroupModel(GroupModel):
"""
A group of PSF models. Behaves similarly to a `GroupModel`, but specifically
designed for PSF models. Note that there is no concept of a PSFImageList, so
they always represent a single PSF model.
When sampling, a PSFGroupModel tells each sub-PSFModel (including nested
sub-PSFGroupModels) to sample without normalization. This way they can fit
with relative strengths. The final top-level PSFGroupModel will normalize
the resulting PSF, so that the image that gets passed to the regular model
objects for the purpose of convolution is always normalized. This means that
the sub-PSFModels in a PSFGroupModel should have their brightness parameters
(i.e., `I0` for the MoffatPSF) set to dynamic so they can participate in the
fit. Though this is not strictly a requirement (say you already know the
relative brightnesses).
"""
_model_type = "psf"
usable = True
@property
def target(self):
try:
return self._target
except AttributeError:
return None
@target.setter
def target(self, target):
if not (target is None or isinstance(target, PSFImage)):
raise InvalidTarget("GroupModel target must be a PSFImage instance.")
try:
del self._target # Remove old target if it exists
except AttributeError:
pass
self._target = target
[docs]
@forward
def sample(self, normalize_psf=True) -> PSFImage:
"""Sample the PSF group model on the target image."""
image = self.target.model_image(self.window)
for model in self.models:
model_image = model(normalize_psf=False)
self._ensure_vmap_compatible(image, model_image)
image += model_image
if normalize_psf:
image.normalize()
return image
@forward
def __call__(
self,
normalize_psf=True,
) -> PSFImage:
return self.sample(normalize_psf=normalize_psf)