source: branch/MPbranch/G2importphase_CIF.py @ 4755

Last change on this file since 4755 was 484, checked in by vondreele, 13 years ago

change authorship
split GSASIIelem into a GUI & non-GUI parts
replace MsgDialogs? in GSASIIElem.py with simple prints
cleanup & refactor distance/angle/torsion calcs.

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