/
CalculateSampleTransmission.py
119 lines (82 loc) · 4.27 KB
/
CalculateSampleTransmission.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#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
if density < 0.0:
issues['NumberDensity'] = 'NumberDensity must be positive'
thickness = self.getProperty('Thickness').value
if thickness < 0.0:
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)