Unit Conversions#
In this tutorial we give an example of how to deal with magnetic units in python. Including converting between CGS and SI units.
To do this, we use mammos_units
which is built on top of astropy.units, a package aimed at the astrophysics community for its unit converting functionality.
[15]:
import mammos_units as u
In mammos_units
we use astropy.units.Quantity: the combination of a value and a unit. The most convenient way to create a Quantity is to multiply or divide a value by one of the built-in units. It works with scalars, sequences, and numpy
arrays.
[16]:
length = 1 * u.meter
length
[16]:
A quantity is composed of a value and a unit
[17]:
print(length.value)
print(length.unit)
1.0
m
Most units in mammos_units
support adding prefix to the unit e.g. k for kilo.
[18]:
length = 1 * u.km
length
[18]:
You can perform operations on quantities. Units remain and combine through the set of operations.
[19]:
time = 2 * u.s
velocity = length / time
velocity
[19]:
It is simple to convert between CGS and SI units by using the .cgs
and .si
properties.
[20]:
velocity.si
[20]:
[21]:
velocity.cgs
[21]:
It is also possible to specify explicitly which units you wish to convert to.
[22]:
velocity.to(u.um / u.Gs) # micrometer per gigasecond
[22]:
As mammos_units
also work with numpy
arrays.
[23]:
import numpy as np
a = np.array([1, 2, 3]) * u.m
b = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) * u.cm
display(a)
display(b)
They keep the units even through complex operations.
[24]:
out = np.matmul(b, a)
out.si
[24]:
Magnetic units#
Here we show how to use magnetic units with astropy. Often in the magnetism community, a mix of CGS and SI units are used. Here, we show a convenient way of converting between the two.
Quantity Symbol |
SI Units |
cgs Units |
---|---|---|
Length \((x)\) |
\(10^{-2} \, \text{m}\) |
\(1 \, \text{cm}\) |
Mass \((m)\) |
\(10^{-3} \, \text{kg}\) |
\(1 \, \text{g}\) |
Force \((F)\) |
\(10^{-5} \, \text{N}\) |
\(1 \, \text{dyne}\) |
Energy \((E)\) |
\(10^{-7} \, \text{J}\) |
\(1 \, \text{erg}\) |
Magnetic Induction \((B)\) |
\(10^{-4} \, \text{T}\) |
\(1 \, \text{G}\) |
Magnetic Field Strength \((H)\) |
\(\frac{10^{-4}}{\mu_0} \, \text{Am}^{-1}\) |
\(1 \, \text{Oe}\) |
Magnetic Moment \((\mu)\) |
\(10^{-3} \, \text{JT}^{-1}\) or \(\text{Am}^2\) |
\(1 \, \text{erg G}^{-1}\) or emu |
Magnetization \((M)\) |
\(10^3 \, \text{Am}^{-1}\) or \(\text{JT}^{-1} \, \text{m}^{-3}\) |
\(1 \, \text{Oe}\) or emu cm \(^{-3}\) |
Magnetic Susceptibility \((\chi)\) |
\(4\pi\) (dimensionless) |
\(1 \, \text{emu cm}^{-3} \, \text{Oe}^{-1}\) |
Molar Susceptibility \((\chi_m)\) |
\(4\pi \times 10^{-6} \, \text{m}^3 \, \text{mol}^{-1}\) |
\(1 \, \text{emu mol}^{-1} \, \text{Oe}^{-1}\) |
Mass Susceptibility \((\chi_g)\) |
\(4\pi \times 10^{-3} \, \text{m}^3 \, \text{kg}^{-1}\) |
\(1 \, \text{emu g}^{-1} \, \text{Oe}^{-1}\) |
Magnetic Flux \((\phi)\) |
\(10^{-8} \, \text{Tm}^2\) or \(\text{Wb}\) |
\(1 \, \text{G cm}^2\) or \(\text{Mx}\) |
Demagnetization Factor (N) |
\(0 < N < 1\) |
\(0 < N < 4\pi\) |
[25]:
# Initialize quantities in cgs units
length = 1 * u.cm
mass = 1 * u.g
force = 1 * u.dyn
energy = 1 * u.erg
magnetic_induction = 1 * u.G
magnetic_field_strength = 1 * u.Oe
magnetic_moment = 1 * u.erg * u.G**-1
magnetization = 1 * u.Oe
magnetic_flux = 1 * u.Mx
# Print the results in a table format using conversions in the f-string
print("| Quantity | cgs Unit | Converted SI Unit")
print("|------------------------|----------------|--------------------")
print(f"| Length | 1 cm | {length.to(u.m):.2g}")
print(f"| Mass | 1 g | {mass.to(u.kg):.2g}")
print(f"| Force | 1 dyne | {force.to(u.N):.2g}")
print(f"| Energy | 1 erg | {energy.to(u.J):.2g}")
print(f"| Magnetic Induction | 1 G | {magnetic_induction.to(u.T):.2g}")
print(f"| Magnetic Field Strength| 1 Oe | {magnetic_field_strength.to(u.A / u.m):.2g}")
print(f"| Magnetic Moment | 1 erg G^-1 | {magnetic_moment.to(u.J * u.T**-1):.2g}")
print(f"| Magnetization | 1 emu cm^-3 | {magnetization.to(u.A / u.m):.2g}")
print(f"| Magnetic Flux | 1 Mx | {magnetic_flux.to(u.Wb):.2g}")
| Quantity | cgs Unit | Converted SI Unit
|------------------------|----------------|--------------------
| Length | 1 cm | 0.01 m
| Mass | 1 g | 0.001 kg
| Force | 1 dyne | 1e-05 N
| Energy | 1 erg | 1e-07 J
| Magnetic Induction | 1 G | 0.0001 T
| Magnetic Field Strength| 1 Oe | 80 A / m
| Magnetic Moment | 1 erg G^-1 | 0.001 J / T
| Magnetization | 1 emu cm^-3 | 80 A / m
| Magnetic Flux | 1 Mx | 1e-08 Wb
There are multiple aliases for certain units.
[26]:
u.G == u.Gauss == u.gauss
[26]:
True
Here is a list of all Astropy units. mammos_units
defines some additional magnetic units as documented here.
Equivalency#
The mammos_units
also enables conversions of units with different equivalencies, e.g. temperature and energy. To use this we can create a variable with the relevant units of temperature and use the to
function to convert to the relevant units with the relevant equivalency.
For example, we can convert the exchange interaction energy given in Kelvin to Joules. Because Kelvin and Joule cannot be decomposed into the same base SI units, we have to use the equivalencies
argument.
[27]:
exchange = 4.15 * u.K
exchange.to(u.J, equivalencies=u.temperature_energy())
[27]:
We can also do this with magnetic units such as converting magnetic field between magnetic field strength \((\mathbf{H})\) and magnetic flux density \((\mathbf{B})\) using the relationship:
Where:
\(\mu_0\) is the vacuum permeability, a physical constant,
\(\mu_r\) is the relative permeability of the medium, a dimensionless quantity.
Without this conversion we can see that these two quantities cannot be converted between each other.
[28]:
H = 1 * u.Oe
H.to(u.G)
---------------------------------------------------------------------------
UnitConversionError Traceback (most recent call last)
Cell In[28], line 2
1 H = 1 * u.Oe
----> 2 H.to(u.G)
File /srv/conda/envs/notebook/lib/python3.12/site-packages/astropy/units/quantity.py:931, in Quantity.to(self, unit, equivalencies, copy)
927 unit = Unit(unit)
928 if copy:
929 # Avoid using to_value to ensure that we make a copy. We also
930 # don't want to slow down this method (esp. the scalar case).
--> 931 value = self._to_value(unit, equivalencies)
932 else:
933 # to_value only copies if necessary
934 value = self.to_value(unit, equivalencies)
File /srv/conda/envs/notebook/lib/python3.12/site-packages/astropy/units/quantity.py:884, in Quantity._to_value(self, unit, equivalencies)
881 equivalencies = self._equivalencies
882 if not self.dtype.names or isinstance(self.unit, StructuredUnit):
883 # Standard path, let unit to do work.
--> 884 return self.unit.to(
885 unit, self.view(np.ndarray), equivalencies=equivalencies
886 )
888 else:
889 # The .to() method of a simple unit cannot convert a structured
890 # dtype, so we work around it, by recursing.
891 # TODO: deprecate this?
892 # Convert simple to Structured on initialization?
893 result = np.empty_like(self.view(np.ndarray))
File /srv/conda/envs/notebook/lib/python3.12/site-packages/astropy/units/core.py:1208, in UnitBase.to(self, other, value, equivalencies)
1206 return UNITY
1207 else:
-> 1208 return self.get_converter(Unit(other), equivalencies)(value)
File /srv/conda/envs/notebook/lib/python3.12/site-packages/astropy/units/core.py:1137, in UnitBase.get_converter(self, other, equivalencies)
1134 else:
1135 return lambda v: b(converter(v))
-> 1137 raise exc
File /srv/conda/envs/notebook/lib/python3.12/site-packages/astropy/units/core.py:1120, in UnitBase.get_converter(self, other, equivalencies)
1118 # if that doesn't work, maybe we can do it with equivalencies?
1119 try:
-> 1120 return self._apply_equivalencies(
1121 self, other, self._normalize_equivalencies(equivalencies)
1122 )
1123 except UnitsError as exc:
1124 # Last hope: maybe other knows how to do it?
1125 # We assume the equivalencies have the unit itself as first item.
1126 # TODO: maybe better for other to have a `_back_converter` method?
1127 if hasattr(other, "equivalencies"):
File /srv/conda/envs/notebook/lib/python3.12/site-packages/astropy/units/core.py:1071, in UnitBase._apply_equivalencies(self, unit, other, equivalencies)
1068 unit_str = get_err_str(unit)
1069 other_str = get_err_str(other)
-> 1071 raise UnitConversionError(f"{unit_str} and {other_str} are not convertible")
UnitConversionError: 'Oe' (magnetic field strength) and 'G' (magnetic flux density) are not convertible
However, we can introduce the magnetic_flux_field
equivalency to solve this issue.
[29]:
H.to(u.G, equivalencies=u.magnetic_flux_field())
[29]:
By default, it is calculated for free space i.e. a vacuum with \(\mu_r=1\). However, the magnetic_flux_field also accepts the relative permeability of the medium as an argument for the conversion.
[30]:
H.to(u.G, equivalencies=u.magnetic_flux_field(mu_r=0.9))
[30]:
If we are doing multiple conversions then it may be worth enabling this equivalency for a set of lines as shown below. This will only turn on the equivalency for things within the with
block.
[31]:
with u.set_enabled_equivalencies(u.magnetic_flux_field(mu_r=0.9)):
B = H.to(u.G)
display(B)
If you wish to turn on the equivalency for all of your document then you can run the following command. We recommend doing this straight after you import mammos_units
e.g.
[34]:
u.set_enabled_equivalencies(u.magnetic_flux_field())
[34]:
<astropy.units.core._UnitContext at 0x70296114a3f0>
[35]:
H.to(u.G)
[35]:
We can now convert between SI and CGS using the equivalency.
[36]:
display(H)
display(H.to(u.G))
display(H.to(u.T))
display(H.to(u.A / u.m))
Equivalencies can also be used to convert other common units in magnetism.
The magnetic moment can be converted to magnetic induction by providing the volume of the respective counting unit.
In the case of formula unit
[37]:
magnetic_moment = 8 * u.mu_B / u.f_u
vol_per_fu = (5 * u.Angstrom) ** 3
magnetic_moment.to(u.T, equivalencies=u.moment_induction(vol_per_fu))
[37]:
[38]:
magnetic_induction = 1 * u.T
magnetic_induction.to(u.mu_B / u.f_u, equivalencies=u.moment_induction(vol_per_fu))
[38]:
[39]:
magnetic_moment = 2 * u.mu_B / u.atom
vol_per_atom = (3 * u.Angstrom) ** 3
magnetic_moment.to(u.T, equivalencies=u.moment_induction(vol_per_atom))
[39]:
[40]:
magnetic_induction = 1 * u.T
magnetic_induction.to(u.mu_B / u.atom, equivalencies=u.moment_induction(vol_per_atom))
[40]:
We can also convert using other forms of induction.
[42]:
magnetic_induction = 10000 * u.G
magnetic_induction.to(u.mu_B / u.atom, equivalencies=u.moment_induction(vol_per_atom))
[42]:
However, we cannot use multiple equivalencies at once and need to chain them.
[43]:
magnetic_field_strength = 10000 * u.Oe
magnetic_field_strength.to(u.T, equivalencies=u.magnetic_flux_field()).to(
u.mu_B / u.atom, equivalencies=u.moment_induction(vol_per_atom)
)
[43]:
A comment on emu#
emu is not a unit in the conventional manner and can have many different meanings depending on context.
Within magnetism emu can represent the magnetic moment
However, it can sometimes have dimensions
such as representing emu in magnetic susceptibility if defined as (emu cm \(^{-3}\)).