Source code for photutils.morphology.core

# Licensed under a 3-clause BSD style license - see LICENSE.rst
"""
Tools for measuring morphological properties of sources.
"""

import numpy as np

from photutils.utils._deprecation import deprecated_positional_kwargs

__all__ = ['data_properties']


[docs] @deprecated_positional_kwargs(since='3.0', until='4.0') def data_properties(data, mask=None, background=None, wcs=None): """ Calculate the morphological properties (and centroid) of a 2D array (e.g., an image cutout of an object) using image moments. Parameters ---------- data : array_like or `~astropy.units.Quantity` The 2D array of the image. mask : array_like (bool), optional A boolean mask, with the same shape as ``data``, where a `True` value indicates the corresponding element of ``data`` is masked. Masked data are excluded from all calculations. background : float or array_like, optional The background level previously present in the input ``data``. ``background`` may be a scalar value or a 2D array with the same shape as ``data``. The input ``background`` is not subtracted from ``data``, which should already be background-subtracted; providing it only enables background-related properties to be measured. wcs : WCS object or `None`, optional A world coordinate system (WCS) transformation that supports the `astropy shared interface for WCS <https://docs.astropy.org/en/stable/wcs/wcsapi.html>`_ (e.g., `astropy.wcs.WCS`, `gwcs.wcs.WCS`). If `None`, then all sky-based properties will be set to `None`. Returns ------- result : `~photutils.segmentation.SourceCatalog` instance A scalar `~photutils.segmentation.SourceCatalog` object (single source) containing the morphological properties. Raises ------ ValueError If ``data`` is not a 2D array. ValueError If ``mask`` is provided and does not have the same shape as ``data``. ValueError If ``mask`` is provided and all pixels are masked. ValueError If ``background`` is provided and is not a scalar or a 2D array with the same shape as ``data``. """ # Prevent circular import from photutils.segmentation import SegmentationImage, SourceCatalog data = np.asanyarray(data) if len(data.shape) != 2: msg = 'data must be a 2D array' raise ValueError(msg) seg_arr = np.ones(data.shape, dtype=int) if mask is not None: mask = np.asarray(mask, dtype=bool) if mask.shape != data.shape: msg = 'mask must have the same shape as data' raise ValueError(msg) if np.all(mask): msg = 'All pixels in data are masked' raise ValueError(msg) seg_arr[mask] = 0 segment_image = SegmentationImage(seg_arr) if background is not None: background = np.asarray(background) if background.ndim == 0: background = np.full(data.shape, float(background)) elif background.shape != data.shape: msg = ('background must be a scalar or a 2D array ' 'with the same shape as data') raise ValueError(msg) # mask is encoded in seg_arr (masked pixels set to 0), so # mask=None is intentional here return SourceCatalog(data, segment_image, mask=None, background=background, wcs=wcs)[0]