source: trunk/G2importphase_CIF.py @ 523

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

fix plotting with as-inititalized values (oldxy & Fourier map); fix CIF import; fix command-line load; fix early Destroy in SumDialog?

File size: 9.2 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        cellitems = (
46            '_cell_length_a','_cell_length_b','_cell_length_c',
47            '_cell_angle_alpha','_cell_angle_beta','_cell_angle_gamma',)
48        reqitems = (
49             '_atom_site_type_symbol',
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            print cf
77            # scan blocks for structural info
78            str_blklist = []
79            for blk in cf.keys():
80                for r in reqitems+cellitems:
81                    if r not in cf[blk].keys():
82                        break
83                else:
84                    str_blklist.append(blk)
85            self.DoneBusy()
86            if not str_blklist:
87                return False            # no blocks with coordinates
88            elif len(str_blklist) == 1: # no choices
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: return False # User pressed cancel
124            blknm = str_blklist[selblk]
125            blk = cf[str_blklist[selblk]]
126            SpGrp = blk.get("_symmetry_space_group_name_H-M")
127            if SpGrp:
128                 E,SGData = G2spc.SpcGroup(SpGrp)
129            if E:
130                self.warnings += ' ERROR in space group symbol '+SpGrp
131                self.warnings += ' N.B.: make sure spaces separate axial fields in symbol' 
132                self.warnings += G2spc.SGErrors(E)
133            else:
134                self.Phase['General']['SGData'] = SGData
135            # cell parameters
136            cell = []
137            for lbl in (
138                '_cell_length_a','_cell_length_b','_cell_length_c',
139                '_cell_angle_alpha','_cell_angle_beta','_cell_angle_gamma',
140                ):
141                cell.append(cif.get_number_with_esd(blk[lbl])[0])
142            Volume = G2lat.calc_V(G2lat.cell2A(cell))
143            self.Phase['General']['Cell'] = [False,]+cell+[Volume,]
144            # read in atoms
145            atomloop = blk.GetLoop('_atom_site_label')
146            atomkeys = [i.lower() for i in atomloop.keys()]
147            if blk.get('_atom_site_aniso_label'):
148                anisoloop = blk.GetLoop('_atom_site_aniso_label')
149                anisokeys = [i.lower() for i in anisoloop.keys()]
150            else:
151                anisoloop = None
152                anisokeys = []
153            self.Phase['Atoms'] = []
154            G2AtomDict = {  '_atom_site_type_symbol' : 1,
155                            '_atom_site_label' : 0,
156                            '_atom_site_fract_x' : 3,
157                            '_atom_site_fract_y' : 4,
158                            '_atom_site_fract_z' : 5,
159                            '_atom_site_occupancy' : 6,
160                            '_atom_site_aniso_u_11' : 11,
161                            '_atom_site_aniso_u_22' : 12,
162                            '_atom_site_aniso_u_33' : 13,
163                            '_atom_site_aniso_u_12' : 14,
164                            '_atom_site_aniso_u_13' : 15,
165                            '_atom_site_aniso_u_23' : 16, }
166            for aitem in atomloop:
167                atomlist = ['','','',0,0,0,1.0,'',0,'I',0.01,0,0,0,0,0,0]
168                atomlist.append(ran.randint(0,sys.maxint)) # add a unique label
169                for val,key in zip(aitem,atomkeys):
170                    col = G2AtomDict.get(key)
171                    if col >= 3:
172                        atomlist[col] = cif.get_number_with_esd(val)[0]
173                    elif col is not None:
174                        atomlist[col] = val
175                    elif key in ('_atom_site_thermal_displace_type',
176                               '_atom_site_adp_type'):   #Iso or Aniso?
177                        if val.lower() == 'uani':
178                            atomlist[9] = 'A'
179                    elif key == '_atom_site_u_iso_or_equiv':
180                        atomlist[10] =cif.get_number_with_esd(val)[0]
181                ulbl = '_atom_site_aniso_label'
182                if  atomlist[9] == 'A' and atomlist[0] in blk.get(ulbl):
183                    for val,key in zip(anisoloop.GetKeyedPacket(ulbl,atomlist[0]),
184                                       anisokeys):
185                        col = G2AtomDict.get(key)
186                        if col:
187                            atomlist[col] = cif.get_number_with_esd(val)[0]
188                atomlist[7],atomlist[8] = G2spc.SytSym(atomlist[3:6],SGData)
189                self.Phase['Atoms'].append(atomlist)
190            for lbl in phasenamefields: # get a name for the phase
191                name = blk.get(lbl)
192                if name is None:
193                    continue
194                name = name.strip()
195                if name == '?' or name == '.':
196                    continue
197                else:
198                    break
199            else: # no name found, use block name for lack of a better choice
200                name = blknm
201            self.Phase['General']['Name'] = name.strip()[:20]
202            return True
203        except Exception as detail:
204            print 'CIF error:',detail # for testing
205            print sys.exc_info()[0] # for testing
206            import traceback
207            print traceback.format_exc()
208            return False
209        finally:
210            self.DoneBusy()
211
Note: See TracBrowser for help on using the repository browser.