def subtract_psf(data, psf, positions, fluxes, mask=None): """ Removes PSF/PRF at the given positions. To calculate residual images the PSF/PRF model is subtracted from the data at the given positions. Parameters ---------- data : ndarray Image data. psf : `photutils.psf.DiscretePRF` or `photutils.psf.GaussianPSF` PSF/PRF model to be substracted from the data. positions : ndarray List of center positions where PSF/PRF is removed. fluxes : ndarray List of fluxes of the sources, for correct normalization. """ # Set up indices indices = np.indices(data.shape) data_ = data.copy() # Loop over position for i, position in enumerate(positions): x_0, y_0 = position y = extract_array(indices[0], psf.shape, (y_0, x_0)) x = extract_array(indices[1], psf.shape, (y_0, x_0)) psf.amplitude.value = fluxes[i] psf.x_0.value, psf.y_0.value = x_0, y_0 psf_image = psf(x, y) data_ = add_array(data_, -psf_image, (y_0, x_0)) return data_
def test_add_array_equal_shape(): """ Test add_array_2D utility function. Test by adding an array of ones out of an array of zeros. """ large_test_array = np.zeros((11, 11)) small_test_array = np.ones((11, 11)) large_test_array_ref = large_test_array.copy() large_test_array_ref += small_test_array added_array = add_array(large_test_array, small_test_array, (5, 5)) assert np.all(added_array == large_test_array_ref)
def test_add_array_even_shape(): """ Test add_array_2D utility function. Test by adding an array of ones out of an array of zeros. """ large_test_array = np.zeros((11, 11)) small_test_array = np.ones((4, 4)) large_test_array_ref = large_test_array.copy() large_test_array_ref[0:2, 0:2] += small_test_array[2:4, 2:4] added_array = add_array(large_test_array, small_test_array, (0, 0)) assert np.all(added_array == large_test_array_ref)
def test_add_array_odd_shape(): """ Test add_array utility function. Test by adding an array of ones out of an array of zeros. """ large_test_array = np.zeros((11, 11)) small_test_array = np.ones((5, 5)) large_test_array_ref = large_test_array.copy() large_test_array_ref[3:8, 3:8] += small_test_array added_array = add_array(large_test_array, small_test_array, (5, 5)) assert np.all(added_array == large_test_array_ref)
def subtract_psf(data, psf, posflux, subshape=None): """ Subtract PSF/PRFs from an image. Parameters ---------- data : `~astropy.nddata.NDData` or array (must be 2D) Image data. psf : `astropy.modeling.Fittable2DModel` instance PSF/PRF model to be substracted from the data. posflux : Array-like of shape (3, N) or `~astropy.table.Table` Positions and fluxes for the objects to subtract. If an array, it is interpreted as ``(x, y, flux)`` If a table, the columns 'x_fit', 'y_fit', and 'flux_fit' must be present. subshape : length-2 or None The shape of the region around the center of the location to subtract the PSF from. If None, subtract from the whole image. Returns ------- subdata : same shape and type as ``data`` The image with the PSF subtracted """ if data.ndim != 2: raise ValueError(f'{data.ndim}-d array not supported. Only 2-d ' 'arrays can be passed to subtract_psf.') # translate array input into table if hasattr(posflux, 'colnames'): if 'x_fit' not in posflux.colnames: raise ValueError('Input table does not have x_fit') if 'y_fit' not in posflux.colnames: raise ValueError('Input table does not have y_fit') if 'flux_fit' not in posflux.colnames: raise ValueError('Input table does not have flux_fit') else: posflux = Table(names=['x_fit', 'y_fit', 'flux_fit'], data=posflux) # Set up contstants across the loop psf = psf.copy() xname, yname, fluxname = _extract_psf_fitting_names(psf) indices = np.indices(data.shape) subbeddata = data.copy() if subshape is None: indicies_reversed = indices[::-1] for row in posflux: getattr(psf, xname).value = row['x_fit'] getattr(psf, yname).value = row['y_fit'] getattr(psf, fluxname).value = row['flux_fit'] subbeddata -= psf(*indicies_reversed) else: for row in posflux: x_0, y_0 = row['x_fit'], row['y_fit'] # float dtype needed for fill_value=np.nan y = extract_array(indices[0].astype(float), subshape, (y_0, x_0)) x = extract_array(indices[1].astype(float), subshape, (y_0, x_0)) getattr(psf, xname).value = x_0 getattr(psf, yname).value = y_0 getattr(psf, fluxname).value = row['flux_fit'] subbeddata = add_array(subbeddata, -psf(x, y), (y_0, x_0)) return subbeddata
def subtract_psf(data, psf, posflux, subshape=None): """ Subtract PSF/PRFs from an image. Parameters ---------- data : `~astropy.nddata.NDData` or array (must be 2D) Image data. psf : `astropy.modeling.Fittable2DModel` instance PSF/PRF model to be substracted from the data. posflux : Array-like of shape (3, N) or `~astropy.table.Table` Positions and fluxes for the objects to subtract. If an array, it is interpreted as ``(x, y, flux)`` If a table, the columns 'x_fit', 'y_fit', and 'flux_fit' must be present. subshape : length-2 or None The shape of the region around the center of the location to subtract the PSF from. If None, subtract from the whole image. Returns ------- subdata : same shape and type as ``data`` The image with the PSF subtracted """ if data.ndim != 2: raise ValueError('{0}-d array not supported. Only 2-d arrays can be ' 'passed to subtract_psf.'.format(data.ndim)) # translate array input into table if hasattr(posflux, 'colnames'): if 'x_fit' not in posflux.colnames: raise ValueError('Input table does not have x_fit') if 'y_fit' not in posflux.colnames: raise ValueError('Input table does not have y_fit') if 'flux_fit' not in posflux.colnames: raise ValueError('Input table does not have flux_fit') else: posflux = Table(names=['x_fit', 'y_fit', 'flux_fit'], data=posflux) # Set up contstants across the loop psf = psf.copy() xname, yname, fluxname = _extract_psf_fitting_names(psf) indices = np.indices(data.shape) subbeddata = data.copy() if subshape is None: indicies_reversed = indices[::-1] for row in posflux: getattr(psf, xname).value = row['x_fit'] getattr(psf, yname).value = row['y_fit'] getattr(psf, fluxname).value = row['flux_fit'] subbeddata -= psf(*indicies_reversed) else: for row in posflux: x_0, y_0 = row['x_fit'], row['y_fit'] y = extract_array(indices[0], subshape, (y_0, x_0)) x = extract_array(indices[1], subshape, (y_0, x_0)) getattr(psf, xname).value = x_0 getattr(psf, yname).value = y_0 getattr(psf, fluxname).value = row['flux_fit'] subbeddata = add_array(subbeddata, -psf(x, y), (y_0, x_0)) return subbeddata