def test_create_psf_cube(): src = Source.from_file(get_data_file('sdetect', 'origin-00026.fits')) cube = Cube(get_data_file('sdetect', 'subcub_mosaic.fits')) src.add_FSF(cube) wcs = src.images['MUSE_WHITE'].wcs shape = src.images['MUSE_WHITE'].shape # a, b, beta, field = src.get_FSF() a = 0.862 b = -3.46e-05 beta = 2.8 psf = b * cube.wave.coord() + a # Gaussian gauss = create_psf_cube(psf.shape + shape, psf, wcs=wcs) im = Image(data=gauss[0], wcs=wcs) res = im.gauss_fit() assert_almost_equal(wcs.sky2pix(res.center)[0], [12., 12.]) assert np.allclose(res.fwhm, psf[0]) assert np.allclose(res.flux, 1.0) # Moffat moff = create_psf_cube(psf.shape + shape, psf, wcs=wcs, beta=beta) im = Image(data=moff[0], wcs=wcs) res = im.moffat_fit() assert_almost_equal(wcs.sky2pix(res.center)[0], [12., 12.]) assert np.allclose(res.fwhm, psf[0]) assert np.allclose(res.flux, 1.0, atol=1e-2)
def test_get_FSF_from_cube_keywords(): cube = Cube(get_data_file('sdetect', 'minicube.fits')) with pytest.raises(ValueError): # This cube has no FSF info PSF, fwhm_pix, fwhm_arcsec = get_FSF_from_cube_keywords(cube, 13) cube = Cube(get_data_file('sdetect', 'subcub_mosaic.fits')) PSF, fwhm_pix, fwhm_arcsec = get_FSF_from_cube_keywords(cube, 13) assert len(PSF) == 9 assert len(fwhm_pix) == 9 np.testing.assert_allclose(fwhm_pix[0] * 0.2, fwhm_arcsec[0])
def test_add_FSF(minicube): """Source class: testing add_FSF method""" src = Source.from_file(get_data_file('sdetect', 'origin-00026.fits')) assert src.get_FSF() is None with pytest.raises(ValueError): src.add_FSF(minicube) cube = Cube(get_data_file('sdetect', 'subcub_mosaic.fits')) src.add_FSF(cube) assert src.FSF99BET == 2.8 assert src.FSF99FWA == 0.843 assert src.FSF99FWB == -3.301e-05 assert src.get_FSF() == (0.843, -3.301e-05, 2.8, 99)
def test_add_FSF(minicube): """Source class: testing add_FSF method""" src = Source.from_file(get_data_file('sdetect', 'origin-00026.fits')) assert src.get_FSF() is None with pytest.raises(ValueError): src.add_FSF(minicube) cube = Cube(get_data_file('sdetect', 'subcub_mosaic.fits')) src.add_FSF(cube) assert src.FSFMODE == 2 assert src.FSF99FNC == 2 assert src.FSF99BNC == 1 assert np.isclose(src.FSF99B00, 2.8, 1e-2)
def test_rot(self): """WCS class: testing constructor 2 """ h = fits.getheader(get_data_file('obj', 'IMAGE-HDFS-1.34.fits'), ext=1) wcs = WCS(h) assert wcs.get_rot() == 0 wcs.rotate(90) assert wcs.get_rot() == 90
def test_copy_header(): hdr = fits.getheader(get_data_file('sdetect', 'a478hst-cutout.fits'))[:50] hdr2 = copy_header(hdr) for c, c2 in zip(hdr.cards, hdr2.cards): assert ((c.keyword, c.value, c.comment) == (c2.keyword, c2.value, c2.comment))
def test_from_hdr(self): """WaveCoord class: testing constructor """ h = fits.getheader(get_data_file('obj', 'Spectrum_Novariance.fits')) wave = WaveCoord(h) h2 = wave.to_header() wave2 = WaveCoord(h2) wave2.shape = wave.shape assert wave.isEqual(wave2)
def test_from_hdr2(self): """WCS class: testing constructor 2 """ with fits.open(get_data_file('sdetect', 'a478hst-cutout.fits')) as h: frame, equinox = determine_refframe(h[0].header) wcs = WCS(h[1].header, frame=frame, equinox=equinox) assert wcs.wcs.wcs.equinox == 2000.0 assert wcs.wcs.wcs.radesys == 'FK5' assert wcs.is_deg()
def test_make_white_image2(tmpdir): src = get_data_file('sdetect', 'minicube.fits') with pytest.raises(SystemExit): main(['-v', src]) cube = str(tmpdir.join('DATACUBE.fits')) shutil.copy(src, cube) main(['-v', cube]) assert os.path.isfile(str(tmpdir.join('IMAGE.fits')))
def test_from_hdr(self): """WCS class: testing constructor """ h = fits.getheader(get_data_file('obj', 'a370II.fits')) wcs = WCS(h) h2 = wcs.to_header() wcs2 = WCS(h2) wcs2.naxis1 = wcs.naxis1 wcs2.naxis2 = wcs.naxis2 assert wcs.isEqual(wcs2)
def test_mag(): """Spectrum class: testing magnitude computations.""" Vega = Spectrum(get_data_file('obj', 'Vega.fits')) Vega.unit = u.Unit('2E-17 erg / (Angstrom cm2 s)') Vega.wave.wcs.wcs.cunit[0] = u.angstrom assert_almost_equal(Vega.abmag_filter_name('V')[0], 0, 1) mag = Vega.abmag_filter_name('Ic')[0] assert mag > 0.4 and mag < 0.5 mag = Vega.abmag_band(22500, 2500)[0] assert mag > 1.9 and mag < 2.0
def test_from_file(): filename = get_data_file('sdetect', 'sing-0032.fits') src = Source.from_file(filename, ext='NB*') assert 'NB7317' in src.images src = Source.from_file(filename, ext=['NB*']) assert 'NB7317' in src.images src = Source.from_file(filename, ext='FOO') assert 'NB7317' not in src.images
def test_tods9(tmpdir): cat = Catalog.read(get_data_file('sdetect', 'cat.txt'), format='ascii') regfile = str(tmpdir.join('test.reg')) cat.to_ds9_regions(regfile) with open(regfile) as f: assert f.readlines()[:4] == [ '# Region file format: DS9 astropy/regions\n', 'fk5\n', 'circle(63.356106,10.466166,0.000278)\n', 'circle(63.355404,10.464703,0.000278)\n', ]
def test_get_band_image(): c = Cube(get_data_file('obj', 'CUBE.fits')) # Test unknown filter with pytest.raises(ValueError): c.get_band_image('foo') # Test non-overlapping filter with pytest.raises(ValueError): c.get_band_image('Johnson_B') im = c.get_band_image('Cousins_I') assert im.data.count() == 200 assert im.primary_header['ESO DRS MUSE FILTER NAME'] == 'Cousins_I'
def test_fsf_model(tmpdir): cubename = get_data_file('sdetect', 'subcub_mosaic.fits') cube = Cube(cubename) # Read FSF model with the old method with pytest.warns(MpdafWarning): PSF, fwhm_pix, fwhm_arcsec = get_FSF_from_cube_keywords(cube, 13) # Read FSF model from file fsf = FSFModel.read(cubename) assert len(fsf) == 9 assert fsf[0].model == 2 assert_allclose(fsf[0].get_fwhm(cube.wave.coord()), fwhm_arcsec[0]) # Read FSF model from cube fsf = FSFModel.read(cube) assert len(fsf) == 9 assert fsf[0].model == 2 assert_allclose(fsf[0].get_fwhm(cube.wave.coord()), fwhm_arcsec[0]) # Read FSF model from header and for a specific field hdr = cube.primary_header.copy() hdr.update(cube.data_header) fsf = FSFModel.read(hdr, field=2) assert fsf.model == 2 assert_allclose(fsf.get_fwhm(cube.wave.coord()), fwhm_arcsec[1]) # test to_header assert [str(x).strip() for x in fsf.to_header().cards] == [ 'FSFMODE = 2 / Circular MOFFAT beta=poly(lbda) fwhm=poly(lbda)', 'FSFLB1 = 5000 / FSF Blue Ref Wave (A)', 'FSFLB2 = 9000 / FSF Red Ref Wave (A)', 'FSF00FNC= 2 / FSF00 FWHM Poly Ncoef', 'FSF00F00= -0.1204 / FSF00 FWHM Poly C00', 'FSF00F01= 0.6143 / FSF00 FWHM Poly C01', 'FSF00BNC= 1 / FSF00 BETA Poly Ncoef', 'FSF00B00= 2.8 / FSF00 BETA Poly C00' ] testfile = str(tmpdir.join('test.fits')) outcube = cube.copy() fsf.to_header(hdr=outcube.primary_header) outcube.write(testfile) fsf3 = FSFModel.read(testfile, field=0) assert fsf3.model == 2 assert fsf3.get_beta(7000) == fsf.get_beta(7000) assert fsf3.get_fwhm(7000) == fsf.get_fwhm(7000) assert fsf3.get_fwhm(7000, unit='pix') == fsf.get_fwhm(7000, unit='pix')
def test_fsf_model_errors(): # This cube has no FSF info with pytest.raises(ValueError): FSFModel.read(get_data_file('sdetect', 'minicube.fits')) with pytest.raises(ValueError): find_model_cls(fits.Header({'FSFMODE': 5})) with pytest.raises(ValueError): MoffatModel2.from_header(fits.Header(), 0) for hdr in [fits.Header(), fits.Header({'FSFLB1': 5000, 'FSFLB2': 9000}), fits.Header({'FSFLB1': 9000, 'FSFLB2': 5000})]: with pytest.raises(ValueError): MoffatModel2.from_header(hdr, 0)
def test_segmap(): segfile = get_data_file('segmap', 'segmap.fits') img = Image(segfile) refdata = np.arange(14) for arg in (segfile, img, img.data): segmap = Segmap(arg) assert segmap.img.shape == (90, 90) assert str(segmap.img.data.dtype) == '>i8' assert np.max(segmap.img._data) == 13 assert_array_equal(np.unique(segmap.img._data), refdata) assert_array_equal(segmap.copy().img.data, segmap.img.data) cmap = segmap.cmap() assert cmap.N == 14 # nb of values in the segmap
def test_SEA(minicube, a478hst): """test SEA""" cat = Table.read(get_data_file('sdetect', 'cat.txt'), format='ascii') size = 10 width = 8 margin = 10. fband = 3. origin = ('sea', '0.0', os.path.basename(minicube.filename), 'v0') for obj in cat[0:3]: source = Source.from_data(obj['ID'], obj['RA'], obj['DEC'], origin) z = float(obj['Z']) try: errz = (float(obj['Z_MAX']) - float(obj['Z_MIN'])) / 2.0 except Exception: errz = np.nan source.add_z('CAT', z, errz) # create white image source.add_white_image(minicube, size, unit_size=u.arcsec) # create narrow band images source.add_narrow_band_images(cube=minicube, z_desc='CAT', size=None, unit_size=u.arcsec, width=width, margin=margin, fband=fband, is_sum=False) # extract images stamps source.add_image(a478hst, 'HST_') # segmentation maps source.add_seg_images(DIR=None) tags = [tag for tag in source.images.keys() if tag[0:4] == 'SEG_'] source.find_sky_mask(tags) source.find_union_mask(tags) source.find_intersection_mask(tags) # extract spectra source.extract_spectra(minicube, skysub=True, psf=None) source.extract_spectra(minicube, skysub=False, psf=None) Nz = np.array([sp.shape[0] for sp in source.spectra.values()]) assert len(np.unique(Nz)) == 1 tags = [tag for tag in source.images.keys() if tag[0:4] != 'HST_'] Ny = np.array([source.images[tag].shape[0] for tag in tags]) assert len(np.unique(Ny)) == 1 Nx = np.array([source.images[tag].shape[1] for tag in tags]) assert len(np.unique(Nx)) == 1
def test_fsf_arrays(): cubename = get_data_file('sdetect', 'subcub_mosaic.fits') cube = Cube(cubename) fsf = FSFModel.read(cube, field=2) with pytest.raises(ValueError): fsf.get_2darray([7000], (20, 20)) with pytest.raises(ValueError): fsf.get_image([7000], cube.wcs) ima = fsf.get_image(7000, cube.wcs, center=(10, 10)) assert np.unravel_index(ima.data.argmax(), ima.shape) == (10, 10) tcube = cube[:5, :, :] c = fsf.get_cube(tcube.wave, cube.wcs, center=(10, 10)) assert c.shape == (5, 30, 30) assert np.unravel_index(c[0].data.argmax(), c.shape[1:]) == (10, 10)
def test_select(minicube): cat = Catalog.read(get_data_file('sdetect', 'cat.txt'), format='ascii') im = minicube.mean(axis=0) # Note im.shape is (40, 40) and cat has 8 rows all inside the image assert len(cat) == 8 # all sources are in the image assert len(cat.select(im.wcs, margin=0)) == 8 # using a margin removing sources on the edges assert len(cat.select(im.wcs, margin=5)) == 4 # Create a mask with the bottom and left edges masked mask = np.ones(im.shape, dtype=bool) mask[5:, 5:] = False # using a margin removing sources on the edges assert len(cat.select(im.wcs, mask=mask)) == 4 assert len(cat.select(im.wcs, margin=1, mask=mask)) == 4
def test_pickle(filename): filename = get_data_file('sdetect', filename) src = Source.from_file(filename) s1 = pickle.loads(pickle.dumps(src)) # Force loading all extensions for objtype in ('images', 'cubes', 'spectra', 'tables'): for name, obj in getattr(src, objtype).items(): print(name, obj) s2 = pickle.loads(pickle.dumps(src)) for s in (s1, s2): assert src.header.tostring() == s.header.tostring() for objtype in ('images', 'cubes', 'spectra', 'tables'): attr_ref = getattr(src, objtype) attr_new = getattr(s, objtype) if attr_ref is None: assert attr_new is None else: assert list(attr_ref.keys()) == list(attr_new.keys())
def test_make_white_image(tmpdir): cube = get_data_file('sdetect', 'minicube.fits') out = str(tmpdir.join('image.fits')) main(['-v', cube, out]) assert os.path.isfile(out)
def test_align_segmap(): segmap = Segmap(get_data_file('segmap', 'segmap.fits')) ref = Image(get_data_file('segmap', 'image.fits')) aligned = segmap.align_with_image(ref, truncate=True) assert aligned.img.shape == ref.shape assert (aligned.img.wcs.get_rot() - ref.wcs.get_rot()) < 1e-3
def test_add_image(tmpdir, source2, a478hst, a370II): """Source class: testing add_image method""" minicube = Cube(get_data_file('sdetect', 'minicube.fits'), dtype=float) source2.add_white_image(minicube) ima = minicube.mean(axis=0) # The position source2.dec, source2.ra corresponds # to pixel index 18.817,32.432 in the cube. The default 5 # arcsecond requested size of the white-light image corresponds # to 25 pixels. There will thus be 12 pixels on either side of # a central pixel. The nearest pixel to the center is 19,32, so # we expect add_white_image() to have selected the following # range of pixels cube[19-12:19+12+1, 32-12:32+12+1], which # is cube[7:32, 20:45]. However the cube only has 40 pixels # along the X-axis, so the white-light image should correspond # to: # # white[:,:] = cube[7:32, 20:40] # white.shape=(25,20) # # So: cube[15,25] = white[15-7, 25-20] = white[8, 5] assert ima[15, 25] == source2.images['MUSE_WHITE'][8, 5] # Add a square patch of an HST image equal in width and height # to the height of the white-light image, which has a height # of 25 white-light pixels. source2.add_image(a478hst, 'HST1') # Add the same HST image, but this time set the width and height # equal to the height of the above HST patch (ie. 50 pixels). This # should have the same result as giving it the same size as the # white-light image. size = source2.images['HST1'].shape[0] source2.add_image(a478hst, 'HST2', size=size, minsize=size, unit_size=None) assert source2.images['HST1'][10, 10] == source2.images['HST2'][10, 10] # Add the HST image again, but this time rotate it to the same # orientation as the white-light image, then check that they end # up with the same rotation angles. source2.add_image(a478hst, 'HST3', rotate=True) assert_almost_equal(source2.images['HST3'].get_rot(), source2.images['MUSE_WHITE'].get_rot(), 3) # Trying to add image not overlapping with Source assert source2.add_image(a370II, 'ERROR') is None white = source2.images['MUSE_WHITE'] mean, std = white.background() mask = white.data > (mean + 2 * std) mask = Image.new_from_obj(white, data=mask.astype(int)) mask.data = mask.data.astype(int) source2.add_image(mask, 'MYMASK') filename = str(tmpdir.join('source.fits')) source2.write(filename) src = Source.from_file(filename) assert src.images['MYMASK'].data.dtype == '>i8' assert_masked_allclose(mask.data, src.images['MYMASK'].data) with fits.open(filename) as hdul: 'IMA_MYMASK_DQ' in hdul assert (np.count_nonzero(hdul['IMA_MYMASK_DQ'].data) == np.count_nonzero(white.mask))
def test_edgedist(minicube): cat = Catalog.read(get_data_file('sdetect', 'cat.txt'), format='ascii') im = minicube.mean(axis=0) ref = [2.29, 0.43, 2.83, 0.19, 2.70, 0.16, 0.11, 1.51] assert_almost_equal(cat.edgedist(im.wcs), ref, decimal=2)
def test_cut_header(): segmap = Segmap(get_data_file('segmap', 'segmap.fits'), cut_header_after='NAXIS2') assert 'RADESYS' not in segmap.img.primary_header assert 'RADESYS' not in segmap.img.data_header
def test_create_masks(tmpdir): segfile = get_data_file('segmap', 'segmap.fits') reffile = get_data_file('segmap', 'image.fits') catalog = get_data_file('segmap', 'catalog.fits') create_masks_from_segmap(segfile, catalog, reffile, n_jobs=1, masksky_name=str(tmpdir.join('mask-sky.fits')), maskobj_name=str( tmpdir.join('mask-source-%05d.fits')), idname='id', raname='ra', decname='dec', margin=5, mask_size=(10, 10)) assert len(glob(str(tmpdir.join('mask-source*')))) == 13 assert len(glob(str(tmpdir.join('mask-sky*')))) == 1 mask = fits.getdata(str(tmpdir.join('mask-source-00001.fits'))) assert mask.shape == (50, 50) assert mask.sum() == 56 # test skip_existing create_masks_from_segmap(segfile, catalog, reffile, n_jobs=1, skip_existing=True, masksky_name=str(tmpdir.join('mask-sky.fits')), maskobj_name=str( tmpdir.join('mask-source-%05d.fits')), idname='id', raname='ra', decname='dec', margin=5, mask_size=(10, 10), convolve_fwhm=0) # test convolve_fwhm and callables for mask filenames masksky_func = lambda: str(tmpdir.join('mask2-sky.fits')) maskobj_func = lambda x: str(tmpdir.join('mask2-source-%05d.fits' % x)) create_masks_from_segmap(segfile, catalog, reffile, n_jobs=1, skip_existing=True, masksky_name=masksky_func, maskobj_name=maskobj_func, idname='id', raname='ra', decname='dec', margin=5, mask_size=(10, 10), convolve_fwhm=1, psf_threshold=0.5) mask = fits.getdata(str(tmpdir.join('mask2-source-00001.fits'))) assert mask.shape == (50, 50) assert mask.sum() == 106