Skip to content

Commit 8edd656

Browse files
committed
Merge branch 'use-sg-site-isotropy'
* set `Atom.anisotropy` per CIF spacegroup constraints * test symmetry-derived site isotropy and its CIF overrides. Resolves #30.
2 parents 1f788d7 + 7d1a968 commit 8edd656

File tree

2 files changed

+88
-17
lines changed

2 files changed

+88
-17
lines changed

src/diffpy/structure/parsers/p_cif.py

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -412,11 +412,8 @@ def _parse_atom_site_aniso_label(self, block):
412412
No return value.
413413
"""
414414
if '_atom_site_aniso_label' not in block: return
415-
# was anisotropy set in the _atom_site_label loop?
416-
atom_site_loop = block.GetLoop('_atom_site_label')
417-
anisotropy_already_set = (
418-
'_atom_site_adp_type' in atom_site_loop or
419-
'_atom_site_thermal_displace_type' in atom_site_loop)
415+
# was anisotropy processed in the _atom_site_label loop?
416+
isotropy_done = _hasAtomSiteADPType(block)
420417
# something to do here:
421418
adp_loop = block.GetLoop('_atom_site_aniso_label')
422419
# index of the _atom_site_label column
@@ -427,7 +424,7 @@ def _parse_atom_site_aniso_label(self, block):
427424
for values in sitedatalist:
428425
idx = self.labelindex[values[ilb]]
429426
a = self.stru[idx]
430-
if not anisotropy_already_set:
427+
if not isotropy_done:
431428
a.anisotropy = True
432429
for fset, val in zip(prop_setters, values):
433430
fset(a, val)
@@ -494,22 +491,32 @@ def _parse_space_group_symop_operation_xyz(self, block):
494491
if self.spacegroup is None:
495492
emsg = "CIF file has unknown space group identifier {!r}."
496493
raise StructureFormatError(emsg.format(sgid))
497-
self._expandAsymmetricUnit()
494+
self._expandAsymmetricUnit(block)
498495
return
499496

500497

501-
def _expandAsymmetricUnit(self):
498+
def _expandAsymmetricUnit(self, block):
502499
"""Perform symmetry expansion of self.stru using self.spacegroup.
500+
503501
This method updates data in stru and eau.
504502
505-
No return value.
503+
Parameters
504+
----------
505+
block : CifBlock
506+
The top-level block containing crystal structure data.
506507
"""
507508
from diffpy.structure.symmetryutilities import ExpandAsymmetricUnit
508-
# get reverse-ordered unique indices
509509
corepos = [a.xyz for a in self.stru]
510510
coreUijs = [a.U for a in self.stru]
511511
self.eau = ExpandAsymmetricUnit(self.spacegroup, corepos, coreUijs,
512512
eps=self.eps)
513+
# setup anisotropy according to symmetry requirements
514+
# was isotropy flag already processed
515+
isotropy_done = (_hasAtomSiteADPType(block) or
516+
'_atom_site_aniso_label' in block)
517+
if not isotropy_done:
518+
for ca, uisotropy in zip(self.stru, self.eau.Uisotropy):
519+
ca.anisotropy = not uisotropy
513520
# build a nested list of new atoms:
514521
newatoms = []
515522
for i, ca in enumerate(self.stru):
@@ -727,3 +734,12 @@ def _suppressCifParserOutput():
727734
finally:
728735
yapps3_compiled_rt.print_error = print_error
729736
pass
737+
738+
739+
def _hasAtomSiteADPType(block):
740+
"""Return True if the CIF specifies _atom_site_adp_type.
741+
"""
742+
atom_site_loop = block.GetLoop('_atom_site_label')
743+
rv = ('_atom_site_adp_type' in atom_site_loop or
744+
'_atom_site_thermal_displace_type' in atom_site_loop)
745+
return rv

src/diffpy/structure/tests/testp_cif.py

Lines changed: 62 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ def test_getSymOp(self):
6666

6767
class TestP_cif(unittest.TestCase):
6868

69-
goodciffile = datafile('PbTe.cif')
69+
pbteciffile = datafile('PbTe.cif')
7070
badciffile = datafile('LiCl-bad.cif')
7171
graphiteciffile = datafile('graphite.cif')
7272
cdsebulkpdffitfile = datafile('CdSe_bulk.stru')
@@ -86,12 +86,12 @@ def tearDown(self):
8686
def test_parse(self):
8787
"""check P_cif.parse()
8888
"""
89-
with open(self.goodciffile) as fp1:
89+
with open(self.pbteciffile) as fp1:
9090
sgood = fp1.read()
9191
with open(self.badciffile) as fp2:
9292
sbad = fp2.read()
9393
pfile, ptest = self.pfile, self.ptest
94-
stru_check = pfile.parseFile(self.goodciffile)
94+
stru_check = pfile.parseFile(self.pbteciffile)
9595
stru = ptest.parse(sgood)
9696
self.assertEqual(str(stru_check), str(stru))
9797
self.assertEqual(str(stru_check.lattice), str(stru.lattice))
@@ -106,12 +106,12 @@ def test_parse(self):
106106
def test_parseLines(self):
107107
"""check P_cif.parseLines()
108108
"""
109-
with open(self.goodciffile) as fp1:
109+
with open(self.pbteciffile) as fp1:
110110
goodlines = fp1.readlines()
111111
with open(self.badciffile) as fp2:
112112
badlines = fp2.readlines()
113113
pfile, ptest = self.pfile, self.ptest
114-
stru_check = pfile.parseFile(self.goodciffile)
114+
stru_check = pfile.parseFile(self.pbteciffile)
115115
stru = ptest.parseLines(goodlines)
116116
self.assertEqual(str(stru_check), str(stru))
117117
self.assertEqual(str(stru_check.lattice), str(stru.lattice))
@@ -126,8 +126,8 @@ def test_parseLines(self):
126126
def test_parseFile(self):
127127
"""check P_cif.parseFile()
128128
"""
129-
# goodciffile
130-
stru = self.pfile.parseFile(self.goodciffile)
129+
# pbteciffile
130+
stru = self.pfile.parseFile(self.pbteciffile)
131131
self.assertEqual(8, len(stru))
132132
self.assertEqual(6.461, stru.lattice.a)
133133
self.assertEqual(6.461, stru.lattice.b)
@@ -289,6 +289,61 @@ def test_custom_spacegroup_cif(self):
289289
return
290290

291291

292+
def test_spacegroup_isotropy(self):
293+
"verify site isotropy due to site symmetry."
294+
# remove the _atom_site_thermal_displace_type field
295+
with open(self.pbteciffile) as fp:
296+
lines = [line.replace(' Uiso ', ' ') for line in fp
297+
if '_atom_site_thermal_displace_type' not in line]
298+
ciftxt = ''.join(lines)
299+
ptest = self.ptest
300+
stru = ptest.parse(ciftxt)
301+
self.assertFalse(any(stru.anisotropy))
302+
self.assertTrue(all(not a.anisotropy for a in ptest.asymmetric_unit))
303+
return
304+
305+
306+
def test_spacegroup_anisotropy(self):
307+
"verify site anisotropy due to site symmetry."
308+
stru = self.ptest.parseFile(self.graphiteciffile)
309+
self.assertTrue(all(stru.anisotropy))
310+
return
311+
312+
313+
def test_adp_type_ani(self):
314+
"verify adp type override to anisotropic"
315+
with open(self.pbteciffile) as fp:
316+
ciftxt = fp.read()
317+
ciftxt = ciftxt.replace(' Uiso ', ' Uani ')
318+
stru = self.ptest.parse(ciftxt)
319+
self.assertTrue(all(stru.anisotropy))
320+
return
321+
322+
323+
def test_adp_type_iso(self):
324+
"verify adp type override to isotropic"
325+
with open(self.graphiteciffile) as fp:
326+
lines = fp.readlines()
327+
lines.insert(-2, '_atom_site_adp_type\n')
328+
lines[-2] = lines[-2].rstrip() + ' Uiso\n'
329+
lines[-1] = lines[-1].rstrip() + ' Uiso\n'
330+
ciftxt = ''.join(lines)
331+
stru = self.ptest.parse(ciftxt)
332+
self.assertFalse(any(a.anisotropy for a in stru))
333+
return
334+
335+
336+
def test_adp_aniso_label(self):
337+
"verify ADP type setting from _atom_site_aniso_label loop"
338+
with open(self.teiciffile) as fp:
339+
lines = [line.replace(' Uani ', ' ') for line in fp
340+
if not '_atom_site_adp_type' in line]
341+
ciftxt = ''.join(lines)
342+
stru = self.ptest.parse(ciftxt)
343+
self.assertTrue(all(stru.anisotropy))
344+
return
345+
346+
292347
def test_getParser(self):
293348
"""Test passing of eps keyword argument by getParser function.
294349
"""

0 commit comments

Comments
 (0)