1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 """Parser for PDFfit structure format
16 """
17
18 __id__ = "$Id: P_pdffit.py 2825 2009-03-09 04:33:12Z juhas $"
19
20 import sys
21 import numpy
22
23 from diffpy.Structure import PDFFitStructure, Lattice, Atom
24 from diffpy.Structure import StructureFormatError
25 from diffpy.Structure.Parsers import StructureParser
26
28 """Parser for PDFfit structure format.
29
30 stru -- Structure instance used for cif input or output
31 """
32
34 StructureParser.__init__(self)
35 self.format = "pdffit"
36 self.ignored_lines = []
37 self.stru = None
38 return
39
41 """Parse list of lines in PDFfit format.
42
43 Return Structure object or raise StructureFormatError.
44 """
45 p_nl = 0
46 rlist = []
47 try:
48 self.stru = PDFFitStructure()
49 stru = self.stru
50 cell_line_read = False
51 stop = len(lines)
52 while stop>0 and lines[stop-1].strip() == "":
53 stop -= 1
54 ilines = iter(lines[:stop])
55
56 for l in ilines:
57 p_nl += 1
58 words = l.split()
59 if len(words) == 0 or words[0][0] == '#':
60 continue
61 elif words[0] == 'title':
62 stru.title = l.lstrip()[5:].strip()
63 elif words[0] == 'scale':
64 stru.pdffit['scale'] = float(words[1])
65 elif words[0] == 'sharp':
66 l1 = l.replace(',', ' ')
67 sharp_pars = [ float(w) for w in l1.split()[1:] ]
68 if len(sharp_pars) < 4:
69 stru.pdffit['delta2'] = sharp_pars[0]
70 stru.pdffit['sratio'] = sharp_pars[1]
71 stru.pdffit['rcut'] = sharp_pars[2]
72 else:
73 stru.pdffit['delta2'] = sharp_pars[0]
74 stru.pdffit['delta1'] = sharp_pars[1]
75 stru.pdffit['sratio'] = sharp_pars[2]
76 stru.pdffit['rcut'] = sharp_pars[3]
77 elif words[0] == 'spcgr':
78 key = 'spcgr'
79 start = l.find(key) + len(key)
80 value = l[start:].strip()
81 stru.pdffit['spcgr'] = value
82 elif words[0] == 'shape':
83 self._parse_shape(l)
84 elif words[0] == 'cell':
85 cell_line_read = True
86 l1 = l.replace(',', ' ')
87 latpars = [ float(w) for w in l1.split()[1:7] ]
88 stru.lattice = Lattice(*latpars)
89 elif words[0] == 'dcell':
90 l1 = l.replace(',', ' ')
91 stru.pdffit['dcell'] = [ float(w) for w in l1.split()[1:7] ]
92 elif words[0] == 'ncell':
93 l1 = l.replace(',', ' ')
94 stru.pdffit['ncell'] = [ int(w) for w in l1.split()[1:5] ]
95 elif words[0] == 'format':
96 if words[1] != 'pdffit':
97 emsg = "%d: file is not in PDFfit format" % p_nl
98 raise StructureFormatError(emsg)
99 elif words[0] == 'atoms' and cell_line_read:
100 break
101 else:
102 self.ignored_lines.append(l)
103
104 if not cell_line_read:
105 emsg = "%d: file is not in PDFfit format" % p_nl
106 raise StructureFormatError(emsg)
107
108 p_natoms = reduce(lambda x,y : x*y, stru.pdffit['ncell'])
109
110 for l in ilines:
111 p_nl += 1
112 wl1 = l.split()
113 element = wl1[0][0].upper() + wl1[0][1:].lower()
114 xyz = [ float(w) for w in wl1[1:4] ]
115 occ = float(wl1[4])
116 stru.addNewAtom(element, xyz=xyz, occupancy=occ)
117 a = stru.getLastAtom()
118 p_nl += 1
119 wl2 = ilines.next().split()
120 a.sigxyz = [ float(w) for w in wl2[0:3] ]
121 a.sigo = float(wl2[3])
122 p_nl += 1
123 wl3 = ilines.next().split()
124 p_nl += 1
125 wl4 = ilines.next().split()
126 p_nl += 1
127 wl5 = ilines.next().split()
128 p_nl += 1
129 wl6 = ilines.next().split()
130 a.sigU = numpy.zeros((3,3), dtype=float)
131 a.U11 = float(wl3[0])
132 a.U22 = float(wl3[1])
133 a.U33 = float(wl3[2])
134 a.sigU[0,0] = float(wl4[0])
135 a.sigU[1,1] = float(wl4[1])
136 a.sigU[2,2] = float(wl4[2])
137 a.U12 = float(wl5[0])
138 a.U13 = float(wl5[1])
139 a.U23 = float(wl5[2])
140 a.sigU[0,1] = a.sigU[1,0] = float(wl6[0])
141 a.sigU[0,2] = a.sigU[2,0] = float(wl6[1])
142 a.sigU[1,2] = a.sigU[2,1] = float(wl6[2])
143 if len(stru) != p_natoms:
144 emsg = "expected %d atoms, read %d" % (p_natoms, len(stru))
145 raise StructureFormatError(emsg)
146 if stru.pdffit['ncell'][:3] != [1,1,1]:
147 superlatpars = [ latpars[i]*stru.pdffit['ncell'][i]
148 for i in range(3) ] + latpars[3:]
149 superlattice = Lattice(*superlatpars)
150 stru.placeInLattice(superlattice)
151 stru.pdffit['ncell'] = [1, 1, 1, p_natoms]
152 except (ValueError, IndexError):
153 emsg = "%d: file is not in PDFfit format" % p_nl
154 exc_type, exc_value, exc_traceback = sys.exc_info()
155 raise StructureFormatError, emsg, exc_traceback
156 return stru
157
158
159
160
162 """Convert Structure stru to a list of lines in PDFfit format.
163
164 Return list of strings.
165 """
166
167 if not isinstance(stru, PDFFitStructure):
168 pfstru = PDFFitStructure()
169 pfstru.__dict__.update(stru.__dict__)
170 pfstru[:] = stru[:]
171 stru = pfstru
172 lines = []
173
174 d_sigxyz = numpy.zeros(3, dtype=float)
175 d_sigo = 0.0
176 d_sigU = numpy.zeros((3,3), dtype=float)
177
178 l = "title " + stru.title
179 lines.append( l.strip() )
180 lines.append( "format pdffit" )
181 lines.append( "scale %9.6f" % stru.pdffit["scale"] )
182 lines.append( "sharp %9.6f, %9.6f, %9.6f, %9.6f" % (
183 stru.pdffit["delta2"],
184 stru.pdffit["delta1"],
185 stru.pdffit["sratio"],
186 stru.pdffit["rcut"]) )
187 lines.append( "spcgr " + stru.pdffit["spcgr"] )
188 if stru.pdffit.get('spdiameter', 0.0) > 0.0:
189 line = 'shape sphere, %g' % stru.pdffit['spdiameter']
190 lines.append(line)
191 if stru.pdffit.get('stepcut', 0.0) > 0.0:
192 line = 'shape stepcut, %g' % stru.pdffit['stepcut']
193 lines.append(line)
194 lat = stru.lattice
195 lines.append( "cell %9.6f, %9.6f, %9.6f, %9.6f, %9.6f, %9.6f" % (
196 lat.a, lat.b, lat.c, lat.alpha, lat.beta, lat.gamma) )
197 lines.append( "dcell %9.6f, %9.6f, %9.6f, %9.6f, %9.6f, %9.6f" %
198 tuple(stru.pdffit["dcell"]) )
199 lines.append( "ncell %9i, %9i, %9i, %9i" % (1, 1, 1, len(stru)) )
200 lines.append( "atoms" )
201 for a in stru:
202 ad = a.__dict__
203 lines.append( "%-4s %17.8f %17.8f %17.8f %12.4f" % (
204 a.element.upper(), a.xyz[0], a.xyz[1], a.xyz[2], a.occupancy) )
205 sigmas = numpy.concatenate(
206 ( ad.get("sigxyz", d_sigxyz), [ad.get("sigo", d_sigo)] ) )
207 lines.append( " %18.8f %17.8f %17.8f %12.4f" % tuple(sigmas) )
208 sigU = ad.get("sigU", d_sigU)
209 Uii = ( a.U[0][0], a.U[1][1], a.U[2][2] )
210 Uij = ( a.U[0][1], a.U[0][2], a.U[1][2] )
211 sigUii = ( sigU[0][0], sigU[1][1], sigU[2][2] )
212 sigUij = ( sigU[0][1], sigU[0][2], sigU[1][2] )
213 lines.append( " %18.8f %17.8f %17.8f" % Uii )
214 lines.append( " %18.8f %17.8f %17.8f" % sigUii )
215 lines.append( " %18.8f %17.8f %17.8f" % Uij )
216 lines.append( " %18.8f %17.8f %17.8f" % sigUij )
217 return lines
218
219
220
221
222
223
224
226 """Process shape line from PDFfit file and update self.stru
227
228 line -- line containing data for particle shape correction
229
230 No return value.
231 Raise StructureFormatError for invalid record.
232 """
233 line_nocommas = line.replace(',', ' ')
234 words = line_nocommas.split()
235 assert words[0] == 'shape'
236 shapetype = words[1]
237 if shapetype == 'sphere':
238 self.stru.pdffit['spdiameter'] = float(words[2])
239 elif shapetype == 'stepcut':
240 self.stru.pdffit['stepcut'] = float(words[2])
241 else:
242 emsg = 'Invalid type of particle shape correction %r' % shapetype
243 raise StructureFormatError, emsg
244 return
245
246
247
248
249
250
253
254
255