Ticket #11413: IndirectAnnulusAbsorption.py

File IndirectAnnulusAbsorption.py, 11.5 KB (added by Dan Nixon, 6 years ago)
Line 
1from mantid.simpleapi import *
2from mantid.api import DataProcessorAlgorithm, AlgorithmFactory, MatrixWorkspaceProperty, PropertyMode
3from mantid.kernel import StringMandatoryValidator, Direction, logger
4
5
6class IndirectAnnulusAbsorption(DataProcessorAlgorithm):
7
8    def category(self):
9        return "Workflow\\Inelastic;PythonAlgorithms;CorrectionFunctions\\AbsorptionCorrections;Workflow\\MIDAS"
10
11
12    def summary(self):
13        return "Calculates indirect absorption corrections for an annulus sample shape."
14
15
16    def PyInit(self):
17        self.declareProperty(MatrixWorkspaceProperty('SampleWorkspace', '', direction=Direction.Input),
18                             doc='Sample workspace.')
19
20        self.declareProperty(name='SampleChemicalFormula', defaultValue='', validator=StringMandatoryValidator(),
21                             doc='Chemical formula for the sample')
22        self.declareProperty(name='SampleNumberDensity', defaultValue=0.1, doc='Sample number density')
23        self.declareProperty(name='SampleInnerRadius', defaultValue=0.0, doc='Sample radius')
24        self.declareProperty(name='SampleOuterRadius', defaultValue=0.0, doc='Sample radius')
25
26        self.declareProperty(MatrixWorkspaceProperty('CanWorkspace', '', optional=PropertyMode.Optional,
27                                                     direction=Direction.Input),
28                             doc='Container workspace.')
29        self.declareProperty(name='UseCanCorrections', defaultValue=False, doc='Use can corrections in subtraction')
30        self.declareProperty(name='CanChemicalFormula', defaultValue='', validator=StringMandatoryValidator(),
31                             doc='Chemical formula for the can')
32        self.declareProperty(name='CanNumberDensity', defaultValue=0.1, doc='Can number density')
33        self.declareProperty(name='CanInnerRadius', defaultValue=0.0, doc='Sample radius')
34        self.declareProperty(name='CanOuterRadius', defaultValue=0.0, doc='Sample radius')
35        self.declareProperty(name='CanScaleFactor', defaultValue=1.0, doc='Scale factor to multiply can data')
36
37        self.declareProperty(name='Events', defaultValue=5000, doc='Number of neutron events')
38        self.declareProperty(name='Plot', defaultValue=False, doc='Plot options')
39
40        self.declareProperty(MatrixWorkspaceProperty('OutputWorkspace', '', direction=Direction.Output),
41                             doc='The output corrected workspace.')
42
43        self.declareProperty(MatrixWorkspaceProperty('CorrectionsWorkspace', '', direction=Direction.Output,
44                                                     optional=PropertyMode.Optional),
45                             doc='The corrections workspace for scattering and absorptions in sample.')
46
47
48    def PyExec(self):
49        from IndirectCommon import getEfixed, addSampleLogs
50
51        self._setup()
52
53        efixed = getEfixed(self._sample_ws_name)
54
55        sample_wave_ws = '__sam_wave'
56        ConvertUnits(InputWorkspace=self._sample_ws_name, OutputWorkspace=sample_wave_ws,
57                     Target='Wavelength', EMode='Indirect', EFixed=efixed)
58
59        sample_thickness = self._sample_outer_radius - self._sample_inner_radius
60        logger.information('Sample thickness: ' + str(sample_thickness))
61
62        AnnularRingAbsorption(InputWorkspace=sample_wave_ws,
63                              OutputWorkspace=self._ass_ws,
64                              SampleHeight=3.0,
65                              SampleThickness=sample_thickness,
66                              CanInnerRadius=self._can_inner_radius,
67                              CanOuterRadius=self._can_outer_radius,
68                              SampleChemicalFormula=self._sample_chemical_formula,
69                              SampleNumberDensity=self._sample_number_density,
70                              NumberOfWavelengthPoints=10,
71                              EventsPerPoint=self._events)
72
73        plot_data = [self._output_ws, self._sample_ws_name]
74        plot_corr = [self._ass_ws]
75        group = self._ass_ws
76
77        if self._can_ws_name is not None:
78            can1_wave_ws = '__can1_wave'
79            can2_wave_ws = '__can2_wave'
80            ConvertUnits(InputWorkspace=self._can_ws_name, OutputWorkspace=can1_wave_ws,
81                         Target='Wavelength', EMode='Indirect', EFixed=efixed)
82            if self._can_scale != 1.0:
83                logger.information('Scaling can by: ' + str(self._can_scale))
84                Scale(InputWorkspace=can1_wave_ws, OutputWorkspace=can1_wave_ws, Factor=self._can_scale, Operation='Multiply')
85            CloneWorkspace(InputWorkspace=can1_wave_ws, OutputWorkspace=can2_wave_ws)
86
87            can_thickness1 = self._sample_inner_radius - self._can_inner_radius
88            can_thickness2 = self._can_outer_radius - self._sample_outer_radius
89            logger.information('Can thickness: ' + str(can_thickness1) + ' & ' + str(can_thickness2))
90
91            if self._use_can_corrections:
92                Divide(LHSWorkspace=sample_wave_ws, RHSWorkspace=self._ass_ws, OutputWorkspace=sample_wave_ws)
93
94                SetSampleMaterial(can1_wave_ws, ChemicalFormula=self._can_chemical_formula, SampleNumberDensity=self._can_number_density)
95                AnnularRingAbsorption(InputWorkspace=can1_wave_ws,
96                              OutputWorkspace='__Acc1',
97                              SampleHeight=3.0,
98                              SampleThickness=can_thickness1,
99                              CanInnerRadius=self._can_inner_radius,
100                              CanOuterRadius=self._sample_outer_radius,
101                              SampleChemicalFormula=self._can_chemical_formula,
102                              SampleNumberDensity=self._can_number_density,
103                              NumberOfWavelengthPoints=10,
104                              EventsPerPoint=self._events)
105                SetSampleMaterial(can2_wave_ws, ChemicalFormula=self._can_chemical_formula, SampleNumberDensity=self._can_number_density)
106                AnnularRingAbsorption(InputWorkspace=can2_wave_ws,
107                              OutputWorkspace='__Acc2',
108                              SampleHeight=3.0,
109                              SampleThickness=can_thickness2,
110                              CanInnerRadius=self._sample_inner_radius,
111                              CanOuterRadius=self._can_outer_radius,
112                              SampleChemicalFormula=self._can_chemical_formula,
113                              SampleNumberDensity=self._can_number_density,
114                              NumberOfWavelengthPoints=10,
115                              EventsPerPoint=self._events)
116                Multiply(LHSWorkspace='__Acc1', RHSWorkspace='__Acc2', OutputWorkspace=self._acc_ws)
117                Divide(LHSWorkspace=can1_wave_ws, RHSWorkspace=self._acc_ws, OutputWorkspace=can1_wave_ws)
118                Minus(LHSWorkspace=sample_wave_ws, RHSWorkspace=can1_wave_ws, OutputWorkspace=sample_wave_ws)
119                plot_corr.append(self._acc_ws)
120                group += ',' + self._acc_ws
121
122            else:
123                Minus(LHSWorkspace=sample_wave_ws, RHSWorkspace=can1_wave_ws, OutputWorkspace=sample_wave_ws)
124                Divide(LHSWorkspace=sample_wave_ws, RHSWorkspace=self._ass_ws, OutputWorkspace=sample_wave_ws)
125
126                DeleteWorkspace(can1_wave_ws)
127                DeleteWorkspace(can2_wave_ws)
128                plot_data.append(self._can_ws_name)
129
130        else:
131            Divide(LHSWorkspace=sample_wave_ws, RHSWorkspace=self._ass_ws, OutputWorkspace=sample_wave_ws)
132
133        ConvertUnits(InputWorkspace=sample_wave_ws, OutputWorkspace=self._output_ws, Target='DeltaE',
134                     EMode='Indirect', EFixed=efixed)
135        DeleteWorkspace(sample_wave_ws)
136
137        sample_logs = {'sample_shape': 'annulus',
138                       'sample_filename': self._sample_ws_name,
139                       'sample_inner': self._sample_inner_radius,
140                       'sample_outer': self._sample_outer_radius,
141                       'can_inner': self._can_inner_radius,
142                       'can_outer': self._can_outer_radius}
143        addSampleLogs(self._ass_ws, sample_logs)
144        addSampleLogs(self._output_ws, sample_logs)
145
146        if self._can_ws_name is not None:
147            AddSampleLog(Workspace=self._output_ws, LogName='can_filename', LogType='String', LogText=str(self._can_ws_name))
148            AddSampleLog(Workspace=self._output_ws, LogName='can_scale', LogType='String', LogText=str(self._can_scale))
149            if self._use_can_corrections:
150                addSampleLogs(self._acc_ws, sample_logs)
151                AddSampleLog(Workspace=self._acc_ws, LogName='can_filename', LogType='String', LogText=str(self._can_ws_name))
152                AddSampleLog(Workspace=self._acc_ws, LogName='can_scale', LogType='String', LogText=str(self._can_scale))
153                AddSampleLog(Workspace=self._output_ws, LogName='can_thickness1', LogType='String', LogText=str(can_thickness1))
154                AddSampleLog(Workspace=self._output_ws, LogName='can_thickness2', LogType='String', LogText=str(can_thickness2))
155
156        self.setProperty('OutputWorkspace', self._output_ws)
157
158        # Output the Ass workspace if it is wanted, delete if not
159        if self._abs_ws == '':
160            DeleteWorkspace(self._ass_ws)
161            if self._can_ws_name is not None:
162                if self._use_can_corrections:
163                    DeleteWorkspace(self._acc_ws)
164        else:
165            group_name = self._abs_ws + '_abs'
166            GroupWorkspaces(InputWorkspaces=group, OutputWorkspace=group_name)
167            self.setProperty('CorrectionsWorkspace', group_name)
168
169        if self._plot:
170            from IndirectImport import import_mantidplot
171            mantid_plot = import_mantidplot()
172            mantid_plot.plotSpectrum(plot_data, 0)
173            mantid_plot.plotSpectrum(plot_corr, 0)
174
175
176    def _setup(self):
177        """
178        Get algorithm properties.
179        """
180
181        self._sample_ws_name = self.getPropertyValue('SampleWorkspace')
182        self._sample_chemical_formula = self.getPropertyValue('SampleChemicalFormula')
183        self._sample_number_density = self.getProperty('SampleNumberDensity').value
184        self._sample_inner_radius = self.getProperty('SampleInnerRadius').value
185        self._sample_outer_radius = self.getProperty('SampleOuterRadius').value
186
187        self._can_ws_name = self.getPropertyValue('CanWorkspace')
188        if self._can_ws_name == '':
189            self._can_ws_name = None
190        self._use_can_corrections = self.getProperty('UseCanCorrections').value
191        self._can_chemical_formula = self.getPropertyValue('CanChemicalFormula')
192        self._can_number_density = self.getProperty('CanNumberDensity').value
193        self._can_inner_radius = self.getProperty('CanInnerRadius').value
194        self._can_outer_radius = self.getProperty('CanOuterRadius').value
195        self._can_scale = self.getProperty('CanScaleFactor').value
196
197        self._events = self.getProperty('Events').value
198        self._plot = self.getProperty('Plot').value
199        self._output_ws = self.getPropertyValue('OutputWorkspace')
200
201        self._abs_ws = self.getPropertyValue('CorrectionsWorkspace')
202        if self._abs_ws == '':
203            self._ass_ws = '__ass'
204            self._acc_ws = '__acc'
205        else:
206            self._ass_ws = self._abs_ws + '_ass'
207            self._acc_ws = self._abs_ws + '_acc'
208
209# Register algorithm with Mantid
210AlgorithmFactory.subscribe(IndirectAnnulusAbsorption)