from abc import abstractmethod
import numpy as np
from hexrd.material.utils import calculate_linear_absorption_length
[docs]class AbstractPhysicsPackage:
"""abstract class for the physics package.
there will be two separate physics package class
types -- one for HED samples and the other for
HEDM samples.
Parameters
----------
sample_material : str or hexrd.material.Material
either the formula or a hexrd material instance
sample_density : float
density of sample material in g/cc
sample_thickness : float
sample thickness in microns
sample_geometry : FIXME
FIXME
pinhole_material : str or hexrd.material.Material, optional
either the formula or a hexrd material instance
pinhole_density : float
density of pinhole material in g/cc
pinhole_thickness : float
pinhole thickness in microns
pinhole_diameter : float
pinhole diameter in microns
window_material : str or hexrd.material.Material
either the formula or a hexrd material instance
window_density : float
density of window material in g/cc
window_thickness : float
window thickness in microns
Notes
-----
[1] Rygg et al., X-ray diffraction at the National
Ignition Facility, Rev. Sci. Instrum. 91, 043902 (2020)
[2] M. Stoeckl, A. A. Solodov
Readout models for BaFBr0.85I0.15:Eu image plates
Rev. Sci. Instrum. 89, 063101 (2018
"""
# Abstract methods that must be redefined in derived classes
@property
@abstractmethod
def type(self):
pass
def __init__(self,
sample_material=None,
sample_density=None,
sample_thickness=None,
pinhole_material=None,
pinhole_density=None,
pinhole_thickness=None,
pinhole_diameter=None,
**kwargs
):
self._sample_material = sample_material
self._sample_density = sample_density
self._sample_thickness = sample_thickness
self._pinhole_material = pinhole_material
self._pinhole_density = pinhole_density
self._pinhole_thickness = pinhole_thickness
self._pinhole_diameter = pinhole_diameter
@property
def attributes_to_serialize(self):
return [
'sample_material',
'sample_density',
'sample_thickness',
'pinhole_material',
'pinhole_density',
'pinhole_thickness',
'pinhole_diameter',
]
@property
def sample_material(self):
return self._sample_material
@sample_material.setter
def sample_material(self, material):
self._sample_material = material
@property
def sample_density(self):
if self._sample_density is None:
return 0.0
return self._sample_density
@sample_density.setter
def sample_density(self, density):
self._sample_density = density
@property
def sample_thickness(self):
if self._sample_thickness is None:
return 0.0
return self._sample_thickness
@sample_thickness.setter
def sample_thickness(self, value):
self._sample_thickness = value
@property
def pinhole_material(self):
return self._pinhole_material
@pinhole_material.setter
def pinhole_material(self, material):
self._pinhole_material = material
@property
def pinhole_density(self):
if self._pinhole_density is None:
return 0.0
return self._pinhole_density
@pinhole_density.setter
def pinhole_density(self, density):
self._pinhole_density = density
@property
def pinhole_thickness(self):
if self._pinhole_thickness is None:
return 0.0
return self._pinhole_thickness
@pinhole_thickness.setter
def pinhole_thickness(self, value):
self._pinhole_thickness = value
@property
def pinhole_radius(self):
if self.pinhole_diameter is None:
return 0.0
return 0.5 * self.pinhole_diameter
@pinhole_radius.setter
def pinhole_radius(self, value):
self._pinhole_diameter = 2.0 * value
@property
def pinhole_diameter(self):
if self._pinhole_diameter is None:
return 0.0
return self._pinhole_diameter
@pinhole_diameter.setter
def pinhole_diameter(self, value):
self._pinhole_diameter = value
[docs] def absorption_length(self, energy, flag):
if isinstance(energy, float):
energy_inp = np.array([energy])
elif isinstance(energy, list):
energy_inp = np.array(energy)
elif isinstance(energy, np.ndarray):
energy_inp = energy
if flag.lower() == 'sample':
args = (self.sample_density,
self.sample_material,
energy_inp,
)
elif flag.lower() == 'window':
args = (self.window_density,
self.window_material,
energy_inp,
)
elif flag.lower() == 'pinhole':
args = (self.pinhole_density,
self.pinhole_material,
energy_inp,
)
abs_length = calculate_linear_absorption_length(*args)
if abs_length.shape[0] == 1:
return abs_length[0]
else:
return abs_length
[docs] def sample_absorption_length(self, energy):
return self.absorption_length(energy, 'sample')
[docs] def pinhole_absorption_length(self, energy):
return self.absorption_length(energy, 'pinhole')
[docs] def serialize(self):
return {a: getattr(self, a) for a in self.attributes_to_serialize}
[docs] def deserialize(self, **kwargs):
for key, value in kwargs.items():
setattr(self, key, value)
[docs]class HEDPhysicsPackage(AbstractPhysicsPackage):
def __init__(self, **pp_kwargs):
super().__init__(**pp_kwargs)
self._window_material = pp_kwargs.get('window_material', None)
self._window_density = pp_kwargs.get('window_density', None)
self._window_thickness = pp_kwargs.get('window_thickness', None)
@property
def attributes_to_serialize(self):
return [
'sample_material',
'sample_density',
'sample_thickness',
'pinhole_material',
'pinhole_density',
'pinhole_thickness',
'pinhole_diameter',
'window_material',
'window_density',
'window_thickness',
]
@property
def type(self):
return 'HED'
@property
def window_material(self):
return self._window_material
@window_material.setter
def window_material(self, material):
self._window_material = material
@property
def window_density(self):
if self._window_density is None:
return 0.0
return self._window_density
@window_density.setter
def window_density(self, density):
self._window_density = density
@property
def window_thickness(self):
if self._window_thickness is None:
return 0.0
return self._window_thickness
@window_thickness.setter
def window_thickness(self, thickness):
self._window_thickness = thickness
[docs] def window_absorption_length(self, energy):
return self.absorption_length(energy, 'window')
[docs]class HEDMPhysicsPackage(AbstractPhysicsPackage):
def __init__(self, **pp_kwargs):
super().__init__(**pp_kwargs)
self._sample_geometry = pp_kwargs.get('sample_geometry', None)
@property
def attributes_to_serialize(self):
return [
'sample_material',
'sample_density',
'sample_thickness',
'sample_geometry',
'pinhole_material',
'pinhole_density',
'pinhole_thickness',
'pinhole_diameter',
]
@property
def sample_geometry(self):
return self._sample_geometry
@property
def sample_diameter(self):
if self.sample_geometry == 'cylinder':
return self._sample_thickness
else:
msg = (f'sample geometry does not have diameter '
f'associated with it.')
print(msg)
return
@property
def type(self):
return 'HEDM'