Skip to content
Snippets Groups Projects
CalculateSampleTransmission.py 4.27 KiB
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):
Dan Nixon's avatar
Dan Nixon committed
        self.declareProperty(name='WavelengthRange', defaultValue='',
                             validator=StringMandatoryValidator(),
                             doc='Wavelength range to calculate transmission for.')

Dan Nixon's avatar
Dan Nixon committed
        self.declareProperty(name='ChemicalFormula', defaultValue='',
                             validator=StringMandatoryValidator(),
                             doc='Sample chemical formula')

        self.declareProperty(name='NumberDensity', defaultValue=0.1,
Dan Nixon's avatar
Dan Nixon committed
                             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.')


Dan Nixon's avatar
Dan Nixon committed
    def validateInputs(self):
        issues = dict()

        density = self.getProperty('NumberDensity').value
        if density < 0.0:
Dan Nixon's avatar
Dan Nixon committed
            issues['NumberDensity'] = 'NumberDensity must be positive'

        thickness = self.getProperty('Thickness').value
        if thickness < 0.0:
Dan Nixon's avatar
Dan Nixon committed
            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)
Dan Nixon's avatar
Dan Nixon committed
        @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)