def test_resample(self): """WCS class: testing resampling method""" wave = WaveCoord(crval=0, cunit=u.nm, shape=10) wave2 = wave.resample(step=2.5, start=20, unit=u.angstrom) assert wave2.get_step(unit=u.nm) == 0.25 assert wave2.get_start(unit=u.nm) == 2.0 assert wave2.shape == 32
def test_convolve(): shape = (3, 12, 25) data = np.zeros(shape) data[:, 7, 5] = 1.0 mask = np.zeros(shape, dtype=bool) mask[:, 5, 3] = True c = generate_cube(data=data, mask=mask, shape=shape, wave=WaveCoord(crval=1, cunit=u.angstrom)) # 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 = ma.array(data=np.zeros(shape), mask=mask) expected_data.data[:, 6:9, 4:8] = kern res = c.convolve(kern) assert_masked_allclose(res.data, expected_data, atol=1e-15) res = c.convolve(Image(data=kern)) assert_masked_allclose(res.data, expected_data, atol=1e-15) res = c.fftconvolve(kern) assert_masked_allclose(res.data, expected_data, atol=1e-15)
def test_subcube(mask): """Cube class: testing sub-cube extraction methods""" cube1 = generate_cube(data=np.arange(10 * 6 * 5).reshape(10, 6, 5), wave=WaveCoord(crval=1), mask=mask) # Extract a sub-cube whose images are centered close to pixel # (2.3, 2.8) of the cube and have a width and height of 2 pixels. # The center of a 2x2 pixel region is at the shared corner between # these pixels, and the closest corner to the requested center # of 2.3,2.8 is 2.5,2.5. Thus the sub-images should be from pixels # 2,3 along both the X and Y axes. cube2 = cube1.subcube(center=(2.3, 2.8), size=2, lbda=(5, 8), unit_center=None, unit_size=None, unit_wave=None) assert_allclose(cube1.data[5:9, 2:4, 2:4], cube2.data) # Test when subcube is on the edges cube2 = cube1.subcube(center=(0.3, 0.8), size=4, unit_center=None, unit_size=None) assert_allclose(cube1.data[:, :3, :3], cube2.data[:, 1:, 1:]) # pixels inside the selected region are not masked assert np.all(~cube2.mask[:, 1:, 1:]) # pixels outside the selected region are masked assert np.all(cube2.mask[:, :, 0]) assert np.all(cube2.mask[:, 0, :]) # The following should select the same image area as above, followed by # masking pixels in this area outside a circle of radius 1. cube2 = cube1.subcube_circle_aperture(center=(2.3, 2.8), radius=1, unit_center=None, unit_radius=None) # masking the subcube should not mask the original cube assert ma.count_masked(cube1[0].data) == 0 if cube2.mask is not ma.nomask: assert bool(cube2.mask[0, 0, 0]) is True assert_array_equal(cube2.get_start(), (1, 2, 2)) assert_array_equal(cube2.shape, (10, 2, 2))
def poly_sub(cfg_par, x, y, deg): ''' Continuum subtraction on spectrum through polynomial fitting INPUT: parameter file x-axis of the spectrum y-axis of the spectrum degre of polynomial to fit OUTPUT: continuum subtracted y-axis of spectrum ''' if cfg_par['abs_ex'].get('zunit') == 'm/s': unit_z = u.m / u.s else: unit_z = u.Hz step = (x[-1] - x[0]) / len(x) wave_for_spec = WaveCoord(cdelt=step, crval=x[0], cunit=unit_z) spe = Spectrum(wave=wave_for_spec, data=y) cont = spe.poly_spec(deg) cont_sub = y - cont.data return cont_sub
def test_spectrum_methods(spec_var, spec_novar): """Spectrum class: testing sum/mean/abs/sqrt methods""" wave = WaveCoord(crpix=2.0, cdelt=3.0, crval=0.5, cunit=u.nm, shape=10) spectrum1 = Spectrum(data=np.array([0.5, 1, 2, 3, 4, 5, 6, 7, 8, 9]), wave=wave) sum1 = spectrum1.sum() assert_almost_equal(sum1[0], spectrum1.data.sum()) spectrum2 = spectrum1[1:-2] sum1 = spectrum1.sum(lmin=spectrum1.wave.coord(1), lmax=spectrum1.wave.coord(10 - 3), unit=u.nm) sum2 = spectrum2.sum() assert_almost_equal(sum1, sum2) mean1 = spectrum1.mean(lmin=spectrum1.wave.coord(1), lmax=spectrum1.wave.coord(10 - 3), unit=u.nm) mean2 = spectrum2.mean() assert_almost_equal(mean1, mean2) spvar2 = spec_var.abs() assert spvar2[23] == np.abs(spec_var[23]) spvar2 = spec_var.abs().sqrt() assert spvar2[8] == np.sqrt(np.abs(spec_var[8])) assert_almost_equal(spec_var.mean()[0], 11.526, 2) assert_almost_equal(spec_novar.mean()[0], 11.101, 2) spvarsum = spvar2 + 4 * spvar2 - 56 / spvar2 assert_almost_equal(spvarsum[10], spvar2[10] + 4 * spvar2[10] - 56 / spvar2[10], 2) assert_almost_equal(spec_var.get_step(), 0.630, 2) assert_almost_equal(spec_var.get_start(), 4602.604, 2) assert_almost_equal(spec_var.get_end(), 7184.289, 2) assert_almost_equal(spec_var.get_range()[0], 4602.604, 2) assert_almost_equal(spec_var.get_range()[1], 7184.289, 2)
def test_rebin(spec_var, spec_novar): """Spectrum class: testing rebin function""" wave = WaveCoord(crpix=2.0, cdelt=3.0, crval=0.5, shape=10) spectrum1 = Spectrum(data=np.array([0.5, 1, 2, 3, 4, 5, 6, 7, 8, 9]) * 2.3, wave=wave) unit = spectrum1.wave.unit factor = 3 s = slice(0, factor * (spectrum1.shape[0] // factor)) # The rebinned slice flux1 = spectrum1[s].sum()[0] * spectrum1[s].wave.get_step(unit=unit) spectrum2 = spectrum1.rebin(factor, margin='left') flux2 = spectrum2.sum()[0] * spectrum2.wave.get_step(unit=unit) assert_almost_equal(flux1, flux2, 2) unit = spec_novar.wave.unit factor = 4 s = slice(0, factor * (spec_novar.shape[0] // factor)) flux1 = spec_novar[s].sum()[0] * spec_novar[s].wave.get_step(unit=unit) spnovar2 = spec_novar.rebin(factor, margin='left') flux2 = spnovar2.sum()[0] * spnovar2.wave.get_step(unit=unit) assert_almost_equal(flux1, flux2, 2) unit = spec_var.wave.unit factor = 4 s = slice(0, factor * (spec_var.shape[0] // factor)) flux1 = spec_var[s].sum(weight=False)[0] * \ spec_var[s].wave.get_step(unit=unit) spvar2 = spec_var.rebin(factor, margin='left') flux2 = spvar2.sum(weight=False)[0] * spvar2.wave.get_step(unit=unit) assert_almost_equal(flux1, flux2, 2)
def test_write(tmpdir): """Cube class: testing write""" unit = u.Unit('1e-20 erg/s/cm2/Angstrom') cube = generate_cube(data=1, wave=WaveCoord(crval=1, cunit=u.angstrom), unit=unit) cube.data[:, 0, 0] = ma.masked cube.var = np.ones_like(cube.data) testfile = str(tmpdir.join('cube.fits')) cube.write(testfile) hdu = fits.open(testfile) assert_array_equal(hdu[1].data.shape, cube.shape) assert_array_equal([h.name for h in hdu], ['PRIMARY', 'DATA', 'STAT', 'DQ']) hdr = hdu[0].header assert hdr['AUTHOR'] == 'MPDAF' hdr = hdu[1].header assert hdr['EXTNAME'] == 'DATA' assert hdr['NAXIS'] == 3 assert u.Unit(hdr['BUNIT']) == unit assert u.Unit(hdr['CUNIT3']) == u.angstrom assert hdr['NAXIS1'] == cube.shape[2] assert hdr['NAXIS2'] == cube.shape[1] assert hdr['NAXIS3'] == cube.shape[0] for key in ('CRPIX1', 'CRPIX2'): assert hdr[key] == 1.0 hdu.close()
def test_aperture(): """Cube class: testing spectrum extraction""" cube = generate_cube(data=1, wave=WaveCoord(crval=1)) spe = cube.aperture(center=(2, 2.8), radius=1, unit_center=None, unit_radius=None) assert spe.shape[0] == 10 assert spe.get_start() == 1
def get_sky_spectrum(filename) : """Read sky spectrum from MUSE data reduction """ sky = pyfits.getdata(filename) crval = sky['lambda'][0] cdelt = sky['lambda'][1] - crval wavein = WaveCoord(cdelt=cdelt, crval=crval, cunit= units.angstrom) spec = Spectrum(wave=wavein, data=sky['data'], var=sky['stat']) return spec
def test_truncate(): """Cube class: testing truncation""" cube1 = generate_cube(data=2, wave=WaveCoord(crval=1)) coord = [2, 0, 1, 5, 1, 3] cube2 = cube1.truncate(coord, unit_wcs=cube1.wcs.unit, unit_wave=cube1.wave.unit) assert_array_equal(cube2.shape, (4, 2, 3)) assert_array_equal(cube2.get_start(), (2, 0, 1)) assert_array_equal(cube2.get_end(), (5, 1, 3))
def test_rebin(self): """WCS class: testing rebin method""" wave = WaveCoord(crval=0, cunit=u.nm, shape=10) wave.rebin(factor=2) assert wave.get_step(unit=u.nm) == 2.0 assert wave.get_start(unit=u.nm) == 0.5 assert wave.coord(2, unit=u.nm) == 4.5 assert wave.shape == 5
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_resample2(): """Spectrum class: testing resampling function with a spectrum of integers and resampling to a smaller pixel size""" wave = WaveCoord(crpix=2.0, cdelt=3.0, crval=0.5, cunit=u.nm) spectrum1 = Spectrum(data=np.array([0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0]), wave=wave) flux1 = spectrum1.sum()[0] * spectrum1.wave.get_step() spectrum2 = spectrum1.resample(0.3) flux2 = spectrum2.sum()[0] * spectrum2.wave.get_step() assert_almost_equal(flux1, flux2, 2)
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'] h_vt = par['h_v'] csize = par['csize'] r_0t = par['r_0'] print(par) h_v = 10**h_vt col_dens = 10**col_denst r_0 = 10**r_0t coord_sky = datacube.wcs.pix2sky([int(pos[0]), int(pos[1])], unit=u.deg) dec = coord_sky[0][0] ra = coord_sky[0][1] c1 = SkyCoord(ra * u.degree, dec * u.degree, frame='icrs') flux = datacube[:, int(pos[0]), int(pos[1])] abso = flux.data[specwidth[0]:specwidth[1] + 1] sigma = np.sqrt(flux.var[specwidth[0]:specwidth[1] + 1]) scale = 7.28 # z=0.73379 # plat scale (kpc/") for Planck c1 = SkyCoord(ra * u.degree, dec * u.degree, frame='icrs') #D = scale * galcen.separation(c1).arcsec #pa = galcen.position_angle(c1).to(u.deg) #alpha = galPA - pa.value alpha = csu.get_alpha(c1, galcen, galPA) D = csu.get_impactparam(c1, galcen, scale) lam2 = np.arange(4825.12, 4886.37 + 1.5, 0.1) wave1 = WaveCoord(cdelt=0.1, crval=4825.12, cunit=u.angstrom) model = Disco(h, incli, Rcore=0.1) spec = model.averagelos(D, alpha, lam2, 100, 12, z, csize, col_dens, bes, r_0, v_max, h_v, 0) spe = Spectrum(wave=wave1, data=spec) rspe = spe.resample(1.25) fluxmodel = rspe.data absomodel = fluxmodel[specwidth[0]:specwidth[1] + 1] #ymodelt = np.concatenate((ymodel[0][14:36],ymodel[1][16:36],ymodel[2][16:36])) rest = ((abso - absomodel) / sigma)**2 dif = abso - absomodel return (fluxmodel, rest, datacube[:, int(pos[0]), int(pos[1])].data, sigma, dif)
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_write(tmpdir): """Spectrum class: testing write.""" testfile = str(tmpdir.join('spec.fits')) sp = Spectrum(data=np.arange(10), wave=WaveCoord(cunit=u.nm)) sp.write(testfile) with fits.open(testfile) as hdu: assert_array_equal(hdu[1].data.shape, sp.shape) hdr = hdu[1].header assert hdr['EXTNAME'] == 'DATA' assert hdr['NAXIS'] == 1 assert u.Unit(hdr['CUNIT1']) == u.nm assert hdr['NAXIS1'] == sp.shape[0] # Same with Angstrom sp = Spectrum(data=np.arange(10), wave=WaveCoord(cunit=u.angstrom)) sp.write(testfile) with fits.open(testfile) as hdu: assert u.Unit(hdu[1].header['CUNIT1']) == u.angstrom
def test_coord_transform(self): """WaveCoord class: testing coordinates transformations""" wave = WaveCoord(crval=0, cunit=u.nm, shape=10) pixel = wave.pixel(wave.coord(5, unit=u.nm), nearest=True, unit=u.nm) assert pixel == 5 wave2 = np.arange(10) pixel = wave.pixel(wave.coord(wave2, unit=u.nm), nearest=True, unit=u.nm) assert_array_equal(pixel, wave2) pix = np.arange(wave.shape, dtype=float) np.testing.assert_allclose(wave.pixel(wave.coord(unit=u.nm), unit=u.nm), pix)
def get_sky_spectrum(specname): """Read sky spectrum from MUSE data reduction """ if not os.path.isfile(specname): upipe.print_error("{0} not found".format(specname)) return None sky = pyfits.getdata(specname) crval = sky['lambda'][0] cdelt = sky['lambda'][1] - crval wavein = WaveCoord(cdelt=cdelt, crval=crval, cunit=u.angstrom) spec = Spectrum(wave=wavein, data=sky['data'], var=sky['stat']) return spec
def to_mpdaf(self, row=1, scale=True): """ Creates a mpdaf.obj.Spectrum object from FADO 1D files. The spectrum can be specified as a row or as a name. Allowed names are the following 1: 'Observed' spectrum de-redshifted and rebinned' 2: 'Error' 3: 'Mask' 4: 'Best' 5: 'Average' of individual solutions 6: 'Median' 7: 'Stdev' 8: 'Stellar' using best fit' 9: 'Nebular' using best fit' 10: 'AGN' using best fit' 11: 'M/L' 12: 'LSF' Line spread function The best-fits for individual solution can only be specified as a number 13-XX see self.max_rows Parameters ---------- row: str, int Allowed names: 'observed', 'error', 'mask', 'best', 'average', 'median', 'stdev', 'stellar', 'nebular' 'agn', 'm/l', 'lsf' The row number where the spectra is extracted, default=1 (0 in python notation) scale: bool, whether to scale the spectra or not, default True Returns ------- a mpdaf.obj.Spectrum object """ try: from mpdaf.obj import Spectrum, WaveCoord except ImportError as e: print(e, "MPDAF not installed, cannot continue") raise sp = self.spectrum(row, scale) wave_coord = WaveCoord(cdelt=self.header["CDELT1"], crval=self.header["CRVAL1"], cunit=self.fado_load.wave_unit) sp_mpdaf = Spectrum(wave=wave_coord, data=sp.flux) return sp_mpdaf
def read(self): """Read sky continuum spectrum from MUSE data reduction """ if not os.path.isfile(self.filename): upipe.print_error("{0} not found".format(self.filename)) crval = 0.0 data = np.zeros(0) cdelt = 1.0 else: sky = pyfits.getdata(self.filename) crval = sky['lambda'][0] cdelt = sky['lambda'][1] - crval data = sky['flux'] wavein = WaveCoord(cdelt=cdelt, crval=crval, cunit=u.angstrom) self.spec = Spectrum(wave=wavein, data=data)
def test_get_Spectrum(spec_var): """Spectrum class: testing getters""" 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]) * 2.3, wave=wave) a = spectrum1[1:7] assert a.shape[0] == 6 a = spectrum1.subspec(1.2, 15.6, unit=u.nm) assert a.shape[0] == 6 unit = spec_var.wave.unit spvarcut = spec_var.subspec(5560, 5590, unit=unit) assert spvarcut.shape[0] == 48 assert_almost_equal(spvarcut.get_start(unit=unit), 5560.25, 2) assert_almost_equal(spvarcut.get_end(unit=unit), 5589.89, 2) assert_almost_equal(spvarcut.get_step(unit=unit), 0.63, 2)
def test_sum(): """Cube class: testing sum method""" cube1 = generate_cube(data=1, wave=WaveCoord(crval=1)) ind = np.arange(10) refsum = ind.sum() cube1.data = (ind[:, np.newaxis, np.newaxis] * np.ones((6, 5))[np.newaxis, :, :]) assert cube1.sum() == 6 * 5 * refsum assert_array_equal(cube1.sum(axis=0).data, np.full((6, 5), refsum, float)) weights = np.ones(shape=(10, 6, 5)) assert cube1.sum(weights=weights) == 6 * 5 * refsum weights = np.ones(shape=(10, 6, 5)) * 2 assert cube1.sum(weights=weights) == 6 * 5 * refsum assert_array_equal(cube1.sum(axis=(1, 2)).data, ind * 6 * 5)
def test_min(): """Cube class: testing min method""" cube1 = generate_cube(data=1., wave=WaveCoord(crval=1)) ind = np.arange(10) minimum = np.amin(ind) cube1.data = (ind[:, np.newaxis, np.newaxis] * np.ones((6, 5))[np.newaxis, :, :]) m = cube1.min() assert m == minimum m = cube1.min(axis=0) assert m[3, 3] == minimum m = cube1.min(axis=(1, 2)) assert_array_equal(m.data, ind) with pytest.raises(ValueError): m = cube1.min(axis=-1)
def image2cube(image): """ Parameters ---------- image : mpdaf.obj.Image Input image object Returns ------- cube : mpdaf.obj.Cube A cube version of the input image. """ from mpdaf.obj import Cube, Image, WaveCoord # get the wcs wcs = image.wcs # create dummy WaveCoord wv_coord = WaveCoord(shape=1)
def test_gauss_fit(capsys, cont): """Spectrum class: testing Gaussian fit""" contval = cont or 0 wave = WaveCoord(crpix=1, cdelt=0.3, crval=400, cunit=u.nm) spem = Spectrum(data=np.zeros(600) + contval, wave=wave) spem.add_gaussian(5000, 1200, 20, unit=u.angstrom) setup_logging() gauss = spem.gauss_fit(lmin=(4500, 4800), lmax=(5200, 6000), lpeak=5000, cont=cont, unit=u.angstrom) gauss.print_param() out, err = capsys.readouterr() assert '[INFO] Gaussian center = 5000 ' in err assert_almost_equal(gauss.lpeak, 5000, 2) assert_almost_equal(gauss.flux, 1200, 2) assert_almost_equal(gauss.fwhm, 20, 2) assert_allclose(spem.fwhm(gauss.lpeak, cont=contval), 20, atol=0.2)
def test_get_item(): """Spectrum class: testing __getitem__""" # Set the shape and contents of the spectrum's data array. shape = (5, ) data = np.arange(shape[0]) # Create a test spectrum with the above data array. s = generate_spectrum(data=data, shape=shape, wave=WaveCoord(crval=1, cunit=u.angstrom)) s.primary_header['KEY'] = 'primary value' s.data_header['KEY'] = 'data value' # Select the whole spectrum. r = s[:] assert_array_equal(r.shape, s.shape) assert_allclose(r.data, s.data) assert r.primary_header['KEY'] == s.primary_header['KEY'] assert r.data_header['KEY'] == s.data_header['KEY'] assert isinstance(r, Spectrum) assert r.wcs is None assert r.wave.isEqual(s.wave) # Select a sub-spectrum. r = s[1:3] assert_array_equal(r.shape, (2)) assert_allclose(r.data, s.data[1:3]) assert r.primary_header['KEY'] == s.primary_header['KEY'] assert r.data_header['KEY'] == s.data_header['KEY'] assert isinstance(r, Spectrum) assert r.wave.isEqual(s.wave[1:3]) assert r.wcs is None # Select a single pixel of the spectrum. r = s[2] assert np.isscalar(r) assert_allclose(r, s.data[2])
if (pixi[:, None] == all_pixels).all(-1).any(-1): print(i, j) coord_sky = datacube.wcs.pix2sky([i, j], unit=u.deg) dec = coord_sky[0][0] ra = coord_sky[0][1] scale = 7.28 # z=0.73379 # plat scale (kpc/") for Planck c1 = SkyCoord(ra * u.degree, dec * u.degree, frame='icrs') alpha = csu.get_alpha(c1, galcen, galPA) D = csu.get_impactparam(c1, galcen, scale) flux = datacube[:, i, j] abso = flux.data[specwidth[0]:specwidth[1] + 1] sigma = np.sqrt(flux.var[specwidth[0]:specwidth[1] + 1]) lam2 = np.arange(4825.12, 4886.37 + 1.5, 0.1) wave1 = WaveCoord(cdelt=0.1, crval=4825.12, cunit=u.angstrom) model = Disco(h, incli, Rcore=0.1) spec = model.averagelos(D, alpha, lam2, 100, 12, z, csize, col_dens, bes, r_0, v_max, h_v, 0) spe = Spectrum(wave=wave1, data=spec) rspe = spe.resample(1.25) fluxmodel = rspe.data absomodel = fluxmodel[specwidth[0]:specwidth[1] + 1] #ymodelt = np.concatenate((ymodel[0][14:36],ymodel[1][16:36],ymodel[2][16:36])) dif = np.sum(((abso - absomodel) / sigma)**2) ima.data[i, j] = dif ima.mask[i, j] = False else:
wave1 = WaveCoord(cdelt=0.1, crval=4751.37, cunit= u.angstrom, shape=247.5) spec = model.averagelosspec(D, alpha, lam1, 100,12,z,csize, col_dens, b, r_0, v_max, h_v, 0) spe = Spectrum(wave=wave1, data=spec[1]) rspe = spe.resample(1.25) modelcube[:,i-1,j-1] = rspe.data modelcube.write('modelcube_i%s' %incli +'_N%s' %col_dens + '_h%s' %h+'_b%s' %b + '_vmax%s'%v_max +'_hv%s' %h_v+'_csize%s'%csize+'_r0%s'%r_0+'.fits')''' #create only one spectra in position pixel pixel = [12,12] from timeit import default_timer as timer start = timer() coord_sky = datacube.wcs.pix2sky([pixel[0]-1, pixel[1]-1], unit=u.deg) dec = coord_sky[0][0] ra = coord_sky[0][1] scale = 7.28 # z=0.73379 # plat scale (kpc/") for Planck c1 = SkyCoord(ra*u.degree,dec*u.degree,frame='icrs') D = scale * galcen.separation(c1).arcsec pa = galcen.position_angle(c1).to(u.deg) alpha = galPA - pa.value wave1 = WaveCoord(cdelt=0.1, crval=4751.37, cunit= u.angstrom, shape=247.5) spec = model.averagelos(D, alpha, lam1, 100,12,z,csize, col_dens, b, r_0, v_max, h_v, 0) spe = Spectrum(wave=wave1, data=spec) rspe = spe.resample(1.25) print(timer() - start)
def test_resample(): """Spectrum class: Test resampling""" # Choose the dimensions of the spectrum, choosing a large number that is # *not* a convenient power of 2. oldshape = 4000 # Choose the wavelength pixel size and the default wavelength units. oldstep = 1.0 oldunit = u.angstrom # Create the wavelength axis coordinates. wave = WaveCoord(crpix=2.0, cdelt=oldstep, crval=0.5, cunit=oldunit, shape=oldshape) # Specify the desired increase in pixel size, and the resulting pixel size. factor = 6.5 newstep = ((factor * oldstep) * oldunit).to(u.nm).value # Specify the wavelength at which the peak of the resampled spectrum should # be expected. expected_peak_wave = 3000.0 # Create the array in which the test spectrum will be composed. data = np.zeros(oldshape) # Get the wavelength coordinates of each pixel in the spectrum. w = wave.coord() # Add the following list gaussians to the spectrum, where each # gaussian is specified as: (amplitude, sigma_in_pixels, # center_wavelength). Given that narrow gaussians are reduced in # amplitude by resampling more than wide gaussians, we arrange # that the peak gaussian before and after correctly resampling are # different. gaussians = [ (0.5, 12.0, 800.0), (0.7, 5.0, 1200.0), (0.4, 700.0, 1600.0), (1.5, 2.6, 1980.0), # Peak before resampling (1.2, 2.6, 2000.0), (1.3, 15.0, expected_peak_wave), # Peak if resampled correctly (1.0, 2.0, 3200.0) ] for amp, sigma, center in gaussians: sigma *= oldstep data += amp * np.exp(-0.5 * ((center - w) / sigma)**2) # Fill the variance array with a simple window function. var = np.hamming(oldshape) # Add gaussian random noise to the spectrum, but leave 3 output # pixel widths zero at each end of the spectrum so that the PSF of # the output grid doesn't spread flux from the edges off the edge # of the output grid. It takes about 3 pixel widths for the gaussian # PSF to drop to about 0.01 of its peak. margin = np.ceil(3 * factor).astype(int) data[margin:-margin] += np.random.normal(scale=0.1, size=data.shape - 2 * margin) # Install the spectral data in a Spectrum container. oldsp = Spectrum(data=data, var=var, wave=wave) # Mask a few pixels. masked_slice = slice(900, 910) oldsp.mask[masked_slice] = True # Create a down-sampled version of the input spectrum. newsp = oldsp.resample(newstep, unit=u.nm) # Check that the integral flux in the resampled spectrum matches that of # the original spectrum. expected_flux = oldsp.sum(weight=False)[0] * oldsp.wave.get_step( unit=oldunit) actual_flux = newsp.sum(weight=False)[0] * newsp.wave.get_step( unit=oldunit) assert_allclose(actual_flux, expected_flux, 1e-2) # Do the same test, but with fluxes weighted by the inverse of the variances. expected_flux = oldsp.sum(weight=True)[0] * oldsp.wave.get_step( unit=oldunit) actual_flux = newsp.sum(weight=True)[0] * newsp.wave.get_step(unit=oldunit) assert_allclose(actual_flux, expected_flux, 1e-2) # Check that the peak of the resampled spectrum is at the wavelength # where the strongest gaussian was centered in the input spectrum. assert_allclose(np.argmax(newsp.data), newsp.wave.pixel(expected_peak_wave, nearest=True)) # Now upsample the downsampled spectrum to the original pixel size. # This won't recover the same spectrum, since higher spatial frequencies # are lost when downsampling, but the total flux should be about the # same, and the peak should be at the same wavelength as the peak in # original spectrum within one pixel width of the downsampled spectrum. newsp2 = newsp.resample(oldstep, unit=oldunit) # Check that the doubly resampled spectrum has the same integrated flux # as the original. expected_flux = oldsp.sum(weight=False)[0] * oldsp.wave.get_step( unit=oldunit) actual_flux = newsp2.sum(weight=False)[0] * newsp2.wave.get_step( unit=oldunit) assert_allclose(actual_flux, expected_flux, 1e-2) # Check that the peak of the up-sampled spectrum is at the wavelength # of the peak of the down-sampled spectrum to within the pixel resolution # of the downsampled spectrum. assert_allclose( newsp.wave.pixel(newsp2.wave.coord(np.argmax(newsp2.data)), nearest=True), newsp.wave.pixel(expected_peak_wave, nearest=True)) # Check that pixels that were masked in the input spectrum are still # masked in the final spectrum. np.testing.assert_equal(newsp2.mask[masked_slice], oldsp.mask[masked_slice])
def test_integrate(): """Spectrum class: testing integration""" 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, unit=u.Unit('ct/Angstrom')) # Integrate the whole spectrum, by not specifying starting or ending # wavelengths. This should be the sum of the pixel values multiplied # by cdelt in angstroms (because the flux units are per angstrom). result, err = spectrum1.integrate() expected = spectrum1.get_step(unit=u.angstrom) * spectrum1.sum()[0] assert_almost_equal(result.value, expected) assert result.unit == u.ct assert np.isinf(err) # The result should not change if we change the wavelength units of # the wavelength limits to nanometers. result = spectrum1.integrate(unit=u.nm)[0] expected = spectrum1.get_step(unit=u.angstrom) * spectrum1.sum()[0] assert_almost_equal(result.value, expected) assert result.unit == u.ct # new spectrum with variance spectrum1 = Spectrum(data=np.array([0.5, 1, 2, 3, 4, 5, 6, 7, 8, 9]), var=np.ones(10), wave=wave, unit=u.Unit('ct/Angstrom')) # Integrate over a wavelength range 3.5 to 6.5 nm. The WCS # conversion equation from wavelength to pixel index is, # # index = crpix-1 + (lambda-crval)/cdelt # index = 1 + (lambda - 0.5) / 3.0 # # So wavelengths 3.5 and 6.5nm, correspond to pixel indexes # of 2.0 and 3.0. These are the centers of pixels 2 and 3. # Thus the integration should be the value of pixel 2 times # half of cdelt, plus the value of pixel 3 times half of cdelt. # This comes to 2*3.0/2 + 3*3.0/2 = 7.5 ct/Angstrom*nm, which # should be rescaled to 75 ct, since nm/Angstrom is 10.0. result, err = spectrum1.integrate(lmin=3.5, lmax=6.5, unit=u.nm) assert_almost_equal(result.value, 75) assert result.unit == u.ct datasum, var = spectrum1.sum(lmin=3.5, lmax=6.5, unit=u.nm) assert_almost_equal(result.value, datasum * 15) assert_almost_equal(err.value, var * 15) # Do the same test, but specify the wavelength limits in angstroms. # The result should be the same as before. result = spectrum1.integrate(lmin=35.0, lmax=65.0, unit=u.angstrom)[0] assert_almost_equal(result.value, 75) assert result.unit == u.ct assert_almost_equal(result.value, datasum * 15) assert_almost_equal(err.value, var * 15) # Do the same experiment yet again, but this time after changing # the flux units of the spectrum to simple counts, without any per # wavelength units. Since there are no wavelength units in the # flux units, the result should not be rescaled from the native # value of 7.5, and because we specified a wavelength range in # angstroms, the resulting units should be counts * nm. spectrum1.unit = u.ct result = spectrum1.integrate(lmin=3.5, lmax=6.5, unit=u.nm)[0] assert_almost_equal(result.value, 7.5) assert result.unit == u.ct * u.nm