Skip to content
Snippets Groups Projects
Unverified Commit d105850a authored by Martyn Gigg's avatar Martyn Gigg Committed by GitHub
Browse files

Merge pull request #20966 from mantidproject/19578_gsas_ii_integration

GSASIIRefineFitPeaks reintegrated with latest version of GSAS-II
parents 5ebdfdb5 d1849ce4
No related branches found
No related tags found
No related merge requests found
from __future__ import (absolute_import, division, print_function)
import os
import tempfile
import unittest
from mantid.simpleapi import *
import mantid.simpleapi as mantid
from mantid.api import *
class GSASIIRefineFitPeaksTest(unittest.TestCase):
class _GSASFinder(object):
"""
Very limited test, as executing this algorithm requires a modified
version of GSASII. At least it does some check that the algorithm is
registered succesfully and basic sanity checks.
Helper class for unit test - the algorithm can't run without a version of GSAS-II that includes the module
GSASIIscriptable (added April 2017)
"""
@staticmethod
def _find_directory_by_name(cur_dir_name, cur_dir_path, name_to_find, level, max_level):
"""
Perform a depth-limited depth-first search to try and find a directory with a given name
"""
if level == max_level:
return None
if cur_dir_name == name_to_find:
return cur_dir_path
list_dir = os.listdir(cur_dir_path)
for child in list_dir:
child_path = os.path.join(cur_dir_path, child)
if os.path.isdir(child_path):
try:
path = _GSASFinder._find_directory_by_name(cur_dir_name=child, cur_dir_path=child_path,
level=level + 1, name_to_find=name_to_find,
max_level=max_level)
except OSError: # Probably "Permission denied". Either way, just ignore it
pass
else:
if path is not None:
return path
def test_wrong_properties(self):
@staticmethod
def _path_to_g2conda():
"""
Handle in/out property issues appropriately.
Find the g2conda directory (where GSAS-II normally sits), as long as it exists less than 2 levels away from
the root directory
"""
ws_name = 'out_ws'
peak = "name=BackToBackExponential, I=5000,A=1, B=1., X0=10000, S=150"
sws = CreateSampleWorkspace(Function="User Defined", UserDefinedFunction=peak,
NumBanks=1, BankPixelWidth=1, XMin=5000, XMax=30000,
BinWidth=5, OutputWorkspace=ws_name)
instr_filename = 'inexistent_instr_par_file'
# No InputWorkspace property (required)
self.assertRaises(RuntimeError,
GSASIIRefineFitPeaks,
WorkspaceIndex=0, ExpectedPeaks='1.2, 3.1')
# Wrong WorkspaceIndex value
self.assertRaises(RuntimeError,
GSASIIRefineFitPeaks,
InputWorkspace=ws_name,
WorkspaceIndex=-3)
# Wrong property
self.assertRaises(RuntimeError,
GSASIIRefineFitPeaks,
InputWorkspace=ws_name, BankPixelFoo=33,
WorkspaceIndex=0)
# missing instrument file property
self.assertRaises(RuntimeError,
GSASIIRefineFitPeaks,
InputWorkspace=ws_name,
WorkspaceIndex=0)
# Wrong InstrumentFile property name
self.assertRaises(ValueError,
GSASIIRefineFitPeaks,
InputWorkspace=ws_name,
InstruMentFile=instr_filename,
WorkspaceIndex=0, ExpectedPeaks='a')
# Missing file for InstrumentFile
self.assertRaises(ValueError,
GSASIIRefineFitPeaks,
InputWorkspace=ws_name,
InstrumentFile=instr_filename,
WorkspaceIndex=0, ExpectedPeaks='a')
def test_exec_import_fails(self):
pass
root_directory = os.path.abspath(os.sep)
return _GSASFinder._find_directory_by_name(cur_dir_path=root_directory, cur_dir_name=root_directory, level=0,
name_to_find="g2conda", max_level=2)
@staticmethod
def GSASIIscriptable_location():
"""
Find the path to GSASIIscriptable.py, if it exists and is less than 2 levels away from the root directory
"""
path_to_g2conda = _GSASFinder._path_to_g2conda()
if path_to_g2conda is None:
return None
path_to_gsasii_scriptable = os.path.join(path_to_g2conda, "GSASII")
if os.path.isfile(os.path.join(path_to_gsasii_scriptable, "GSASIIscriptable.py")):
return path_to_gsasii_scriptable
return None
class GSASIIRefineFitPeaksTest(unittest.TestCase):
_path_to_gsas = None
_gsas_proj = None
_input_ws = None
_phase_file = None
_inst_file = None
def setUp(self):
data_dir = mantid.config["datasearch.directories"].split(";")[0]
print(mantid.config["datasearch.directories"].split(";"))
self._phase_file = os.path.join(data_dir, "FE_ALPHA.cif")
self._inst_file = os.path.join(data_dir, "template_ENGINX_241391_236516_North_bank.prm")
self._path_to_gsas = _GSASFinder.GSASIIscriptable_location()
if self._path_to_gsas is None:
self.skipTest("Could not find GSASIIscriptable.py")
temp_dir = tempfile.gettempdir()
self._gsas_proj = os.path.join(temp_dir, "GSASIIRefineFitPeaksTest.gpx")
spectrum_file = os.path.join(data_dir, "focused_bank1_ENGINX00256663.nxs")
self._input_ws = mantid.Load(Filename=spectrum_file, OutputWorkspace="input")
def tearDown(self):
if os.path.isfile(self._gsas_proj):
os.remove(self._gsas_proj)
def test_rietveld_refinement_with_default_params(self):
gof, rwp, lattice_table = mantid.GSASIIRefineFitPeaks(RefinementMethod="Rietveld refinement",
InputWorkspace=self._input_ws,
PhaseInfoFile=self._phase_file,
InstrumentFile=self._inst_file,
PathToGSASII=self._path_to_gsas,
SaveGSASIIProjectFile=self._gsas_proj,
MuteGSASII=True)
self.assertAlmostEqual(gof, 3.57776, delta=1e-6)
self.assertAlmostEquals(rwp, 77.75499, delta=1e6)
row = lattice_table.row(0)
self.assertAlmostEqual(row["a"], 2.8665)
self.assertAlmostEqual(row["b"], 2.8665)
self.assertAlmostEqual(row["c"], 2.8665)
self.assertAlmostEqual(row["alpha"], 90)
self.assertAlmostEqual(row["beta"], 90)
self.assertAlmostEqual(row["gamma"], 90)
self.assertAlmostEqual(row["volume"], 23.554, delta=1e4)
def test_pawley_refinement_with_default_params(self):
gof, rwp, lattice_table = mantid.GSASIIRefineFitPeaks(RefinementMethod="Pawley refinement",
InputWorkspace=self._input_ws,
PhaseInfoFile=self._phase_file,
InstrumentFile=self._inst_file,
PathToGSASII=self._path_to_gsas,
SaveGSASIIProjectFile=self._gsas_proj,
MuteGSASII=True)
self.assertAlmostEqual(gof, 3.57847, delta=1e-6)
self.assertAlmostEquals(rwp, 77.75515, delta=1e6)
row = lattice_table.row(0)
self.assertAlmostEqual(row["a"], 2.8665)
self.assertAlmostEqual(row["b"], 2.8665)
self.assertAlmostEqual(row["c"], 2.8665)
self.assertAlmostEqual(row["alpha"], 90)
self.assertAlmostEqual(row["beta"], 90)
self.assertAlmostEqual(row["gamma"], 90)
self.assertAlmostEqual(row["volume"], 23.554, delta=1e4)
if __name__ == '__main__':
unittest.main()
b184c411cf657178803326c733b2a34c
\ No newline at end of file
5e52c1fa6927d04649b6456e70a07999
\ No newline at end of file
093020d8461c62709297603faf712449
\ No newline at end of file
......@@ -11,31 +11,19 @@ Description
.. warning::
This algorithm is experimental and at the moment is being developed
for a specific technique. It might be changed, renamed or even
removed without a notification, should instrument scientists decide
to do so.
.. warning::
This algorithm requires GSAS-II, with custom modifications to
enable it to be used from Mantid. Please contact the Mantid
developers for details. The GSAS-II installation instructions are
available from the `GSAS-II website
<https://subversion.xray.aps.anl.gov/trac/pyGSAS>`_.
This algorithm requires GSAS-II to be installed on your computer. A
version of GSAS-II containing the module GSASIIscriptable (added in
April 2017) is required.
Uses `GSAS-II <https://subversion.xray.aps.anl.gov/trac/pyGSAS>`_
[TobyVonDreele2013]_ as external software to fit peaks to a powder /
engineering diffraction pattern. Here the process of peak fitting is
in the context of Rietveld / Pawley / Le Bail analysis [LeBail2005]_
The algorithm supports three refinement or fitting methods: Pawley
refinement, Rietveld refinement, and single peak fitting (or "Peaks
List" of GSAS-II). The first two methods of this algorithm implement
whole diffraction pattern fitting whereas the third method fits peaks
individually. The use of this algorithm is very close to the examples
described in these two GSAS-II tutorials: `Rietveld fitting / CW
Neutron Powder fit for Yttrium-Iron Garnet
The algorithm supports two refinement methods: Pawley refinement and
Rietveld refinement. The use of this algorithm is very close to the
examples described in these two GSAS-II tutorials: `Rietveld fitting /
CW Neutron Powder fit for Yttrium-Iron Garnet
<https://subversion.xray.aps.anl.gov/pyGSAS/Tutorials/CWNeutron/Neutron%20CW%20Powder%20Data.htm>`_,
and `Getting started / Fitting individual peaks & autoindexing
<https://subversion.xray.aps.anl.gov/pyGSAS/Tutorials/FitPeaks/Fit%20Peaks.htm>`_,
......@@ -46,42 +34,28 @@ and the `structure routines
<https://subversion.xray.aps.anl.gov/pyGSAS/sphinxdocs/build/html/GSASIIstruc.html>`_
of GSAS-II.
To run this algorithm GSAS-II must be installed and it must be
available for importing from the Mantid Python interpreter. This
algorithm requires a modified version of GSAS-II. Please contact the
developers for details.
The methods "Pawley refinement" and "Rietveld refinement" of this
algorithm are equivalent to the function "Calculate / Refine" from the
main menu of the GSAS-II GUI. The method "Peak fitting" is equivalent
to the "Peak Fitting / Peak fit" action of the "Peaks List" window
menu of the GSAS-II GUI.
The refinement methods of this algorithm are equivalent to the
function "Calculate / Refine" from the main menu of the GSAS-II GUI.
The main inputs required are histogram data, an instrument definition
parameter (in GSAS format, readable by GSAS-II), and various
parameters for the fitting/refinement process. Phase information is
also required to use the Pawley and Rietveld refinement.
parameter (in GSAS format, readable by GSAS-II), phase information and
various parameters for the fitting/refinement process.
The phase information must be provided in `CIF format
(Crystallographic Information File)
<https://en.wikipedia.org/wiki/Crystallographic_Information_File>`_.
When phase information is available and the Rietveld/Pawley method is
used the algorithm will output the lattice parameters in a table
workspace. The values are given for the the full set of lattice
parameters (three lattice constants, three angles, and volume in this
sequence: a, b, c, alpha, beta, gamma, volume). The a,b, and c values
are given in Angstroms (:math:`\mathrm{\AA{}}`). The angles are given
in degrees, and the volume in :math:`\mathrm{\AA{}}^3`.
When phase information is available the algorithm will output the
lattice parameters in a table workspace. The values are given for the
the full set of lattice parameters (three lattice constants, three
angles, and volume in this sequence: a, b, c, alpha, beta, gamma,
volume). The a,b, and c values are given in Angstroms
(:math:`\mathrm{\AA{}}`). The angles are given in degrees, and the
volume in :math:`\mathrm{\AA{}}^3`.
The algorithm provides goodness-of-fit estimates in the outputs *GoF*
and *Rwp* or weighted profile R-factor [Toby2008]_. The *Rwp* is given
as a percentage value.
Note that the option to save the GSAS-II project file
(*SaveGSASIIProjectFile*) is mandatory. This is a requirement of
GSAS-II. These project files can be opened in the GSAS-II GUI for
further processing and analysis of the data.
When Pawley refinement is selected as refinement method the flag for
histogram scale factor refinement is disabled, as recommended in the
`GSAS-II documentation
......@@ -95,23 +69,6 @@ the same name as the output GSAS-II project file but with extension
".lst". This is noted in a log message that specifies where the file
has been written (next to the output project file).
When fitting individual peaks using the peak fitting method (not using
Rietveld/Pawley refinement), the algorithm only supports peaks with
shape of type back-to-back exponential convoluted with pseudo-voigt
(BackToBackExponentialPV). It is possible to enable the refinement of
the different function parameters via several properties (RefineAlpha,
RefineSigma, etc.). The fitted peak parameters are given in an output
table with as many rows as peaks have been found. The columns of the
table give the parameters fitted, similarly to the information found
in the "Peaks List" window of the GSAS-II GUI. These results are
printed in the log messages as well.
.. seealso:: For fitting single peaks, one at a time, :ref:`EnggFitPeaks
<algm-EnggFitPeaks>`. For other algorithms that implement different
variants of whole diffraction pattern refinement and fitting by
:ref:`PawleyFit <algm-PawleyFit>` and :ref:`LeBailFit <algm-LeBailFit>`.
*References*:
.. [LeBail2005] Le Bail, A (2005). "Whole Powder Pattern Decomposition Methods and
......@@ -128,6 +85,13 @@ printed in the log messages as well.
Usage
-----
.. warning::
Take these usage examples with a pinch of salt, as they are not
tested for correctness on our servers, due to the requirement to
have GSAS-II installed. Please contact the Mantid developers if
something is awry.
**Example - Pawley refinement of lattice parameters from a diffraction spectrum**
.. code-block:: python
......@@ -145,11 +109,11 @@ Usage
#
wks=Load('focused_bank1_ENGINX00256663.nxs')
GoF, Rwp, lattice_tbl = GSASIIRefineFitPeaks(InputWorkspace=wks,
InstrumentFile='ENGINX_255924_254854_North_bank.par',
RefinementMethods="PawleyRefinement",
InstrumentFile='template_ENGINX_241391_236516_North_bank.prm',
PhaseInfoFile='FE_ALPHA.cif',
PathToGSASII='/home/user/gsas',
SaveGSASIIProjectFile='example_gsas2_project',
LatticeParameters='lattice_tbl')
SaveGSASIIProjectFile='example_gsas2_project')
print "Goodness of fit coefficient: {0:.5f}".format(GoF)
print "Weighted profile R-factor (Rwp): {0:.5f}".format(Rwp)
print ("Lattice parameters, a: {a}, b: {b}, c: {c}, alpha: {alpha}, beta: {beta}, gamma: {gamma}, "
......@@ -159,8 +123,8 @@ Output:
.. code-block:: none
Goodness of fit coefficient: 3.63591
Weighted profile R-factor (Rwp): 77.27831
Goodness of fit coefficient: 3.57776
Weighted profile R-factor (Rwp): 77.75449
Lattice parameters, a: 2.8665, b: 2.8665, c: 2.8665, alpha: 90.0, beta: 90.0, gamma: 90.0, Volume: 23.554
**Example - Rietveld refinement of lattice parameters from a diffraction spectrum**
......@@ -169,12 +133,11 @@ Output:
wks=Load('focused_bank1_ENGINX00256663.nxs')
GoF, Rwp, lattice_tbl = GSASIIRefineFitPeaks(InputWorkspace=wks,
Method='Rietveld refinement',
InstrumentFile='ENGINX_255924_254854_North_bank.par',
RefinementMethod='Rietveld refinement',
InstrumentFile='template_ENGINX_241391_236516_North_bank.prm',
PhaseInfoFile='FE_ALPHA.cif',
PathToGSASII='/home/user/gsas',
SaveGSASIIProjectFile='example_gsas2_project',
LatticeParameters='lattice_tbl')
print "Goodness of fit coefficient: {0:.5f}".format(GoF)
print "Weighted profile R-factor (Rwp): {0:.5f}".format(Rwp)
print ("Lattice parameters, a: {a}, b: {b}, c: {c}, alpha: {alpha}, beta: {beta}, gamma: {gamma}, "
......@@ -184,37 +147,10 @@ Output:
.. code-block:: none
Goodness of fit coefficient: 3.62483
Weighted profile R-factor (Rwp): 77.03530
Goodness of fit coefficient: 3.57847
Weighted profile R-factor (Rwp): 77.75515
Lattice parameters, a: 2.8665, b: 2.8665, c: 2.8665, alpha: 90.0, beta: 90.0, gamma: 90.0, Volume: 23.554
**Example - Fit several peaks from a diffraction spectrum**
.. code-block:: python
wks=Load('focused_bank1_ENGINX00256663.nxs')
params_tbl_name = 'tbl_fitted_params'
GoF, Rwp, lattice_tbl = GSASIIRefineFitPeaks(InputWorkspace=wks,
Method='Peak fitting',
FittedPeakParameters=params_tbl_name,
InstrumentFile='ENGINX_255924_254854_North_bank.par',
PhaseInfoFile='FE_ALPHA.cif',
PathToGSASII='/home/user/mantid-repos/gsas',
SaveGSASIIProjectFile='test_gsas2_project',
FittedPeakParameters=params_tbl_name)
tbl_fitted_params = mtd[params_tbl_name]
print "Fitted {0} peaks.".format(tbl_fitted_params.rowCount())
print ("Parameters of the first peak. Center: {Center:.6g}, intensity: {Intensity:.5f}, "
"alpha: {Alpha:.5f}, beta: {Beta:.5f}, sigma: {Sigma:.5f}, gamma: {Gamma:.5f}".
format(**tbl_fitted_params.row(0)))
Output:
.. code-block:: none
Fitted 18 peaks.
Parameters of the first peak. Center: 38563.8, intensity: 26.22137, alpha: 0.13125, beta: 0.01990, sigma: 125475.11036, gamma: -6681.38965
.. categories::
.. sourcelink::
......@@ -22,6 +22,9 @@ Powder Diffraction
Engineering Diffraction
-----------------------
- :ref:`algm-GSASIIRefineFitPeaks>` has been re-integrated with the
latest version of GSAS-II, allowing Rietveld and Pawley refinement
within Mantid.
- Usability improvements in the GUI:
- The "Invalid RB number" popup window in the GUI has been replaced with a more user-friendly message
- Improved progress reporting for Calibration and Focus
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment