source: trunk/G2importphase_CIF.py @ 525

Last change on this file since 525 was 525, checked in by toby, 10 years ago

reorder CIF logic to return after finally for better clarity

File size: 9.6 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
15import urllib
16
17class CIFPhaseReader(G2IO.ImportPhase):
18    def __init__(self):
19        super(self.__class__,self).__init__( # fancy way to say ImportPhase.__init__
20            #extensionlist=('.CIF','.cif'),
21            extensionlist=('.CIF','.cif','.pdb'), # just for test!
22            strictExtension=False,
23            formatName = 'CIF',
24            longFormatName = 'Crystallographic Information File import'
25            )
26    def ContentsValidator(self, filepointer):
27        filepointer.seek(0) # rewind the file pointer
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):
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_type_symbol',
51             '_atom_site_fract_x',
52             '_atom_site_fract_y',
53             '_atom_site_fract_z',
54            )
55        phasenamefields = (
56            '_chemical_name_common',
57            '_pd_phase_name',
58            '_chemical_formula_sum'
59            )
60        try:
61#### development code (to speed testing)
62#            try:
63#                    fp = open(filename+'cP',"rb")
64#                    print("reading from "+filename+'cP')
65#                    cf = cPickle.load(fp)
66#                    fp.close()
67#            except:
68#                    cf = cif.ReadCif(filename)
69#                    fp = open(filename+'cP',"wb")
70#                    cPickle.dump(cf,fp)
71#                    fp.close()
72####
73#### end development code
74            self.ShowBusy() # this can take a while
75            ciffile = 'file:'+urllib.pathname2url(filename)
76            cf = cif.ReadCif(ciffile)
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).strip()
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                SpGrp = blk.get("_symmetry_space_group_name_H-M")
129                if SpGrp:
130                     E,SGData = G2spc.SpcGroup(SpGrp)
131                if E:
132                    self.warnings += ' ERROR in space group symbol '+SpGrp
133                    self.warnings += ' N.B.: make sure spaces separate axial fields in symbol' 
134                    self.warnings += G2spc.SGErrors(E)
135                else:
136                    self.Phase['General']['SGData'] = SGData
137                # cell parameters
138                cell = []
139                for lbl in (
140                    '_cell_length_a','_cell_length_b','_cell_length_c',
141                    '_cell_angle_alpha','_cell_angle_beta','_cell_angle_gamma',
142                    ):
143                    cell.append(cif.get_number_with_esd(blk[lbl])[0])
144                Volume = G2lat.calc_V(G2lat.cell2A(cell))
145                self.Phase['General']['Cell'] = [False,]+cell+[Volume,]
146                # read in atoms
147                atomloop = blk.GetLoop('_atom_site_label')
148                atomkeys = [i.lower() for i in atomloop.keys()]
149                if blk.get('_atom_site_aniso_label'):
150                    anisoloop = blk.GetLoop('_atom_site_aniso_label')
151                    anisokeys = [i.lower() for i in anisoloop.keys()]
152                else:
153                    anisoloop = None
154                    anisokeys = []
155                self.Phase['Atoms'] = []
156                G2AtomDict = {  '_atom_site_type_symbol' : 1,
157                                '_atom_site_label' : 0,
158                                '_atom_site_fract_x' : 3,
159                                '_atom_site_fract_y' : 4,
160                                '_atom_site_fract_z' : 5,
161                                '_atom_site_occupancy' : 6,
162                                '_atom_site_aniso_u_11' : 11,
163                                '_atom_site_aniso_u_22' : 12,
164                                '_atom_site_aniso_u_33' : 13,
165                                '_atom_site_aniso_u_12' : 14,
166                                '_atom_site_aniso_u_13' : 15,
167                                '_atom_site_aniso_u_23' : 16, }
168                for aitem in atomloop:
169                    atomlist = ['','','',0,0,0,1.0,'',0,'I',0.01,0,0,0,0,0,0]
170                    atomlist.append(ran.randint(0,sys.maxint)) # add a unique label
171                    for val,key in zip(aitem,atomkeys):
172                        col = G2AtomDict.get(key)
173                        if col >= 3:
174                            atomlist[col] = cif.get_number_with_esd(val)[0]
175                        elif col is not None:
176                            atomlist[col] = val
177                        elif key in ('_atom_site_thermal_displace_type',
178                                   '_atom_site_adp_type'):   #Iso or Aniso?
179                            if val.lower() == 'uani':
180                                atomlist[9] = 'A'
181                        elif key == '_atom_site_u_iso_or_equiv':
182                            atomlist[10] =cif.get_number_with_esd(val)[0]
183                    ulbl = '_atom_site_aniso_label'
184                    if  atomlist[9] == 'A' and atomlist[0] in blk.get(ulbl):
185                        for val,key in zip(anisoloop.GetKeyedPacket(ulbl,atomlist[0]),
186                                           anisokeys):
187                            col = G2AtomDict.get(key)
188                            if col:
189                                atomlist[col] = cif.get_number_with_esd(val)[0]
190                    atomlist[7],atomlist[8] = G2spc.SytSym(atomlist[3:6],SGData)
191                    self.Phase['Atoms'].append(atomlist)
192                for lbl in phasenamefields: # get a name for the phase
193                    name = blk.get(lbl)
194                    if name is None:
195                        continue
196                    name = name.strip()
197                    if name == '?' or name == '.':
198                        continue
199                    else:
200                        break
201                else: # no name found, use block name for lack of a better choice
202                    name = blknm
203                self.Phase['General']['Name'] = name.strip()[:20]
204                returnstat = True
205        except Exception as detail:
206            print 'CIF error:',detail # for testing
207            print sys.exc_info()[0] # for testing
208            import traceback
209            print traceback.format_exc()
210            returnstat = False
211        finally:
212            self.DoneBusy()
213        return returnstat
Note: See TracBrowser for help on using the repository browser.