def source_morphology(in_image, ext_name, **kwargs): fo = fits.open(in_image, "append") hdu = fo[ext_name] segm_obj = SegmentationImage(fo["DEBLEND"].data) errmap = fo["WEIGHT_MAP"].data seg_props = fo["DEBLEND_PROPS"].data im = hdu.data bkg_estimator = photutils.MedianBackground() bkg = photutils.Background2D(hdu.data, (50, 50), bkg_estimator=bkg_estimator) im -= bkg.background npix = im.shape[0] center_slice = segm_obj.data[int(npix / 2) - 2:int(npix / 2) + 2, int(npix / 2) - 2:int(npix / 2) + 2] central_index = np.where(seg_props["id"] == center_slice[0, 0])[0][0] fo.flush() fo.close() source_morph = statmorph.SourceMorphology(im, segm_obj, central_index, weightmap=errmap, **kwargs) return source_morph
def test_catastrophic(): label = 1 image = np.full((3, 3), -1.0) segmap = np.full((3, 3), label) gain = 1.0 with catch_warnings(AstropyUserWarning) as w: morph = statmorph.SourceMorphology(image, segmap, label, gain=gain) assert w[0].category == AstropyUserWarning assert 'Total flux is nonpositive.' in str(w[0].message) assert morph.flag_catastrophic == 1
def test_full_gini_segmap(): """ This produces a "full" Gini segmap. """ label = 1 ny, nx = 11, 11 y, x = np.mgrid[0:ny, 0:nx] image = np.exp(-((x - nx // 2)**2 + (y - ny // 2)**2) / 50) segmap = np.int64(image > 0.5) with catch_warnings(AstropyUserWarning) as w: morph = statmorph.SourceMorphology(image, segmap, label, gain=1.0) assert w[-3].category == AstropyUserWarning assert 'Full Gini segmap!' in str(w[-3].message) assert morph.flag == 1
def test_random_noise(): np.random.seed(1) ny, nx = 11, 11 image = 0.1 * np.random.standard_normal(size=(ny, nx)) weightmap = 0.01 * np.random.standard_normal(size=(ny, nx)) segmap = np.ones((ny, nx), dtype=np.int64) label = 1 with catch_warnings(AstropyUserWarning) as w: morph = statmorph.SourceMorphology(image, segmap, label, weightmap=weightmap) assert w[-1].category == AstropyUserWarning assert morph.flag == 1
def test_negative_source(): label = 1 ny, nx = 51, 51 y, x = np.mgrid[0:ny, 0:nx] r = np.sqrt((x - nx // 2)**2 + (y - ny // 2)**2) image = np.ones((ny, nx), dtype=np.float64) locs = r > 0 image[locs] = 2.0 / r[locs] - 1.0 segmap = np.int64(r < 2) with catch_warnings(AstropyUserWarning) as w: morph = statmorph.SourceMorphology(image, segmap, label, gain=1.0) assert w[0].category == AstropyUserWarning assert 'Total flux sum is negative.' in str(w[0].message) assert morph.flag == 1
def test_asymmetric(): """ Test a case in which the asymmetry center is pushed outside of the image boundaries. """ label = 1 y, x = np.mgrid[0:25, 0:25] image = x - 20 segmap = image > 0 with catch_warnings(AstropyUserWarning) as w: morph = statmorph.SourceMorphology(image, segmap, label, gain=1.0) assert w[0].category == AstropyUserWarning assert 'Minimizer tried to exit bounds.' in str(w[0].message) assert morph.flag == 1 assert morph._use_centroid
def test_empty_gini_segmap(): """ This pathological case results in an "empty" Gini segmap. """ label = 1 np.random.seed(0) ny, nx = 11, 11 y, x = np.mgrid[0:ny, 0:nx] image = x - 9.0 segmap = image > 0 image += 0.1 * np.random.standard_normal(size=(ny, nx)) with catch_warnings(AstropyUserWarning) as w: morph = statmorph.SourceMorphology(image, segmap, label, gain=1.0) assert w[-1].category == AstropyUserWarning assert 'Segmaps are empty!' in str(w[-1].message) assert morph.flag == 1
def test_full_segmap(): ny, nx = 11, 11 y, x = np.mgrid[0:ny, 0:nx] image = np.exp(-(x - 5)**2 - (y - 5)**2) segmap = np.ones((ny, nx), dtype=np.int64) label = 1 with catch_warnings(AstropyUserWarning) as w: morph = statmorph.SourceMorphology(image, segmap, label, gain=1.0, verbose=True) assert w[-1].category == AstropyUserWarning assert 'Image is not background-subtracted.' in str(w[-1].message) assert morph.flag == 1 assert morph._slice_skybox == (slice(0, 0), slice(0, 0))
def test_masked_centroid(): label = 1 ny, nx = 11, 11 y, x = np.mgrid[0:ny, 0:nx] image = np.exp(-(x - 5)**2 - (y - 5)**2) segmap = np.int64(image > 1e-3) mask = np.zeros((ny, nx), dtype=np.bool8) mask[5, 5] = True with catch_warnings(AstropyUserWarning) as w: morph = statmorph.SourceMorphology(image, segmap, label, gain=1.0, mask=mask) assert w[0].category == AstropyUserWarning assert 'Centroid is masked.' in str(w[0].message) assert morph.flag == 1
def test_merger(): """ Test a "merger" scenario. This manages to produce different Gini and MID segmaps, as well as a failed Sersic fit. """ label = 1 ny, nx = 25, 25 y, x = np.mgrid[0:ny, 0:nx] image = np.exp(-(x - 8)**2 / 4 - (y - 12)**2) image += np.exp(-(x - 16)**2 / 4 - (y - 12)**2) segmap = np.int64(np.abs(image) > 1e-3) with catch_warnings(AstropyUserWarning) as w: morph = statmorph.SourceMorphology(image, segmap, label, gain=1.0) assert w[-1].category == AstropyUserWarning assert 'Gini and MID segmaps are quite different.' in str( w[-1].message) assert morph.flag == 1
def test_insufficient_data(): """ Test insufficient data for Sersic fit (< 7 pixels). Note that we do not remove outliers. """ label = 1 image = np.zeros((2, 3), dtype=np.float64) image[:, 1] = 1.0 segmap = np.int64(image) with catch_warnings(AstropyUserWarning) as w: morph = statmorph.SourceMorphology(image, segmap, label, gain=1.0, n_sigma_outlier=-1) assert w[-2].category == AstropyUserWarning assert '[sersic] Not enough data for fit.' in str(w[-2].message) assert morph.flag == 1
def test_tiny_source(): """ Test tiny source (actually consisting of a single bright pixel). Note that we do not remove outliers. """ label = 1 image = np.zeros((5, 5), dtype=np.float64) image[2, 2] = 1.0 segmap = np.int64(image) with catch_warnings(AstropyUserWarning) as w: morph = statmorph.SourceMorphology(image, segmap, label, gain=1.0, n_sigma_outlier=-1) assert w[0].category == AstropyUserWarning assert 'Nonpositive second moment.' in str(w[0].message) assert morph.flag == 1
def test_small_source(): np.random.seed(1) ny, nx = 11, 11 y, x = np.mgrid[0:ny, 0:nx] image = np.exp(-(x - 5)**2 - (y - 5)**2) image += 0.001 * np.random.standard_normal(size=(ny, nx)) segmap = np.int64(image > 0.1) label = 1 with catch_warnings(AstropyUserWarning) as w: morph = statmorph.SourceMorphology(image, segmap, label, gain=1.0, verbose=True) assert w[-1].category == AstropyUserWarning assert 'Single clump!' in str(w[-1].message) assert morph.flag == 0 assert morph.multimode == 0 assert morph.intensity == 0
def test_bright_pixel(): """ Test bright pixel outside of main segment. Note that we do not remove outliers. """ label = 1 ny, nx = 11, 11 y, x = np.mgrid[0:ny, 0:nx] image = np.exp(-(x - 5)**2 - (y - 5)**2) image[7, 7] = 1.0 segmap = np.int64(image > 1e-3) segmap[5, 5] = 0 with catch_warnings(AstropyUserWarning) as w: morph = statmorph.SourceMorphology(image, segmap, label, gain=1.0, n_sigma_outlier=-1) assert w[0].category == AstropyUserWarning assert 'Adding brightest pixel to segmap.' in str(w[0].message) assert morph.flag == 1
def test_missing_arguments(): label = 1 image = np.ones((3, 3), dtype=np.float64) segmap = np.ones((3, 3), dtype=np.int64) with pytest.raises(AssertionError): _ = statmorph.SourceMorphology(image, segmap, label)