Source code for neutronbraggedge.lattice_handler.lattice
import numpy as np
import configparser
from ..config import config_file as config_config_file
from ..braggedges_handler.braggedge_calculator import BraggEdgeCalculator
[docs]class Lattice(object):
"""When the Bragg Edges, crystal structure and hkl are known, this class calculates the
lattice parameter
"""
space = 75
material = None
crystal_structure = None
use_local_metadata = True
bragg_edge_array = None
def __init__(self, material=None,
crystal_structure=None,
bragg_edge_array=None,
bragg_edge_error_array=None,
use_local_metadata_table=True):
self.material = material
self._crystal_structure = crystal_structure
self.crystal_structure = crystal_structure #only used to run test
self.use_local_metadata = use_local_metadata_table
self.bragg_edge_array = self._format_array(bragg_edge_array)
self.bragg_edge_error_array = self._format_array(bragg_edge_error_array)
#retrieve hkl
o_bragg_calculator = BraggEdgeCalculator(structure_name = crystal_structure,
lattice = None,
number_of_set = len(bragg_edge_array))
o_bragg_calculator.calculate_hkl()
self.hkl = o_bragg_calculator.hkl
self._calculate()
@property
def crystal_structure(self):
return self._crystal_structure
@crystal_structure.setter
def crystal_structure(self, structure_name):
_config_file = config_config_file
config_obj = configparser.ConfigParser()
config_obj.read(_config_file)
self._list_structure = config_obj['DEFAULT']['list_structure']
if not (structure_name in self._list_structure):
raise ValueError("Structure name should be in the list " , self._list_structure)
self._crystal_structure = structure_name
def _format_array(self, bragg_edge_array):
"""Make sure that None value are replaced by np.NaN"""
_bragg_edge_array_formated = []
if bragg_edge_array is None:
sz = len(self.bragg_edge_array)
_bragg_edge_array_formated = np.zeros((sz))
return _bragg_edge_array_formated
for _value in bragg_edge_array:
if _value is None:
_value = np.NaN
_bragg_edge_array_formated.append(_value)
_bragg_edge_array_formated = np.array(_bragg_edge_array_formated)
return _bragg_edge_array_formated
def _calculate(self):
"""calculate the lattice parameters step by step"""
self._match_bragg_edge_with_hkl()
self._calculate_lattice_array()
self._calculate_lattice_statistics()
def _match_bragg_edge_with_hkl(self):
"""Match each bragg edge with its equivalent hkl"""
_bragg_edge_array = self.bragg_edge_array
_bragg_edge_array_error = self.bragg_edge_error_array
zipped = zip(self.hkl, _bragg_edge_array, _bragg_edge_array_error)
self.hkl_bragg_edge = list(zipped)
[docs] def display_hkl_bragg_edge(self):
"""Display the hkl_bragg_edge list using pretty table form"""
print("hkl Bragg Edge Table")
print("=" * self.space)
print("hkl \t\t Bragg Edge Value\t Bragg Edge Error \t Lattice")
print("-" * self.space)
_lattice_array = self.lattice_array
for _index, _row in enumerate(self.hkl_bragg_edge):
_key = _row[0]
_value = _row[1]
_error = _row[2]
_lattice = _lattice_array[_index]
if np.isnan(_error):
print("%r\t %.5f \t\t\t %.5f \t\t\t %.5f" %(_key, _value, _error, _lattice))
else:
print("%r\t %.5f \t\t %.5f \t\t %.5f" %(_key, _value, _error, _lattice))
print("-" * self.space)
print()
return True
def _calculate_lattice_array(self):
"""Calculate the array of lattice parameters"""
_hkl_bragg_edge = self.hkl_bragg_edge
_lattice_array = []
_lattice_error_array = []
for _row in _hkl_bragg_edge:
_hkl = _row[0]
_bragg_edge = _row[1]
_bragg_error = _row[2]
[_lattice, _lattice_error] = self._calculate_lattice_coefficient(hkl = _hkl,
bragg_edge = _bragg_edge,
bragg_error = _bragg_error)
_lattice_array.append(_lattice)
_lattice_error_array.append(_lattice_error)
self.lattice_array = _lattice_array
self.lattice_error = _lattice_error_array
def _calculate_lattice_coefficient(self, hkl=None, bragg_edge=None, bragg_error=None):
"""Calculate the lattice coefficient for the given set of hkl and bragg edge"""
_h, _k, _l = hkl
_term1 = np.sqrt(_h**2 + _k**2 + _l**2)
_term2 = bragg_edge/2.
_lattice = _term2 * _term1
_lattice_error = _term1 * bragg_error / 2.
return [_lattice, _lattice_error]
def _calculate_lattice_statistics(self):
"""Calculate the statistics of the lattice array
- median
- average
- mean
- std (standard deviation)
- min
- max
"""
_lattice_statistics = {}
#min
_min = np.nanmin(self.lattice_array)
_lattice_statistics['min'] = _min
#max
_max = np.nanmax(self.lattice_array)
_lattice_statistics['max'] = _max
#median
_median = np.nanmedian(self.lattice_array)
_lattice_statistics['median'] = _median
#mean
_mean = np.nanmean(self.lattice_array)
_error = self._calculate_mean_error(self.lattice_error)
_lattice_statistics['mean'] = [_mean, _error]
#std
_std = np.nanstd(self.lattice_array)
_lattice_statistics['std'] = _std
self.lattice_statistics = _lattice_statistics
def _calculate_mean_error(self, lattice_error):
_mean_error = 0
_index = 0
_sum = 0
for _error in lattice_error:
if not np.isnan(_error):
_step1 = _error * _error
_sum += _step1
_index += 1
_mean_error = np.sqrt(_sum)/ _index
return _mean_error
[docs] def display_lattice_statistics(self):
"""Display the lattice statistics using a pretty table form"""
_lattice_statistics = self.lattice_statistics
print("Lattice Statistics")
print("=" * self.space)
print("min: %.5f" %_lattice_statistics['min'])
print("max: %.5f" %_lattice_statistics['max'])
print("median: %.5f" %_lattice_statistics['median'])
print("mean: %.5f +/- %.5f" %(_lattice_statistics['mean'][0], _lattice_statistics['mean'][1]))
print("std: %.5f" %_lattice_statistics['std'])
print("-" * self.space)
print("")
[docs] def display_recap(self):
"""Display a summary of input and outputs"""
print(" -- Recap --")
print("=" * self.space)
print("Material: %r" %self.material)
print("Crystal Structure: %r" %self._crystal_structure)
print("-" * self.space)
print("")
self.display_hkl_bragg_edge()
self.display_lattice_statistics()