Skip to content

Commit 116a076

Browse files
committed
new importer for RRUFF database entries
1 parent db0326a commit 116a076

File tree

2 files changed

+168
-0
lines changed

2 files changed

+168
-0
lines changed

GSASII/imports/G2phase_RRUFF.py

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
# -*- coding: utf-8 -*-
2+
'''Reads structure files downloaded from the RRUFF database either as ASCII
3+
text files or .rtf files that somehow are generated
4+
'''
5+
from __future__ import division, print_function
6+
import sys
7+
import numpy as np
8+
import random as ran
9+
from .. import GSASIIobj as G2obj
10+
from .. import GSASIIspc as G2spc
11+
from .. import GSASIIlattice as G2lat
12+
13+
class PhaseReaderClass(G2obj.ImportPhase):
14+
'''A quickly-written importer to open a .txt file from the RRUFF database
15+
https://rruff.info
16+
and pull out the phase info
17+
'''
18+
def __init__(self):
19+
super(self.__class__,self).__init__( # fancy way to say ImportPhase.__init__
20+
extensionlist=('.txt'),
21+
strictExtension=True,
22+
formatName = 'RRUFF DIF file',
23+
longFormatName = 'RRUFF database DIF file download (*.txt)'
24+
)
25+
26+
def ContentsValidator(self, filename):
27+
"Test if the file has CELL PARAMETERS: and SPACE GROUP: entries"
28+
with open(filename,'r') as fp:
29+
txt = fp.read()
30+
status = True
31+
for s in ('CELL PARAMETERS:','SPACE GROUP:'):
32+
if not s in txt:
33+
print(s,'not found')
34+
if self.errors is None: self.errors = ''
35+
self.errors += f'no {s} record found; not valid. '
36+
status = False
37+
if not ' ATOM ' in txt:
38+
print('ATOM line not found')
39+
if self.errors is None: self.errors = ''
40+
self.errors += 'no ATOM record found; no structure. '
41+
status = False
42+
fp.close()
43+
return status
44+
45+
def Reader(self,filename,ParentFrame=None, **unused):
46+
'Read a DIF file from RRUFF'
47+
#self.errors = 'Error opening file'
48+
Title = ''
49+
atomsmode = False
50+
fp = open(filename, 'r')
51+
SGData = None
52+
Atoms = []
53+
cell = None
54+
for line in fp.readlines():
55+
if len(line) == 0: continue
56+
line = line.strip()
57+
if atomsmode:
58+
# all DIF files appear to have atoms as element, X, Y, Z, OCCUPANCY, ISO(B)
59+
if r'\par' in line: # some files seem to have some formatting
60+
line = line.split('\\par')[0]
61+
try:
62+
Atype = line.split()[0]
63+
x,y,z,Afrac,B = [float(i) for i in line.split()[1:]]
64+
Uiso = B/(8*np.pi**2)
65+
XYZ = np.array([float(x),float(y),float(z)])
66+
XYZ = np.where(np.abs(XYZ)<0.00001,0,XYZ)
67+
SytSym,Mult = G2spc.SytSym(XYZ,SGData)[:2]
68+
IA = 'I'
69+
i = 1
70+
while f"{Atype}{i}" in [i[0] for i in Atoms]:
71+
i += 1
72+
if i > 999:
73+
Aname = f"{Atype}?"
74+
break
75+
else:
76+
Aname = f"{Atype}{i}"
77+
if Atype.upper() in ['WA','OH','OW','OA','OB','OC','OD','OE','OL','OP','OO']:
78+
Atype = 'O'
79+
Atom = [Aname,Atype,'',x,y,z,Afrac,SytSym,Mult,IA,Uiso]
80+
Atom += 6*[0]
81+
Atom.append(ran.randint(0,sys.maxsize))
82+
Atoms.append(Atom)
83+
except:
84+
atomsmode = False
85+
break
86+
if Title == '':
87+
if '\\rtf' in line: continue
88+
Title = line
89+
if r'\par' in line: # some files seem to have some formatting
90+
Title = line.split()[-1].split('\\')[0]
91+
if 'CELL PARAMETERS:' in line:
92+
L = line.split(':')[1]
93+
if r'\par' in line: # some files seem to have some formatting
94+
L = L.split('\\par')[0]
95+
cellRec = L.split()
96+
abc = cellRec[0:3]
97+
angles = cellRec[3:]
98+
cell=[float(abc[0]),float(abc[1]),float(abc[2]),
99+
float(angles[0]),float(angles[1]),float(angles[2])]
100+
Volume = float(G2lat.calc_V(G2lat.cell2A(cell)))
101+
elif 'SPACE GROUP:' in line:
102+
SGData = G2obj.P1SGData # P 1
103+
S = line.split(':')[1].strip()
104+
if r'\par' in S: # some files seem to have some formatting
105+
S = S.split()[0]
106+
Sinit = S
107+
E,SGData = G2spc.SpcGroup(S)
108+
if E:
109+
SpGrpNorm = G2spc.StandardizeSpcName(S)
110+
if SpGrpNorm:
111+
E,SGData = G2spc.SpcGroup(SpGrpNorm)
112+
if E and '_' in S:
113+
S = S.replace('_','')
114+
if E:
115+
E,SGData = G2spc.SpcGroup(S[0]+' '+S[1:])
116+
# some space group names that show up in RRUFF
117+
SGfixDict = {'B2/b': 'B 2/b 1 1', 'Bb21m':'B b 21 m',
118+
'P21/b': 'P 21/b 1 1', 'P21212': 'P 21 21 2',
119+
'P21ca': 'P 21 c a', 'P21cn': 'P 21 c n',
120+
'P21nb': 'P21 n b', 'P21nm': 'P21 n m',
121+
'P63cm': 'P63 c m', 'P63mc': 'P63 m c',
122+
'Pn21a': 'P n 21 a', 'Pn21m': 'P n 21 m'}
123+
124+
if E and S in SGfixDict:
125+
E,SGData = G2spc.SpcGroup(SGfixDict[S])
126+
if E:
127+
self.warnings += f'ERROR in space group symbol {Sinit!r}'
128+
self.warnings += '\nThe space group has been set to "P 1". '
129+
self.warnings += "Change this in phase's General tab."
130+
self.warnings += " Error msg="+G2spc.SGErrors(E)
131+
print(self.warnings)
132+
#import GSASII.GSASIIpath
133+
#GSASII.GSASIIpath.IPyBreak_base()
134+
elif SGData['SpGrp'] in G2spc.spg2origins:
135+
self.warnings += f"WARNING space group {SGData['SpGrp']} has two Origins"
136+
#import GSASII.GSASIIpath
137+
#GSASII.GSASIIpath.IPyBreak_base()
138+
elif 'ATOM ' in line:
139+
atomsmode = True
140+
if SGData is None:
141+
if self.errors is None: self.errors = ''
142+
self.errors += 'no Space Group record found; not valid. '
143+
return False
144+
if cell is None:
145+
if self.errors is None: self.errors = ''
146+
self.errors += 'no CELL record found; not valid. '
147+
return False
148+
if len(Atoms) == 0:
149+
if self.errors is None: self.errors = ''
150+
self.errors += 'no Atoms found; not valid. '
151+
return False
152+
if cell[3] == cell[4] == cell[5] and cell[3] != 90:
153+
self.warnings += f'Note: {filename!r} has rhombohedral cell, changing space group'
154+
E,SGData = G2spc.SpcGroup(SGData['SpGrp'] + ' R')
155+
print(self.warnings)
156+
#import GSASII.GSASIIpath
157+
#GSASII.GSASIIpath.IPyBreak_base()
158+
#breakpoint()
159+
self.MPhase = None
160+
self.Phase = G2obj.SetNewPhase(Name=Title,SGData=SGData,cell=cell+[Volume,])
161+
self.Phase['General']['Name'] = Title
162+
self.Phase['General']['Type'] = 'nuclear'
163+
self.Phase['General']['AtomPtrs'] = [3,1,7,9]
164+
self.Phase['Atoms'] = Atoms
165+
fp.close()
166+
return True

GSASII/imports/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
from . import G2phase_GPX
1818
from . import G2phase_INS
1919
from . import G2phase_rmc6f
20+
from . import G2phase_RRUFF
2021
from . import G2phase_xyz
2122
from . import G2pwd_BrukerBRML
2223
from . import G2pwd_BrukerRAW
@@ -56,6 +57,7 @@
5657
"G2phase_GPX",
5758
"G2phase_INS",
5859
"G2phase_rmc6f",
60+
"G2phase_RRUFF",
5961
"G2phase_xyz",
6062
"G2pwd_BrukerBRML",
6163
"G2pwd_BrukerRAW",

0 commit comments

Comments
 (0)