Commit ab92b0a0 authored by Matias Guijarro's avatar Matias Guijarro

Merge branch 'energy_tools' into 'master'

extract energy handling functions to physics module. + tests and doc

See merge request !1357
parents 8b3ff773 afbd67fe
Pipeline #11597 failed with stages
in 30 minutes and 12 seconds
......@@ -14,6 +14,9 @@ Bliss controller for 5-motors spectrometer test bench in EH1
from bliss.controllers.motor import CalcController
import math
from bliss.physics import spectroscopy
# GLOBAL VARIABLES #
HC = 1.2398418743309972e-06 # eV * m
ALAT_SI = 5.431065 # Ang at 25C
......@@ -26,17 +29,6 @@ CRYST_ALPHA = 0.0 # miscut angle in degrees
CRYST_R = 1000. # analyser bending radius in mm (=2*Rm)
# UTILITY FUNCTIONS #
def kev2wlen(energy):
""" convert photon energy (E, keV) to wavelength ($\lambda$, \AA$^{-1}$)"""
return (HC / energy) * 1e7
def wlen2kev(wlen):
""" convert photon wavelength ($\lambda$, \AA$^{-1}$) to energy (E, keV)"""
return (HC / wlen) * 1e7
def sqrt1over(d2m):
if d2m == 0:
return 0
......@@ -52,9 +44,11 @@ def d_cubic(a, hkl):
def theta_b(ene, d):
"""Bragg angle (rad) given energy (keV) and d-spacing (\AA)"""
"""Bragg angle (rad) given energy (keV) and d-spacing (Angstroms)"""
if not (d == 0):
return math.asin((kev2wlen(ene)) / (2 * d))
return math.asin(
(spectroscopy.energy_kev_to_wavelength_angstrom(ene)) / (2 * d)
)
else:
print("ERROR: d-spacing is 0")
return
......@@ -62,7 +56,9 @@ def theta_b(ene, d):
def bragg_kev(theta, d):
"""energy (keV) given Bragg angle (deg) and d-spacing (\AA)"""
return wlen2kev(2 * d * math.sin(math.radians(theta)))
return spectroscopy.wavelength_angstrom_to_energy_kev(
2 * d * math.sin(math.radians(theta))
)
def get_dspacing(mat, hkl):
......
......@@ -27,8 +27,9 @@ Author: Mauro Rovezzi (mauro.rovezzi@esrf.eu)
from bliss.controllers.motor import CalcController
import math
from bliss.physics import spectroscopy
# GLOBAL VARIABLES #
HC = 1.2398418743309972e-06 # eV * m
ALAT_SI = 5.431065 # Ang at 25C
ALAT_GE = 5.6579060 # Ang at 25C
......@@ -38,16 +39,6 @@ CRYST_HKL = [4, 4, 4] # analyser crystal reflection [h,k,l]
CRYST_ALPHA = 0.0 # miscut angle in degrees
CRYST_R = 1000. # analyser bending radius in mm (=2*Rm)
# UTILITY FUNCTIONS #
def kev2wlen(energy):
""" convert photon energy (E, keV) to wavelength ($\lambda$, \AA$^{-1}$)"""
return (HC / energy) * 1e7
def wlen2kev(wlen):
""" convert photon wavelength ($\lambda$, \AA$^{-1}$) to energy (E, keV)"""
return (HC / wlen) * 1e7
def sqrt1over(d2m):
if d2m == 0:
......@@ -66,7 +57,9 @@ def d_cubic(a, hkl):
def theta_b(ene, d):
"""Bragg angle (rad) given energy (keV) and d-spacing (\AA)"""
if not (d == 0):
return math.asin((kev2wlen(ene)) / (2 * d))
return math.asin(
(spectroscopy.energy_kev_to_wavelength_angstrom(ene)) / (2 * d)
)
else:
print("ERROR: d-spacing is 0")
return
......@@ -74,7 +67,9 @@ def theta_b(ene, d):
def bragg_kev(theta, d):
"""energy (keV) given Bragg angle (deg) and d-spacing (\AA)"""
return wlen2kev(2 * d * math.sin(math.radians(theta)))
return spectroscopy.wavelength_angstrom_to_energy_kev(
2 * d * math.sin(math.radians(theta))
)
def get_dspacing(mat, hkl):
......
......@@ -50,3 +50,33 @@ def wavevector_to_energy(edge_energy, k):
khbar = k * (1.0 * ur("hbar"))
result = (khbar * khbar) / (2.0 * ur("electron_mass"))
return result + edge_energy
# same kind of functions, but usable is user code:
def energy_kev_to_wavelength_angstrom(ene_kev):
"""
Converts photon energy in keV to wavelength in angstroms
i.e: 1e7 * HC / ene
Parameters:
* <ene_kev>: energy in keV (float)
Returns:
* wavelength in angstroms (float)
"""
energy_kev = ene_kev * ur.eV * 1000
wavelength = ur.c * ur.h / energy_kev
return wavelength.to(ur.angstrom).magnitude
def wavelength_angstrom_to_energy_kev(wl_angstrom):
"""
Converts wavelength in angstroms to photon energy in keV
Parameters:
* <wl_angstrom>: wavelength in angstroms (float)
Returns:
* energy in keV (float)
"""
wavelength_angstrom = wl_angstrom * ur.angstrom
energy_kev = ur.c * ur.h / wavelength_angstrom
return energy_kev.to(ur.eV).magnitude / 1000
......@@ -88,13 +88,16 @@ units which are SI units. Failure to comply will result in unexpected values.
### Example
import bliss.physics.diffraction
from bliss.physics.units import ur
mass = 0.1 * ur.mg
E = mass * ur.c**2
print( E.to(ur.kJ) )
>>> 8987551.78737 kilojoule
Example to convert 0.1 miligram in Kjoules with unknown formula.
```python
import bliss.physics.diffraction
from bliss.physics.units import ur
mass = 0.1 * ur.mg
E = mass * ur.c**2
print( E.to(ur.kJ) )
>>> 8987551.78737 kilojoule
```
## Example of usage
......@@ -103,11 +106,12 @@ units which are SI units. Failure to comply will result in unexpected values.
`mendeleev.elements` usage example:
from mendeleev import elements
Si = elements.Si
print("Atomic number of {} is {}.".format(Si.name, Si.atomic_number))
>>> Atomic number of Silicon is 14.
```python
from mendeleev import elements
Si = elements.Si
print("Atomic number of {} is {}.".format(Si.name, Si.atomic_number))
>>> Atomic number of Silicon is 14.
```
### Crystal
......@@ -187,3 +191,24 @@ plane when the angle is 25.6 degrees:
print( energy.to(ur.keV).magnitude )
>>> 17.5618627264
### spectroscopy
`energy_to_wavevector(edge_energy, energy)`:
`wavevector_to_energy(edge_energy, k)`:
user-friendly functions:
```python
from bliss.physics import spectroscopy
spectroscopy.energy_kev_to_wavelength_angstrom(7.5)
# 1.6531226083801578
spectroscopy.wavelength_angstrom_to_energy_kev(1.653122)
# 7.500002760141831
```
......@@ -17,6 +17,9 @@ from bliss.physics.diffraction import CrystalPlane, MultiPlane
from bliss.physics.diffraction import string_to_crystal_plane
from bliss.physics.diffraction import distance_lattice_diffraction_plane
import bliss.physics.diffraction as diff
import bliss.physics.spectroscopy as spectro
# Patch default 1e-12 default value for abs
approx = partial(approx, rel=1e-3, abs=0.)
......@@ -148,3 +151,11 @@ def test_multi_plane():
assert multi.bragg_angle(b_energy) == approx(b_theta)
assert multi.bragg_energy(b_thetas) == approx(b_energies)
assert multi.bragg_angle(b_energies) == approx(b_thetas)
def test_w2e_e2w():
# 7.5 keV ≈ 1.65 angstrom
assert spectro.energy_kev_to_wavelength_angstrom(7.5) == approx(1.653122)
# 1.653122 angstrom ≈ 7.5 keV
assert spectro.wavelength_angstrom_to_energy_kev(1.653122) == approx(7.5)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment