Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Spatial frequency, with spectral equivalence support #38

Merged
merged 5 commits into from
Jul 26, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions docs/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -450,7 +450,8 @@ for the problem you are working on.
The :mod:`unyt` library implements the following equivalencies:

* "thermal": conversions between temperature and energy (:math:`E = k_BT`)
* "spectral": conversions between wavelength, frequency, and energy for photons
* "spectral": conversions between wavelength, spatial frequency, frequency, and
energy for photons
(:math:`E = h\nu = hc/\lambda`, :math:`c = \lambda\nu`)
* "mass_energy": conversions between mass and energy (:math:`E = mc^2`)
* "lorentz": conversions between velocity and Lorentz factor
Expand All @@ -471,7 +472,7 @@ array, use the :meth:`unit_array.list_equivalencies
schwarzschild: mass <-> length
compton: mass <-> length
>>> km.list_equivalencies()
spectral: length <-> frequency <-> energy
spectral: length <-> spatial_frequency <-> frequency <-> energy
schwarzschild: mass <-> length
compton: mass <-> length

Expand Down
2 changes: 1 addition & 1 deletion unyt/array.py
Original file line number Diff line number Diff line change
Expand Up @@ -1022,7 +1022,7 @@ def list_equivalencies(self):
-------
>>> from unyt import km
>>> (1.0*km).list_equivalencies()
spectral: length <-> frequency <-> energy
spectral: length <-> spatial_frequency <-> frequency <-> energy
schwarzschild: mass <-> length
compton: mass <-> length
"""
Expand Down
5 changes: 4 additions & 1 deletion unyt/dimensions.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@
# frequency (alias for rate)
frequency = rate

# spatial frequency
spatial_frequency = 1 / length

#: solid_angle
solid_angle = angle * angle
#: velocity
Expand Down Expand Up @@ -135,7 +138,7 @@
luminous_flux, area, current_cgs, charge_mks, electric_field_mks,
magnetic_field_mks, electric_potential_cgs, electric_potential_mks,
resistance_cgs, resistance_mks, magnetic_flux_mks, magnetic_flux_cgs,
luminance]
luminance, spatial_frequency]


#: a list containing all dimensions
Expand Down
27 changes: 21 additions & 6 deletions unyt/equivalencies.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
density,
number_density,
flux,
spatial_frequency,
)
from unyt.exceptions import InvalidUnitEquivalence

Expand Down Expand Up @@ -182,9 +183,9 @@ def __str__(self):
class SpectralEquivalence(Equivalence):
"""Equivalence between wavelength, frequency, and energy of a photon.

Given a photon with wavelength :math:`\\lambda`, frequency :math:`\\nu`
and Energy :math:`E`, these quantities are related by the following
forumlae:
Given a photon with wavelength :math:`\\lambda`, spatial frequency
:math:`\\bar\\nu`, frequency :math:`\\nu` and Energy :math:`E`,
these quantities are related by the following forumlae:

.. math::

Expand All @@ -195,15 +196,15 @@ class SpectralEquivalence(Equivalence):
Example
------
>>> print(SpectralEquivalence())
spectral: length <-> frequency <-> energy
spectral: length <-> spatial_frequency <-> frequency <-> energy
>>> from unyt import angstrom, km
>>> (3*angstrom).to_equivalent('keV', 'spectral')
unyt_quantity(4.13280644, 'keV')
>>> (1*km).to_equivalent('MHz', 'spectral')
unyt_quantity(0.29979246, 'MHz')
"""
type_name = "spectral"
_dims = (length, rate, energy,)
_dims = (length, rate, energy, spatial_frequency)

def _convert(self, x, new_dims):
from unyt import physical_constants as pc
Expand All @@ -212,19 +213,33 @@ def _convert(self, x, new_dims):
return np.divide(pc.clight*pc.hmks, x, out=self._get_out(x))
elif x.units.dimensions == rate:
return np.multiply(x, pc.hmks, out=self._get_out(x))
elif x.units.dimensions == spatial_frequency:
return np.multiply(x, pc.hmks*pc.clight, out=self._get_out(x))
elif new_dims == length:
if x.units.dimensions == rate:
return np.divide(pc.clight, x, out=self._get_out(x))
elif x.units.dimensions == energy:
return np.divide(pc.hmks*pc.clight, x, out=self._get_out(x))
elif x.units.dimensions == spatial_frequency:
return np.divide(1, x, out=self._get_out(x))
elif new_dims == rate:
if x.units.dimensions == length:
return np.divide(pc.clight, x, out=self._get_out(x))
elif x.units.dimensions == energy:
return np.divide(x, pc.hmks, out=self._get_out(x))
elif x.units.dimensions == spatial_frequency:
return np.multiply(x, pc.clight, out=self._get_out(x))
elif new_dims == spatial_frequency:
if x.units.dimensions == length:
return np.divide(1, x, out=self._get_out(x))
elif x.units.dimensions == energy:
return np.divide(x, pc.clight*pc.hmks, out=self._get_out(x))
elif x.units.dimensions == rate:
return np.divide(x, pc.clight, out=self._get_out(x))

def __str__(self):
return "spectral: length <-> frequency <-> energy"
return ("spectral: length <-> spatial_frequency <-> frequency "
+ "<-> energy")


class SoundSpeedEquivalence(Equivalence):
Expand Down
60 changes: 60 additions & 0 deletions unyt/tests/test_unyt_array.py
Original file line number Diff line number Diff line change
Expand Up @@ -1365,6 +1365,16 @@ def test_equivalencies():
assert lam.units == u.eV.units
assert hnu.units == u.erg.units

# wavelength to spatial frequency

lam = 4000*u.angstrom
nubar = lam.in_units('1/angstrom', 'spectral')
assert_allclose_units(nubar, 1/lam)
lam.convert_to_units('1/cm', 'spectral')
assert_allclose_units(lam, nubar)
assert lam.units == (1 / u.cm).units
assert nubar.units == (1 / u.angstrom).units

# frequency to wavelength

nu = 1*u.MHz
Expand All @@ -1375,6 +1385,16 @@ def test_equivalencies():
assert lam.units == u.km.units
assert nu.units == u.m.units

# frequency to spatial frequency

nu = 1*u.MHz
nubar = nu.to('1/km', 'spectral')
assert_allclose_units(nubar, nu/u.clight)
nu.convert_to_units('1/m', 'spectral')
assert_allclose_units(nubar, nu)
assert nubar.units == (1 / u.km).units
assert nu.units == (1 / u.m).units

# frequency to photon energy

nu = 1*u.MHz
Expand Down Expand Up @@ -1405,6 +1425,46 @@ def test_equivalencies():
assert E.units == u.angstrom.units
assert lam.units == u.nm.units

# photon energy to spatial frequency

E = 13.6*u.eV
nubar = E.to('1/nm', 'spectral')
assert_allclose_units(nubar, E/(u.hmks*u.clight))
E.convert_to_units('1/angstrom', 'spectral')
assert_allclose_units(E, nubar)
assert E.units == (1 / u.angstrom).units
assert nubar.units == (1 / u.nm).units

# spatial frequency to frequency

nubar = 1500. / u.cm
nu = nubar.to('Hz', 'spectral')
assert_allclose_units(nu, nubar*u.clight)
nubar.convert_to_units('MHz', 'spectral')
assert_allclose_units(nu, nubar)
assert nubar.units == u.MHz.units
assert nu.units == u.Hz.units

# spatial frequency to wavelength

nubar = 1500. / u.cm
lam = nubar.to('nm', 'spectral')
assert_allclose_units(lam, 1/nubar)
nubar.convert_to_units('angstrom', 'spectral')
assert_allclose_units(nubar, lam)
assert nubar.units == u.angstrom.units
assert lam.units == u.nm.units

# spatial frequency to photon energy

nubar = 1500. / u.cm
E = nubar.to('erg', 'spectral')
assert_allclose_units(E, u.hmks*u.clight*nubar)
nubar.convert_to_units('J', 'spectral')
assert_allclose_units(nubar, E)
assert nubar.units == u.J.units
assert E.units == u.erg.units

# Sound-speed

# tempearature <-> velocity
Expand Down
2 changes: 1 addition & 1 deletion unyt/unit_object.py
Original file line number Diff line number Diff line change
Expand Up @@ -600,7 +600,7 @@ def list_equivalencies(self):
--------
>>> from unyt import km
>>> km.units.list_equivalencies()
spectral: length <-> frequency <-> energy
spectral: length <-> spatial_frequency <-> frequency <-> energy
schwarzschild: mass <-> length
compton: mass <-> length
"""
Expand Down