-
-
Notifications
You must be signed in to change notification settings - Fork 138
PSF photometry plans (2017‐2018)
Archive of plans from the "PSF Photometry Algorithms and Software Workshop" held at STScI October 3-4, 2017.
The block diagram:
![block_diagram](https://github.com/user-attachments/assets/f2f61c46-9c41-42c0-970b-853e671a694f)
[Link to code if it exists]
A single sentence summarizing this block.
A longer description. Can be multiple paragraphs. You can link to other things like photutils.background.
- first_parameter_name : ~astropy.table.Table
- Description of first input
- second_parameter_name : SomeOtherType
- Description of second input (if any)
- first_return : ~astropy.table.Table
- Description of the first thing this block outputs.
- second_return
- Many blocks will only return one object, but if more things are returned
they can be described here (e.g., in python this is
first, second = some_function(...)
)
Not all blocks will have these, but if desired some blocks can have methods that let you do something other than just running the block. E.g:
some_block = BlockClassName() output = some_block(input1, input2, ...) # this is what is documented above result = some_block.method_name(...) #this is documented here
Description of method
- first_parameter : type
- Description ...
- second_parameter : type
- Description ...
- first_return : type
- Description ...
An example of using the block should be provided. This needs to be after a
::
in the rst and indented:
print("This is example code")
Existing code documented here
-- while the __call__
function has no docstring, the calc_background
function is the actual block API. This function is used significantly through photutils
and is heavily used within the PSF fitting process, so the documentation is summarized
again here.
Routine to estimate the background level of images and provide background subtraction. Can either be applied across an entire image or applied in a two-dimensional grid, at which point background estimation is applied at each grid location locally.
Base class from which all background estimators are defined. Further parameters may be
specified by subclass estimators, such as the ModeEstimatorBackground
in photutils
which takes median_factor
and mean_factor
as additional variables.
- sigma_clip : ~astropy.stats.SigmaClip object or None
- The object which defines the level of sigma clipping applied to the data. If None
then no clipping is performed. Passed when creating the class in
__init__
. - data : array_like or ~numpy.ma.MaskedArray
- The array for which to calculate the background value. Passed to the
__call__
function. - axis : int or None, optional
- The array axis along which the background is calculated. If
None, then the entire array is used. Passed to the
__call__
function.
- result : float or ~numpy.ma.MaskedArray
- The calculated background value. If
axis
is None then a scalar will be returned, otherwise a ~numpy.ma.MaskedArray will be returned.
This block requires no methods beyond first initialisation, and __call__()
.
A variety of implementations of this block already exist in photutils
. A
canonical example is the mode estimation algorithm 3 * median - 2 * mean
.
This can be done on an array called image_data
by using the block like so:
from photutils.background import ModeEstimatorBackground bkg_estimator = ModeEstimatorBackground() bkg_value = bkg_estimator(image_data)
The median/mean parameter values can be adjusted as keyword arguments to the estimator object if desired:
tweaked_bkg_estimator = ModeEstimatorBackground(median_factor=3.2, mean_factor=1.8) new_bkg_value = tweaked_bkg_estimator(image_data)
The estimator will also accept a sigma clipping object that automatically does sigma clipping before the background is subtracted, like so:
from astropy.stats import SigmaClip clipped_bkg_estimator = ModeEstimatorBackground(sigma_clip=SigmaClip(sigma=3.)) clipped_bkg_value = clipped_bkg_estimator(image_data)
CullerAndEnder determines the fit quality of any sources found in PSF fitting routines that build off ~photutils.psf.BasicPSFPhotometry to include an iterative element, such as ~photutils.psf.IterativelySubtractedPSFPhotometry. It removes any sources from the input ~astropy.table.Table below a minimum fit criterion, and subsequently determines whether the loop can be ended prematurely, most likely when all found sources are of good quality and no additional sources have been found. This method may be subject to API changes in future versions and should not be considered final.
This block is an extra step at the end of each iterative PSF fitting loop, set up
to consider whether the fitting process is complete, or if any sources can have
their fits improved or be added to the output table. As such it requires three
inputs: data
, the ~astropy.table.Table of sources found in the N-1 previous
iterations of the routine with their corresponding positions, fluxes, etc.;
psf_model
, the ~astropy.modeling.Fittable2DModel describing the PSF; and
new_sources
, a ~astropy.table.Table list of those sources found in the
residual image once the data
sources are removed (i.e., additional sources
with no previously derived parameters).
The two halves of the block are further split into "cull" and "end": one function
determining whether any sources in data
are sufficiently poorly explained by
psf_model
that they should not be considered sources at all (e.g., they are
cosmic ray hits picked up as being above some local background); and a second
function, which considers whether we have reached the end of the finding of new
sources prematurely (whether finding all sources before the loop counter reaches
niters
or simply because there are no new sources if niters = None
). These
functions (cull_data
and end_loop
) return a new_data
table, with culled
sources (those whose goodness-of-fit criteria are sufficiently low to be deemed
non-stellar, e.g.), and end_flag
, a boolean for whether the iterations can be
ceased (prematurely or not), respectively.
Each subclass of CullerAndEnderBase
can then provide its own definitions of
cull_data
and end_loop
depending on the specific user cases. For example,
end_loop
could simply be return len(new_sources) == 0
, while cull_data
would likely involve the removal of sources with a chi-squared fit to psf_model
above some threshold, or equivalent.
- data : ~astropy.table.Table
- Table containing the sources.
- psf_model : astropy.modeling.Fittable2DModel instance
- PSF/PRF model to which the data are being fit.
- new_sources : ~astropy.table.Table
- Newly found list of sources to compare with the sources
in
data
, when deciding whether to end iteration.
- culled_data : ~astropy.table.Table
-
data
with poor fits removed. - end_flag : boolean
- Flag indicating whether to end iterative PSF fitting before the maximum number of loops.
In the simplest example, a list of sources found_sources
with parameters x_0
, y_0
and flux
are compared to the expected PSF model (a ~astropy.modeling.Fittable2DModel
such as photutils.psf.IntegratedGaussianPRF) and any fits above some minimum goodness-of-fit
criterion are removed. If len(new_sources) == 0 then end_flag would return True, otherwise
it will be set to False.:
from photutils.psf import CullerAndEnder culler_and_ender = CullerAndEnder() good_sources, end_flag = culler_and_ender(found_sources, psf_model, new_sources)
Existing code documented here
-- see the find_stars
function for the basic API. Finder
is a relatively
independent routine in the PSF fitting process, and as such it is documented within its
own documentation blocks, based on StarFinderBase
; it is documented here for
completeness.
The object which defines the detection of objects in an image. Subclass finders
may require additional parameters -- see below for the example of DAOStarFinder
. The
class is defined entirely by its find_stars
function, with some initialization,
depending on the individual subclass.
find_stars
accepts data
, the two-dimensional image in which sources should be
found, and returns table
, an ~astropy.table.Table list of sources which passed
the given detection criteria. For example, in ~photutils.detection.DAOStarFinder
a source must have given sharpness
and roundness
within specified ranges for
acceptance as a detected source.
- data : array_like
- The 2D image array in which the finder should detection sources.
- table : ~astropy.table.Table
- The table of detected sources.
StarFinder currently implements two methods: DAOFind and IRAFFind. For example, daofind can be run to find objects with FWHM of approximately 3 pixels with a peak 5-sigma above the background:
from photutils import DAOStarFinder daofind = DAOStarFinder(fwhm=3.0, threshold=5.*std) sources = daofind(data)
The fitter block is unique in that it is a class not implemented as part of photutils. Rather, it is an object that follows the interface for fitters in the astropy.modeling package. Note that implicitly the fitters for PSF photometry are always fitters appropriate for 2D models (i.e., 2 input dimensions for the x and y pixel coordinates and a "flux" output).
Documented as the __call__
method of GroupStarsBase
-- see here
for more information. The API for the group maker may be subject to change if group_stars
requires changes to accommodate future revisions to the PSF fitting process -- primarily it
would require updates if the PSF fitting is extended to include non-point sources and
"scene maker" functionality. These large changes would subsequently require significant
changes to the PSF fitting routines (e.g., ~photutils.psf.IterativelySubtractedPSFPhotometry)
as a whole.
A function which groups stars within some critical separation, returning potentially
overlapping sources with an additional column indicating their common group members.
Subclasses of GroupStarsBase
may require further input parameters, such as
crit_separation
required for DAOGroup
.
The main functionality of this routine is within group_stars
, which accepts
starlist
, a ~astropy.table.Table of sources with centroid positions, and returns
group_starlist
, the same ~astropy.table.Table passed to the routine but with an
additional column indicating the group number of the sources. These sources are grouped
by the individual criteria specified within the group_stars
function defined by the
GroupStarsBase
subclass in question.
- starlist : ~astropy.table.Table
- List of star positions;
x_0
andy_0
, the centroids of the sources, must be provided.
- group_starlist : ~astropy.table.Table
-
starlist
with an additional column appended --group_id
gives unique group number of mutually overlapping sources.
Convenience function provided by DAOGroup
returning all objects within
crit_separation
from a given star from starlist
.
- star : ~astropy.table.Row
- Single star from
starlist
whose mutual group members are required. - starlist : ~astropy.table.Table
- List of star positions;
x_0
andy_0
, the centroids of the sources, must be provided.
~numpy.array with the IDs of all stars with distance less than crit_separation
to star
.
Here we create a DAOGroup
list of overlapping sources, then find all sources within 3 pixels
of the first source in the list.
from photutils.psf.groupstars import DAOGroup group = DAOGroup(starlist, crit_separation=3) stargroups = group.group_stars(starlist) id_overlap = group.find_stars(starlist[0], starlist)
NoiseData handles the determination and use of data uncertainty in the fitting of PSF models to image arrays, either by calculating the uncertainty of each image array value or by allowing the passing of a previously determined uncertainty array along with the array containing the image counts. This method may be subject to API changes and should not currently be considered the final API specification.
NoiseData is currently handled as an additional input parameter for ~photutils.psf.BasicPSFPhotometry, and by extension more complex PSF fitting routines, such as ~photutils.psf.IterativelySubtractedPSFPhotometry. It is either a function that calculates the corresponding uncertainty value of a given data value, a value such that the uncertainty array is ignored and all data values effectively given unity weighting, or set to indicate that the uncertainties for the image array were pre-computed and passed into the routine.
noise_calc
should therefore be provided as a callable
function (or None in
which case it is ignored) returning the uncertainty (in standard deviations)
of each pixel, the same shape as the input image
array. The data and
uncertainty arrays are then wrapped in an ~astropy.nddata.NDData
instance. Alternatively, if image
is provided as an
~astropy.nddata.NDData instance with both data
and uncertainty
attributes then noise_calc
is ignored and the provided uncertainty array
in image
is used directly when calling the chosen fitter
in the PSF
fitting routine.
- image : array-like
- The input image for which the uncertainty of each pixel is to be calculated.
- uncertainty : array-like
- The uncertainties of the input
image
values, as determined by the callable functionnoise_calc
. Must return an array of the same shape asimage
.
The simplest, and perhaps most common, uncertainty used in photometry is that
derived from Poissonian statistics, where the standard deviation is the square
root of the photon counts. We can then simply pass the ~numpy.sqrt function
as noise_calc
:
import numpy as np from astropy.modeling.fitting import LevMarLSQFitter from photutils.psf import (DAOGroup, IntegratedGaussianPRF, IterativelySubtractedPSFPhotometry) from photutils.background import MMMBackground from photutils.detection import IRAFStarFinder daogroup = DAOGroup(crit_separation=8) mmm_bkg = MMMBackground() iraffind = IRAFStarFinder(threshold=2.5*self.mmm_bkg(image), fwhm=4.5) fitter = LevMarLSQFitter() psf_model = IntegratedGaussianPRF(sigma=2.05) psf_model.sigma.fixed = False iter_phot_psf = IterativelySubtractedPSFPhotometry(finder=iraffind, group_maker=daogroup, bkg_estimator=mmm_bkg, psf_model=psf_model, fitter=fitter, fitshape=(11, 11), niters=2, noise_calc=np.sqrt)
However, if we wished, we could instead derive our own, more complex function to determine the corresponding uncertainty of a given pixel value. For instance, if -- for whatever reason -- the uncertainty of our data points was determined to be the logarithm of the absolute value of the counts, we could write such a function, remembering that the returned array must match in shape the input image:
def new_uncert_func(image): return np.log10(np.abs(image) + 5) iter_phot_psf = IterativelySubtractedPSFPhotometry(finder=iraffind, group_maker=daogroup, bkg_estimator=mmm_bkg, psf_model=psf_model, fitter=fitter, fitshape=(11, 11), niters=2, noise_calc=new_uncert_func)
The model for the PSF -- integrated over discrete pixels (see discussion
on terminology for more details) -- on which we should evaluate the parameters
of the source. The main input is a 2D image, with the model returning flux
,
x_0
, and y_0
, the overall source flux and centroid position. PSF models
in the current photutils.psf
are not explicitly defined as a specific class,
but any 2D model (inputs: x,y, output: flux) can be considered a PSF Model.
This block is primarily an external block, defined as a
~astropy.modeling.Fittable2DModel, and should have a well documented subclass.
The requirements for use within the PSF model block are that the
~astropy.modeling.Fittable2DModel have parameters flux
, x_0
, and y_0
,
as well as the evaluate
function. When the model is combined with a minimization
routine the best fitting flux and position for the input data
image array
containing the source are returned.
The ~photutils.psf.PRFAdapter class allows for the wrapping of any arbitrary
other models to make it compatible with the machinery. Some individual models
will require additional parameters, such as the IntegratedGaussianPRF
which
additionally requiring sigma
as a parameter that describes the underlying
Gaussian PSF.
- data : np.ndarray
- Array containing the 2D image representing the source(s) that should be evaluated for centroiding and flux.
- flux : float
- The flux of the source; if any normalization has been applied then
flux
will be set to 1. - x_0 : float
- The position of the source in the x axis, to sub-pixel resolution.
- y_0 : float
- The position of the source in the y axis, to sub-pixel resolution.
Function that returns the values of the pixels of a model with flux
, x_0
and
y_0
as parameters.
- x : float
- Central values of the pixels in the x axis at which to evaluate the PSF.
- y : float
- Central values of the pixels in the y axis at which to evaluate the PSF.
- flux : float
- Overall flux level of source, setting the scaling of each pixel.
- x_0 : float
- The centroid position of the source in the x axis.
- y_0 : float
- The centroid position of the source in the y axis.
The evaluation of the PSF, integrated over discrete pixels, at the centroid position and with the flux level specified.
Here we create a discrete Gaussian PSF with standard deviation of 2 pixels, and fit for centroid and overall flux level of a source.:
from photutils.psf import IntegratedGaussianPRF psf_model = IntegratedGaussianPRF(sigma=2) model_image = psf_model.evaluate(x, y, flux, x_0, y_0, sigma=2)
SceneMaker does not yet exist in the framework of PSF Photometry. This API is therefore a work in progress and should be considered as such.
However, the block will likely involve an additional column or variable attributed
to each source in the input ~astropy.table.Table indicating whether sources are
stars or more extended objects. This column will be used in conjunction with
SingleObjectModel
, which already has the framework to accept object_type
which
allows for individual extended sources to be handled, depending on the specific
class used for the specific purpose. The given list of single object models allowed
by, and available to, SingleObjectModel
must be the same list of physical
source classes (stars, galaxies, etc.) as SceneMaker
uses to group and merge
detected sources into point sources or extended objects. The block must also handle
the possibility of merging several point sources into an extended object and vice
versa.
SceneMaker should be considered an extension of GroupMaker, and will likely accept
outputs from that block. Sources grouped together by GroupMaker will subsequently
be assigned as multiple single sources or one larger, extended source erroneously split
up by the Finder, or some combination of the two. This information will then be used by
SingleObjectModel to fit the grouped sources as either individual point sources or
extended sources, based on object_type
.
SingleObjectModel handles the creation of the model image of an
astrophysical object, combining physical on-sky flux distributions with the
effects of the PSF, extending the psf_model
block of the PSF
fitting routine to include non-point sources. This method may be subject
to API changes in future versions and should not be considered final.
This block is an additional step between the PSF (or PRF) ~astropy.modeling.Fittable2DModel and the ~astropy.modeling.fitting.Fitter instance, to allow for cases where the images being fit contain sources other than point sources. In these instances a combined PRF, combining the PSF resulting from telescope optics, CCD, etc. with that of the intrinsic source as it would appear with infinite resolution is required. If the source is a simple point source, then the block simply returns the given PSF, avoiding the lengthy computational time of image convolution.
The single object model -- the model determining what type of object
(single star, binary star, galaxy, supernova, etc.) this source is assumed
to be -- is described by an additional column of the star
source list
created during the PSF fitting routine. For a given fit the object is
determined by star['object_type']
which is accepted as the string
argument object_type
by SingleObjectModel
. Additionally,
psf_model
, the ~astropy.modeling.Fittable2DModel describing the PSF,
accounting for quantized detector pixels, is required. The block then returns
convolve_psf_model
, the convolution of psf_model
with the flux
distribution intrinsic to the source with given internal parameters
(such as galaxy distance to correct for apparent size, time since
supernova explosion to produce the correct lightcurve, etc.). The class must
be a subclass of SingleObjectModelBase
, with the individual class provided
to the PSF fitting routine accepting a specific set of sources to be passed
in object_type
, with each object being handled on a case-by-case basis.
This block is also related to SceneMaker
, the future extension to the
standard "source grouping" aspect of the PSF fitting process, which additionally
allows for the grouping of several objects, otherwise assumed to be single point
sources, into a composite extended source, and vice versa. It is
SceneMaker
which therefore dictates the object_type
of a given source
in the created star
catalogue. SceneMaker
must be set up such that it
will group and merge star
sources into groups such that all object types
determined are accepted by SingleObjectModel
-- the two blocks must therefore
work closely in parallel with one another.
- psf_model : ~astropy.modeling.Fittable2DModel instance
- The model describing the PSF/PRF of the image, used to fit individual point source objects.
- object_type : string
- The extended source type used to determine the innate light distribution of the source.
- convolve_psf_model : ~astropy.modeling.Fittable2DModel instance
- The new, combined PRF of the extended source, combining the intrinsic light distribution and PSF effects.
This class simply takes the ~astropy.modeling.Fittable2DModel instance and convolves it with the appropriate model describing the, e.g., galaxy light distribution:
from photutils.psf import SingleObjectModel single_object_model = SingleObjectModel() new_composite_psf = single_object_model(psf_to_add, star['object_type'])
The photutils.psf sub-package implements a variety of PSF fitting algorithms. These fitting algorithms are broken down into a series of modules, allowing the user to implement specific versions of each part of the fitting process, implementing a variety of fitting procedures best suited to the specific science cases. However, at its most basic, all choices share the same basic functionality: a 2D image is supplied and a ~astropy.table.Table of detected sources, with positions and flux counts, is returned. Optionally, the user can also supply a ~astropy.table.Table of previously detected source positions as an input, for cases such as forced photometry where sources have previously been found in an image and their positions known already.
This simplified workflow is expanded below for the case of the
~photutils.psf.IterativelySubtractedPSFPhotometry class, building upon the simpler
~photutils.psf.BasicPSFPhotometry algorithm. While there are additional blocks
used within the workflow, the main ~photutils.psf.BasicPSFPhotometry flow is
image
-> finder
-> group maker
-> fitter
-> sources
. The extension to more
complex fitting classes, such as ~photutils.psf.IterativelySubtractedPSFPhotometry,
have the flow image
-> finder
-> group maker
-> fitter
-> culler and ender
->
finder
-> ... -> sources
.
A brief summary of each block is given here, with context for how it fits into the overall PSF fitting framework, providing a top-down view of the process. More detailed descriptions of the blocks are available in other documentation pages (linked from each section below).
<img width="602" alt="graphviz_figure" src="https://github.com/user-attachments/assets/8bd1977f-b52b-4a74-a81c-7d9d34d55899">
(graphviz code) digraph PSFFitting { compound = true; newrank = true; subgraph cluster0 { label="IterativePSFPhotometry" subgraph cluster2 { label="BasicPSFPhotometry" f [label = "finder"]; g [label = "group maker"]; some [label = "single object model"]; n [label = "noise"]; ft [label = "fitter"]; b [label = "background estimator"]; // required to allow finder and guess to combine into group maker invis [shape = circle, width = .1, fixedsize = true, style = invis]; } c [label = "culler and ender"]; im2 [label = "changes to image/sources inputs"]; } w [label = "wcs"]; i [label = "input image", shape = box]; gs [label = "guess at sources", shape = box]; p [label = "psf model"]; sm [label = "scene maker"]; st [label = "sources\n(astropy.table)", shape = box]; label = <<FONT POINT-SIZE = "20"><I>photutils.psf</I> class structures</FONT>>; labelloc = top; w -> i [style = dashed]; // lhead = cluster0 sets the arrow end at the subgraph, rather than at finder itself i -> f; i -> b [style = dashed]; gs -> invis [style = dashed]; f -> g; f -> invis; invis -> g; some -> f [style = dashed]; n -> ft; some -> ft; g -> ft; b -> f [style = dashed]; b -> g [style = dashed]; b -> ft [style = dashed]; ft -> c [style = dashed]; c -> im2 [style = dashed]; im2 -> f [style = dashed]; i -> gs [style = invis]; p -> some; sm -> g [style = dotted]; c -> st; // reverse arrow to put psf model above scene maker, saving space with scene // maker next to the middle of the main box p -> sm [style = dotted, dir = back]; // puts things that should be at the top of the box at the top for orientation // and structuring; requires 'newrank' above to set subgraph items equal {rank = same; w; some;} {rank = same; p; f; n;} {rank = same; gs; g; sm;} {rank = same; c; st} subgraph cluster1 { ranksep=0 label="Legend"; solid [label = "Required flow of data", shape=plaintext]; dashed [label = "Optional information flow", shape=plaintext]; dotted [label = "Optional component", shape=plaintext]; invis_1 [width = .1, fixedsize = true, style = invis]; invis_2 [width = .1, fixedsize = true, style = invis]; invis_3 [width = .1, fixedsize = true, style = invis]; } solid -> invis_1 [style = solid]; dashed -> invis_2 [style = dashed]; dotted -> invis_3 [style = dotted]; {rank = same; solid; invis_1; dashed; invis_2; dotted; invis_3;} im2 -> dashed [style = invis] }
The input image is the most fundamental part of the PSF fitting process, as it is the
product on which all subsequent methodology is applied. The image must be a two-dimensional
array of x
and y
coordinates with flux
represented by array values. If a
WCS -- contained within a FITS file, for instance -- is passed with the two-dimensional
array then the position of sources can be given in sky coordinates, instead of pixel values.
These, as well as arrays corresponding to the uncertainty of each data
array value
and a pixel-wise mask for data
may be passed in an ~astropy.nddata.NDData object;
alternatively, if they are passed separately an ~astropy.nddata.NDData object will be
automatically converted. The given image's ~astropy.nddata.NDData is passed as an input
to the chosen PSF fitting class.
The finder is the first step in the PSF fitting process, as sources must be discovered in
the image before any kind of fit can be applied to them. All finders must be an implementation
of ~photutils.detection.StarFinderBase; the finder must accept the input image
and produce a ~astropy.table.Table of detected sources, by a set of criteria internal to
the given Finder
(see, e.g., ~photutils.detection.DAOStarFinder using roundness
and sharpness
to determine if sources are point-like). If an initial set of detected
sources is passed to the fitter as init_guesses
then Finder
is not run on the first
pass of an iterative fitting class, instead using the provided positions and fluxes. See
the finder documentation for more details.
The second block to run in the fitting process, the various group maker processes, such as ~photutils.psf.DAOGroup, allow for the merging of sources that are astrometrically near to one another into a set of multiple sources. These sources must be fit simultaneously (see Fitter_) as a composite model, making deblending of sources possible. The block accepts the ~astropy.table.Table output from Finder and returns a second ~astropy.table.Table containing the same columns as the input as well as an additional column indicating the group number of each source. More information on this block can be found in Group Maker.
Once a set of sources has been detected and grouped, each source must have its respective
properties -- always position and flux, but potentially other properties -- determined. For
this a Fitter
instance is required; these are drawn from a separate class or instance of
minimization routines, such as those implemented in ~astropy.modeling.fitting. The fitter has to
accept the image -- or image cutout -- and a ~astropy.table.Table containing the initial guesses
of source flux and position (and any additional derived parameters), and return an instance of the
class with its parameters set to the best fit values. See below for more details on
the PSF model, the fitter documentation for further information on the
Fitter
instance and its properties, and the
Astropy documentation for information on the fitter API.
Perhaps the most important aspect of PSF fitting, the PSF Model
describes the distribution
of light falling on a given pixel from a source at some position with some total flux, fully
describing the effects of telescope optics, quantized CCD pixels, etc. In this respect it is
more properly described as a pixel response function (PRF) than a point spread function (PSF) --
see the PSF model documentation and
PSF terminology pages for
more details -- but we use a single term here for brevity. Similar to the Fitter
, it is
a separate callable class detailing a specific PSF response. This can be some analytical
function, such as ~photutils.psf.IntegratedGaussianPRF, or an empirical description of the
PSF, such as that implemented by the effective PSF functionality (see build-epsf
details). These models must follow the Astropy modeling API for two-dimensional models; please refer there for more information.
The noise
block within the PSF fitting process is, in much the same way as the Fitter
block, a separate callable
function mapping the relationship between the pixel values in
the input image
and the corresponding uncertainty of the pixel. It must therefore accept a
two-dimensional array and return an array of the same shape as image
. Alternatively it can be
overloaded to indicate that the uncertainty array was passed along with image
via an
~astropy.nddata.NDData instance. A more detailed description of this block is available in the noise data section.
The image
on which source extraction and evaluation is to be performed is not necessarily
assumed to have had any pre-processing applied to it, and thus it may be necessary to account
for the counts of the image background when handling PSF fitting. This block handles
the determination of the background levels, and should provide the typical count of an otherwise
empty pixel. The block must therefore accepts the two-dimensional image
and returns either a
single value -- the background count of the entire image, as calculated by the criteria of the
specific block implementation -- or a 2D array of values, allowing for the possibility of varying
background counts across the image. More information on this block can be found
"background_estimator".
Only implemented in iterative fitting classes, part of the extension to
~photutils.psf.BasicPSFPhotometry, this block is the final step of a single iteration. While
a maximum number of iterations can be specified for, e.g.,
~photutils.psf.IterativelySubtractedPSFPhotometry, this block -- specifically, the ender half
-- assesses whether all sources have been found within the image
. If no new sources have
been found within an iteration, fitting can be stopped prematurely, avoiding wasteful computational
time. Similarly, the culler aspect of this block examines sources found within an iteration for
quality; it should calculate some goodness-of-fit criterion and reject sources picked up by the
Finder
but fall below a given threshold. This block therefore accepts the sources
output ~astropy.table.Table and returns a new ~astropy.table.Table with low quality sources
-- such as cosmic ray hits present in the image -- removed as well as a boolean flag indicating
whether the iterative fitting process has reached a conclusion and can be terminated. Please refer
to the culler_and_ender documentation for further details.
An additional block sitting between the PSF model and the Fitter_, the Single Object Model
extends the fitting capability of the class from purely point-source objects to extended sources.
This block, effectively, convolves the PSF of the given observation with a physical light
distribution, producing the flux seen in each pixel by the system of such an extended source. This
block therefore requires as its inputs the PSF model and the object type -- a string representing
the type of source (point-like, spiral galaxy, etc.) to create the intrinsic light distribution
for -- and returns a new ~astropy.modeling.Fittable2DModel instance, the convolution of the PSF
and the true source. Further specifics on this block, including how it connects to Scene Maker
can be found in the single object model documentation. This block is optional; if no
additional physical object options are provided, the object type defaults to a point source and
the input PSF model is returned.
The final block within the scope of PSF fitting, the scene maker is also the last to be implemented. Currently no PSF fitting class extends its functionality to include this block, but it will eventually generalize and extend the Group Maker as the method of merging and assigning non-independent detections within a given image. While current grouping is simply the determining of point sources with potentially overlapping flux, the scene maker will allow for the grouping of both point sources into an overlapping, simultaneous fit group but also into a single extended object. Thus each iteration will require a step in which multiple-point-source extended objects are evaluated for their separation, and newly detected point sources are evaluated for potential assignment as part of an extended source. This block will be optional: if no additional object types are provided, all sources will be returned as point sources, as given by the group maker. The details of this block are available in the scene_maker docs, and will be expanded upon as the API is finalized.