def _project_reference_hdu(self, name_hdr, muse_hdu=None): """Project the reference image onto the MUSE field """ if self.use_montage: # The original way. Sometimes this introduces an offset hdu_repr = montage.reproject_hdu(self.reference_hdu, header=name_hdr, exact_size=True) else: # The mpdaf way if muse_hdu is not None: wcs_ref = WCS(hdr=self.reference_hdu.header) ima_ref = Image(data=self.reference_hdu.data, wcs=wcs_ref) wcs_muse = WCS(hdr=muse_hdu.header) ima_muse = Image(data=muse_hdu.data, wcs=wcs_muse) ima_ref = ima_ref.align_with_image(ima_muse) hdu_repr = ima_ref.get_data_hdu() else: hdu_repre = None print( "Warning: provide target HDU when not using montage to reproject" ) return hdu_repr
def test_get(self): """WCS class: testing getters""" wcs = WCS(crval=(0, 0), shape=(5, 6), crpix=(1, 1)) assert_array_equal(wcs.get_step(), [1.0, 1.0]) assert_array_equal(wcs.get_start(), [0.0, 0.0]) assert_array_equal(wcs.get_end(), [4.0, 5.0]) assert_array_equal(wcs.get_range(), [0.0, 0.0, 4.0, 5.0]) assert_array_equal(wcs.get_center(), [2.0, 2.5]) wcs2 = WCS(crval=(0, 0), shape=(5, 6)) assert_array_equal(wcs2.get_step(), [1.0, 1.0]) assert_array_equal(wcs2.get_start(), [-2.0, -2.5]) assert_array_equal(wcs2.get_end(), [2.0, 2.5]) assert_array_equal(wcs2.get_center(), [0, 0]) wcs2.set_step([0.5, 2.5]) assert_array_equal(wcs2.get_step(), [0.5, 2.5]) assert wcs2.get_crval1() == 0.0 assert wcs2.get_crval2() == 0.0 wcs2.set_crval1(-2, unit=2 * u.pix) assert wcs2.get_crval1(unit=2 * u.pix) == -2.0 wcs2.set_crval2(-2, unit=2 * u.pix) assert wcs2.get_crval2(unit=2 * u.pix) == -2.0
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_gauss(fwhm, flux, factor, weight, fit_back, cont, center, pos_min, pos_max): """Image class: testing Gaussian fit""" params = dict(fwhm=(2, 1), rot=60, cont=2.0, flux=5.) wcs = WCS(cdelt=(0.2, 0.3), crval=(8.5, 12), shape=(40, 30)) ima = gauss_image(wcs=wcs, factor=factor, unit_center=u.pix, unit_fwhm=u.pix, **params) ima._var = np.ones_like(ima._data) gauss = ima.gauss_fit(fit_back=fit_back, cont=cont, verbose=True, center=center, pos_min=pos_min, pos_max=pos_max, factor=factor, fwhm=fwhm, flux=flux, weight=weight, unit_center=None, unit_fwhm=None, circular=False, full_output=True, maxiter=200) assert isinstance(gauss.ima, Image) if factor == 1: assert_array_almost_equal(gauss.center, (19.5, 14.5)) else: # FIXME: This must be fixed, when factor=2 center is wrong assert_array_almost_equal(gauss.center, (19.25, 14.25)) for param, value in params.items(): if np.isscalar(value): assert_almost_equal(getattr(gauss, param), value) else: assert_array_almost_equal(getattr(gauss, param), value)
def test_convolve(): """Image class: testing discrete convolution method.""" shape = (12, 25) wcs = WCS(cdelt=(1.0, 1.0), crval=(0.0, 0.0), shape=shape) data = np.zeros(shape) data[7, 5] = 1.0 mask = np.zeros(shape, dtype=bool) mask[5, 3] = True ima = Image(wcs=wcs, data=data, mask=mask, copy=False) # Create a symmetric convolution kernel with an even number of elements # along one dimension and and odd number along the other dimension. # Make the kernel symmetric around (shape-1)//2. This requires that # the final column be all zeros. kern = np.array([[0.1, 0.25, 0.1, 0.0], [0.25, 0.50, 0.25, 0.0], [0.1, 0.25, 0.1, 0.0]]) # The image should consist of a copy of the convolution kernel, centered # such that pixels (kern.shape-1)//2 is at pixel 7,5 of data. expected_data = np.ma.array(data=np.zeros(shape), mask=mask) expected_data.data[6:9, 4:8] = kern res = ima.convolve(kern) assert_masked_allclose(res.data, expected_data) res = ima.convolve(Image(data=kern)) assert_masked_allclose(res.data, expected_data) res = ima.fftconvolve(kern) assert_masked_allclose(res.data, expected_data, atol=1e-15)
def test_moffat(fwhm, flux, fit_n, n, fit_back, cont, center, pos_min, pos_max): """Image class: testing Moffat fit""" params = dict(flux=12.3, fwhm=(2.8, 2.1), n=1.6, cont=8.24, center=(50., 50.), rot=30) ima = moffat_image(wcs=WCS(cdelt=(1., 1.), crval=(0, 0)), shape=(101, 101), unit_center=u.pix, unit_fwhm=u.pix, **params) moffat = ima.moffat_fit(fit_back=fit_back, cont=cont, verbose=True, unit_center=None, unit_fwhm=None, full_output=True, center=center, pos_min=pos_min, pos_max=pos_max, fit_n=fit_n, n=n, circular=False, fwhm=fwhm, flux=flux) assert isinstance(moffat.ima, Image) for param, value in params.items(): if np.isscalar(value): assert_almost_equal(getattr(moffat, param), value, 2) else: assert_array_almost_equal(getattr(moffat, param), value, 2)
def test_segment(): wcs = WCS(cdelt=(0.2, 0.2), crval=(8.5, 12), shape=(100, 100)) ima = gauss_image(wcs=wcs, fwhm=(2, 2), cont=2.0, unit_center=u.pix, unit_fwhm=u.pix, flux=10, peak=True) subimages = ima.segment(minpts=20, background=2.1, median=(5, 5)) assert len(subimages) == 1 assert subimages[0].shape == (45, 45)
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_coordTransform(self): """WCS class: testing coordinates transformations""" wcs = WCS(crval=(0, 0), shape=(5, 6)) pixcrd = [[0, 0], [2, 3], [3, 2]] pixsky = wcs.pix2sky(pixcrd) pixcrd2 = wcs.sky2pix(pixsky) assert_array_equal(pixcrd, pixcrd2)
def test_dtype(): """Image class: testing dtype.""" wcs = WCS(cdelt=(0.2, 0.3), crval=(8.5, 12), shape=(40, 30), deg=True) data = np.zeros((40, 30)) data[19, 14] = 1 ima = Image(wcs=wcs, data=data, dtype=int) ima2 = ima.fftconvolve_gauss(center=None, flux=1., fwhm=(20000., 10000.), peak=False, rot=60., factor=1, unit_center=u.deg, unit_fwhm=u.arcsec) g = ima2.gauss_fit(verbose=False) assert_almost_equal(g.fwhm[0], 20000, 2) assert_almost_equal(g.fwhm[1], 10000, 2) assert_almost_equal(g.center[0], 8.5) assert_almost_equal(g.center[1], 12) assert_equal(ima2.dtype, np.float64) ima3 = ima2.resample(newdim=(32, 24), newstart=None, newstep=ima2.get_step(unit=u.arcsec) * 0.8) assert_equal(ima3.dtype, np.float64)
def test_fftconvolve(): """Image class: testing FFT convolution method.""" wcs = WCS(cdelt=(0.2, 0.3), crval=(8.5, 12), shape=(40, 30), deg=True) data = np.zeros((40, 30)) data[19, 14] = 1 ima = Image(wcs=wcs, data=data) ima2 = ima.fftconvolve_gauss(center=None, flux=1., fwhm=(20000., 10000.), peak=False, rot=60., factor=1, unit_center=u.deg, unit_fwhm=u.arcsec) g = ima2.gauss_fit(verbose=False) assert_almost_equal(g.fwhm[0], 20000, 2) assert_almost_equal(g.fwhm[1], 10000, 2) assert_almost_equal(g.center[0], 8.5) assert_almost_equal(g.center[1], 12) ima2 = ima.fftconvolve_moffat(center=None, flux=1., a=10000, q=1, n=2, peak=False, rot=60., factor=1, unit_center=u.deg, unit_a=u.arcsec) m = ima2.moffat_fit(verbose=False) assert_almost_equal(m.center[0], 8.5) assert_almost_equal(m.center[1], 12)
def test_ee(): """Image class: testing ensquared energy.""" wcs = WCS() data = np.ones(shape=(6, 5)) * 2 image1 = Image(data=data, wcs=wcs) image1.mask_region((2, 2), (1.5, 1.5), inside=False, unit_center=None, unit_radius=None) assert image1.ee() == 9 * 2 assert image1.ee(frac=True) == 1.0 ee = image1.ee(center=(2, 2), unit_center=None, radius=1, unit_radius=None) assert ee == 4 * 2 r, eer = image1.eer_curve(center=(2, 2), unit_center=None, unit_radius=None, cont=0) assert r[1] == 1.0 assert eer[1] == 1.0 size = image1.ee_size(center=(2, 2), unit_center=None, unit_size=None, cont=0) assert_almost_equal(size[0], 1.775)
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_init(self): wcs = WCS() assert wcs.naxis1 == 0 assert wcs.naxis2 == 0 wcs.naxis1 = 10 assert wcs.naxis1 == 10 assert wcs.naxis2 == 0
def test_rebin(): """Image class: testing rebin methods.""" wcs = WCS(crval=(0, 0)) data = np.arange(30).reshape(6, 5) image1 = Image(data=data, wcs=wcs, var=np.ones(data.shape) * 0.5) image1.mask_region((2, 2), (1.5, 1.5), inside=False, unit_center=None, unit_radius=None) # The test data array looks as follows: # # ---- ---- ---- ---- ---- # ---- 6.0 7.0 8.0 ---- # ---- 11.0 12.0 13.0 ---- # ---- 16.0 17.0 18.0 ---- # ---- ---- ---- ---- ---- # ---- ---- ---- ---- ---- # # Where ---- signifies a masked value. # # After reducing both dimensions by a factor of 2, we should # get a data array of the following 6 means of 4 pixels each: # # ---- ---- => 6/1 ---- ---- => (7+8)/2 # ---- 6.0 7.0 8.0 # # ---- 11.0 => (11+16)/2 12.0 13.0 => (12+13+17+18)/4 # ---- 16.0 17.0 18.0 # # ---- ---- => ---- ---- ---- => ---- # ---- ---- ---- ---- expected = np.ma.array(data=[[6.0, 7.5], [13.5, 15], [0.0, 0.0]], mask=[[False, False], [False, False], [True, True]]) image2 = image1.rebin(2) assert_masked_allclose(image2.data, expected) image2 = image1.rebin(factor=(2, 2)) assert_masked_allclose(image2.data, expected) # The variances of the original pixels were all 0.5, so taking the # mean of N of these should give the mean a variance of 0.5/N. # Given the number of pixels averaged in each of the above means, # we thus expect the variance array to look as follows. expected = np.ma.array(data=[[0.5, 0.25], [0.25, 0.125], [0.0, 0.0]], mask=[[False, False], [False, False], [True, True]]) assert_masked_allclose(image2.var, expected) # Check the WCS information. start = image2.get_start() assert start[0] == 0.5 assert start[1] == 0.5
def test_peak_detection_and_fwhm(): shape = (101, 101) fwhm = (5, 5) wcs = WCS(cdelt=(1., 1.), crval=(8.5, 12), shape=shape) ima = gauss_image(wcs=wcs, fwhm=fwhm, cont=2.0, unit_center=u.pix, unit_fwhm=u.pix, flux=10, peak=True) peaks = ima.peak_detection(5, 2) assert peaks.shape == (1, 2) assert_allclose(peaks[0], (np.array(shape) - 1) / 2.0) assert_allclose(ima.fwhm(unit_radius=None), fwhm, rtol=0.1)
def test_background(a370II): """Image class: testing background value""" wcs = WCS() data = np.ones(shape=(6, 5)) * 2 image1 = Image(data=data, wcs=wcs) (background, std) = image1.background() assert background == 2 assert std == 0 (background, std) = a370II[1647:1732, 618:690].background() # compare with IRAF results assert (background - std < 1989) & (background + std > 1989)
def test_arithmetric(): """Spectrum class: testing arithmetic functions""" wave = WaveCoord(crpix=2.0, cdelt=3.0, crval=0.5, cunit=u.nm) spectrum1 = Spectrum(data=np.array([0.5, 1, 2, 3, 4, 5, 6, 7, 8, 9]), wave=wave) spectrum2 = spectrum1 > 6 # [-,-,-,-,-,-,-,7,8,9] # + spectrum3 = spectrum1 + spectrum2 assert spectrum3.data.data[3] == 3 assert spectrum3.data.data[8] == 16 spectrum3 = 4.2 + spectrum1 assert spectrum3.data.data[3] == 3 + 4.2 # - spectrum3 = spectrum1 - spectrum2 assert spectrum3.data.data[3] == 3 assert spectrum3.data.data[8] == 0 spectrum3 = spectrum1 - 4.2 assert spectrum3.data.data[8] == 8 - 4.2 # * spectrum3 = spectrum1 * spectrum2 assert spectrum3.data.data[8] == 64 spectrum3 = 4.2 * spectrum1 assert spectrum3.data.data[9] == 9 * 4.2 # / spectrum3 = spectrum1 / spectrum2 # divide functions that have a validity domain returns the masked constant # whenever the input is masked or falls outside the validity domain. assert spectrum3.data.data[8] == 1 spectrum3 = 1.0 / (4.2 / spectrum1) assert spectrum3.data.data[5] == 5 / 4.2 # with cube wcs = WCS() cube1 = Cube(data=np.ones(shape=(10, 6, 5)), wave=wave, wcs=wcs) cube2 = spectrum1 + cube1 sp1data = spectrum1.data[:, np.newaxis, np.newaxis] assert_array_almost_equal(cube2.data, sp1data + cube1.data) cube2 = spectrum1 - cube1 assert_array_almost_equal(cube2.data, sp1data - cube1.data) cube2 = spectrum1 * cube1 assert_array_almost_equal(cube2.data, sp1data * cube1.data) cube2 = spectrum1 / cube1 assert_array_almost_equal(cube2.data, sp1data / cube1.data) # spectrum * image data = np.ones(shape=(6, 5)) * 2 image1 = Image(data=data, wcs=wcs) cube2 = spectrum1 * image1 assert_array_almost_equal(cube2.data, sp1data * image1.data[np.newaxis, :, :])
def test_peak(a370II): """Image class: testing peak research""" wcs = WCS() data = np.ones(shape=(6, 5)) * 2 image1 = Image(data=data, wcs=wcs) image1.data[2, 3] = 8 p = image1.peak() assert p['p'] == 2 assert p['q'] == 3 p = a370II.peak(center=(790, 875), radius=20, plot=False, unit_center=None, unit_radius=None) assert_almost_equal(p['p'], 793.1, 1) assert_almost_equal(p['q'], 875.9, 1)
def make_empty_cube(radec_center, pixscale, nside, wave_coord, wcs=None): """Makes a new datacube with different WCS and 2*nside+1 pixels per side Parameters ---------- radec_center : SkyCoord Coordinate of the central spaxel pixscale : Angle Pixel scale of the cube nside : int Number of pixels at each side of the central one wave_coord : mpdaf.obj.WaveCoord The WaveCoord object of the new datacube wcs : mpdaf.obj.WCS ; optional If given, it will overwrite radec_center, pixscale, nside Returns ------- cube : mpdaf.obj.Cube Cube object filled with zeros """ if wcs is None: ntot = 2 * nside + 1 # total side always odd ny, nx = ntot, ntot crpix = (nside + 1, nside + 1) crval = radec_center[1].to('deg').value, radec_center[0].to( 'deg').value cdelt = pixscale.to('deg').value dy, dx = cdelt, -1 * cdelt # dx is negative for convention East goes to negative x's # cd_matrix = np.zeros((2,2)) # cd_matrix[0,0] = cdelt # cd_matrix[1,1] = cdelt deg_bool = True shape = (ny, nx) wcs_new = WCS(crpix=crpix, crval=crval, cdelt=(dy, dx), deg=deg_bool, shape=shape) else: wcs_new = wcs nx = wcs.naxis1 ny = wcs.naxis2 nw = wave_coord.shape # data = np.zeros((nw, ny, nx)) cube = Cube(wcs=wcs_new, data=data, var=data, wave=wave_coord) return cube
def test_coord(self): """WCS class: testing coord""" wcs = WCS(shape=(4, 5), crval=(-23.0, 5.0), cdelt=(0.2 / 3600., -0.2 / 3600.), deg=True) p, q = wcs.coord(spaxel=True, relative=True) assert p.mean() == 0 assert q.mean() == 0 assert p.shape == (4, 5) assert q.shape == (4, 5) p, q = wcs.coord(spaxel=True, relative=True, reshape=True) assert p.shape == (4, ) assert q.shape == (5, ) p, q = wcs.coord(spaxel=True, relative=True, center=(5.2, 6.3)) assert p.min() == -5.2 assert q.min() == -6.3 assert p.shape == (4, 5) assert q.shape == (4, 5) dec, ra = wcs.coord() assert_allclose(ra.min(), 4.99987929, rtol=1e-6) assert_allclose(dec.min(), -23.000083333, rtol=1e-6) dec, ra = wcs.coord(relative=True, unit='arcsec') assert_allclose(ra.min(), -0.4345444, rtol=1e-6) assert_allclose(dec.min(), -0.3000001, rtol=1e-6) r, theta = wcs.coord(polar=True, unit='arcsec') assert_allclose(r.max(), 0.5280425, rtol=1e-6) assert_allclose(theta.mean(), 0.314159265, rtol=1e-6) mask = np.empty(shape=(4, 5), dtype=bool) mask[:, :] = False mask[0, 0] = True p, q = wcs.coord(spaxel=True, mask=mask) assert p.shape == (19, ) assert q.shape == (19, )
def test_coordTransform2(self): """WCS class: testing transformations with a more complete header.""" w = pywcs.WCS(naxis=2) w.wcs.crpix = [167.401033093, 163.017401336] w.wcs.cd = np.array([[-5.5555555555555003e-05, 0], [0, 5.5555555555555003e-05]]) w.wcs.crval = [338.23092027, -60.56375796] w.wcs.ctype = ["RA---TAN", "DEC--TAN"] wcs = WCS() wcs.wcs = w pix = np.array([[108.41, 81.34]]) pix2 = pix[:, [1, 0]] pixint = pix2.astype(int) ref = np.array([[338.2375, -60.5682]]) ref2 = ref[:, [1, 0]] sky = wcs.pix2sky(pix2) assert_allclose(wcs.wcs.wcs_pix2world(pix, 0), ref, rtol=1e-4) assert_allclose(sky, ref2, rtol=1e-4) assert_allclose(wcs.sky2pix(wcs.pix2sky(pix2)), pix2) assert_allclose(wcs.sky2pix(sky, nearest=True), pixint)
def test_mask(cube): """Cube class: testing mask functionalities""" # A region of half-width=1 and half-height=1 should have a size of # 2x2 pixels. A 2x2 region of pixels has a center at the shared # corner of the 4 pixels, and the closest corner to the requested # center of 2.1,1.8 is 2.5,1.5, so we expect the square of unmasked pixels # to be pixels 2,3 along the Y axis, and pixels 1,2 along the X axis. cube.mask_region((2.1, 1.8), (1, 1), lmin=2, lmax=5, inside=True, unit_center=None, unit_radius=None, unit_wave=None) # The expected mask for the images between lmin and lmax. expected_mask = np.array([[False, False, False, False, False], [False, False, False, False, False], [False, True, True, False, False], [False, True, True, False, False], [False, False, False, False, False], [False, False, False, False, False]], dtype=bool) assert_array_equal(np.any(cube.mask[:2, :, :], axis=0), np.zeros(cube.shape[1:])) assert_array_equal(np.all(cube._mask[2:5, :, :], axis=0), expected_mask) assert_array_equal(np.any(cube.mask[5:, :, :], axis=0), np.zeros(cube.shape[1:])) cube.unmask() # Do the same experiment, but this time mask pixels outside the region # instead of within the region. cube.mask_region((2.1, 1.8), (1, 1), lmin=2, lmax=5, inside=False, unit_center=None, unit_radius=None, unit_wave=None) assert_array_equal(np.any(cube.mask[:2, :, :], axis=0), np.ones(cube.shape[1:])) assert_array_equal(np.all(cube._mask[2:5, :, :], axis=0), ~expected_mask) assert_array_equal(np.any(cube.mask[5:, :, :], axis=0), np.ones(cube.shape[1:])) cube.unmask() # Do the same experiment, but this time with the center and size # of the region specified using the equivalent world coordinates. wcs = WCS(deg=True) wave = WaveCoord(cunit=u.angstrom) cube = Cube(data=cube.data, wave=wave, wcs=wcs, copy=False) cube.mask_region(wcs.pix2sky([2.1, 1.8]), (3600, 3600), lmin=2, lmax=5, inside=False) assert_array_equal(np.any(cube.mask[:2, :, :], axis=0), np.ones(cube.shape[1:])) assert_array_equal(np.all(cube._mask[2:5, :, :], axis=0), ~expected_mask) assert_array_equal(np.any(cube.mask[5:, :, :], axis=0), np.ones(cube.shape[1:])) cube.unmask() # Mask around a region of half-width and half-height 1.1 pixels, # specified in arcseconds, centered close to pixel 2.4,3.8. This # ideally corresponds to a region of 2.2x2.2 pixels. The closest # possible size is 2x2 pixels. A region of 2x2 pixels has its # center at the shared corner of these 4 pixels, and the nearest # corner to the desired central index of (2.4,3.8) is (2.5,3.5). # So all of the image should be masked, except for a 2x2 area of # pixel indexes 2,3 along the Y axis and pixel indexes 3,4 along # the X axis. cube.mask_region(wcs.pix2sky([2.4, 3.8]), 1.1 * 3600.0, inside=False, lmin=2, lmax=5) # The expected mask for the images between lmin and lmax. expected_mask = np.array([[True, True, True, True, True], [True, True, True, True, True], [True, True, True, False, False], [True, True, True, False, False], [True, True, True, True, True], [True, True, True, True, True]], dtype=bool) assert_array_equal(np.any(cube.mask[:2, :, :], axis=0), np.ones(cube.shape[1:])) assert_array_equal(np.all(cube._mask[2:5, :, :], axis=0), expected_mask) assert_array_equal(np.any(cube.mask[5:, :, :], axis=0), np.ones(cube.shape[1:])) cube.unmask() # Mask outside an elliptical region centered at pixel 3.5,3.5. # The boolean expected_mask array given below was a verified # output of mask_ellipse() for the specified ellipse parameters. cube = generate_cube(shape=(10, 8, 8), wcs=wcs, var=None) cube.mask_ellipse([3.5, 3.5], (2.5, 3.5), 45.0, unit_radius=None, unit_center=None, inside=False, lmin=2, lmax=5) expected_mask = np.array([ [True, True, True, True, True, True, True, True], [True, True, True, False, False, False, True, True], [True, True, False, False, False, False, False, True], [True, False, False, False, False, False, False, True], [True, False, False, False, False, False, False, True], [True, False, False, False, False, False, True, True], [True, True, False, False, False, True, True, True], [True, True, True, True, True, True, True, True]], dtype=bool) assert_array_equal(np.any(cube.mask[:2, :, :], axis=0), np.ones(cube.shape[1:])) assert_array_equal(np.all(cube._mask[2:5, :, :], axis=0), expected_mask) assert_array_equal(np.any(cube.mask[5:, :, :], axis=0), np.ones(cube.shape[1:])) # Check that we can select the same mask via the output of np.where() # passed to mask_selection(). ksel = np.where(cube.data.mask) cube.unmask() cube.mask_selection(ksel) assert_array_equal(np.any(cube.mask[:2, :, :], axis=0), np.ones(cube.shape[1:])) assert_array_equal(np.all(cube._mask[2:5, :, :], axis=0), expected_mask) assert_array_equal(np.any(cube.mask[5:, :, :], axis=0), np.ones(cube.shape[1:])) # The cube was generated without any variance information. # Check that mask_variance() raises an error due to this. with pytest.raises(ValueError): cube.mask_variance(0.1) # Add an array of variances to the cube and check that mask_variance() # masks all pixels that have variances greater than 0.1. cube.unmask() cube.var = np.random.randn(*cube.shape) mask = cube.var > 0.1 cube.mask_variance(0.1) assert_array_equal(cube.data.mask, mask)
def _generate_test_data(data=2.3, var=1.0, mask=None, shape=None, unit=u.ct, uwave=u.angstrom, wcs=None, wave=None, copy=True, ndim=None, crpix=2.0, cdelt=3.0, crval=0.5): # Determine a shape for the data and var arrays. This is either a # specified shape, the shape of a specified data or var array, or # the default shape. if shape is None: if isinstance(data, np.ndarray): shape = data.shape ndim = data.ndim elif isinstance(var, np.ndarray): shape = var.shape ndim = var.ndim elif isinstance(mask, np.ndarray): shape = mask.shape ndim = mask.ndim elif ndim is not None: if ndim == 1: shape = DEFAULT_SHAPE[0] elif ndim == 2: shape = DEFAULT_SHAPE[1:] elif ndim == 3: shape = DEFAULT_SHAPE else: raise ValueError('Missing shape/ndim specification') if np.isscalar(shape): shape = (shape, ) if len(shape) != ndim: raise ValueError('shape does not match the number of dimensions') # Convert the data and var arguments to ndarray's if data is None: if ndim == 1: # Special case for spectra ... data = np.arange(shape[0], dtype=float) data[0] = 0.5 elif np.isscalar(data): data = data * np.ones(shape, dtype=type(data)) elif data is not None: data = np.array(data, copy=copy) assert shape == data.shape if np.isscalar(var): var = var * np.ones(shape, dtype=type(var)) elif var is not None: var = np.array(var, copy=copy) assert shape == var.shape if mask is None: mask = False if not np.isscalar(mask): mask = np.array(mask, copy=copy, dtype=bool) assert shape == mask.shape # Substitute default world-coordinates where not specified. if ndim == 2: wcs = wcs or WCS(crval=(0, 0), crpix=1.0, shape=shape) elif ndim == 3: wcs = wcs or WCS(crval=(0, 0), crpix=1.0, shape=shape[1:]) # Substitute default wavelength-coordinates where not specified. if ndim in (1, 3): wave = wave or WaveCoord( crpix=crpix, cdelt=cdelt, crval=crval, shape=shape[0], cunit=uwave) if wave.shape is None: wave.shape = shape[0] if ndim == 1: cls = Spectrum elif ndim == 2: cls = Image elif ndim == 3: cls = Cube return cls(data=data, var=var, mask=mask, wave=wave, wcs=wcs, unit=unit, copy=copy, dtype=None)
#cosmological parameters to calculate the distance z = 0.73379 scale = 7.28 cosmo = FlatLambdaCDM(H0=70, Om0=0.3) dist = cosmo.luminosity_distance(z) #galaxy imputs galPA = 55 galcen = SkyCoord(ra=237.52059628552735 * u.degree, dec=-78.188149277705151 * u.degree, frame='icrs') datacube = Cube('nor_cut_cube.fits') head = datacube.primary_header wcs1 = WCS(head) wave1 = WaveCoord(cdelt=0.1, crval=4825.12, cunit=u.angstrom) def residual(p, datacube=datacube, pos=None, specwidth=spectralpixel, galcen=galcen, galPA=galPA): par = p.valuesdict() incli = par['incli'] col_denst = par['col_dens'] h = par['height'] bes = par['dop_param'] v_max = par['vel_max']
def test_get_image(): """Cube class: testing get_image method""" shape = (2000, 6, 5) wave = WaveCoord(crpix=1, cdelt=3.0, crval=2000, cunit=u.angstrom, shape=shape[0]) wcs = WCS(crval=(0, 0)) data = np.ones(shape=shape) * 2 cube1 = Cube(data=data, wave=wave, wcs=wcs) # Add a gaussian shaped spectral line at image pixel 2,2. cube1[:, 2, 2].add_gaussian(5000, 1200, 20) # Specify the range of wavelengths to be combined and the corresponding # slice along the wavelength axis. The wavelength range is chosen to # include all wavelengths affected by add_gaussian(). lrange = (4800, 5200) lslice = slice(np.rint(cube1.wave.pixel(lrange[0])).astype(int), np.rint(cube1.wave.pixel(lrange[1])).astype(int) + 1) # Get an image that is the mean of all images in the above wavelength # range, minus a background image estimated from outside this range, # where all image values are 2.0. ima = cube1.get_image(wave=lrange, method='mean', subtract_off=True) # In the cube, all spectral pixels of image pixel 0,0 were 2.0, # so the mean over the desired wavelength range, minus the mean # over background ranges either side of this should be zero. assert ima[0, 0] == 0 # Spectral pixels of image pixel 2,2 in the original cube were all # 2.0 everywhere except where the gaussian was added to 2.0. Hence # pixel 2,2 of the mean image should be the mean of the gaussian # minus the average 2.0 background. assert_almost_equal(ima[2, 2], cube1[lslice, 2, 2].mean()[0] - 2, 3) # Get another mean image, but this time without subtracting off a # background. Image pixel 0,0 should have a mean of 2.0, and # pixel 2,2 should equal the mean of the gaussian added to 2.0 ima = cube1.get_image(wave=lrange, method='mean', subtract_off=False) assert ima[0, 0] == 2 assert_almost_equal(ima[2, 2], cube1[lslice, 2, 2].mean()[0], 3) # For this test, perform a sum over the chosen wavelength range, # and subtract off a background image taken from wavelength # regions above and below the wavelength range. Pixel 0,0 of the # summed image should be zero, since both the summed wavelength # range and the background image wavelength ranges have the same # pixel values, and the background sum is scaled to have the same # units as the output image. Check the background subtraction of # pixel 2,2 using an equal number of pixels that were not affected # by the addition of the gaussian. ima = cube1.get_image(wave=lrange, method='sum', subtract_off=True) assert ima[0, 0] == 0 assert_almost_equal(ima[2, 2], cube1[lslice, 2, 2].sum()[0] - cube1[lslice, 0, 0].sum()[0], 3) # repeat with median filter method ima = cube1.get_image(wave=lrange, method='sum', subtract_off=True, median_filter=200) assert ima[0, 0] == 0 assert_almost_equal(ima[2, 2], cube1[lslice, 2, 2].sum()[0] - cube1[lslice, 0, 0].sum()[0], 3) # Finally, perform a sum of the chosen wavelength range without # subtracting a background image. This is easy to test by doing # equivalent sums through the cube over the chosen wavelength range. ima = cube1.get_image(wave=lrange, method='sum', subtract_off=False) assert ima[0, 0] == cube1[lslice, 0, 0].sum()[0] assert_almost_equal(ima[2, 2], cube1[lslice, 2, 2].sum()[0])
def __init__(self,shape=(41,101,101),lmbda=20,noise=None, \ spectraSourcesLmbda=None,spectraSourcesWidth=5,listCenter=None, \ listRadius=None,link=None,intens=0.2,rho=0,variation=0,noiseType='student',\ decrease='True',noiseCube=None,df_stu=5,randomShape=False,seed=None,steps=50,dilate_factor=5): """ Param: Param: Param: """ self.shape = shape self.lmbda = lmbda self.data = np.zeros(shape) self.listCenter = listCenter self.center = listCenter[0] self.listRadius = listRadius self.intens = intens self.link = link if randomShape == False: self.maskSources, self.label = buildMaskSources( self.listCenter, self.listRadius, shape, decrease) else: self.maskSources, self.label = buildRandomMaskSources( shape, self.listCenter, self.listRadius, seed=seed, steps=steps, dilate_factor=dilate_factor) np.random.seed() self.spectraSources = [] self.spectraSourcesLmbda = spectraSourcesLmbda self.spectraSourcesWidth = spectraSourcesWidth self.maskAll = self.maskSources > 0 #create "filament link" between point sources if link is not None: for k in link: self.linkGal2(k[0], k[1], intens) if spectraSourcesLmbda is not None: for k in range(len(spectraSourcesLmbda)): self.spectraSources.append( createSpectra(spectraSourcesLmbda[k], shape[0], width=5)) for i in range(shape[1]): for j in range(shape[2]): if self.label[i, j] == k + 1: if variation != 0: if decrease == True: spectra = createSpectra( spectraSourcesLmbda[k] + np.random.randint(variation), shape[0], width=5) else: spectra = createSpectra( spectraSourcesLmbda[k] + 1 / 2. * np.sqrt((listCenter[k][0] - i)**2 + (listCenter[k][1] - j)**2), shape[0], width=5) else: spectra = self.spectraSources[k] self.data[:, i, j] = spectra * self.maskSources[i, j] self.noise = noise self.rho = rho if self.noise != None: if noiseType == 'student': self.dataClean = self.data.copy() self.noiseCube = sst.t.rvs(df_stu, loc=0, scale=self.noise, size=shape[0] * shape[1] * shape[2]).reshape(shape) if rho != 0: ker = np.array([[0.05, 0.1, 0.05], [0.1, 0.4, 0.1], [0.05, 0.1, 0.05]]) self.noiseCube = ssl.fftconvolve(self.noiseCube, ker[np.newaxis, :], mode='same') self.data = self.data + self.noiseCube self.var = np.ones((shape)) * self.noise**2 else: self.dataClean = self.data.copy() if rho == 0: #no correlation self.noiseCube = np.random.normal( scale=self.noise, size=shape[0] * shape[1] * shape[2]).reshape(shape) self.data = self.data + self.noiseCube else: if rho == 1: #generate spatially correlated noise #self.createCorrNoiseCube() ker = np.array([[0.05, 0.1, 0.05], [0.1, 0.4, 0.1], [0.05, 0.1, 0.05]]) elif rho == 2: ker = np.array([[0.00, 0.1, 0.00], [0.1, 0.6, 0.1], [0.00, 0.1, 0.00]]) elif rho == 3: ker = np.array([[0.02, 0.02, 0.02, 0.02, 0.02], [0.02, 0.05, 0.05, 0.05, 0.02], [0.02, 0.05, 0.28, 0.05, 0.02], [0.02, 0.05, 0.05, 0.05, 0.02], [0.02, 0.02, 0.02, 0.02, 0.02]]) elif rho == 4: ker = generateMoffatIm(shape=(15, 15), alpha=3.1, beta=2.8, center=(7, 7), dim=None) self.noiseCube = np.random.normal( scale=self.noise, size=shape[0] * shape[1] * shape[2]).reshape(shape) self.noiseCube = ssl.fftconvolve(self.noiseCube, ker[np.newaxis, :], mode='same') self.data = self.data + self.noiseCube self.var = np.ones((shape)) * self.noise**2 elif noiseCube is not None: self.dataClean = self.data.copy() self.noiseCube = noiseCube self.data = self.data + self.noiseCube self.var = np.ones((shape)) * np.var(noiseCube) else: self.dataClean = self.data self.var = np.ones((shape)) cubeClean = Cube(data=self.dataClean, wcs=WCS(), wave=WaveCoord()) cubeNoisy = Cube(data=self.data, var=self.var, wcs=WCS(), wave=WaveCoord()) ra, dec = listCenter[0] self.src = Source.from_data(4000, ra + 1, dec + 1, origin='Simulated', cubes={ 'TRUTH_CUBE': cubeClean, 'MUSE_CUBE': cubeNoisy }) self.src.add_line(['LBDA_OBS', 'LINE'], [lmbda, "LYALPHA"])
def test_mask(): """Image class: testing mask functionalities""" wcs = WCS() data = np.ones(shape=(6, 5)) * 2 # A region of half-width=1 and half-height=1 should have a size of # 2x2 pixels. A 2x2 region of pixels has a center at the shared # corner of the 4 pixels, and the closest corner to the requested # center of 2.1,1.8 is 2.5,1.5, so we expect the square of unmasked pixels # to be pixels 2,3 along the Y axis, and pixels 1,2 along the X axis. image1 = Image(data=data, wcs=wcs) image1.mask_region((2.1, 1.8), (1, 1), inside=False, unit_center=None, unit_radius=None) expected_mask = np.array([[1, 1, 1, 1, 1], [1, 1, 1, 1, 1], [1, 0, 0, 1, 1], [1, 0, 0, 1, 1], [1, 1, 1, 1, 1], [1, 1, 1, 1, 1]], dtype=bool) assert_array_equal(image1._mask, expected_mask) # Test that inside=True gives the opposite result image1.unmask() image1.mask_region((2.1, 1.8), (1, 1), inside=True, unit_center=None, unit_radius=None) assert_array_equal(image1._mask, ~expected_mask) # And test with a rotation, 90° so should give the same result image1.unmask() image1.mask_region((2.1, 1.8), (1, 1), inside=True, unit_center=None, unit_radius=None, posangle=90) assert_array_equal(image1._mask, ~expected_mask) # Try exactly the same experiment as the above, except that the center # and size of the region are specified in world-coordinates instead of # pixels. wcs = WCS(deg=True) image1 = Image(data=data, wcs=wcs) image1.mask_region(wcs.pix2sky([2.1, 1.8]), (3600, 3600), inside=False) assert_array_equal(image1._mask, expected_mask) # And same with a rotation image1.unmask() image1.mask_region(wcs.pix2sky([2.1, 1.8]), (3600, 3600), inside=True, posangle=90) assert_array_equal(image1._mask, ~expected_mask) # Mask around a region of half-width and half-height 1.1 pixels, # specified in arcseconds, centered close to pixel 2.4,3.8. This # ideally corresponds to a region of 2.2x2.2 pixels. The closest # possible size is 2x2 pixels. A region of 2x2 pixels has its # center at the shared corner of these 4 pixels, and the nearest # corner to the desired central index of (2.4,3.8) is (2.5,3.5). # So all of the image should be masked, except for a 2x2 area of # pixel indexes 2,3 along the Y axis and pixel indexes 3,4 along # the X axis. image1.unmask() image1.mask_region(wcs.pix2sky([2.4, 3.8]), 1.1 * 3600.0, inside=False) expected_mask = np.array([[1, 1, 1, 1, 1], [1, 1, 1, 1, 1], [1, 1, 1, 0, 0], [1, 1, 1, 0, 0], [1, 1, 1, 1, 1], [1, 1, 1, 1, 1]], dtype=bool) assert_array_equal(image1._mask, expected_mask) # Mask outside an elliptical region centered at pixel 3.5,3.5. # The boolean expected_mask array given below was a verified # output of mask_ellipse() for the specified ellipse parameters. data = np.ones(shape=(8, 8)) image1 = Image(data=data, wcs=wcs) image1.mask_ellipse([3.5, 3.5], (2.5, 3.5), 45.0, unit_radius=None, unit_center=None, inside=False) expected_mask = np.array([ [1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 0, 0, 0, 1, 1], [1, 1, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 1, 1], [1, 1, 0, 0, 0, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1]], dtype=bool) assert_array_equal(image1._mask, expected_mask) # Use np.where to select the masked pixels and check that mask_selection() # then reproduces the same mask. ksel = np.where(image1.data.mask) image1.unmask() image1.mask_selection(ksel) assert_array_equal(image1._mask, expected_mask) # Check inside=True image1.unmask() image1.mask_ellipse([3.5, 3.5], (2.5, 3.5), 45.0, unit_radius=None, unit_center=None, inside=True) assert_array_equal(image1._mask, ~expected_mask)
specwidth = [14, 36] s_n_mask = np.load('out_r4_3.npy') all_pixels = [] for i in range(len(s_n_mask)): posi = [s_n_mask[i][0], s_n_mask[i][1]] all_pixels.append(posi) all_pixels = np.asarray(all_pixels) datacube = Cube('nor_cut_cube.fits') xlen = len(datacube[0, :, 0].data) ylen = len(datacube[0, 0, :].data[0]) wcs1 = WCS(crval=0, cdelt=0.2) MyData = np.ones((xlen, ylen)) ima = Image(data=MyData, wcs=wcs1) for i in range(xlen): for j in range(ylen): par = params.valuesdict() incli = par['incli'] col_denst = par['col_dens'] h = par['height'] bes = par['dop_param'] v_max = par['vel_max'] h_vt = par['h_v'] csize = par['csize'] r_0t = par['r_0']
def test_rebin(): """Cube class: testing rebin methods""" # Create spectral and spatial world coordinates that make each # pixel equal its index. wcs = WCS(crval=(0, 0), crpix=(1, 1), cdelt=(1.0, 1.0)) wave = WaveCoord(crval=0.0, crpix=1.0, cdelt=1.0) # Create a cube with even valued dimensions, filled with ones. data = ma.ones((4, 6, 8)) # Start with all pixels 1.0 data.reshape(4 * 6 * 8)[::2] = 0.0 # Set every second pixel to 0.0 data.mask = data < -1 # Unmask all pixels. cube1 = generate_cube(data=data.data, mask=data.mask, wcs=wcs, wave=wave) # Rebin each of the axes such as to leave only 2 pixels along each # dimension. factor = (2, 3, 4) cube2 = cube1.rebin(factor=factor) # Compute the expected output cube, given that the input cube is a # repeating pattern of 1,0, and we divided the x-axis by a # multiple of 2, the output pixels should all be 0.5. expected = ma.ones((2, 2, 2)) * 0.5 expected.mask = expected < 0 # All pixels unmasked. assert_masked_allclose(cube2.data, expected) # Do the same experiment but with the zero valued pixels all masked. data = ma.ones((4, 6, 8)) # Start with all pixels 1.0 data.reshape(4 * 6 * 8)[::2] = 0.0 # Set every second pixel to 0.0 data.mask = data < 0.1 # Mask the pixels that are 0.0 cube1 = generate_cube(data=data.data, mask=data.mask, wcs=wcs, wave=wave) # Rebin each of the axes such as to leave only 2 pixels along each # dimension. factor = np.array([2, 3, 4]) cube2 = cube1.rebin(factor=factor) # Compute the expected output cube. The zero valued pixels are all # masked, leaving just pixels with values of 1, so the mean that is # recorded in each output pixel should be 1.0. expected = ma.ones((2, 2, 2)) * 1.0 expected.mask = expected < 0 # All output pixels should be unmasked. assert_masked_allclose(cube2.data, expected) # Check that the world coordinates are correct. We averaged # factor[] pixels whose coordinates were equal to their pixel # indexes, so the coordinates of the first pixel of the rebinned # cube should be the mean of the first factor indexes along each # dimension. The sum from k=0 to factor-1 is # ((factor-1)*factor)/2, and dividing this by the number of pixels # gives (factor-1)/2. assert_allclose(np.asarray(cube2.get_start()), (factor - 1) / 2.0) # Create a cube that has a larger number of pixels along the # y and x axes of the images, so that we can divide those axes # by a number whose remainder is large enough to test selection # of the truncated part of the cube. shape = np.array([4, 17, 15]) data = ma.ones(shape) # Start with all pixels 1.0 data.reshape(shape.prod())[::2] = 0.0 # Set every second pixel to 0.0 data.mask = data < -1 # Unmask all pixels. cube1 = generate_cube(data=data.data, mask=data.mask, wcs=wcs, wave=wave) # Choose the rebinning factors such that there is a significant # remainder after dividing the final two dimensions of the cube by # the specified factor. We don't do this for the first axis because # we want the interleaved pattern of 0s and 1s to remain. factor = np.array([2, 7, 9]) cube2 = cube1.rebin(factor=factor, margin='origin') # Compute the expected output cube. Given that the input cube is a # repeating pattern of 1,0, and we divided the x-axis by a # multiple of 2, the output pixels should all be 0.5. expected_shape = cube1.shape // factor expected = ma.ones(expected_shape) * 0.5 expected.mask = expected < 0 # All pixels unmasked. assert_masked_allclose(cube2.data, expected) # We chose a margin value of 'origin', so that the outer corner of # pixel 0,0,0 of the input cube would also be the outer corner of # pixel 0,0,0 of the rebinned cube. The output world coordinates # can be calculated as described for the previous test. assert_allclose(np.asarray(cube2.get_start()), (factor - 1) / 2.0) # Do the same test, but with margin='center'. cube2 = cube1.rebin(factor=factor, margin='center') # Compute the expected output cube. The values should be the # same as the previous test. expected_shape = cube1.shape // factor expected = ma.ones(expected_shape) * 0.5 expected.mask = expected < 0 # All pixels unmasked. assert_masked_allclose(cube2.data, expected) # We chose a margin value of 'center'. We need to know which # pixels should have contributed to pixel 0,0,0. First calculate # how many pixels remain after dividing the shape by the reduction # factors. This is the number of extra pixels that should have been # discarded. Divide this by 2 to determine the number of pixels that # are removed from the start of each axis. cut = np.mod(shape, factor).astype(int) // 2 # The world coordinates of the input cube were equal to its pixel # indexes, and the world coordinates of a pixel of the output cube # is thus the mean of the indexes of the pixels that were combined # to make that pixel. In this case, we combine pixels # data[cut:cut+factor] along each axis. This can be calculated as # the sum of pixel indexes from 0 to cut+factor, minus the sum of # pixel indexes from 0 to cut, with the result divided by the number # of pixels that were averaged. Again we make use of the series sum, # sum[n=0..N] = (n*(n-1))/2. tmp = cut + factor assert_allclose(np.asarray(cube2.get_start()), ((tmp * (tmp - 1)) / 2.0 - (cut * (cut - 1)) / 2.0) / factor)