Skip to content

Commit 8f7f251

Browse files
committed
Merge branch 'cherries-from-python3'.
Commits that adjust code function. Skipped documentation changes. Synced with 4c796c8.
2 parents 87c9228 + 9bc7cfc commit 8f7f251

19 files changed

+432
-230
lines changed

.travis.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ install:
8080
- $NOMC || conda install --yes --use-local --file=/tmp/mypackage.txt
8181

8282
- $NOAPT || pip install $MYPIPFLAGS coverage
83+
- $NOAPT || pip install $MYPIPFLAGS "pycifrw==4.2.1"
8384
- $NOAPT || easy_install --user "${MYTARBUNDLE}"
8485

8586
# We need to capitalize MYNAME to match Python module name.

setup.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
"""
77

88
import os
9+
import re
10+
import sys
911
from setuptools import setup, find_packages
1012

1113
# Use this version when git data are not available, like in git zip archive.
@@ -21,7 +23,7 @@
2123

2224
def gitinfo():
2325
from subprocess import Popen, PIPE
24-
kw = dict(stdout=PIPE, cwd=MYDIR)
26+
kw = dict(stdout=PIPE, cwd=MYDIR, universal_newlines=True)
2527
proc = Popen(['git', 'describe', '--match=v[[:digit:]]*'], **kw)
2628
desc = proc.stdout.read()
2729
proc = Popen(['git', 'log', '-1', '--format=%H %at %ai'], **kw)
@@ -33,8 +35,10 @@ def gitinfo():
3335

3436

3537
def getversioncfg():
36-
import re
37-
from ConfigParser import RawConfigParser
38+
if sys.version_info[0] >= 3:
39+
from configparser import RawConfigParser
40+
else:
41+
from ConfigParser import RawConfigParser
3842
vd0 = dict(version=FALLBACK_VERSION, commit='', date='', timestamp=0)
3943
# first fetch data from gitarchivecfgfile, ignore if it is unexpanded
4044
g = vd0.copy()
@@ -63,7 +67,8 @@ def getversioncfg():
6367
cp.set('DEFAULT', 'commit', g['commit'])
6468
cp.set('DEFAULT', 'date', g['date'])
6569
cp.set('DEFAULT', 'timestamp', g['timestamp'])
66-
cp.write(open(versioncfgfile, 'w'))
70+
with open(versioncfgfile, 'w') as fp:
71+
cp.write(fp)
6772
return cp
6873

6974
versiondata = getversioncfg()
@@ -79,7 +84,7 @@ def getversioncfg():
7984
include_package_data = True,
8085
zip_safe = False,
8186
install_requires = [
82-
'pycifrw != 4.3.0',
87+
'pycifrw',
8388
],
8489

8590
author = 'Simon J.L. Billinge group',

src/diffpy/Structure/Parsers/P_pdffit.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -114,17 +114,17 @@ def parseLines(self, lines):
114114
stru.addNewAtom(element, xyz=xyz, occupancy=occ)
115115
a = stru.getLastAtom()
116116
p_nl += 1
117-
wl2 = ilines.next().split()
117+
wl2 = next(ilines).split()
118118
a.sigxyz = [ float(w) for w in wl2[0:3] ]
119119
a.sigo = float(wl2[3])
120120
p_nl += 1
121-
wl3 = ilines.next().split()
121+
wl3 = next(ilines).split()
122122
p_nl += 1
123-
wl4 = ilines.next().split()
123+
wl4 = next(ilines).split()
124124
p_nl += 1
125-
wl5 = ilines.next().split()
125+
wl5 = next(ilines).split()
126126
p_nl += 1
127-
wl6 = ilines.next().split()
127+
wl6 = next(ilines).split()
128128
U = numpy.zeros((3,3), dtype=float)
129129
sigU = numpy.zeros((3,3), dtype=float)
130130
U[0,0] = float(wl3[0])

src/diffpy/Structure/Parsers/P_xcfg.py

Lines changed: 85 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -177,13 +177,16 @@ def parseLines(self, lines):
177177
p_nl = 0
178178
p_auxiliary_re = re.compile(r"^auxiliary\[(\d+)\] =")
179179
p_auxiliary = {}
180+
stru = Structure()
181+
# ignore trailing blank lines
182+
stop = len(lines)
183+
for line in reversed(lines):
184+
if line.strip():
185+
break
186+
stop -= 1
187+
# iterator over the valid data lines
188+
ilines = iter(lines[:stop])
180189
try:
181-
stru = Structure()
182-
# ignore trailing blank lines
183-
stop = len(lines)
184-
while stop>0 and lines[stop-1].strip() == "":
185-
stop -= 1
186-
ilines = iter(lines[:stop])
187190
# read XCFG header
188191
for line in ilines:
189192
p_nl += 1
@@ -201,7 +204,7 @@ def parseLines(self, lines):
201204
elif line.find("A =") == 0:
202205
xcfg_A = float(line[3:].split(None, 1)[0])
203206
elif line.find("H0(") == 0:
204-
i, j = ( int(line[3])-1 , int(line[5])-1 )
207+
i, j = (int(line[3]) - 1, int(line[5]) - 1)
205208
xcfg_H0[i,j] = float(line[10:].split(None, 1)[0])
206209
xcfg_H0_set[i,j] = True
207210
elif line.find(".NO_VELOCITY.") == 0:
@@ -222,51 +225,22 @@ def parseLines(self, lines):
222225
for i in range(p_auxnum):
223226
if not i in p_auxiliary:
224227
p_auxiliary[i] = "aux%d" % i
225-
sorted_aux_keys = p_auxiliary.keys()
226-
sorted_aux_keys.sort()
228+
sorted_aux_keys = sorted(p_auxiliary.keys())
227229
if p_auxnum != 0:
228230
stru.xcfg = {
229231
'auxiliaries' : [ p_auxiliary[k]
230232
for k in sorted_aux_keys ]
231233
}
232-
if 6-3*xcfg_NO_VELOCITY+len(p_auxiliary) != xcfg_entry_count:
233-
emsg = ("%d: auxiliary fields " +
234+
ecnt = len(p_auxiliary) + (3 if xcfg_NO_VELOCITY else 6)
235+
if ecnt != xcfg_entry_count:
236+
emsg = ("%d: auxiliary fields are "
234237
"not consistent with entry_count") % p_nl
235238
raise StructureFormatError(emsg)
236239
# define proper lattice
237240
stru.lattice.setLatBase(xcfg_H0)
238-
# build p_assign_atom function to assign entries to proper fields
239-
p_exprs = [ "a.xyz[0]=fields[0]",
240-
"a.xyz[1]=fields[1]",
241-
"a.xyz[2]=fields[2]" ]
242-
if not xcfg_NO_VELOCITY:
243-
p_exprs += [ "a.v=numpy.zeros(3, dtype=float)",
244-
"a.v[0]=fields[3]",
245-
"a.v[1]=fields[4]",
246-
"a.v[2]=fields[5]" ]
247-
for idx in sorted_aux_keys:
248-
prop = p_auxiliary[idx]
249-
col = idx + 6 - 3*xcfg_NO_VELOCITY
250-
if prop == "Uiso":
251-
p_exprs.append("a.Uisoequiv=fields[%d]" % col)
252-
elif re.match(r"^U\d\d$", prop) \
253-
and 1<=int(prop[1])<=3 and 1<=int(prop[2])<=3 :
254-
p_exprs.append("a.anisotropy=True")
255-
i, j = int(prop[1])-1, int(prop[2])-1
256-
if i==j:
257-
p_exprs.append("a.U[%i,%i]=fields[%d]" % (i, j, col) )
258-
else:
259-
p_exprs.append("a.U[%i,%i]=a.U[%i,%i]=fields[%d]" % \
260-
(i, j, j, i, col) )
261-
else:
262-
p_exprs.append( "a.__dict__[%r]=fields[%d]" % \
263-
(prop, col) )
264-
p_assign_expr = "pass; " + "; ".join(p_exprs[3:])
265-
exec "def p_assign_atom(a, fields) : %s" % p_assign_expr
266-
# here we are inside data
241+
# here we are inside the data block
267242
p_element = None
268-
p_nl -= 1
269-
for line in lines[p_nl:stop]:
243+
for line in ilines:
270244
p_nl += 1
271245
words = line.split()
272246
# ignore atom mass
@@ -277,11 +251,12 @@ def parseLines(self, lines):
277251
w = line.strip()
278252
p_element = w[:1].upper() + w[1:].lower()
279253
elif len(words) == xcfg_entry_count and p_element is not None:
280-
fields = [ float(w) for w in words ]
281-
stru.addNewAtom(p_element, fields[:3])
282-
a = stru.getLastAtom()
283-
a.xyz *= xcfg_A
284-
p_assign_atom(a, fields)
254+
fields = [float(w) for w in words]
255+
xyz = [xcfg_A * xi for xi in fields[:3]]
256+
stru.addNewAtom(p_element, xyz=xyz)
257+
a = stru[-1]
258+
_assign_auxiliaries(a, fields, auxiliaries=p_auxiliary,
259+
no_velocity=xcfg_NO_VELOCITY)
285260
else:
286261
emsg = "%d: invalid record" % p_nl
287262
raise StructureFormatError(emsg)
@@ -304,7 +279,7 @@ def toLines(self, stru):
304279
emsg = "cannot convert empty structure to XCFG format"
305280
raise StructureFormatError(emsg)
306281
lines = []
307-
lines.append( "Number of particles = %i" % len(stru) )
282+
lines.append("Number of particles = %i" % len(stru))
308283
# figure out length unit A
309284
allxyz = numpy.array([a.xyz for a in stru])
310285
lo_xyz = allxyz.min(axis=0)
@@ -318,7 +293,7 @@ def toLines(self, stru):
318293
hi_ucvect = max([numpy.sqrt(numpy.dot(v,v)) for v in stru.lattice.base])
319294
if hi_ucvect*p_A < 3.5:
320295
p_A = numpy.ceil(3.5 / hi_ucvect)
321-
lines.append( "A = %.8g Angstrom" % p_A )
296+
lines.append("A = %.8g Angstrom" % p_A)
322297
# how much do we need to shift the coordinates?
323298
p_dxyz = numpy.zeros(3, dtype=float)
324299
for i in range(3):
@@ -328,8 +303,8 @@ def toLines(self, stru):
328303
# H0 tensor
329304
for i in range(3):
330305
for j in range(3):
331-
lines.append( "H0(%i,%i) = %.8g A" % \
332-
(i+1, j+1, stru.lattice.base[i,j]) )
306+
lines.append("H0(%i,%i) = %.8g A" %
307+
(i + 1, j + 1, stru.lattice.base[i, j]))
333308
# get out for empty structure
334309
if len(stru) == 0: return lines
335310
a_first = stru[0]
@@ -347,7 +322,7 @@ def toLines(self, stru):
347322
# add occupancy if any atom has nonunit occupancy
348323
for a in stru:
349324
if a.occupancy != 1.0:
350-
p_auxiliaries.append( ('occupancy', 'a.occupancy') )
325+
p_auxiliaries.append(('occupancy', 'a.occupancy'))
351326
break
352327
# add temperature factor with as many terms as needed
353328
# check whether all temperature factors are zero or isotropic
@@ -363,36 +338,31 @@ def toLines(self, stru):
363338
if p_allUzero:
364339
pass
365340
elif p_allUiso:
366-
p_auxiliaries.append( ('Uiso', 'a.U[0,0]') )
341+
p_auxiliaries.append(('Uiso', 'uflat[0]'))
367342
else:
368-
p_auxiliaries.extend([ ('U11', 'a.U[0,0]'),
369-
('U22', 'a.U[1,1]'),
370-
('U33', 'a.U[2,2]') ])
343+
p_auxiliaries.extend([('U11', 'uflat[0]'),
344+
('U22', 'uflat[4]'),
345+
('U33', 'uflat[8]')])
371346
# check if there are off-diagonal elements
372347
allU = numpy.array([a.U for a in stru])
373348
if numpy.any(allU[:,0,1] != 0.0):
374-
p_auxiliaries.append( ('U12', 'a.U[0,1]') )
349+
p_auxiliaries.append(('U12', 'uflat[1]'))
375350
if numpy.any(allU[:,0,2] != 0.0):
376-
p_auxiliaries.append( ('U13', 'a.U[0,2]') )
351+
p_auxiliaries.append(('U13', 'uflat[2]'))
377352
if numpy.any(allU[:,1,2] != 0.0):
378-
p_auxiliaries.append( ('U23', 'a.U[1,2]') )
353+
p_auxiliaries.append(('U23', 'uflat[5]'))
379354
# count entries
380-
p_entry_count = 6 - 3*p_NO_VELOCITY + len(p_auxiliaries)
355+
p_entry_count = (3 if p_NO_VELOCITY else 6) + len(p_auxiliaries)
381356
lines.append("entry_count = %d" % p_entry_count)
382357
# add auxiliaries
383358
for i in range(len(p_auxiliaries)):
384359
lines.append("auxiliary[%d] = %s [au]" % (i, p_auxiliaries[i][0]))
385-
# now define p_entry_line function for representing atom properties
386-
p_exprs = [ "def p_entry_line(a, p_A, p_dxyz):",
387-
" fields = list( a.xyz/p_A+p_dxyz )" ]
360+
# now define entry format efmt for representing atom properties
361+
fmwords = ["{pos[0]:.8g}", "{pos[1]:.8g}", "{pos[2]:.8g}"]
388362
if not p_NO_VELOCITY:
389-
p_exprs.append( \
390-
" fields += [ a.v[0], a.v[1], a.v[2] ]" )
391-
p_exprs += [" fields += [ " +
392-
",".join([e for p,e in p_auxiliaries]) + " ]",
393-
" line = ' '.join([ '%.8g' % x for x in fields ])",
394-
" return line" ]
395-
exec "\n".join(p_exprs)
363+
fmwords += ["{v[0]:.8g}", "{v[1]:.8g}", "{v[2]:.8g}"]
364+
fmwords += (('{' + e + ':.8g}') for p, e in p_auxiliaries)
365+
efmt = ' '.join(fmwords)
396366
# we are ready to output atoms:
397367
lines.append("")
398368
p_element = None
@@ -401,15 +371,58 @@ def toLines(self, stru):
401371
p_element = a.element
402372
lines.append("%.4f" % AtomicMass.get(p_element, 0.0))
403373
lines.append(p_element)
404-
lines.append(p_entry_line(a, p_A, p_dxyz))
374+
pos = a.xyz / p_A + p_dxyz
375+
v = None if p_NO_VELOCITY else a.v
376+
uflat = numpy.ravel(a.U)
377+
entry = efmt.format(pos=pos, v=v, uflat=uflat, a=a)
378+
lines.append(entry)
405379
return lines
406380
# End of toLines
407381

408382
# End of class P_xcfg
409383

410-
# Routines
384+
# Routines -------------------------------------------------------------------
411385

412386
def getParser():
413387
return P_xcfg()
414388

389+
# Local Helpers --------------------------------------------------------------
390+
391+
def _assign_auxiliaries(a, fields, auxiliaries, no_velocity):
392+
"""\
393+
Assing auxiliary properties for Atom object when reading CFG format.
394+
395+
Parameters
396+
----------
397+
a : Atom
398+
The Atom instance for which the auxiliary properties need to be set.
399+
fields : list
400+
Floating point values for the current row of the processed CFG file.
401+
auxiliaries : dict
402+
Dictionary of zero-based indices and names of auxiliary properties
403+
defined in the CFG format.
404+
no_velocity : bool
405+
When `False` set atom velocity `a.v` to `fields[3:6]`.
406+
Use `fields[3:6]` for auxiliary values otherwise.
407+
408+
No return value.
409+
"""
410+
if not no_velocity:
411+
a.v = numpy.asarray(fields[3:6], dtype=float)
412+
auxfirst = 3 if no_velocity else 6
413+
for i, prop in auxiliaries.items():
414+
value = fields[auxfirst + i]
415+
if prop == "Uiso":
416+
a.Uisoequiv = value
417+
elif prop == "Biso":
418+
a.Bisoequiv = value
419+
elif prop[0] in 'BU' and all(d in '123' for d in prop[1:]):
420+
nm = (prop if prop[1] <= prop[2]
421+
else prop[0] + prop[2] + prop[1])
422+
a.anisotropy = True
423+
setattr(a, nm, value)
424+
else:
425+
setattr(a, prop, value)
426+
return
427+
415428
# End of file

src/diffpy/Structure/Parsers/structureparser.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,8 @@ def parseFile(self, filename):
7373
Raise StructureFormatError or IOError.
7474
"""
7575
self.filename = filename
76-
f = open(filename)
77-
s = f.read()
76+
with open(filename) as fp:
77+
s = fp.read()
7878
stru = self.parse(s)
7979
return stru
8080

0 commit comments

Comments
 (0)