Units¶
This package provides unit conversion tools
In [1]:
Copied!
# Useful for debugging
%load_ext autoreload
%autoreload 2
# Useful for debugging
%load_ext autoreload
%autoreload 2
In [2]:
Copied!
from pmd_beamphysics import particle_paths
from pmd_beamphysics.units import dimension_name, sqrt_unit, known_unit
from h5py import File
from pmd_beamphysics import particle_paths
from pmd_beamphysics.units import dimension_name, sqrt_unit, known_unit
from h5py import File
This is the basic class:
In [3]:
Copied!
?pmd_unit
?pmd_unit
Object `pmd_unit` not found.
Get a known units. These can be multiplied and divided:
In [4]:
Copied!
u1 = known_unit["J"]
u2 = known_unit["m"]
u1, u2, u1 / u2, u1 * u2
u1 = known_unit["J"]
u2 = known_unit["m"]
u1, u2, u1 / u2, u1 * u2
Out[4]:
(pmd_unit('J', 1, (2, 1, -2, 0, 0, 0, 0)), pmd_unit('m', 1, (1, 0, 0, 0, 0, 0, 0)), pmd_unit('J/m', 1.0, (1, 1, -2, 0, 0, 0, 0)), pmd_unit('J*m', 1, (3, 1, -2, 0, 0, 0, 0)))
Special function for sqrt:
In [5]:
Copied!
sqrt_unit(u1)
sqrt_unit(u1)
Out[5]:
pmd_unit('\sqrt{ J }', 1.0, (1.0, 0.5, -1.0, 0.0, 0.0, 0.0, 0.0))
openPMD HDF5 units¶
Open a file, find the particle paths from the root attributes
In [6]:
Copied!
# Pick one:
# H5FILE = 'data/bmad_particles.h5'
H5FILE = "data/distgen_particles.h5"
# H5FILE = 'data/astra_particles.h5'
h5 = File(H5FILE, "r")
ppaths = particle_paths(h5)
print(ppaths)
# Pick one:
# H5FILE = 'data/bmad_particles.h5'
H5FILE = "data/distgen_particles.h5"
# H5FILE = 'data/astra_particles.h5'
h5 = File(H5FILE, "r")
ppaths = particle_paths(h5)
print(ppaths)
['//']
This points to a single particle group:
In [7]:
Copied!
ph5 = h5[ppaths[0]]
list(ph5)
ph5 = h5[ppaths[0]]
list(ph5)
Out[7]:
['momentum', 'particleStatus', 'position', 'time', 'weight']
Each component should have a dimension and a conversion factor to SI:
In [8]:
Copied!
d = dict(ph5["momentum/x"].attrs)
d
d = dict(ph5["momentum/x"].attrs)
d
Out[8]:
{'unitDimension': array([ 1, 1, -1, 0, 0, 0, 0]), 'unitSI': np.float64(5.344285992678308e-28), 'unitSymbol': 'eV/c'}
In [9]:
Copied!
tuple(d["unitDimension"])
tuple(d["unitDimension"])
Out[9]:
(np.int64(1), np.int64(1), np.int64(-1), np.int64(0), np.int64(0), np.int64(0), np.int64(0))
This will extract the name of this dimension:
In [10]:
Copied!
dimension_name(d["unitDimension"])
dimension_name(d["unitDimension"])
Out[10]:
'momentum'
Nice arrays¶
In [11]:
Copied!
from pmd_beamphysics.units import nice_array
from pmd_beamphysics.units import nice_array
This will scale the array, and return the appropriate SI prefix:
In [12]:
Copied!
x = 1e-4
unit = "m"
nice_array(x)
x = 1e-4
unit = "m"
nice_array(x)
Out[12]:
(np.float64(100.00000000000001), np.float64(1e-06), 'µ')
In [13]:
Copied!
nice_array([-0.01, 0.01])
nice_array([-0.01, 0.01])
Out[13]:
(array([-10., 10.]), np.float64(0.001), 'm')
In [14]:
Copied!
from pmd_beamphysics.units import nice_scale_prefix
from pmd_beamphysics.units import nice_scale_prefix
In [15]:
Copied!
nice_scale_prefix(0.009)
nice_scale_prefix(0.009)
Out[15]:
(np.float64(0.001), 'm')
Limitations¶
This is a simple class for use with this package. So even simple things like the example below will fail.
For more advanced units, use a package like Pint: https://pint.readthedocs.io/
In [16]:
Copied!
try:
u1 / 1
except AttributeError:
print("you cannot do this")
try:
u1 / 1
except AttributeError:
print("you cannot do this")
you cannot do this