Skip to content
Snippets Groups Projects
Commit 0163596a authored by Michael Wedel's avatar Michael Wedel
Browse files

Refs #15068. More flexible atom strings

parent 7016904f
No related merge requests found
# 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)
......
......@@ -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):
......
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