|
| 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 |
0 commit comments