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