[yt-svn] commit/yt: MatthewTurk: Merged in ngoldbaum/yt/yt-3.0 (pull request #993)
commits-noreply at bitbucket.org
commits-noreply at bitbucket.org
Thu Jul 17 14:15:06 PDT 2014
1 new commit in yt:
https://bitbucket.org/yt_analysis/yt/commits/b58796ca1988/
Changeset: b58796ca1988
Branch: yt-3.0
User: MatthewTurk
Date: 2014-07-17 23:14:53
Summary: Merged in ngoldbaum/yt/yt-3.0 (pull request #993)
Adding boltzmann's constant, speed of light, Fahrenheit, Celsius, and Rankine units.
Affected #: 7 files
diff -r dd9c415ca94dcf54849b3760a290a783f5cd44e4 -r b58796ca19881fca5b1244e13152816ad2164200 yt/units/tests/test_units.py
--- a/yt/units/tests/test_units.py
+++ b/yt/units/tests/test_units.py
@@ -31,7 +31,8 @@
# classes
from yt.units.unit_object import Unit, UnitParseError
# objects
-from yt.units.unit_lookup_table import default_unit_symbol_lut, unit_prefixes
+from yt.units.unit_lookup_table import \
+ default_unit_symbol_lut, unit_prefixes, prefixable_units
# unit definitions
from yt.utilities.physical_constants import \
cm_per_pc, sec_per_year, cm_per_km, cm_per_mpc, \
@@ -46,13 +47,17 @@
# go through all possible prefix combos
for symbol in default_unit_symbol_lut.keys():
- for prefix in unit_prefixes.keys():
+ if symbol in prefixable_units:
+ keys = unit_prefixes.keys()
+ else:
+ keys = [symbol]
+ for prefix in keys:
new_symbol = "%s%s" % (prefix, symbol)
# test if we have seen this symbol
if new_symbol in full_set:
print "Duplicate symbol: %s" % new_symbol
- yield assert_true, False
+ raise RuntimeError
full_set.add(new_symbol)
yield assert_true, True
@@ -417,7 +422,7 @@
yield assert_true, u2.dimensions == mass_density
yield assert_true, u3.dimensions == mass_density
- yield assert_allclose, get_conversion_factor(u1, u3), \
+ yield assert_allclose, get_conversion_factor(u1, u3)[0], \
Msun_cgs / Mpc_cgs**3, 1e-12
def test_is_code_unit():
diff -r dd9c415ca94dcf54849b3760a290a783f5cd44e4 -r b58796ca19881fca5b1244e13152816ad2164200 yt/units/tests/test_ytarray.py
--- a/yt/units/tests/test_ytarray.py
+++ b/yt/units/tests/test_ytarray.py
@@ -27,7 +27,8 @@
from numpy.testing import \
assert_array_equal, \
assert_equal, assert_raises, \
- assert_array_almost_equal_nulp
+ assert_array_almost_equal_nulp, \
+ assert_array_almost_equal
from numpy import array
from yt.units.yt_array import \
YTArray, YTQuantity, \
@@ -418,7 +419,9 @@
yield assert_equal, km_in_cm.in_mks(), 1e3
yield assert_equal, km_in_cm.units, cm_unit
+ km_view = km.ndarray_view()
km.convert_to_units('cm')
+ assert_true(km_view.base is km.base)
yield assert_equal, km, YTQuantity(1, 'km')
yield assert_equal, km.in_cgs(), 1e5
@@ -426,6 +429,7 @@
yield assert_equal, km.units, cm_unit
km.convert_to_units('kpc')
+ assert_true(km_view.base is km.base)
yield assert_array_almost_equal_nulp, km, YTQuantity(1, 'km')
yield assert_array_almost_equal_nulp, km.in_cgs(), YTQuantity(1e5, 'cm')
@@ -453,6 +457,49 @@
yield assert_equal, str(em3.in_mks().units), 'kg/(m*s**2)'
yield assert_equal, str(em3.in_cgs().units), 'g/(cm*s**2)'
+def test_temperature_conversions():
+ """
+ Test conversions between various supported temperatue scales.
+
+ Also ensure we only allow compound units with temperature
+ scales that have a proper zero point.
+
+ """
+ from yt.units.unit_object import InvalidUnitOperation
+
+ km = YTQuantity(1, 'km')
+ balmy = YTQuantity(300, 'K')
+ balmy_F = YTQuantity(80.33, 'F')
+ balmy_C = YTQuantity(26.85, 'C')
+ balmy_R = YTQuantity(540, 'R')
+
+ assert_array_almost_equal(balmy.in_units('F'), balmy_F)
+ assert_array_almost_equal(balmy.in_units('C'), balmy_C)
+ assert_array_almost_equal(balmy.in_units('R'), balmy_R)
+
+ balmy_view = balmy.ndarray_view()
+
+ balmy.convert_to_units('F')
+ yield assert_true, balmy_view.base is balmy.base
+ yield assert_array_almost_equal, np.array(balmy), np.array(balmy_F)
+
+ balmy.convert_to_units('C')
+ yield assert_true, balmy_view.base is balmy.base
+ yield assert_array_almost_equal, np.array(balmy), np.array(balmy_C)
+
+ balmy.convert_to_units('R')
+ yield assert_true, balmy_view.base is balmy.base
+ yield assert_array_almost_equal, np.array(balmy), np.array(balmy_R)
+
+ balmy.convert_to_units('F')
+ yield assert_true, balmy_view.base is balmy.base
+ yield assert_array_almost_equal, np.array(balmy), np.array(balmy_F)
+
+ yield assert_raises, InvalidUnitOperation, np.multiply, balmy, km
+
+ # Does CGS convergion from F to K work?
+ yield assert_array_almost_equal, balmy.in_cgs(), YTQuantity(300, 'K')
+
def test_yt_array_yt_quantity_ops():
"""
diff -r dd9c415ca94dcf54849b3760a290a783f5cd44e4 -r b58796ca19881fca5b1244e13152816ad2164200 yt/units/unit_lookup_table.py
--- a/yt/units/unit_lookup_table.py
+++ b/yt/units/unit_lookup_table.py
@@ -18,7 +18,9 @@
mass_sun_grams, sec_per_year, sec_per_day, sec_per_hr, \
sec_per_min, temp_sun_kelvin, luminosity_sun_ergs_per_sec, \
metallicity_sun, erg_per_eV, amu_grams, mass_electron_grams, \
- cm_per_ang, jansky_cgs, mass_jupiter_grams, mass_earth_grams
+ cm_per_ang, jansky_cgs, mass_jupiter_grams, mass_earth_grams, \
+ boltzmann_constant_erg_per_K, kelvin_per_rankine, \
+ speed_of_light_cm_per_s
import numpy as np
# Lookup a unit symbol with the symbol string, and provide a tuple with the
@@ -37,6 +39,7 @@
"erg": (1.0, dimensions.energy),
"esu": (1.0, dimensions.charge),
"gauss": (1.0, dimensions.magnetic_field),
+ "C" : (1.0, dimensions.temperature, -273.15),
# some SI
"m": (1.0e2, dimensions.length),
@@ -47,6 +50,8 @@
# Imperial units
"ft": (30.48, dimensions.length),
"mile": (160934, dimensions.length),
+ "F": (kelvin_per_rankine, dimensions.temperature, -459.67),
+ "R": (kelvin_per_rankine, dimensions.temperature),
# dimensionless stuff
"h": (1.0, dimensions.dimensionless), # needs to be added for rho_crit_now
@@ -58,6 +63,9 @@
"day": (sec_per_day, dimensions.time),
"yr": (sec_per_year, dimensions.time),
+ # Velocities
+ "c": (speed_of_light_cm_per_s, dimensions.velocity),
+
# Solar units
"Msun": (mass_sun_grams, dimensions.mass),
"msun": (mass_sun_grams, dimensions.mass),
@@ -89,6 +97,8 @@
"angstrom": (cm_per_ang, dimensions.length),
"Jy": (jansky_cgs, dimensions.specific_flux),
"counts": (1.0, dimensions.dimensionless),
+ "kB": (boltzmann_constant_erg_per_K,
+ dimensions.energy/dimensions.temperature),
"photons": (1.0, dimensions.dimensionless),
# for AstroPy compatibility
diff -r dd9c415ca94dcf54849b3760a290a783f5cd44e4 -r b58796ca19881fca5b1244e13152816ad2164200 yt/units/unit_object.py
--- a/yt/units/unit_object.py
+++ b/yt/units/unit_object.py
@@ -21,7 +21,8 @@
from sympy.parsing.sympy_parser import \
parse_expr, auto_number, rationalize
from keyword import iskeyword
-from yt.units import dimensions as dimensions_mod
+from yt.units.dimensions import \
+ base_dimensions, temperature
from yt.units.unit_lookup_table import \
latex_symbol_lut, unit_prefixes, \
prefixable_units, cgs_base_units, \
@@ -114,10 +115,11 @@
is_number = False
# Extra attributes
- __slots__ = ["expr", "is_atomic", "cgs_value", "dimensions", "registry"]
+ __slots__ = ["expr", "is_atomic", "cgs_value", "cgs_offset", "dimensions",
+ "registry"]
- def __new__(cls, unit_expr=sympy_one, cgs_value=None, dimensions=None,
- registry=None, **assumptions):
+ def __new__(cls, unit_expr=sympy_one, cgs_value=None, cgs_offset=0.0,
+ dimensions=None, registry=None, **assumptions):
"""
Create a new unit. May be an atomic unit (like a gram) or combinations
of atomic units (like g / cm**3).
@@ -130,7 +132,11 @@
The unit's value in cgs.
dimensions : sympy.core.expr.Expr
A sympy expression representing the dimensionality of this unit.
- It must contain only mass, length, time, temperature and angle symbols.
+ It must contain only mass, length, time, temperature and angle
+ symbols.
+ offset : float
+ The offset necessary to normalize temperature units to a common
+ zero point.
registry : UnitRegistry object
The unit registry we use to interpret unit symbols.
@@ -185,7 +191,12 @@
validate_dimensions(dimensions)
else:
# lookup the unit symbols
- cgs_value, dimensions = _get_unit_data_from_expr(unit_expr, registry.lut)
+ try:
+ cgs_value, dimensions = \
+ _get_unit_data_from_expr(unit_expr, registry.lut)
+ except ValueError:
+ cgs_value, dimensions, cgs_offset = \
+ _get_unit_data_from_expr(unit_expr, registry.lut)
# Create obj with superclass construct.
obj = Expr.__new__(cls, **assumptions)
@@ -194,6 +205,7 @@
obj.expr = unit_expr
obj.is_atomic = is_atomic
obj.cgs_value = cgs_value
+ obj.cgs_offset = cgs_offset
obj.dimensions = dimensions
obj.registry = registry
@@ -240,24 +252,46 @@
def __mul__(self, u):
""" Multiply Unit with u (Unit object). """
if not isinstance(u, Unit):
- raise InvalidUnitOperation("Tried to multiply a Unit object with " \
- "'%s' (type %s). This behavior is " \
- "undefined." % (u, type(u)) )
+ raise InvalidUnitOperation("Tried to multiply a Unit object with "
+ "'%s' (type %s). This behavior is "
+ "undefined." % (u, type(u)))
+
+ cgs_offset = 0.0
+ if self.cgs_offset or u.cgs_offset:
+ if u.dimensions is temperature and self.is_dimensionless:
+ cgs_offset = u.cgs_offset
+ elif self.dimensions is temperature and u.is_dimensionless:
+ cgs_offset = self.cgs_offset
+ else:
+ raise InvalidUnitOperation("Quantities with units of Fahrenheit "
+ "and Celcius cannot be multiplied.")
return Unit(self.expr * u.expr,
cgs_value=(self.cgs_value * u.cgs_value),
+ cgs_offset=cgs_offset,
dimensions=(self.dimensions * u.dimensions),
registry=self.registry)
def __div__(self, u):
""" Divide Unit by u (Unit object). """
if not isinstance(u, Unit):
- raise InvalidUnitOperation("Tried to divide a Unit object by '%s' "\
+ raise InvalidUnitOperation("Tried to divide a Unit object by '%s' "
"(type %s). This behavior is "
- "undefined." % (u, type(u)) )
+ "undefined." % (u, type(u)))
+
+ cgs_offset = 0.0
+ if self.cgs_offset or u.cgs_offset:
+ if u.dimensions is dims.temperature and self.is_dimensionless:
+ cgs_offset = u.cgs_offset
+ elif self.dimensions is dims.temperature and u.is_dimensionless:
+ cgs_offset = self.cgs_offset
+ else:
+ raise InvalidUnitOperation("Quantities with units of Farhenheit "
+ "and Celcius cannot be multiplied.")
return Unit(self.expr / u.expr,
cgs_value=(self.cgs_value / u.cgs_value),
+ cgs_offset=cgs_offset,
dimensions=(self.dimensions / u.dimensions),
registry=self.registry)
@@ -294,10 +328,11 @@
memodict = {}
expr = str(self.expr)
cgs_value = copy.deepcopy(self.cgs_value)
+ cgs_offset = copy.deepcopy(self.cgs_offset)
dimensions = copy.deepcopy(self.dimensions)
lut = copy.deepcopy(self.registry.lut)
registry = UnitRegistry(lut=lut)
- return Unit(expr, cgs_value, dimensions, registry)
+ return Unit(expr, cgs_value, cgs_offset, dimensions, registry)
#
# End unit operations
@@ -347,8 +382,8 @@
"""
units_string = self._get_system_unit_string(mks_base_units)
- cgs_value = (get_conversion_factor(self, self.get_cgs_equivalent()) /
- get_conversion_factor(self, units_string))
+ cgs_value = (get_conversion_factor(self, self.get_cgs_equivalent())[0] /
+ get_conversion_factor(self, Unit(units_string))[0])
return Unit(units_string, cgs_value=cgs_value,
dimensions=self.dimensions, registry=self.registry)
@@ -383,41 +418,20 @@
-------
conversion_factor : float
`old_units / new_units`
+ offset : float or None
+ Offset between the old unit and new unit.
"""
- # if args are not Unit objects, construct them
- if not isinstance(old_units, Unit):
- old_units = Unit(old_units)
- if not isinstance(new_units, Unit):
- new_units = Unit(new_units)
-
- if not old_units.same_dimensions_as(new_units):
- raise InvalidUnitOperation(
- "Cannot convert from %s to %s because the dimensions do not "
- "match: %s and %s" % (old_units, new_units, old_units.dimensions,
- new_units.dimensions))
-
- return old_units.cgs_value / new_units.cgs_value
-
-
-def convert_values(values, old_units, new_units):
- """
- Take data given in old units and convert to values in new units.
-
- Parameters
- ----------
- values : array_like
- The number or array we will convert.
- old_units : str or Unit object
- The units values are supplied in.
- new_units : str or Unit object
- The units values will be returned in.
-
- Returns values in new units.
-
- """
- return values * get_conversion_factor(old_units, new_units)
-
+ ratio = old_units.cgs_value / new_units.cgs_value
+ if old_units.cgs_offset == 0 and new_units.cgs_offset == 0:
+ return (ratio, None)
+ else:
+ if old_units.dimensions is temperature:
+ return ratio, ratio*old_units.cgs_offset - new_units.cgs_offset
+ else:
+ raise InvalidUnitOperation(
+ "Fahrenheit and Celsius are not absoulte temperature scales "
+ "and cannot be used in compound unit symbols.")
#
# Helper functions
@@ -444,7 +458,6 @@
return _lookup_unit_symbol(str(unit_expr), unit_symbol_lut)
if isinstance(unit_expr, Number):
- # not sure if this should be (1, 1)...
return (float(unit_expr), sympy_one)
if isinstance(unit_expr, Pow):
@@ -515,7 +528,7 @@
for dim in dimensions.args:
validate_dimensions(dim)
elif isinstance(dimensions, Symbol):
- if dimensions not in dimensions_mod.base_dimensions:
+ if dimensions not in base_dimensions:
raise UnitParseError("Dimensionality expression contains an "
"unknown symbol '%s'." % dimensions)
elif isinstance(dimensions, Pow):
diff -r dd9c415ca94dcf54849b3760a290a783f5cd44e4 -r b58796ca19881fca5b1244e13152816ad2164200 yt/units/yt_array.py
--- a/yt/units/yt_array.py
+++ b/yt/units/yt_array.py
@@ -414,10 +414,14 @@
"""
new_units = self._unit_repr_check_same(units)
- conversion_factor = self.units.get_conversion_factor(new_units)
+ (conversion_factor, offset) = self.units.get_conversion_factor(new_units)
self.units = new_units
self *= conversion_factor
+
+ if offset:
+ np.subtract(self, offset*self.uq, self)
+
return self
def convert_to_cgs(self):
@@ -450,11 +454,14 @@
"""
new_units = self._unit_repr_check_same(units)
- conversion_factor = self.units.get_conversion_factor(new_units)
+ (conversion_factor, offset) = self.units.get_conversion_factor(new_units)
new_array = self * conversion_factor
new_array.units = new_units
+ if offset:
+ np.subtract(new_array, offset*new_array.uq, new_array)
+
return new_array
def in_cgs(self):
@@ -672,7 +679,8 @@
def __iadd__(self, other):
""" See __add__. """
oth = sanitize_units_add(self, other, "addition")
- return np.add(self, oth, out=self)
+ np.add(self, oth, out=self)
+ return self
def __sub__(self, right_object):
"""
@@ -691,7 +699,8 @@
def __isub__(self, other):
""" See __sub__. """
oth = sanitize_units_add(self, other, "subtraction")
- return np.subtract(self, oth, out=self)
+ np.subtract(self, oth, out=self)
+ return self
def __neg__(self):
""" Negate the data. """
@@ -718,7 +727,8 @@
def __imul__(self, other):
""" See __mul__. """
oth = sanitize_units_mul(self, other)
- return np.multiply(self, oth, out=self)
+ np.multiply(self, oth, out=self)
+ return self
def __div__(self, right_object):
"""
@@ -736,7 +746,8 @@
def __idiv__(self, other):
""" See __div__. """
oth = sanitize_units_mul(self, other)
- return np.divide(self, oth, out=self)
+ np.divide(self, oth, out=self)
+ return self
def __truediv__(self, right_object):
ro = sanitize_units_mul(self, right_object)
@@ -750,7 +761,8 @@
def __itruediv__(self, other):
""" See __div__. """
oth = sanitize_units_mul(self, other)
- return np.true_divide(self, oth, out=self)
+ np.true_divide(self, oth, out=self)
+ return self
def __floordiv__(self, right_object):
ro = sanitize_units_mul(self, right_object)
@@ -764,7 +776,8 @@
def __ifloordiv__(self, other):
""" See __div__. """
oth = sanitize_units_mul(self, other)
- return np.floor_divide(self, oth, out=self)
+ np.floor_divide(self, oth, out=self)
+ return self
#Should these raise errors? I need to come back and check this.
def __or__(self, right_object):
@@ -774,7 +787,8 @@
return YTArray(super(YTArray, self).__ror__(left_object))
def __ior__(self, other):
- return np.bitwise_or(self, other, out=self)
+ np.bitwise_or(self, other, out=self)
+ return self
def __xor__(self, right_object):
return YTArray(super(YTArray, self).__xor__(right_object))
@@ -783,7 +797,8 @@
return YTArray(super(YTArray, self).__rxor__(left_object))
def __ixor__(self, other):
- return np.bitwise_xor(self, other, out=self)
+ np.bitwise_xor(self, other, out=self)
+ return self
def __and__(self, right_object):
return YTArray(super(YTArray, self).__and__(right_object))
@@ -792,7 +807,8 @@
return YTArray(super(YTArray, self).__rand__(left_object))
def __iand__(self, other):
- return np.bitwise_and(self, other, out=self)
+ np.bitwise_and(self, other, out=self)
+ return self
def __pow__(self, power):
"""
diff -r dd9c415ca94dcf54849b3760a290a783f5cd44e4 -r b58796ca19881fca5b1244e13152816ad2164200 yt/utilities/physical_constants.py
--- a/yt/utilities/physical_constants.py
+++ b/yt/utilities/physical_constants.py
@@ -6,7 +6,7 @@
mass_hydrogen_cgs = 1.007947*amu_cgs
# Velocities
-speed_of_light_cgs = YTQuantity(2.99792458e10, 'cm/s')
+speed_of_light_cgs = YTQuantity(speed_of_light_cm_per_s, 'cm/s')
# Cross Sections
# 8*pi/3 (alpha*hbar*c/(2*pi))**2
@@ -44,7 +44,9 @@
qp = charge_proton_cgs
mh = mp
clight = speed_of_light_cgs
+speed_of_light = speed_of_light_cgs
kboltz = boltzmann_constant_cgs
+kb = kboltz
hcgs = planck_constant_cgs
sigma_thompson = cross_section_thompson_cgs
Na = 1 / amu_cgs
diff -r dd9c415ca94dcf54849b3760a290a783f5cd44e4 -r b58796ca19881fca5b1244e13152816ad2164200 yt/utilities/physical_ratios.py
--- a/yt/utilities/physical_ratios.py
+++ b/yt/utilities/physical_ratios.py
@@ -67,6 +67,9 @@
sec_per_min = 60.0
day_per_year = 365.25
+# velocities
+speed_of_light_cm_per_s = 2.99792458e10
+
# temperature / energy
boltzmann_constant_erg_per_K = 1.3806488e-16
erg_per_eV = 1.602176562e-12
@@ -75,6 +78,7 @@
keV_per_K = 1.0 / K_per_keV
keV_per_erg = 1.0 / erg_per_keV
eV_per_erg = 1.0 / erg_per_eV
+kelvin_per_rankine = 5./9.
# Solar System masses
# Standish, E.M. (1995) "Report of the IAU WGAS Sub-Group on Numerical Standards",
Repository URL: https://bitbucket.org/yt_analysis/yt/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
More information about the yt-svn
mailing list