def __init__(self, model="kpno", extinction=None, spectral_axis=None, cache=True, show_progress=False, **kwargs): if extinction is not None: if not isinstance(extinction, u.Quantity): warnings.warn( "Input extinction is not a Quanitity. Assuming it is given in magnitudes...", AstropyUserWarning) extinction = u.Magnitude( extinction, u.MagUnit(u.dimensionless_unscaled)).to( u.dimensionless_unscaled ) # Spectrum1D wants this to be linear if isinstance( extinction, (u.LogUnit, u.Magnitude)) or extinction.unit == u.mag: # if in log or magnitudes, recast into Magnitude with dimensionless physical units extinction = u.Magnitude(extinction.value, u.MagUnit( u.dimensionless_unscaled)).to( u.dimensionless_unscaled) if extinction.unit != u.dimensionless_unscaled: # if we're given something linear that's not dimensionless_unscaled, # it's an error msg = "Input extinction must have unscaled dimensionless units." raise ValueError(msg) if extinction is None and spectral_axis is None: if model not in SUPPORTED_EXTINCTION_MODELS: msg = (f"Requested extinction model, {model}, not in list " f"of available models: {SUPPORTED_EXTINCTION_MODELS}") raise ValueError(msg) model_file = os.path.join("extinction", f"{model}extinct.dat") model_path = get_reference_file_path(path=model_file, cache=cache, show_progress=show_progress) t = Table.read(model_path, format="ascii", names=['wavelength', 'extinction']) # the specreduce_data models all provide wavelengths in angstroms spectral_axis = t['wavelength'].data * u.angstrom # the specreduce_data models all provide extinction in magnitudes at an airmass of 1 extinction = u.Magnitude(t['extinction'].data, u.MagUnit(u.dimensionless_unscaled)).to( u.dimensionless_unscaled) if spectral_axis is None: msg = "Missing spectral axis for input extinction data." raise ValueError(msg) super(AtmosphericExtinction, self).__init__(flux=extinction, spectral_axis=spectral_axis, unit=u.dimensionless_unscaled, **kwargs)
def test_str(self): """Do some spot checks that str, repr, etc. work as expected.""" lu1 = u.mag(u.Jy) assert str(lu1) == 'mag(Jy)' assert repr(lu1) == 'Unit("mag(Jy)")' assert lu1.to_string('generic') == 'mag(Jy)' with pytest.raises(ValueError): lu1.to_string('fits') with pytest.raises(ValueError): lu1.to_string(format='cds') lu2 = u.dex() assert str(lu2) == 'dex' assert repr(lu2) == 'Unit("dex(1)")' assert lu2.to_string() == 'dex(1)' lu3 = u.MagUnit(u.Jy, function_unit=2 * u.mag) assert str(lu3) == '2 mag(Jy)' assert repr(lu3) == 'MagUnit("Jy", unit="2 mag")' assert lu3.to_string() == '2 mag(Jy)' lu4 = u.mag(u.ct) assert lu4.to_string('generic') == 'mag(ct)' assert lu4.to_string('latex') == ('$\\mathrm{mag}$$\\mathrm{\\left( ' '\\mathrm{ct} \\right)}$') assert lu4._repr_latex_() == lu4.to_string('latex')
def test_custom_mag_model(): """ Test creation of custom model from Quantity arrays """ wave = np.linspace(0.3, 2.0, 50) extinction = u.Magnitude(1. / wave, u.MagUnit(u.dimensionless_unscaled)) ext = AtmosphericExtinction(extinction=extinction, spectral_axis=wave * u.um) assert(len(ext.extinction_mag) > 0) assert(len(ext.transmission) > 0)
def test_littleh(): H0_70 = 70*u.km/u.s/u.Mpc h70dist = 70 * u.Mpc/u.littleh assert_quantity_allclose(h70dist.to(u.Mpc, u.with_H0(H0_70)), 100*u.Mpc) # make sure using the default cosmology works cosmodist = cosmology.default_cosmology.get().H0.value * u.Mpc/u.littleh assert_quantity_allclose(cosmodist.to(u.Mpc, u.with_H0()), 100*u.Mpc) # Now try a luminosity scaling h1lum = .49 * u.Lsun * u.littleh**-2 assert_quantity_allclose(h1lum.to(u.Lsun, u.with_H0(H0_70)), 1*u.Lsun) # And the trickiest one: magnitudes. Using H0=10 here for the round numbers H0_10 = 10*u.km/u.s/u.Mpc # assume the "true" magnitude M = 12. # Then M - 5*log_10(h) = M + 5 = 17 withlittlehmag = 17 * (u.mag - u.MagUnit(u.littleh**2)) assert_quantity_allclose(withlittlehmag.to(u.mag, u.with_H0(H0_10)), 12*u.mag)
@pytest.mark.parametrize( 'strings, unit', [ (["m s", "m*s", "m.s"], u.m * u.s), (["m/s", "m*s**-1", "m /s", "m / s", "m/ s"], u.m / u.s), (["m**2", "m2", "m**(2)", "m**+2", "m+2", "m^(+2)"], u.m**2), (["m**-3", "m-3", "m^(-3)", "/m3"], u.m**-3), (["m**(1.5)", "m(3/2)", "m**(3/2)", "m^(3/2)"], u.m**1.5), (["2.54 cm"], u.Unit(u.cm * 2.54)), (["10+8m"], u.Unit(u.m * 1e8)), # This is the VOUnits documentation, but doesn't seem to follow the # unity grammar (["3.45 10**(-4)Jy"], 3.45 * 1e-4 * u.Jy) (["sqrt(m)"], u.m**0.5), (["dB(mW)", "dB (mW)"], u.DecibelUnit(u.mW)), (["mag"], u.mag), (["mag(ct/s)"], u.MagUnit(u.ct / u.s)), (["dex"], u.dex), (["dex(cm s**-2)", "dex(cm/s2)"], u.DexUnit(u.cm / u.s**2)) ]) def test_unit_grammar(strings, unit): for s in strings: print(s) unit2 = u_format.Generic.parse(s) assert unit2 == unit @pytest.mark.parametrize( 'string', ['sin( /pixel /s)', 'mag(mag)', 'dB(dB(mW))', 'dex()']) def test_unit_grammar_fail(string): with pytest.raises(ValueError): print(string)
>>> import sbpy.units >>> sbpy.units.enable() # doctest: +SKIP """ __all__ = ['spectral_density_vega', 'enable', 'VEGA', 'VEGAmag', 'JM', 'JMmag'] from warnings import warn import numpy as np import astropy.units as u from astropy.utils.exceptions import AstropyWarning from ..spectroscopy.vega import Vega VEGA = u.def_unit(['VEGA', 'VEGAflux'], doc='Spectral flux density of Vega.') VEGAmag = u.MagUnit(VEGA) VEGAmag.__doc__ = "Vega-based magnitude: Vega is 0 mag at all wavelengths" JM = u.def_unit(['JM', 'JMflux'], represents=VEGA * 10**(0.4 * 0.03), doc=('Johnson-Morgan magnitude system flux density ' 'zeropoint (Johnson et al. 1966; Bessell & Murphy ' '2012).')) JMmag = u.MagUnit(JM) JMmag.__doc__ = ("Johnson-Morgan magnitude system: Vega is 0.03 mag at " "all wavelengths (Johnson et al. 1966; Bessell & Murphy " "2012).") def enable():
need to import the module:: >>> import astropy.units as u >>> import etc.units >>> u.Unit('mag(VEGA)') Unit("mag(VEGA)") """ import numpy as np import astropy.units as u VEGA = u.def_unit(['VEGA', 'VEGAflux'], doc='Spectral flux density of Vega.') VEGAmag = u.MagUnit(VEGA) VEGAmag.__doc__ = "Vega-based magnitude: Vega is 0 mag at all wavelengths" u.add_enabled_units(VEGA) def spectral_density(wfb): """Flux density equivalencies, extended for Vega-based magnitude systems. This uses the default Vega spectrum that comes for 4MOST in the Instrument Control Repository (ICR). Vega is assumed to have an apparent magnitude of 0 in the ``VEGAmag`` system. See https://github.com/astropy/astropy/issues/10821 for a
def overplot_spectroscopic(res, drp_logcube, drpall_row, mass_ax, ml_ax, f_ax, pca_system, res_wcs, cmlr, mlb='i'): ''' overplot cumulative spectroscopic masses, log M/L, cumulative fluxes ''' # synthetic photometry of IFU data in rest frame ebvgal = drpall_row['ebvgal'] r_v = 3.1 dustcorr = 10.**(0.4 * extinction.fitzpatrick99( drp_logcube['WAVE'].data, a_v=r_v * ebvgal, r_v=r_v))[:, None, None] ifu_s2p = spectrophot.Spec2Phot( lam=drp_logcube['WAVE'].data / (1. + drpall_row['nsa_z']), flam=1.0e-17 * drp_logcube['FLUX'].data * (1. + drpall_row['nsa_z']) * dustcorr) res_flux = (ifu_s2p.ABmags['sdss2010-{}'.format(mlb)] * u.ABmag).to(m.Mgy) # map sky coordinates to number of effective radii from center pos_to_nRe = RotatedParaboloid(ctr=np.array( [drpall_row['objra'], drpall_row['objdec']]), phi=drpall_row['nsa_elpetro_phi'] * u.deg, axis_ratio=drpall_row['nsa_elpetro_ba'], Re=drpall_row['nsa_elpetro_th50_r'] / 3600.) badpdf = res.badPDF() ml_mask = np.logical_or(res.mask, badpdf) # WCS from results file determines where elliptical projection is sampled #res_wcs = wcs.WCS(res['SNRMED'].header) res_II, res_JJ = np.meshgrid( *[np.linspace(0., s - 1., s) for s in res['SNRMED'].shape], indexing='ij') res_AA, res_DD = res_wcs.wcs_pix2world(res_JJ, res_II, 1) # sample Re at spaxel centers res_Re = pos_to_nRe(np.column_stack([res_AA.flatten(), res_DD.flatten() ])).reshape(res_AA.shape) nRe_to_plot = np.linspace(0., res_Re[~ml_mask].max(), 50.) # mass, log M/L badpdf = res.badPDF() ml_mask = np.logical_or.reduce((res.mask, badpdf)) interior_mask = np.logical_or.reduce( (badpdf, (m.mask_from_maskbits(drp_logcube['MASK'].data, [3]).sum(axis=0) > 0), (m.mask_from_maskbits(drp_logcube['MASK'].data, [2]).sum(axis=0) > 0))) logml = infer_masked(res.param_dist_med(extname='ML{}'.format(mlb)), ml_mask, interior_mask) ml = 10.**logml * m.m_to_l_unit res_MAG = res_flux.to(u.ABmag) - cosmo.distmod(drpall_row['nsa_zdist']) mlb_sollum = 10.**(-0.4 * (res_MAG - spectrophot.absmag_sun_band[mlb] * u.ABmag)).value * \ m.bandpass_sol_l_unit spectro_mass = (ml * mlb_sollum).to(u.Msun) # sum mass within some number of Re mass_within_nRe = np.array( [sum_within_nRe(spectro_mass, res_Re, n) for n in nRe_to_plot]) mass_ax.plot(nRe_to_plot, mass_within_nRe, c='C1') # plot mass to light versus Re ml_sc = ml_ax.scatter(res_Re[~ml_mask], logml[~ml_mask], c='C1', edgecolor='None', s=.5) res_Re_m = np.ma.array(res_Re, mask=ml_mask) # find ring method log M/L outer_ring = np.logical_and((res_Re_m <= res_Re_m.max()), (res_Re_m >= res_Re_m.max() - .5)) outer_logml_ring = np.median(logml[~ml_mask * outer_ring]) ml_ax.scatter(x=[np.median(res_Re_m[~ml_mask * outer_ring])], y=[outer_logml_ring], marker='x', c='C1') # find CMLR log M/L nsa_MAG = (np.array(drpall_row['nsa_elpetro_absmag'][2:]) * \ (u.ABmag - u.MagUnit(u.littleh**2))).to(u.ABmag, u.with_H0(cosmo.H0)) nsa_mag = (nsa_MAG + cosmo.distmod(drpall_row['nsa_zdist'])) nsa_flux = nsa_mag.to(m.Mgy) ifu_mag = np.array( [ifu_s2p.ABmags['sdss2010-{}'.format(b_)] for b_ in 'ugriz']) * u.ABmag ifu_mag[~np.isfinite(ifu_mag)] = 40. * u.ABmag ifu_flux = ifu_mag.to(m.Mgy) flux_deficit = nsa_flux - ifu_flux.sum(axis=(1, 2)) logml_missingflux_cmlr = cmlr(2.5 * np.log10(flux_deficit[1] / flux_deficit[2])) ml_ax.scatter(x=[np.median(res_Re_m[~ml_mask * outer_ring])], y=[logml_missingflux_cmlr], marker='s', c='C1', edgecolor='k') # ml_missingflux_cmlr = 10.**logml_missingflux_cmlr * m.m_to_l_unit ml_missingflux_ring = 10.**outer_logml_ring * m.m_to_l_unit missing_mlb_MAG = flux_deficit[3].to(u.ABmag) - cosmo.distmod( drpall_row['nsa_zdist']) missing_mlb_sollum = 10.**(-0.4 * (missing_mlb_MAG - spectrophot.absmag_sun_band[mlb] * u.ABmag)).value * \ m.bandpass_sol_l_unit missing_mass_cmlr = (ml_missingflux_cmlr * missing_mlb_sollum).to(u.Msun) missing_mass_ring = (ml_missingflux_ring * missing_mlb_sollum).to(u.Msun) mass_ax.scatter(x=res_Re.max() - .1, y=mass_within_nRe[-1] * u.Msun + missing_mass_cmlr, marker='s', c='C1', edgecolor='k', zorder=3, label='+AC(CMLR)') mass_ax.scatter(x=res_Re.max(), y=mass_within_nRe[-1] * u.Msun + missing_mass_ring, marker='x', c='C1', edgecolor='k', zorder=3, label='+AC(RING)') mass_ax.legend(loc='best', prop={'size': 'x-small'}) summed_flux = np.array([ sum_within_nRe(arr=res_flux, Re_a=res_Re, nRe=n) for n in nRe_to_plot ]) f_ax.plot(nRe_to_plot, summed_flux, label='IFU', c='C1') f_ax.scatter(x=res_Re.max() + .1, y=summed_flux[-1] * m.Mgy + flux_deficit[3], marker='o', c='C1', edgecolor='k', zorder=3)
def make_stellarmass_aperture_plot(preimaging, dap_maps, drp_logcube, cmlr, drpall_row, mlb='i', cb1='g', cb2='r'): ''' make aperture plot of included mass (from CMLR and preimaging) versus radius (from DAP) preimaging: MaNGA_PreImage object dap_maps: FITS HDUList with DAP MAPS outputs ''' ebvgal = drpall_row['ebvgal'] # WCS from DAP determines sampling for Re grid, and where k-correction map is sampled dap_wcs = wcs.WCS(dap_maps['SPX_SNR'].header) dap_AA, dap_DD = dap_wcs.wcs_pix2world( *np.meshgrid(*[ np.linspace(0., s - 1., s) for s in dap_maps['SPX_SNR'].data.shape ]), 1) # map sky coordinates to number of effective radii from center pos_to_nRe = RotatedParaboloid(ctr=np.array( [drpall_row['objra'], drpall_row['objdec']]), phi=drpall_row['nsa_elpetro_phi'] * u.deg, axis_ratio=drpall_row['nsa_elpetro_ba'], Re=drpall_row['nsa_elpetro_th50_r'] / 3600.) # WCS from preimaging determines where elliptical projection is resampled preimaging_wcs = wcs.WCS(preimaging['{} img'.format(mlb)].header) preimaging_II, preimaging_JJ = np.meshgrid( *[np.linspace(0., s - 1., s) for s in preimaging.img(mlb).shape], indexing='ij') preimaging_AA, preimaging_DD = preimaging_wcs.wcs_pix2world( preimaging_JJ, preimaging_II, 1) # evaluate Re interpolation on imaging RA/Dec grid preimaging_Re = pos_to_nRe( np.column_stack([preimaging_AA.flatten(), preimaging_DD.flatten() ])).reshape(preimaging_AA.shape) kcorr_cb1_interp, kcorr_cb2_interp, kcorr_mlb_interp = kcorr_spec_to_phot( drp_logcube, dap_maps['SPX_MFLUX_IVAR'], drpall_row['nsa_z'], cb1, cb2, mlb) kcorr_cb1_phot = kcorr_cb1_interp(preimaging_AA.flatten(), preimaging_DD.flatten()).reshape( preimaging_AA.shape) * u.mag kcorr_cb2_phot = kcorr_cb2_interp(preimaging_AA.flatten(), preimaging_DD.flatten()).reshape( preimaging_AA.shape) * u.mag kcorr_color = kcorr_cb1_phot - kcorr_cb2_phot kcorr_mlb_phot = kcorr_mlb_interp(preimaging_AA.flatten(), preimaging_DD.flatten()).reshape( preimaging_AA.shape) * u.mag # evaluate CMLR given preimaging ml_from_cmlr = 10.**cmlr( color=preimaging.color(cb1, cb2, dustcorr=True, ebvgal=ebvgal) + kcorr_color.value) * m.m_to_l_unit img_mag = (preimaging.img(mlb) * 1.0e-9 * m.Mgy).to( u.ABmag) + kcorr_mlb_phot distmod = cosmo.distmod(drpall_row['nsa_zdist']) img_MAG = img_mag - distmod mlb_sollum = 10.**(-0.4 * (img_MAG - spectrophot.absmag_sun_band[mlb] * u.ABmag)).value * \ m.bandpass_sol_l_unit mass_from_cmlr = (ml_from_cmlr * mlb_sollum).to(u.Msun) nRe_to_plot = np.linspace(0., 0.9 * preimaging_Re.max(), 1000) photomass_within_nRe = np.array([ sum_within_nRe(mass_from_cmlr, preimaging_Re, n) for n in nRe_to_plot ]) # solve for number of effective radii enclosing all of NSA flux NSA_bands = 'FNugriz' NSA_bands_ixs = dict(zip(NSA_bands, range(len(NSA_bands)))) NSA_MAG = drpall_row['nsa_elpetro_absmag'][NSA_bands_ixs[mlb]] * \ (u.ABmag - u.MagUnit(u.littleh**2)) NSA_kcorr_flux = (NSA_MAG.to(u.ABmag, u.with_H0(cosmo.H0)) + \ cosmo.distmod(drpall_row['nsa_zdist'])).to(m.Mgy) fig, (ax1, ax2, ax3) = plt.subplots(nrows=3, ncols=1, figsize=(9, 7), dpi=150, sharex=True) ax1.plot(nRe_to_plot, photomass_within_nRe, linewidth=1., color='C0') ax1.set_yscale('log') ax1.set_ylabel(r'$\frac{M_{< R}}{M_{\odot}}$', size='small') ax2.scatter(preimaging_Re.flatten(), np.log10(ml_from_cmlr.value.flatten()), edgecolor='None', s=.5, c='C0') ax2.set_ylabel(r'$\log \Upsilon^*_{{{}}}$'.format(mlb), size='small') ax2.set_ylim([-2.5, 2.5]) summed_flux = np.array([ sum_within_nRe(arr=img_mag.to(m.Mgy), Re_a=preimaging_Re, nRe=n) for n in nRe_to_plot ]) img_var = 1. / preimaging.img_ivar(mlb) * (1.0e-9 * m.Mgy)**2 quadsummed_fluxunc = np.sqrt( np.array([ sum_within_nRe(arr=img_var, Re_a=preimaging_Re, nRe=n) for n in nRe_to_plot ])) ax3.plot(nRe_to_plot, summed_flux, label='K-Corr. Phot.', color='C0') ax3.fill_between(nRe_to_plot, summed_flux - quadsummed_fluxunc, summed_flux + quadsummed_fluxunc, alpha=0.5, linewidth=0.25, color='C0') ax3.set_xlabel(r'$\frac{R}{R_e}$', size='small') ax3.set_ylabel(r'$\frac{F_{<R}}{\rm Mgy}$', size='small') ax3.set_yscale('log') fig.suptitle(drpall_row['plateifu']) return fig, ax1, ax2, ax3
class TestLogQuantityCreation: @pytest.mark.parametrize('lq, lu', zip(lq_subclasses + [u.LogQuantity], lu_subclasses + [u.LogUnit])) def test_logarithmic_quantities(self, lq, lu): """Check logarithmic quantities are all set up correctly""" assert lq._unit_class == lu assert type(lu()._quantity_class(1.)) is lq @pytest.mark.parametrize('lq_cls, physical_unit', itertools.product(lq_subclasses, pu_sample)) def test_subclass_creation(self, lq_cls, physical_unit): """Create LogQuantity subclass objects for some physical units, and basic check on transformations""" value = np.arange(1., 10.) log_q = lq_cls(value * physical_unit) assert log_q.unit.physical_unit == physical_unit assert log_q.unit.function_unit == log_q.unit._default_function_unit assert_allclose(log_q.physical.value, value) with pytest.raises(ValueError): lq_cls(value, physical_unit) @pytest.mark.parametrize( 'unit', (u.mag, u.mag(), u.mag(u.Jy), u.mag(u.m), u.Unit( 2 * u.mag), u.MagUnit('', 2. * u.mag), u.MagUnit( u.Jy, -1 * u.mag), u.MagUnit(u.m, -2. * u.mag))) def test_different_units(self, unit): q = u.Magnitude(1.23, unit) assert q.unit.function_unit == getattr(unit, 'function_unit', unit) assert q.unit.physical_unit is getattr(unit, 'physical_unit', u.dimensionless_unscaled) @pytest.mark.parametrize('value, unit', ((1. * u.mag(u.Jy), None), (1. * u.dex(u.Jy), None), (1. * u.mag(u.W / u.m**2 / u.Hz), u.mag(u.Jy)), (1. * u.dex(u.W / u.m**2 / u.Hz), u.mag(u.Jy)))) def test_function_values(self, value, unit): lq = u.Magnitude(value, unit) assert lq == value assert lq.unit.function_unit == u.mag assert lq.unit.physical_unit == getattr(unit, 'physical_unit', value.unit.physical_unit) @pytest.mark.parametrize( 'unit', (u.mag(), u.mag(u.Jy), u.mag(u.m), u.MagUnit('', 2. * u.mag), u.MagUnit(u.Jy, -1 * u.mag), u.MagUnit(u.m, -2. * u.mag))) def test_indirect_creation(self, unit): q1 = 2.5 * unit assert isinstance(q1, u.Magnitude) assert q1.value == 2.5 assert q1.unit == unit pv = 100. * unit.physical_unit q2 = unit * pv assert q2.unit == unit assert q2.unit.physical_unit == pv.unit assert q2.to_value(unit.physical_unit) == 100. assert (q2._function_view / u.mag).to_value(1) == -5. q3 = unit / 0.4 assert q3 == q1 def test_from_view(self): # Cannot view a physical quantity as a function quantity, since the # values would change. q = [100., 1000.] * u.cm / u.s**2 with pytest.raises(TypeError): q.view(u.Dex) # But fine if we have the right magnitude. q = [2., 3.] * u.dex lq = q.view(u.Dex) assert isinstance(lq, u.Dex) assert lq.unit.physical_unit == u.dimensionless_unscaled assert np.all(q == lq) def test_using_quantity_class(self): """Check that we can use Quantity if we have subok=True""" # following issue #5851 lu = u.dex(u.AA) with pytest.raises(u.UnitTypeError): u.Quantity(1., lu) q = u.Quantity(1., lu, subok=True) assert type(q) is lu._quantity_class
class TestLogUnitArithmetic: def test_multiplication_division(self): """Check that multiplication/division with other units is only possible when the physical unit is dimensionless, and that this turns the unit into a normal one.""" lu1 = u.mag(u.Jy) with pytest.raises(u.UnitsError): lu1 * u.m with pytest.raises(u.UnitsError): u.m * lu1 with pytest.raises(u.UnitsError): lu1 / lu1 for unit in (u.dimensionless_unscaled, u.m, u.mag, u.dex): with pytest.raises(u.UnitsError): lu1 / unit lu2 = u.mag(u.dimensionless_unscaled) with pytest.raises(u.UnitsError): lu2 * lu1 with pytest.raises(u.UnitsError): lu2 / lu1 # But dimensionless_unscaled can be cancelled. assert lu2 / lu2 == u.dimensionless_unscaled # With dimensionless, normal units are OK, but we return a plain unit. tf = lu2 * u.m tr = u.m * lu2 for t in (tf, tr): assert not isinstance(t, type(lu2)) assert t == lu2.function_unit * u.m with u.set_enabled_equivalencies(u.logarithmic()): with pytest.raises(u.UnitsError): t.to(lu2.physical_unit) # Now we essentially have a LogUnit with a prefactor of 100, # so should be equivalent again. t = tf / u.cm with u.set_enabled_equivalencies(u.logarithmic()): assert t.is_equivalent(lu2.function_unit) assert_allclose( t.to(u.dimensionless_unscaled, np.arange(3.) / 100.), lu2.to(lu2.physical_unit, np.arange(3.))) # If we effectively remove lu1, a normal unit should be returned. t2 = tf / lu2 assert not isinstance(t2, type(lu2)) assert t2 == u.m t3 = tf / lu2.function_unit assert not isinstance(t3, type(lu2)) assert t3 == u.m # For completeness, also ensure non-sensical operations fail with pytest.raises(TypeError): lu1 * object() with pytest.raises(TypeError): slice(None) * lu1 with pytest.raises(TypeError): lu1 / [] with pytest.raises(TypeError): 1 / lu1 @pytest.mark.parametrize('power', (2, 0.5, 1, 0)) def test_raise_to_power(self, power): """Check that raising LogUnits to some power is only possible when the physical unit is dimensionless, and that conversion is turned off when the resulting logarithmic unit (such as mag**2) is incompatible.""" lu1 = u.mag(u.Jy) if power == 0: assert lu1**power == u.dimensionless_unscaled elif power == 1: assert lu1**power == lu1 else: with pytest.raises(u.UnitsError): lu1**power # With dimensionless, though, it works, but returns a normal unit. lu2 = u.mag(u.dimensionless_unscaled) t = lu2**power if power == 0: assert t == u.dimensionless_unscaled elif power == 1: assert t == lu2 else: assert not isinstance(t, type(lu2)) assert t == lu2.function_unit**power # also check we roundtrip t2 = t**(1. / power) assert t2 == lu2.function_unit with u.set_enabled_equivalencies(u.logarithmic()): assert_allclose(t2.to(u.dimensionless_unscaled, np.arange(3.)), lu2.to(lu2.physical_unit, np.arange(3.))) @pytest.mark.parametrize('other', pu_sample) def test_addition_subtraction_to_normal_units_fails(self, other): lu1 = u.mag(u.Jy) with pytest.raises(u.UnitsError): lu1 + other with pytest.raises(u.UnitsError): lu1 - other with pytest.raises(u.UnitsError): other - lu1 def test_addition_subtraction_to_non_units_fails(self): lu1 = u.mag(u.Jy) with pytest.raises(TypeError): lu1 + 1. with pytest.raises(TypeError): lu1 - [1., 2., 3.] @pytest.mark.parametrize('other', (u.mag, u.mag(), u.mag(u.Jy), u.mag( u.m), u.Unit(2 * u.mag), u.MagUnit('', 2. * u.mag))) def test_addition_subtraction(self, other): """Check physical units are changed appropriately""" lu1 = u.mag(u.Jy) other_pu = getattr(other, 'physical_unit', u.dimensionless_unscaled) lu_sf = lu1 + other assert lu_sf.is_equivalent(lu1.physical_unit * other_pu) lu_sr = other + lu1 assert lu_sr.is_equivalent(lu1.physical_unit * other_pu) lu_df = lu1 - other assert lu_df.is_equivalent(lu1.physical_unit / other_pu) lu_dr = other - lu1 assert lu_dr.is_equivalent(other_pu / lu1.physical_unit) def test_complicated_addition_subtraction(self): """for fun, a more complicated example of addition and subtraction""" dm0 = u.Unit('DM', 1. / (4. * np.pi * (10. * u.pc)**2)) lu_dm = u.mag(dm0) lu_absST = u.STmag - lu_dm assert lu_absST.is_equivalent(u.erg / u.s / u.AA) def test_neg_pos(self): lu1 = u.mag(u.Jy) neg_lu = -lu1 assert neg_lu != lu1 assert neg_lu.physical_unit == u.Jy**-1 assert -neg_lu == lu1 pos_lu = +lu1 assert pos_lu is not lu1 assert pos_lu == lu1
def nsa_absmags(self): absmags = np.array([ nsa_absmag(self.drpall_row, band, kind='elpetro') for band in self.bands ]) * (u.ABmag - u.MagUnit(u.littleh**2)) return absmags