Newer
Older
#pylint: disable=no-init,invalid-name
from mantid.simpleapi import *
from mantid.api import *
from mantid.kernel import *
import math
import numpy as np
class CalculateSampleTransmission(PythonAlgorithm):
_bin_params = None
_chemical_formula = None
_density = None
_thickness = None
_output_ws = None
def category(self):
return 'Sample'
def summary(self):
return 'Calculates the scattering & transmission for a given sample material and size over a given wavelength range.'
def PyInit(self):
self.declareProperty(name='WavelengthRange', defaultValue='',
validator=StringMandatoryValidator(),
doc='Wavelength range to calculate transmission for.')
self.declareProperty(name='ChemicalFormula', defaultValue='',
validator=StringMandatoryValidator(),
doc='Sample chemical formula')
self.declareProperty(name='NumberDensity', defaultValue=0.1,
doc='Number denisty per atom (atoms/Angstrom^3). Default=0.1')
self.declareProperty(name='Thickness', defaultValue=0.1,
doc='Sample thickness (cm). Default=0.1')
self.declareProperty(MatrixWorkspaceProperty('OutputWorkspace', '', Direction.Output),
doc='Outputs the sample transmission over the wavelength range as a function of wavelength.')
def validateInputs(self):
issues = dict()
density = self.getProperty('NumberDensity').value
issues['NumberDensity'] = 'NumberDensity must be positive'
thickness = self.getProperty('Thickness').value
issues['Thickness'] = 'Thickness must be positive'
return issues
def PyExec(self):
self._setup()
# Create the workspace and set the sample material
CreateWorkspace(OutputWorkspace=self._output_ws, NSpec=2, DataX=[0, 0], DataY=[0, 0],
VerticalAxisUnit='Text', VerticalAxisValues='Transmission,Scattering')
Rebin(InputWorkspace=self._output_ws, OutputWorkspace=self._output_ws,
Params=self._bin_params)
SetSampleMaterial(InputWorkspace=self._output_ws, ChemicalFormula=self._chemical_formula, SampleNumberDensity=self._density)
ConvertToPointData(InputWorkspace=self._output_ws, OutputWorkspace=self._output_ws)
ws = mtd[self._output_ws]
wavelengths = ws.readX(0)
transmission_data = np.zeros(len(wavelengths))
scattering_data = np.zeros(len(wavelengths))
# Calculate transmission and scattering for each wavelength point
for idx in range(0, len(wavelengths)):
transmission, scattering = self._calculate_at_wavelength(wavelengths[idx])
transmission_data[idx] = transmission
scattering_data[idx] = scattering
ws.setY(0, transmission_data)
ws.setY(1, scattering_data)
self.setProperty('OutputWorkspace', self._output_ws)
def _setup(self):
"""
Gets algorithm properties.
"""
self._bin_params = self.getPropertyValue('WavelengthRange')
self._chemical_formula = self.getPropertyValue('ChemicalFormula')
self._density = self.getProperty('NumberDensity').value
self._thickness = self.getProperty('Thickness').value
self._output_ws = self.getPropertyValue('OutputWorkspace')
def _calculate_at_wavelength(self, wavelength):
"""
Calculates transmission and scattering at a given wavelength.
@param wavelength Wavelength at which to calculate (in Angstrom)
@return Tuple of transmission and scattering percentages
"""
material = mtd[self._output_ws].mutableSample().getMaterial()
absorption_x_section = material.absorbXSection() * wavelength
total_x_section = absorption_x_section + material.totalScatterXSection()
transmission = math.exp(-self._density * total_x_section * self._thickness)
scattering = 1.0 - math.exp(-self._density * material.totalScatterXSection() * self._thickness)
return transmission, scattering
# Register algorithm with Mantid
AlgorithmFactory.subscribe(CalculateSampleTransmission)