source: trunk/imports/G2phase_CIF.py @ 850

Last change on this file since 850 was 850, checked in by vondreele, 10 years ago

fix problem with atoms with An+ style of valence
more places for size results
more rigid body work
allow for skinnier images

  • Property svn:eol-style set to native
File size: 10.2 KB
Line 
1# -*- coding: utf-8 -*-
2########### SVN repository information ###################
3# $Date: 2012-02-13 11:33:35 -0600 (Mon, 13 Feb 2012) $
4# $Author: vondreele & toby $
5# $Revision: 482 $
6# $URL: https://subversion.xor.aps.anl.gov/pyGSAS/trunk/G2importphase_CIF.py $
7# $Id: G2importphase_CIF.py 482 2012-02-13 17:33:35Z vondreele $
8########### SVN repository information ###################
9# Routines to import Phase information from CIF files
10import sys
11import random as ran
12import GSASIIIO as G2IO
13import GSASIIspc as G2spc
14import GSASIIElem as G2elem
15import GSASIIlattice as G2lat
16import CifFile as cif # PyCifRW from James Hester
17import urllib
18
19class CIFPhaseReader(G2IO.ImportPhase):
20    def __init__(self):
21        super(self.__class__,self).__init__( # fancy way to say ImportPhase.__init__
22            extensionlist=('.CIF','.cif'),
23            strictExtension=False,
24            formatName = 'CIF',
25            longFormatName = 'Crystallographic Information File import'
26            )
27    def ContentsValidator(self, filepointer):
28        for i,line in enumerate(filepointer):
29            if i >= 1000: break
30            ''' Encountered only blank lines or comments in first 1000
31            lines. This is unlikely, but assume it is CIF since we are
32            even less likely to find a file with nothing but hashes and
33            blank lines'''
34            line = line.strip()
35            if len(line) == 0:
36                continue # ignore blank lines
37            elif line.startswith('#'):
38                continue # ignore comments
39            elif line.startswith('data_'):
40                return True
41            else:
42                return False # found something else
43        return True
44    def Reader(self,filename,filepointer, ParentFrame=None, **unused):
45        returnstat = False
46        cellitems = (
47            '_cell_length_a','_cell_length_b','_cell_length_c',
48            '_cell_angle_alpha','_cell_angle_beta','_cell_angle_gamma',)
49        reqitems = (
50             '_atom_site_fract_x',
51             '_atom_site_fract_y',
52             '_atom_site_fract_z',
53            )
54        phasenamefields = (
55            '_chemical_name_common',
56            '_pd_phase_name',
57            '_chemical_formula_sum'
58            )
59        try:
60#### development code (to speed testing)
61#            try:
62#                    fp = open(filename+'cP',"rb")
63#                    print("reading from "+filename+'cP')
64#                    cf = cPickle.load(fp)
65#                    fp.close()
66#            except:
67#                    cf = cif.ReadCif(filename)
68#                    fp = open(filename+'cP',"wb")
69#                    cPickle.dump(cf,fp)
70#                    fp.close()
71####
72#### end development code
73            self.ShowBusy() # this can take a while
74            ciffile = 'file:'+urllib.pathname2url(filename)
75            cf = cif.ReadCif(ciffile)
76            self.DoneBusy()
77            #print cf
78            # scan blocks for structural info
79            str_blklist = []
80            for blk in cf.keys():
81                for r in reqitems+cellitems:
82                    if r not in cf[blk].keys():
83                        break
84                else:
85                    str_blklist.append(blk)
86            if not str_blklist:
87                selblk = None # no block to choose
88            elif len(str_blklist) == 1: # only one choice
89                selblk = 0
90            else:                       # choose from options
91                choice = []
92                for blknm in str_blklist:
93                    choice.append('')
94                    # accumumlate some info about this phase
95                    choice[-1] += blknm + ': '
96                    for i in phasenamefields: # get a name for the phase
97                        name = cf[blknm].get(i)
98                        if name is None or name == '?' or name == '.':
99                            continue
100                        else:
101                            choice[-1] += name.strip()[:20] + ', '
102                            break
103                    na = len(cf[blknm].get("_atom_site_fract_x"))
104                    if na == 1:
105                        choice[-1] += '1 atom'
106                    else:
107                        choice[-1] += ('%d' % nd) + ' atoms'
108                    choice[-1] += ', cell: '
109                    fmt = "%.2f,"
110                    for i,key in enumerate(cellitems):
111                        if i == 3: fmt = "%.f,"
112                        if i == 5: fmt = "%.f"
113                        choice[-1] += fmt % cif.get_number_with_esd(
114                            cf[blknm].get(key))[0]
115                    sg = cf[blknm].get("_symmetry_space_group_name_H-M")
116                    if sg: choice[-1] += ', (' + sg.strip() + ')'
117                selblk = self.PhaseSelector(
118                    choice,
119                    ParentFrame=ParentFrame,
120                    title= 'Select a phase from one the CIF data_ blocks below',
121                    size=(600,100)
122                    )
123            if selblk is None:
124                returnstat = False # no block selected or available
125            else:
126                blknm = str_blklist[selblk]
127                blk = cf[str_blklist[selblk]]
128                E = True
129                SpGrp = blk.get("_symmetry_space_group_name_H-M")
130                # try normalizing the space group, see if we can pick the space group out of a table
131                SpGrpNorm = G2spc.StandardizeSpcName(SpGrp)
132                if SpGrpNorm:
133                    E,SGData = G2spc.SpcGroup(SpGrpNorm)
134                # nope, try the space group "out of the Box"
135                if E and SpGrp:
136                    E,SGData = G2spc.SpcGroup(SpGrp)
137                if E:
138                    self.warnings += 'ERROR in space group symbol '+SpGrp
139                    self.warnings += '\nAre there spaces separating axial fields?\n\nError msg: '
140                    self.warnings += G2spc.SGErrors(E)
141                    SGData = G2IO.SGData # P 1
142                self.Phase['General']['SGData'] = SGData
143                # cell parameters
144                cell = []
145                for lbl in (
146                    '_cell_length_a','_cell_length_b','_cell_length_c',
147                    '_cell_angle_alpha','_cell_angle_beta','_cell_angle_gamma',
148                    ):
149                    cell.append(cif.get_number_with_esd(blk[lbl])[0])
150                Volume = G2lat.calc_V(G2lat.cell2A(cell))
151                self.Phase['General']['Cell'] = [False,]+cell+[Volume,]
152                # read in atoms
153                atomloop = blk.GetLoop('_atom_site_label')
154                atomkeys = [i.lower() for i in atomloop.keys()]
155                if blk.get('_atom_site_aniso_label'):
156                    anisoloop = blk.GetLoop('_atom_site_aniso_label')
157                    anisokeys = [i.lower() for i in anisoloop.keys()]
158                else:
159                    anisoloop = None
160                    anisokeys = []
161                self.Phase['Atoms'] = []
162                G2AtomDict = {  '_atom_site_type_symbol' : 1,
163                                '_atom_site_label' : 0,
164                                '_atom_site_fract_x' : 3,
165                                '_atom_site_fract_y' : 4,
166                                '_atom_site_fract_z' : 5,
167                                '_atom_site_occupancy' : 6,
168                                '_atom_site_aniso_u_11' : 11,
169                                '_atom_site_aniso_u_22' : 12,
170                                '_atom_site_aniso_u_33' : 13,
171                                '_atom_site_aniso_u_12' : 14,
172                                '_atom_site_aniso_u_13' : 15,
173                                '_atom_site_aniso_u_23' : 16, }
174                for aitem in atomloop:
175                    atomlist = ['','','',0,0,0,1.0,'',0,'I',0.01,0,0,0,0,0,0]
176                    atomlist.append(ran.randint(0,sys.maxint)) # add a unique label
177                    for val,key in zip(aitem,atomkeys):
178                        col = G2AtomDict.get(key)
179                        if col >= 3:
180                            atomlist[col] = cif.get_number_with_esd(val)[0]
181                        elif col is not None:
182                            atomlist[col] = val
183                        elif key in ('_atom_site_thermal_displace_type',
184                                   '_atom_site_adp_type'):   #Iso or Aniso?
185                            if val.lower() == 'uani':
186                                atomlist[9] = 'A'
187                        elif key == '_atom_site_u_iso_or_equiv':
188                            atomlist[10] =cif.get_number_with_esd(val)[0]
189                    if not atomlist[1] and atomlist[0]:
190                        for i in range(2,0,-1):
191                            typ = atomlist[0].strip()[:i]
192                            if G2elem.CheckElement(typ):
193                                atomlist[1] = typ
194                            if not atomlist[1]: atomlist[1] = 'Xe'
195                    ulbl = '_atom_site_aniso_label'
196                    if  atomlist[9] == 'A' and atomlist[0] in blk.get(ulbl):
197                        for val,key in zip(anisoloop.GetKeyedPacket(ulbl,atomlist[0]),
198                                           anisokeys):
199                            col = G2AtomDict.get(key)
200                            if col:
201                                atomlist[col] = cif.get_number_with_esd(val)[0]
202                    atomlist[7],atomlist[8] = G2spc.SytSym(atomlist[3:6],SGData)
203                    atomlist[1] = G2elem.FixValence(atomlist[1])
204                    self.Phase['Atoms'].append(atomlist)
205                for lbl in phasenamefields: # get a name for the phase
206                    name = blk.get(lbl)
207                    if name is None:
208                        continue
209                    name = name.strip()
210                    if name == '?' or name == '.':
211                        continue
212                    else:
213                        break
214                else: # no name found, use block name for lack of a better choice
215                    name = blknm
216                self.Phase['General']['Name'] = name.strip()[:20]
217                returnstat = True
218        except Exception as detail:
219            print 'CIF error:',detail # for testing
220            print sys.exc_info()[0] # for testing
221            import traceback
222            print traceback.format_exc()
223            returnstat = False
224        return returnstat
Note: See TracBrowser for help on using the repository browser.