def test_magnitudes(self, spec_name, filters): sp = Spextrum(spec_name) filter1 = filters[0] filter2 = filters[1] mag1 = sp.get_magnitude(filter_curve=filter1) mag2 = sp.get_magnitude(filter_curve=filter2) assert np.isclose(mag1.value, mag2.value, atol=0.3)
def test_correct_scaling(self, unit): sp1 = Spextrum("kc96/s0").scale_to_magnitude(amplitude=14 * unit, filter_curve="r") sp2 = Spextrum("kc96/s0").scale_to_magnitude(amplitude=15 * unit, filter_curve="r") flux1 = sp1(sp1.waveset[(sp1.waveset.value > 6231 - 200) & (sp1.waveset.value < 6231 + 200)]).value flux2 = sp2(sp2.waveset[(sp2.waveset.value > 6231 - 200) & (sp2.waveset.value < 6231 + 200)]).value mean = np.mean(flux1 / flux2) assert np.isclose(mean, 10**0.4)
def test_ref_spectrum_is_right(self, unit): sp1 = Spextrum.flat_spectrum(amplitude=10 * unit) sp2 = Spextrum.flat_spectrum(amplitude=11 * unit) if unit == u.mag: flux1 = sp1(sp1.waveset[(sp1.waveset.value > 7000 - 200) & (sp1.waveset.value < 7000 + 200)]).value flux2 = sp2(sp2.waveset[(sp2.waveset.value > 7000 - 200) & (sp2.waveset.value < 7000 + 200)]).value else: waves = np.arange(1000, 1e4, 1) * u.AA flux1 = sp1(waves) flux2 = sp2(waves) mean = np.mean(flux1 / flux2) assert np.isclose(mean, 10**0.4)
def test_vega2ab(self, filt): """ test if the convertion between AB and Vega is correct conversions taken from: http://www.astronomy.ohio-state.edu/~martini/usefuldata.html absolute tolerance set to 0.15 mag to account for filter differences Parameters ---------- filt: str name of the filter """ ab2vega = { "U": 0.79, # magAB - magVega taken from "B": -0.09, # "V": 0.02, "R": 0.21, "I": 0.45, "J": 0.91, "H": 1.39, "Ks": 1.85 } sp = Spextrum.flat_spectrum(amplitude=0 * u.ABmag) magAB = sp.get_magnitude(filt, system_name="AB") magVega = sp.get_magnitude(filt, system_name="vega") diff = (magAB.value - magVega.value) assert np.isclose(diff, ab2vega[filt], atol=0.15)
def test_hz2angstrom(self): waves = np.array([1, 2, 3]) * u.Hz flux = np.array([1, 1, 2]) * units.FLAM sp = Spextrum.from_arrays(waves, flux) inwaves = c.value / waves.value outwaves = sp.waveset.to(u.m).value assert np.isclose(inwaves[::-1], outwaves).all()
def data_cube( sed, # The SED of the galaxy, z=0, # redshift mag=15, # magnitude filter_name="g", # passband wmin=None, wmax=None, plate_scale=0.2, # the plate scale "/pix r_eff=10, # effective radius n=4, # sersic index ellip=0.1, # ellipticity theta=0, # position angle vmax=100, sigma=100, extend=2): # extend in units of r_eff): """ Creates a datacube for a galaxy """ if isinstance(mag, u.Quantity) is False: mag = mag * u.ABmag if isinstance(plate_scale, u.Quantity) is False: plate_scale = plate_scale * u.arcsec if isinstance(r_eff, u.Quantity) is False: r_eff = r_eff * u.arcsec if isinstance(vmax, u.Quantity) is False: vmax = vmax * u.km / u.s if isinstance(sigma, u.Quantity) is False: sigma = sigma * u.km / u.s if isinstance(sed, str): sp = Spextrum(sed).redshift(z=z) scaled_sp = sp.scale_to_magnitude(amplitude=mag, filter_name=filter_name) elif isinstance(sed, Spextrum): scaled_sp = sed if wmin is None: wmin = np.min(scaled_sp.waveset) elif isinstance(wmin, u.Quantity) is False: wmin = wmin * u.AA else: wmin = wmin.to(u.AA) if wmax is None: wmax = np.max(scaled_sp.waveset) elif isinstance(wmax, u.Quantity) is False: wmax = wmax * u.AA else: wmax = wmax.to(u.AA) scaled_sp = scaled_sp[(scaled_sp.waveset > wmin) & (scaled_sp.waveset < wmax)] image_size = 2 * (r_eff.value * extend / plate_scale.value ) # TODO: Needs unit check x_0 = image_size // 2 y_0 = image_size // 2 x, y = np.meshgrid(np.arange(image_size), np.arange(image_size)) gal = GalaxyBase(x=x, y=y, x_0=x_0, y_0=y_0, r_eff=r_eff.value / plate_scale.value, amplitude=1, n=n, ellip=ellip, theta=theta, vmax=vmax, sigma=sigma) intensity = gal.intensity velocity = gal.velocity.value dispersion = gal.dispersion.value w, h = intensity.shape length = scaled_sp.waveset.shape header = fits.Header({ "NAXIS": 3, "NAXIS1": 2 * x_0 + 1, "NAXIS2": 2 * y_0 + 1, "NAXIS3": length, "CRPIX1": w // 2, "CRPIX2": h // 2, "CRPIX3": 1.0, "CRVAL1": 0, "CRVAL2": 0, "CRVAL3": np.min(scaled_sp.waveset), "CDELT1": -1 * plate_scale.to(u.deg).value, "CDELT2": plate_scale.to(u.deg).value, "CUNIT1": "DEG", "CUNIT2": "DEG", "CUNIT3": "Angstrom", "CTYPE1": 'RA---TAN', "CTYPE2": 'DEC--TAN', "CTYPE3": "AWAV", "SPEC_REF": 0 }) for i in range(image_size): for j in range(image_size): sp = scaled_sp.redshift(vel=velocity[i, j]).smooth( sigma=dispersion[i, j]) * intensity[i, j]
def test_sum_spectra(self): sp1 = Spextrum("kc96/s0") sp2 = Spextrum("pickles/a0v") sp = sp1 + sp2 assert isinstance(sp, Spextrum)
def test_flat_spectrum(self, unit): sp = Spextrum.flat_spectrum(amplitude=10 * unit) assert isinstance(sp, Spextrum)
class TestSpextrumInstances: """ This class tests whether each method return the correct instances it also tests whether the methods are functional but it doesn't test for correct outputs see cls:TestSpextrum for that """ sp = Spextrum("kc96/s0") def test_load(self, sp=sp): assert isinstance(sp, Spextrum) def test_sub_class(self): assert issubclass(Spextrum, SourceSpectrum) def test_redshift(self, sp=sp): sp2 = sp.redshift(z=1) assert isinstance(sp2, Spextrum) def test_add_emi_lines(self, sp=sp): sp2 = sp.add_emi_lines([5000, 6000], [10, 20], [1e-15, 2e-15]) assert isinstance(sp2, Spextrum) def test_add_abs_lines(self, sp=sp): sp2 = sp.add_abs_lines([5000, 6000], [15, 20], [10, 12]) assert isinstance(sp2, Spextrum) @pytest.mark.parametrize("unit", [u.mag, u.STmag, u.ABmag]) def test_flat_spectrum(self, unit): sp = Spextrum.flat_spectrum(amplitude=10 * unit) assert isinstance(sp, Spextrum) def test_mul_with_scalar(self, sp=sp): sp2 = sp * 2 assert isinstance(sp2, Spextrum) def test_sum_spectra(self): sp1 = Spextrum("kc96/s0") sp2 = Spextrum("pickles/a0v") sp = sp1 + sp2 assert isinstance(sp, Spextrum) def test_scale_to_magnitude(self, sp=sp): sp2 = sp.scale_to_magnitude(amplitude=15 * u.ABmag, filter_curve="g") assert isinstance(sp2, Spextrum) def test_rebin_spectra(self, sp=sp): new_waves = np.linspace(np.min(sp.waveset), np.max(sp.waveset), 100) sp2 = sp.rebin_spectra(new_waves=new_waves) assert isinstance(sp2, Spextrum) def test_get_magnitude(self): sp = Spextrum("pickles/a0v") mag = sp.get_magnitude("elt/micado/Y", system_name="AB") assert isinstance(mag, u.Quantity) def test_black_body_spectrum(self): sp = Spextrum.black_body_spectrum(filter_curve="g") assert isinstance(sp, Spextrum) def test_photons_in_range(self): sp = Spextrum.black_body_spectrum(filter_curve="g") counts = sp.photons_in_range(wmin=4000, wmax=5000) assert isinstance(counts, u.Quantity) def test_smooth(self): sp = Spextrum.black_body_spectrum(filter_curve="g") sp2 = sp.smooth(10 * (u.m / u.s)) assert isinstance(sp2, Spextrum) def test_redden(self): sp = Spextrum.black_body_spectrum(filter_curve="r") sp2 = sp.redden("calzetti/starburst", Ebv=0.1) assert isinstance(sp2, Spextrum) def test_deredden(self): sp = Spextrum.black_body_spectrum(filter_curve="F110W") sp2 = sp.redden("gordon/smc_bar", Ebv=0.1) assert isinstance(sp2, Spextrum) def testing_nesting(self): sp = Spextrum("kc96/s0").redshift(z=1).\ scale_to_magnitude(amplitude=15*u.ABmag, filter_curve="g").\ redden("calzetti/starburst", Ebv=0.1) assert isinstance(sp, Spextrum)
def test_photons_in_range(self): sp = Spextrum.black_body_spectrum(filter_curve="g") counts = sp.photons_in_range(wmin=4000, wmax=5000) assert isinstance(counts, u.Quantity)
def galaxy3d( sed, # The SED of the galaxy, z=0, # redshift mag=15, # magnitude filter_name="g", # passband plate_scale=0.2, # the plate scale "/pix r_eff=10, # effective radius n=4, # sersic index ellip=0.1, # ellipticity theta=0, # position angle vmax=100, sigma=100, extend=2, # extend in units of r_eff ngrid=10): # griding parameter """ Creates a source object of a galaxy described by its Sersic index and other parameters. It also generates a velocity field (set by vmax) and a velocity dispersion map (set by sigma). The maps are binned according to the ngrid parameter, higher ngrid will create finer binned fields but it may increase the computation time. The ngrid parameter does not specify the number of bins. A ngrid=10 will create around 40 independent regions whilst a ngrid of 100 will create around 2300 regions This function is ideal for spectroscopy Parameters ---------- sed : str or Spextrum SED of the galaxy, it can be a string or a Spextrum object, in the later case it won't be re-escaled. z : float redshift of the galaxy mag : float magnitude of the galaxy. The spectrum will be re-escaled to this magnitude filter_name : str name of the filter where the magnitude is measured plate_scale : float the scale of the image in arcsec/pixel r_eff : float effective radius of the galaxy in arcsec. It accepts astropy.units n : float Sersic index of the galaxy ellip : float ellipticity of the galaxy theta : float position angle of the galaxy vmax : float maximum rotation velocity of the galaxy sigma : float velocity dispersion of the galaxy extend : float Size of the image in units of r_eff ngrid : int gridding parameter for creating of the galaxy Returns ------- src : scopesim.Source """ if isinstance(mag, u.Quantity) is False: mag = mag * u.ABmag if isinstance(plate_scale, u.Quantity) is False: plate_scale = plate_scale * u.arcsec if isinstance(r_eff, u.Quantity) is False: r_eff = r_eff * u.arcsec if isinstance(vmax, u.Quantity) is False: vmax = vmax * u.km / u.s if isinstance(sigma, u.Quantity) is False: sigma = sigma * u.km / u.s if isinstance(sed, str): sp = Spextrum(sed).redshift(z=z) scaled_sp = sp.scale_to_magnitude(amplitude=mag, filter_curve=filter_name) elif isinstance(sed, Spextrum): scaled_sp = sed r_eff = r_eff.to(u.arcsec) plate_scale = plate_scale.to(u.arcsec) vmax = vmax.to(u.km / u.s) sigma = sigma.to(u.km / u.s) image_size = 2 * (r_eff.value * extend / plate_scale.value ) # TODO: Needs unit check print(image_size, r_eff) x_0 = image_size // 2 y_0 = image_size // 2 x, y = np.meshgrid(np.arange(image_size), np.arange(image_size)) galaxy = GalaxyBase(x=x, y=y, x_0=x_0, y_0=y_0, r_eff=r_eff.value / plate_scale.value, amplitude=1, n=n, ellip=ellip, theta=theta, vmax=vmax, sigma=sigma) intensity = galaxy.intensity velocity = galaxy.velocity.value dispersion = galaxy.dispersion.value masks = galaxy.get_masks(ngrid=ngrid) w, h = intensity.shape header = fits.Header({ "NAXIS": 2, "NAXIS1": 2 * x_0 + 1, "NAXIS2": 2 * y_0 + 1, "CRPIX1": w // 2, "CRPIX2": h // 2, "CRVAL1": 0, "CRVAL2": 0, "CDELT1": -1 * plate_scale.to(u.deg).value, "CDELT2": plate_scale.to(u.deg).value, "CUNIT1": "DEG", "CUNIT2": "DEG", "CTYPE1": 'RA---TAN', "CTYPE2": 'DEC--TAN', "SPEC_REF": 0 }) src = Source() src.fields = [] src.spectra = [] total_flux = np.sum(intensity) hdulist = [] for i, m in enumerate(masks): data = m * intensity factor = np.sum(data) / total_flux masked_vel = np.ma.array(velocity, mask=m == 0) masked_sigma = np.ma.array(dispersion, mask=m == 0) med_vel = np.ma.median(masked_vel) med_sig = np.ma.median(masked_sigma) spec = scaled_sp.redshift(vel=med_vel).smooth(sigma=med_sig) * factor header["SPEC_REF"] = i hdu = fits.ImageHDU(data=data, header=header) hdulist.append(hdu) src.spectra.append(spec) src.fields = fits.HDUList(hdulist) return src
def test_black_body_spectrum(self): sp = Spextrum.black_body_spectrum(filter_curve="g") assert isinstance(sp, Spextrum)
def test_wrong_load(self): with pytest.raises(ValueError) as e_info: sp = Spextrum("kc96/wrong_name")
def testing_nesting(self): sp = Spextrum("kc96/s0").redshift(z=1).\ scale_to_magnitude(amplitude=15*u.ABmag, filter_curve="g").\ redden("calzetti/starburst", Ebv=0.1) assert isinstance(sp, Spextrum)
def test_deredden(self): sp = Spextrum.black_body_spectrum(filter_curve="F110W") sp2 = sp.redden("gordon/smc_bar", Ebv=0.1) assert isinstance(sp2, Spextrum)
def test_redden(self): sp = Spextrum.black_body_spectrum(filter_curve="r") sp2 = sp.redden("calzetti/starburst", Ebv=0.1) assert isinstance(sp2, Spextrum)
def test_smooth(self): sp = Spextrum.black_body_spectrum(filter_curve="g") sp2 = sp.smooth(10 * (u.m / u.s)) assert isinstance(sp2, Spextrum)
def galaxy( sed, # The SED of the galaxy z=0, # redshift mag=15, # magnitude filter_name="g", # passband plate_scale=0.1, # the plate scale "/pix r_eff=2.5, # effective radius n=4, # sersic index ellip=0.1, # ellipticity theta=0, # position angle extend=2): # extend in units of r_eff """ Creates a source object of a galaxy described by its Sersic index and other parameters. This function is ideal for imaging Parameters ---------- sed : str or Spextrum z : float redshift of the galaxy r_eff : float effective radius of the galaxy in arcsec, it accepts astropy.units mag : float magnitude of the galaxy, it accepts astropy.units filter_name : str name of the filter where the magnitude refer to plate_scale : float the scale in arcsec/pixel of the instrument n : float Sersic index of the galaxy ellip : float ellipticity of the galaxy theta : float position angle of the galaxy extend : float Size of the image in units of r_eff Returns ------- src : scopesim.Source """ if isinstance(mag, u.Quantity) is False: mag = mag * u.ABmag if isinstance(plate_scale, u.Quantity) is False: plate_scale = plate_scale * u.arcsec if isinstance(r_eff, u.Quantity) is False: r_eff = r_eff * u.arcsec if isinstance(sed, str): sp = Spextrum(sed).redshift(z=z) scaled_sp = sp.scale_to_magnitude(amplitude=mag, filter_curve=filter_name) elif isinstance(sed, (Spextrum)): scaled_sp = sed r_eff = r_eff.to(u.arcsec) plate_scale = plate_scale.to(u.arcsec) image_size = 2 * (r_eff.value * extend / plate_scale.value ) # TODO: Needs unit check x_0 = image_size // 2 y_0 = image_size // 2 x, y = np.meshgrid(np.arange(image_size), np.arange(image_size)) galaxy = GalaxyBase(x=x, y=y, x_0=x_0, y_0=y_0, r_eff=r_eff.value, amplitude=1, n=n, ellip=ellip, theta=theta) img = galaxy.intensity w, h = img.shape header = fits.Header({ "NAXIS": 2, "NAXIS1": 2 * x_0 + 1, "NAXIS2": 2 * y_0 + 1, "CRPIX1": w // 2, "CRPIX2": h // 2, "CRVAL1": 0, "CRVAL2": 0, "CDELT1": -1 * plate_scale.to(u.deg).value, "CDELT2": plate_scale.to(u.deg).value, "CUNIT1": "DEG", "CUNIT2": "DEG", "CTYPE1": 'RA---TAN', "CTYPE2": 'DEC--TAN', "SPEC_REF": 0 }) hdu = fits.ImageHDU(data=img, header=header) # hdu.writeto("deleteme.fits", overwrite=True) src = Source() src.spectra = [scaled_sp] src.fields = [hdu] return src
def test_get_magnitude(self): sp = Spextrum("pickles/a0v") mag = sp.get_magnitude("elt/micado/Y", system_name="AB") assert isinstance(mag, u.Quantity)