From 0163596aa5b89e7f6b7ae007fdb5ede31013cd7c Mon Sep 17 00:00:00 2001 From: Michael Wedel <michael.wedel@esss.se> Date: Mon, 25 Jan 2016 14:21:36 -0500 Subject: [PATCH] Refs #15068. More flexible atom strings --- .../plugins/algorithms/LoadCIF.py | 52 ++++++++++++++++--- .../python/plugins/algorithms/LoadCIFTest.py | 39 +++++++++++--- 2 files changed, 76 insertions(+), 15 deletions(-) diff --git a/Framework/PythonInterface/plugins/algorithms/LoadCIF.py b/Framework/PythonInterface/plugins/algorithms/LoadCIF.py index 3d47133ed57..4410076a8a8 100644 --- a/Framework/PythonInterface/plugins/algorithms/LoadCIF.py +++ b/Framework/PythonInterface/plugins/algorithms/LoadCIF.py @@ -1,10 +1,12 @@ -# pylint: disable=no-init,too-few-public-methods +# pylint: disable=no-init,too-few-public-methods,wrong-import-position from mantid.kernel import * from mantid.simpleapi import * from mantid.api import * from mantid.geometry import SpaceGroupFactory, CrystalStructure import re +import math + # pylint: disable=invalid-name def removeErrorEstimateFromNumber(numberString): @@ -16,6 +18,10 @@ def removeErrorEstimateFromNumber(numberString): return numberString[:errorBegin] +def convertBisoToUiso(bIso): + return bIso / (8.0 * math.pi * math.pi) + + class CrystalStructureBuilder(object): ''' Helper class that builds a CrystalStructure file from the result @@ -46,8 +52,8 @@ class CrystalStructureBuilder(object): # pylint: disable=unused-variable,invalid-name except RuntimeError as e: raise RuntimeError( - 'Can not create space group from supplied CIF-file. You could try to modify the HM-symbol'\ - 'to contain spaces between the components.\n'\ + 'Can not create space group from supplied CIF-file. You could try to modify the HM-symbol' \ + 'to contain spaces between the components.\n' \ 'Keys to look for: _space_group_name_H-M_alt, _symmetry_space_group_name_H-M') def _getSpaceGroupFromString(self, cifData): @@ -109,12 +115,12 @@ class CrystalStructureBuilder(object): return ' '.join(unitCellValues) def _getAtoms(self, cifData): - atomFieldsRequirements = [(u'_atom_site_label', True), - (u'_atom_site_fract_x', True), + atomSymbols = self._getAtomSymbols(cifData) + + atomFieldsRequirements = [(u'_atom_site_fract_x', True), (u'_atom_site_fract_y', True), (u'_atom_site_fract_z', True), - (u'_atom_site_occupancy', False), - (u'_atom_site_u_iso_or_equiv', False)] + (u'_atom_site_occupancy', False)] atomFields = [] @@ -127,7 +133,14 @@ class CrystalStructureBuilder(object): 'Mandatory field {0} not found in CIF-file.' \ 'Please check the atomic position definitions.'.format(field)) - atomLists = [cifData[x] for x in atomFields] + atomLists = [atomSymbols] + [cifData[x] for x in atomFields] + + try: + isotropicUs = self._getIsotropicUs(cifData) + atomLists += [isotropicUs] + # pylint: disable=unused-variable,invalid-name + except RuntimeError as e: + pass atomLines = [] for atomLine in zip(*atomLists): @@ -139,6 +152,29 @@ class CrystalStructureBuilder(object): return ';'.join(atomLines) + def _getAtomSymbols(self, cifData): + rawAtomSymbols = [cifData[x] for x in [u'_atom_site_type_symbol', u'_atom_site_label'] if x in + cifData.keys()] + + if len(rawAtomSymbols) == 0: + raise RuntimeError('Cannot determine atom types, both _atom_site_type_symbol and _atom_site_label are ' + 'missing.') + + return [self._getCleanAtomSymbol(x) for x in rawAtomSymbols[0]] + + def _getIsotropicUs(self, cifData): + keyUIso = u'_atom_site_u_iso_or_equiv' + + if keyUIso in cifData.keys(): + return cifData[keyUIso] + + keyBIso = u'_atom_site_b_iso_or_equiv' + + if keyBIso in cifData.keys(): + return [convertBisoToUiso(float(x)) for x in cifData[keyBIso]] + + raise RuntimeError('Neither U_iso nor B_iso are defined in the CIF-file.') + def _getCleanAtomSymbol(self, atomSymbol): nonCharacterRe = re.compile('[^a-z]', re.IGNORECASE) diff --git a/Framework/PythonInterface/test/python/plugins/algorithms/LoadCIFTest.py b/Framework/PythonInterface/test/python/plugins/algorithms/LoadCIFTest.py index 517a682c400..d7ec89b3da6 100644 --- a/Framework/PythonInterface/test/python/plugins/algorithms/LoadCIFTest.py +++ b/Framework/PythonInterface/test/python/plugins/algorithms/LoadCIFTest.py @@ -96,10 +96,19 @@ class CrystalStructureBuilderTestUnitCell(unittest.TestCase): self.assertEqual(self.builder._getUnitCell(cell_errors), '5.6 5.6 2.3 90.0 90.0 120.0') - class CrystalStructureBuilderTestAtoms(unittest.TestCase): def setUp(self): self.builder = CrystalStructureBuilder() + self._baseData = dict([ + (u'_atom_site_fract_x', [u'1/8', u'0.34(1)']), + (u'_atom_site_fract_y', [u'1/8', u'0.56(2)']), + (u'_atom_site_fract_z', [u'1/8', u'0.23(2)'])]) + + def _getData(self, additionalData): + data = self._baseData.copy() + data.update(additionalData) + + return data def test_getAtoms_required_keys(self): mandatoryKeys = dict([(u'_atom_site_label', [u'Si']), @@ -113,15 +122,31 @@ class CrystalStructureBuilderTestAtoms(unittest.TestCase): self.assertRaises(RuntimeError, self.builder._getAtoms, cifData=tmp) def test_getAtoms_correct(self): - data = dict([(u'_atom_site_label', [u'Si', u'Al']), - (u'_atom_site_fract_x', [u'1/8', u'0.34(1)']), - (u'_atom_site_fract_y', [u'1/8', u'0.56(2)']), - (u'_atom_site_fract_z', [u'1/8', u'0.23(2)']), - (u'_atom_site_occupancy', [u'1.0', u'1.0(0)']), - (u'_atom_site_u_iso_or_equiv', [u'0.01', u'0.02'])]) + data = self._getData(dict([(u'_atom_site_label', [u'Si', u'Al']), + (u'_atom_site_occupancy', [u'1.0', u'1.0(0)']), + (u'_atom_site_u_iso_or_equiv', [u'0.01', u'0.02'])])) + + self.assertEqual(self.builder._getAtoms(data), 'Si 1/8 1/8 1/8 1.0 0.01;Al 0.34 0.56 0.23 1.0 0.02') + + def test_getAtoms_atom_type_symbol(self): + data = self._getData(dict([(u'_atom_site_label', [u'Fake1', u'Fake2']), + (u'_atom_site_occupancy', [u'1.0', u'1.0(0)']), + (u'_atom_site_u_iso_or_equiv', [u'0.01', u'0.02'])])) + + self.assertEqual(self.builder._getAtoms(data), 'Fake 1/8 1/8 1/8 1.0 0.01;Fake 0.34 0.56 0.23 1.0 0.02') + + data[u'_atom_site_type_symbol'] = [u'Si', u'Al'] self.assertEqual(self.builder._getAtoms(data), 'Si 1/8 1/8 1/8 1.0 0.01;Al 0.34 0.56 0.23 1.0 0.02') + def test_getAtoms_B_iso(self): + data = self._getData(dict([(u'_atom_site_label', [u'Si', u'Al']), + (u'_atom_site_occupancy', [u'1.0', u'1.0(0)']), + (u'_atom_site_b_iso_or_equiv', [u'1.0', u'2.0'])])) + + self.assertEqual(self.builder._getAtoms(data), + 'Si 1/8 1/8 1/8 1.0 0.0126651479553;Al 0.34 0.56 0.23 1.0 0.0253302959106') + class UBMatrixBuilderTest(unittest.TestCase): def setUp(self): -- GitLab