diff --git a/unyt/_unit_lookup_table.py b/unyt/_unit_lookup_table.py index fc7cfd8a..2289a408 100644 --- a/unyt/_unit_lookup_table.py +++ b/unyt/_unit_lookup_table.py @@ -60,160 +60,164 @@ default_unit_symbol_lut = { # base - "m": (1.0, dimensions.length, 0.0, r"\rm{m}"), - "g": (1.0e-3, dimensions.mass, 0.0, r"\rm{g}"), - "s": (1.0, dimensions.time, 0.0, r"\rm{s}"), - "K": (1.0, dimensions.temperature, 0.0, r"\rm{K}"), - "radian": (1.0, dimensions.angle, 0.0, r"\rm{radian}"), - "A": (1.0, dimensions.current_mks, 0.0, r"\rm{A}"), - "cd": (1.0, dimensions.luminous_intensity, 0.0, r"\rm{cd}"), - "mol": (1.0 / amu_grams, dimensions.dimensionless, 0.0, r"\rm{mol}"), + "m": (1.0, dimensions.length, 0.0, r"\rm{m}", True), + "g": (1.0e-3, dimensions.mass, 0.0, r"\rm{g}", True), + "s": (1.0, dimensions.time, 0.0, r"\rm{s}", True), + "K": (1.0, dimensions.temperature, 0.0, r"\rm{K}", True), + "radian": (1.0, dimensions.angle, 0.0, r"\rm{radian}", True), + "A": (1.0, dimensions.current_mks, 0.0, r"\rm{A}", True), + "cd": (1.0, dimensions.luminous_intensity, 0.0, r"\rm{cd}", True), + "mol": (1.0 / amu_grams, dimensions.dimensionless, 0.0, r"\rm{mol}", True), # some cgs - "dyne": (1.0e-5, dimensions.force, 0.0, r"\rm{dyn}"), - "erg": (1.0e-7, dimensions.energy, 0.0, r"\rm{erg}"), - "Ba": (0.1, dimensions.pressure, 0.0, r"\rm{Ba}"), - "esu": (1.0e-3**1.5, dimensions.charge_cgs, 0.0, r"\rm{esu}"), - "gauss": (0.1**0.5, dimensions.magnetic_field_cgs, 0.0, r"\rm{G}"), - "degC": (1.0, dimensions.temperature, -273.15, r"^\circ\rm{C}"), - "statA": (1.0e-3**1.5, dimensions.current_cgs, 0.0, r"\rm{statA}"), + "dyne": (1.0e-5, dimensions.force, 0.0, r"\rm{dyn}", True), + "erg": (1.0e-7, dimensions.energy, 0.0, r"\rm{erg}", True), + "Ba": (0.1, dimensions.pressure, 0.0, r"\rm{Ba}", True), + "esu": (1.0e-3**1.5, dimensions.charge_cgs, 0.0, r"\rm{esu}", True), + "gauss": (0.1**0.5, dimensions.magnetic_field_cgs, 0.0, r"\rm{G}", True), + "degC": (1.0, dimensions.temperature, -273.15, r"^\circ\rm{C}", True), + "statA": (1.0e-3**1.5, dimensions.current_cgs, 0.0, r"\rm{statA}", True), "statV": (0.1*1.0e-3**0.5, dimensions.electric_potential_cgs, - 0.0, r"\rm{statV}"), - "statohm": (100.0, dimensions.resistance_cgs, 0.0, r"\rm{statohm}"), - "Mx": (1.0e-3**1.5, dimensions.magnetic_flux_cgs, 0.0, r"\rm{Mx}"), + 0.0, r"\rm{statV}", True), + "statohm": (100.0, dimensions.resistance_cgs, 0.0, r"\rm{statohm}", True), + "Mx": (1.0e-3**1.5, dimensions.magnetic_flux_cgs, 0.0, r"\rm{Mx}", True), # some SI - "J": (1.0, dimensions.energy, 0.0, r"\rm{J}"), - "W": (1.0, dimensions.power, 0.0, r"\rm{W}"), - "Hz": (1.0, dimensions.rate, 0.0, r"\rm{Hz}"), - "N": (1.0, dimensions.force, 0.0, r"\rm{N}"), - "C": (1.0, dimensions.charge_mks, 0.0, r"\rm{C}"), - "T": (1.0, dimensions.magnetic_field_mks, 0.0, r"\rm{T}"), - "Pa": (1.0, dimensions.pressure, 0.0, r"\rm{Pa}"), - "V": (1.0, dimensions.electric_potential_mks, 0.0, r"\rm{V}"), - "ohm": (1.0, dimensions.resistance_mks, 0.0, r"\Omega"), - "Wb": (1.0, dimensions.magnetic_flux_mks, 0.0, r"\rm{Wb}"), - "lm": (1.0, dimensions.luminous_flux, 0.0, r"\rm{lm}"), - "lx": (1.0, dimensions.luminous_flux/dimensions.area, 0.0, r"\rm{lx}"), + "J": (1.0, dimensions.energy, 0.0, r"\rm{J}", True), + "W": (1.0, dimensions.power, 0.0, r"\rm{W}", True), + "Hz": (1.0, dimensions.rate, 0.0, r"\rm{Hz}", True), + "N": (1.0, dimensions.force, 0.0, r"\rm{N}", True), + "C": (1.0, dimensions.charge_mks, 0.0, r"\rm{C}", True), + "T": (1.0, dimensions.magnetic_field_mks, 0.0, r"\rm{T}", True), + "Pa": (1.0, dimensions.pressure, 0.0, r"\rm{Pa}", True), + "V": (1.0, dimensions.electric_potential_mks, 0.0, r"\rm{V}", True), + "ohm": (1.0, dimensions.resistance_mks, 0.0, r"\Omega", True), + "Wb": (1.0, dimensions.magnetic_flux_mks, 0.0, r"\rm{Wb}", True), + "lm": (1.0, dimensions.luminous_flux, 0.0, r"\rm{lm}", True), + "lx": (1.0, dimensions.luminous_flux/dimensions.area, 0.0, r"\rm{lx}", + True), # Imperial and other non-metric units - "inch": (m_per_inch, dimensions.length, 0.0, r"\rm{in}"), - "ft": (m_per_ft, dimensions.length, 0.0, r"\rm{ft}"), - "yd": (0.9144, dimensions.length, 0.0, r"\rm{yd}"), - "mile": (1609.344, dimensions.length, 0.0, r"\rm{mile}"), - "fur": (m_per_ft*660.0, dimensions.length, 0.0, r"\rm{fur}"), + "inch": (m_per_inch, dimensions.length, 0.0, r"\rm{in}", False), + "ft": (m_per_ft, dimensions.length, 0.0, r"\rm{ft}", False), + "yd": (0.9144, dimensions.length, 0.0, r"\rm{yd}", False), + "mile": (1609.344, dimensions.length, 0.0, r"\rm{mile}", False), + "fur": (m_per_ft*660.0, dimensions.length, 0.0, r"\rm{fur}", False), "degF": (kelvin_per_rankine, dimensions.temperature, -459.67, - "^\circ\rm{F}"), - "R": (kelvin_per_rankine, dimensions.temperature, 0.0, r"^\circ\rm{R}"), + "^\circ\rm{F}", False), + "R": (kelvin_per_rankine, dimensions.temperature, 0.0, r"^\circ\rm{R}", + False), "lbf": (kg_per_pound*standard_gravity_m_per_s2, - dimensions.force, 0.0, r"\rm{lbf}"), - "lb": (kg_per_pound, dimensions.mass, 0.0, r"\rm{lb}"), - "lbm": (kg_per_pound, dimensions.mass, 0.0, r"\rm{lbm}"), - "atm": (pascal_per_atm, dimensions.pressure, 0.0, r"\rm{atm}"), - "hp": (watt_per_horsepower, dimensions.power, 0.0, r"\rm{hp}"), - "oz": (kg_per_pound/16.0, dimensions.mass, 0.0, r"\rm{oz}"), - "ton": (kg_per_pound*2000.0, dimensions.mass, 0.0, r"\rm{ton}"), + dimensions.force, 0.0, r"\rm{lbf}", False), + "lb": (kg_per_pound, dimensions.mass, 0.0, r"\rm{lb}", False), + "lbm": (kg_per_pound, dimensions.mass, 0.0, r"\rm{lbm}", False), + "atm": (pascal_per_atm, dimensions.pressure, 0.0, r"\rm{atm}", False), + "hp": (watt_per_horsepower, dimensions.power, 0.0, r"\rm{hp}", False), + "oz": (kg_per_pound/16.0, dimensions.mass, 0.0, r"\rm{oz}", False), + "ton": (kg_per_pound*2000.0, dimensions.mass, 0.0, r"\rm{ton}", False), "slug": (kg_per_pound*standard_gravity_m_per_s2/m_per_ft, - dimensions.mass, 0.0, r"\rm{slug}"), - "cal": (4.184, dimensions.energy, 0.0, r"\rm{cal}"), - "BTU": (1055.0559, dimensions.energy, 0.0, r"\rm{BTU}"), + dimensions.mass, 0.0, r"\rm{slug}", False), + "cal": (4.184, dimensions.energy, 0.0, r"\rm{cal}", True), + "BTU": (1055.0559, dimensions.energy, 0.0, r"\rm{BTU}", False), "psi": (kg_per_pound*standard_gravity_m_per_s2/m_per_inch**2, - dimensions.pressure, 0.0, r"\rm{psi}"), - "smoot": (1.7018, dimensions.length, 0.0, r"\rm{smoot}"), + dimensions.pressure, 0.0, r"\rm{psi}", False), + "smoot": (1.7018, dimensions.length, 0.0, r"\rm{smoot}", False), # dimensionless stuff - "h": (1.0, dimensions.dimensionless, 0.0, r"h"), - "dimensionless": (1.0, dimensions.dimensionless, 0.0, r""), + "h": (1.0, dimensions.dimensionless, 0.0, r"h", False), + "dimensionless": (1.0, dimensions.dimensionless, 0.0, r"", False), # times - "min": (sec_per_min, dimensions.time, 0.0, r"\rm{min}"), - "hr": (sec_per_hr, dimensions.time, 0.0, r"\rm{hr}"), - "day": (sec_per_day, dimensions.time, 0.0, r"\rm{d}"), - "d": (sec_per_day, dimensions.time, 0.0, r"\rm{d}"), - "yr": (sec_per_year, dimensions.time, 0.0, r"\rm{yr}"), + "min": (sec_per_min, dimensions.time, 0.0, r"\rm{min}", False), + "hr": (sec_per_hr, dimensions.time, 0.0, r"\rm{hr}", False), + "day": (sec_per_day, dimensions.time, 0.0, r"\rm{d}", False), + "d": (sec_per_day, dimensions.time, 0.0, r"\rm{d}", False), + "yr": (sec_per_year, dimensions.time, 0.0, r"\rm{yr}", True), # Velocities - "c": (speed_of_light_m_per_s, dimensions.velocity, 0.0, r"\rm{c}"), + "c": (speed_of_light_m_per_s, dimensions.velocity, 0.0, r"\rm{c}", False), # Solar units - "Msun": (mass_sun_kg, dimensions.mass, 0.0, r"M_\odot"), - "msun": (mass_sun_kg, dimensions.mass, 0.0, r"M_\odot"), - "Rsun": (m_per_rsun, dimensions.length, 0.0, r"R_\odot"), - "rsun": (m_per_rsun, dimensions.length, 0.0, r"R_\odot"), - "R_sun": (m_per_rsun, dimensions.length, 0.0, r"R_\odot"), - "r_sun": (m_per_rsun, dimensions.length, 0.0, r"R_\odot"), - "Lsun": (luminosity_sun_watts, dimensions.power, 0.0, r"L_\odot"), - "Tsun": (temp_sun_kelvin, dimensions.temperature, 0.0, r"T_\odot"), - "Zsun": (metallicity_sun, dimensions.dimensionless, 0.0, r"Z_\odot"), - "Mjup": (mass_jupiter_kg, dimensions.mass, 0.0, r"M_{\rm{Jup}}"), - "Mearth": (mass_earth_kg, dimensions.mass, 0.0, r"M_\oplus"), + "Msun": (mass_sun_kg, dimensions.mass, 0.0, r"M_\odot", False), + "msun": (mass_sun_kg, dimensions.mass, 0.0, r"M_\odot", False), + "Rsun": (m_per_rsun, dimensions.length, 0.0, r"R_\odot", False), + "rsun": (m_per_rsun, dimensions.length, 0.0, r"R_\odot", False), + "R_sun": (m_per_rsun, dimensions.length, 0.0, r"R_\odot", False), + "r_sun": (m_per_rsun, dimensions.length, 0.0, r"R_\odot", False), + "Lsun": (luminosity_sun_watts, dimensions.power, 0.0, r"L_\odot", False), + "Tsun": (temp_sun_kelvin, dimensions.temperature, 0.0, r"T_\odot", False), + "Zsun": (metallicity_sun, dimensions.dimensionless, 0.0, r"Z_\odot", + False), + "Mjup": (mass_jupiter_kg, dimensions.mass, 0.0, r"M_{\rm{Jup}}", False), + "Mearth": (mass_earth_kg, dimensions.mass, 0.0, r"M_\oplus", False), + "R_jup": (m_per_rjup, dimensions.length, 0.0, r"R_\mathrm{Jup}", False), + "r_jup": (m_per_rjup, dimensions.length, 0.0, r"R_\mathrm{Jup}", False), + "R_earth": (m_per_rearth, dimensions.length, 0.0, r"R_\oplus", False), + "r_earth": (m_per_rearth, dimensions.length, 0.0, r"R_\oplus", False), # astro distances - "AU": (m_per_au, dimensions.length, 0.0, r"\rm{AU}"), - "au": (m_per_au, dimensions.length, 0.0, r"\rm{AU}"), - "ly": (m_per_ly, dimensions.length, 0.0, r"\rm{ly}"), - "pc": (m_per_pc, dimensions.length, 0.0, r"\rm{pc}"), + "AU": (m_per_au, dimensions.length, 0.0, r"\rm{AU}", False), + "au": (m_per_au, dimensions.length, 0.0, r"\rm{AU}", False), + "ly": (m_per_ly, dimensions.length, 0.0, r"\rm{ly}", False), + "pc": (m_per_pc, dimensions.length, 0.0, r"\rm{pc}", True), # angles - "degree": (np.pi/180., dimensions.angle, 0.0, r"\rm{deg}"), # degrees + "degree": (np.pi/180., dimensions.angle, 0.0, r"\rm{deg}", False), "arcmin": (np.pi/10800., dimensions.angle, 0.0, - r"\rm{arcmin}"), # arcminutes + r"\rm{arcmin}", False), # arcminutes "arcsec": (np.pi/648000., dimensions.angle, 0.0, - r"\rm{arcsec}"), # arcseconds + r"\rm{arcsec}", False), # arcseconds "mas": (np.pi/648000000., dimensions.angle, 0.0, - r"\rm{mas}"), # milliarcseconds - "hourangle": (np.pi/12., dimensions.angle, 0.0, r"\rm{HA}"), # hour angle - "steradian": (1.0, dimensions.solid_angle, 0.0, r"\rm{sr}"), - "lat": (-np.pi/180.0, dimensions.angle, 90.0, r"\rm{Latitude}"), - "lon": (np.pi/180.0, dimensions.angle, -180.0, r"\rm{Longitude}"), + r"\rm{mas}", False), # milliarcseconds + "hourangle": (np.pi/12., dimensions.angle, 0.0, r"\rm{HA}", False), + "steradian": (1.0, dimensions.solid_angle, 0.0, r"\rm{sr}", False), + "lat": (-np.pi/180.0, dimensions.angle, 90.0, r"\rm{Latitude}", False), + "lon": (np.pi/180.0, dimensions.angle, -180.0, r"\rm{Longitude}", False), # misc - "eV": (J_per_eV, dimensions.energy, 0.0, r"\rm{eV}"), - "amu": (amu_kg, dimensions.mass, 0.0, r"\rm{amu}"), - "angstrom": (m_per_ang, dimensions.length, 0.0, r"\AA"), - "Jy": (jansky_mks, dimensions.specific_flux, 0.0, r"\rm{Jy}"), - "counts": (1.0, dimensions.dimensionless, 0.0, r"\rm{counts}"), - "photons": (1.0, dimensions.dimensionless, 0.0, r"\rm{photons}"), - "me": (mass_electron_kg, dimensions.mass, 0.0, r"m_e"), - "mp": (mass_hydrogen_kg, dimensions.mass, 0.0, r"m_p"), - 'Sv': (1.0, dimensions.specific_energy, 0.0, r"\rm{Sv}"), - "rayleigh": (2.5e9/np.pi, dimensions.count_intensity, 0.0, r"\rm{R}"), - "lambert": (1.0e4/np.pi, dimensions.luminance, 0.0, r"\rm{L}"), - "nt": (1.0, dimensions.luminance, 0.0, r"\rm{nt}"), + "eV": (J_per_eV, dimensions.energy, 0.0, r"\rm{eV}", True), + "amu": (amu_kg, dimensions.mass, 0.0, r"\rm{amu}", False), + "angstrom": (m_per_ang, dimensions.length, 0.0, r"\AA", False), + "Jy": (jansky_mks, dimensions.specific_flux, 0.0, r"\rm{Jy}", True), + "counts": (1.0, dimensions.dimensionless, 0.0, r"\rm{counts}", False), + "photons": (1.0, dimensions.dimensionless, 0.0, r"\rm{photons}", False), + "me": (mass_electron_kg, dimensions.mass, 0.0, r"m_e", False), + "mp": (mass_hydrogen_kg, dimensions.mass, 0.0, r"m_p", False), + 'Sv': (1.0, dimensions.specific_energy, 0.0, r"\rm{Sv}", True), + "rayleigh": (2.5e9/np.pi, dimensions.count_intensity, 0.0, r"\rm{R}", + False), + "lambert": (1.0e4/np.pi, dimensions.luminance, 0.0, r"\rm{L}", False), + "nt": (1.0, dimensions.luminance, 0.0, r"\rm{nt}", False), # for AstroPy compatibility - "solMass": (mass_sun_kg, dimensions.mass, 0.0, r"M_\odot"), - "solRad": (m_per_rsun, dimensions.length, 0.0, r"R_\odot"), - "solLum": (luminosity_sun_watts, dimensions.power, 0.0, r"L_\odot"), - "dyn": (1.0e-5, dimensions.force, 0.0, r"\rm{dyn}"), - "sr": (1.0, dimensions.solid_angle, 0.0, r"\rm{sr}"), - "rad": (1.0, dimensions.angle, 0.0, r"\rm{rad}"), - "deg": (np.pi/180., dimensions.angle, 0.0, r"\rm{deg}"), - "Fr": (1.0e-3**1.5, dimensions.charge_cgs, 0.0, r"\rm{Fr}"), - "G": (0.1**0.5, dimensions.magnetic_field_cgs, 0.0, r"\rm{G}"), - "Angstrom": (m_per_ang, dimensions.length, 0.0, r"\AA"), - "statC": (1.0e-3**1.5, dimensions.charge_cgs, 0.0, r"\rm{statC}"), + "solMass": (mass_sun_kg, dimensions.mass, 0.0, r"M_\odot", False), + "solRad": (m_per_rsun, dimensions.length, 0.0, r"R_\odot", False), + "solLum": (luminosity_sun_watts, dimensions.power, 0.0, r"L_\odot", False), + "dyn": (1.0e-5, dimensions.force, 0.0, r"\rm{dyn}", False), + "sr": (1.0, dimensions.solid_angle, 0.0, r"\rm{sr}", False), + "rad": (1.0, dimensions.angle, 0.0, r"\rm{rad}", False), + "deg": (np.pi/180., dimensions.angle, 0.0, r"\rm{deg}", False), + "Fr": (1.0e-3**1.5, dimensions.charge_cgs, 0.0, r"\rm{Fr}", False), + "G": (0.1**0.5, dimensions.magnetic_field_cgs, 0.0, r"\rm{G}", True), + "Angstrom": (m_per_ang, dimensions.length, 0.0, r"\AA", False), + "statC": (1.0e-3**1.5, dimensions.charge_cgs, 0.0, r"\rm{statC}", True), # Planck units - "m_pl": (planck_mass_kg, dimensions.mass, 0.0, r"m_{\rm{P}}"), - "l_pl": (planck_length_m, dimensions.length, 0.0, r"\ell_\rm{P}"), - "t_pl": (planck_time_s, dimensions.time, 0.0, r"t_{\rm{P}}"), - "T_pl": (planck_temperature_K, dimensions.temperature, 0.0, r"T_{\rm{P}}"), - "q_pl": (planck_charge_C, dimensions.charge_mks, 0.0, r"q_{\rm{P}}"), - "E_pl": (planck_energy_J, dimensions.energy, 0.0, r"E_{\rm{P}}"), + "m_pl": (planck_mass_kg, dimensions.mass, 0.0, r"m_{\rm{P}}", False), + "l_pl": (planck_length_m, dimensions.length, 0.0, r"\ell_\rm{P}", False), + "t_pl": (planck_time_s, dimensions.time, 0.0, r"t_{\rm{P}}", False), + "T_pl": (planck_temperature_K, dimensions.temperature, 0.0, r"T_{\rm{P}}", + False), + "q_pl": (planck_charge_C, dimensions.charge_mks, 0.0, r"q_{\rm{P}}", + False), + "E_pl": (planck_energy_J, dimensions.energy, 0.0, r"E_{\rm{P}}", False), # Geometrized units - "m_geom": (mass_sun_kg, dimensions.mass, 0.0, r"M_\odot"), + "m_geom": (mass_sun_kg, dimensions.mass, 0.0, r"M_\odot", False), "l_geom": (newton_mks*mass_sun_kg/speed_of_light_m_per_s**2, - dimensions.length, 0.0, r"M_\odot"), + dimensions.length, 0.0, r"M_\odot", False), "t_geom": (newton_mks*mass_sun_kg/speed_of_light_m_per_s**3, - dimensions.time, 0.0, r"M_\odot"), - - # Some Solar System units - "R_earth": (m_per_rearth, dimensions.length, 0.0, r"R_\oplus"), - "r_earth": (m_per_rearth, dimensions.length, 0.0, r"R_\oplus"), - "R_jup": (m_per_rjup, dimensions.length, 0.0, r"R_\mathrm{Jup}"), - "r_jup": (m_per_rjup, dimensions.length, 0.0, r"R_\mathrm{Jup}"), + dimensions.time, 0.0, r"M_\odot", False), } # This dictionary formatting from magnitude package, credit to Juan Reyero. @@ -244,44 +248,6 @@ "u": r"\mu", } -prefixable_units = [ - "m", - "pc", - "mcm", - "pccm", - "g", - "eV", - "s", - "yr", - "K", - "dyne", - "erg", - "esu", - "J", - "Hz", - "W", - "gauss", - "G", - "Jy", - "N", - "T", - "A", - "C", - "statA", - "Pa", - "V", - "statV", - "ohm", - "statohm", - "Sv", - "mol", - "cd", - "lm", - "lx", - "Wb", - "Mx", -] - default_base_units = { dimensions.mass: 'kg', dimensions.length: 'm', diff --git a/unyt/tests/test_unit_registry.py b/unyt/tests/test_unit_registry.py index c3d4c60a..3066a42c 100644 --- a/unyt/tests/test_unit_registry.py +++ b/unyt/tests/test_unit_registry.py @@ -21,6 +21,7 @@ SymbolNotFoundError, UnitParseError, ) +from unyt.unit_object import Unit from unyt.unit_registry import UnitRegistry @@ -52,3 +53,16 @@ def test_add_modify_error(): def test_keys(): ureg = UnitRegistry() assert sorted(ureg.keys()) == sorted(ureg.lut.keys()) + + +def test_prefixable_units(): + ureg = UnitRegistry() + pu = ureg.prefixable_units + assert 'm' in pu + assert 'pc' in pu + assert 'mol' in pu + ureg.add('foobar', 1.0, length, prefixable=True) + assert 'foobar' in ureg.prefixable_units + mfoobar = Unit('mfoobar', registry=ureg) + foobar = Unit('foobar', registry=ureg) + assert (1*foobar)/(1*mfoobar) == 1000 diff --git a/unyt/tests/test_unit_systems.py b/unyt/tests/test_unit_systems.py index 5f2e30c8..7e64b92f 100644 --- a/unyt/tests/test_unit_systems.py +++ b/unyt/tests/test_unit_systems.py @@ -53,7 +53,7 @@ def test_unit_system_id(): reg1 = UnitRegistry() reg1.remove('g') assert reg1.unit_system_id != reg2.unit_system_id - reg1.add('g', 1.0e-3, dimensions.mass) + reg1.add('g', 1.0e-3, dimensions.mass, prefixable=True) assert reg1.unit_system_id == reg2.unit_system_id diff --git a/unyt/tests/test_units.py b/unyt/tests/test_units.py index eea75cc8..6d863fe8 100644 --- a/unyt/tests/test_units.py +++ b/unyt/tests/test_units.py @@ -52,8 +52,7 @@ from unyt.unit_systems import UnitSystem from unyt._unit_lookup_table import ( default_unit_symbol_lut, - unit_prefixes, - prefixable_units + unit_prefixes ) import unyt.unit_symbols as unit_symbols from unyt._physical_ratios import ( @@ -74,7 +73,7 @@ def test_no_conflicting_symbols(): # go through all possible prefix combos for symbol in default_unit_symbol_lut.keys(): - if symbol in prefixable_units: + if default_unit_symbol_lut[symbol][4]: keys = unit_prefixes.keys() else: keys = [symbol] @@ -493,7 +492,7 @@ def test_latex_repr(): # create a fake comoving unit registry.add('pccm', registry.lut['pc'][0]/(1+2), length, - "\\rm{pc}/(1+z)") + "\\rm{pc}/(1+z)", prefixable=True) test_unit = Unit('Mpccm', registry=registry) assert_almost_equal(test_unit.base_value, m_per_mpc/3) @@ -656,3 +655,8 @@ def test_define_unit_error(): define_unit('foobar', 'baz') with pytest.raises(RuntimeError): define_unit('foobar', 12) + + +def test_symbol_lut_length(): + for v in default_unit_symbol_lut.values(): + assert len(v) == 5 diff --git a/unyt/unit_object.py b/unyt/unit_object.py index 3a9c0da6..4220f318 100644 --- a/unyt/unit_object.py +++ b/unyt/unit_object.py @@ -64,7 +64,6 @@ from unyt._physical_ratios import speed_of_light_cm_per_s from unyt._unit_lookup_table import ( unit_prefixes, - prefixable_units, latex_prefixes, ) from unyt.unit_registry import ( @@ -926,6 +925,9 @@ def _lookup_unit_symbol(symbol_str, unit_symbol_lut): symbol_wo_pref = symbol_str[2:] possible_prefix = 'da' + prefixable_units = [u for u in unit_symbol_lut + if unit_symbol_lut[u][4]] + unit_is_si_prefixable = (symbol_wo_pref in unit_symbol_lut and symbol_wo_pref in prefixable_units) @@ -954,7 +956,7 @@ def _lookup_unit_symbol(symbol_str, unit_symbol_lut): # Leave offset and dimensions the same, but adjust scale factor and # LaTeX representation ret = (unit_data[0] * prefix_value, unit_data[1], unit_data[2], - latex_repr) + latex_repr, False) unit_symbol_lut[symbol_str] = ret @@ -1064,10 +1066,8 @@ def define_unit(symbol, value, tex_repr=None, offset=None, prefixable=False, "(value, unit) tuple!") base_value = float(value.in_base(unit_system='mks')) dimensions = value.units.dimensions - registry.add(symbol, base_value, dimensions, tex_repr=tex_repr, - offset=offset) - if prefixable: - prefixable_units.append(symbol) + registry.add(symbol, base_value, dimensions, prefixable=prefixable, + tex_repr=tex_repr, offset=offset) if registry is default_unit_registry: u = Unit(symbol, registry=registry) setattr(unyt, symbol, u) diff --git a/unyt/unit_registry.py b/unyt/unit_registry.py index 5d81ed21..5afeb131 100644 --- a/unyt/unit_registry.py +++ b/unyt/unit_registry.py @@ -69,10 +69,37 @@ def unit_system_id(self): self._unit_system_id = str(m.hexdigest()) return self._unit_system_id - def add(self, symbol, base_value, dimensions, tex_repr=None, offset=None): + @property + def prefixable_units(self): + return [u for u in self.lut if self.lut[u][4]] + + def add(self, symbol, base_value, dimensions, tex_repr=None, offset=None, + prefixable=False): """ Add a symbol to this registry. + Parameters + ---------- + + symbol : str + The name of the unit + base_value : float + The scaling from the units value to the equivalent SI unit + with the same dimensions + dimensions : expr + The dimensions of the unit + tex_repr : str, optional + The LaTeX representation of the unit. If not provided a LaTeX + representation is automatically generated from the name of + the unit. + offset : float, optional + If set, the zero-point offset to apply to the unit to convert + to SI. This is mostly used for units like Farhenheit and + Celcius that are not defined on an absolute scale. + prefixable : bool + If True, then SI-prefix versions of the unit will be created + along with the unit itself. + """ from unyt.unit_object import _validate_dimensions @@ -98,12 +125,19 @@ def add(self, symbol, base_value, dimensions, tex_repr=None, offset=None): tex_repr = r"\rm{" + symbol.replace('_', '\ ') + "}" # Add to lut - self.lut.update({symbol: (base_value, dimensions, offset, tex_repr)}) + self.lut[symbol] = ( + base_value, dimensions, offset, tex_repr, prefixable) def remove(self, symbol): """ Remove the entry for the unit matching `symbol`. + Parameters + ---------- + + symbol : str + The name of the unit symbol to remove from the registry. + """ self._unit_system_id = None @@ -119,6 +153,14 @@ def modify(self, symbol, base_value): Change the base value of a unit symbol. Useful for adjusting code units after parsing parameters. + Parameters + ---------- + + symbol : str + The name of the symbol to modify + base_value : float + The new base_value for the symbol. + """ self._unit_system_id = None @@ -161,6 +203,12 @@ def to_json(self): def from_json(cls, json_text): """ Returns a UnitRegistry object from a json-serialized unit registry + + Parameters + ---------- + + json_text : str + A string containing a json represention of a UnitRegistry """ data = json.loads(json_text) lut = {}