source: trunk/imports/G2sfact_CIF.py @ 1069

Last change on this file since 1069 was 1069, checked in by toby, 8 years ago

finally a working CIF exporter (export mechanism needs configuring); work around windows file names in PyCifRW & missing unicode char

  • Property svn:eol-style set to native
File size: 10.3 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.py $
7# $Id: G2importphase.py 482 2012-02-13 17:33:35Z vondreele $
8########### SVN repository information ###################
9# routines to read in structure factors from a CIF
10#
11import sys
12import numpy as np
13import os.path
14import GSASIIIO as G2IO
15import CifFile as cif # PyCifRW from James Hester
16import urllib
17import GSASIIpath
18GSASIIpath.SetVersionNumber("$Revision: 810 $")
19
20class CIFhklReader(G2IO.ImportStructFactor):
21    'Routines to import Phase information from a CIF file'
22    def __init__(self):
23        super(self.__class__,self).__init__( # fancy way to self-reference
24            extensionlist = ('.CIF','.cif','.FCF','.fcf','.HKL','.hkl'),
25            strictExtension = False,
26            formatName = 'CIF',
27            longFormatName = 'CIF format structure factor file (.cif or .hkl)'
28            )
29    # Validate the contents
30    def ContentsValidator(self, filepointer):
31        for i,line in enumerate(filepointer):
32            if i >= 1000: break
33            ''' Encountered only blank lines or comments in first 1000
34            lines. This is unlikely, but assume it is CIF since we are
35            even less likely to find a file with nothing but hashes and
36            blank lines'''
37            line = line.strip()
38            if len(line) == 0:
39                continue # ignore blank lines
40            elif line.startswith('#'):
41                continue # ignore comments
42            elif line.startswith('data_'):
43                return True
44            else:
45                return False # found something else
46        return True
47    def Reader(self,filename,filepointer, ParentFrame=None, **kwarg):
48        hklitems = ('_refln_index_h','_refln_index_k','_refln_index_l')
49        cellitems = (
50            '_cell_length_a','_cell_length_b','_cell_length_c',
51            '_cell_angle_alpha','_cell_angle_beta','_cell_angle_gamma',)
52        phasenamefields = (
53            '_chemical_name_common',
54            '_pd_phase_name',
55            '_chemical_formula_sum'
56            )
57        rdbuffer = kwarg.get('buffer')
58        cf = None
59        try:
60            if self.repeat and rdbuffer is not None:
61                cf = rdbuffer.get('lastcif')
62                print 'Reuse previously parsed CIF'
63            if cf is None:
64                self.ShowBusy() # this can take a while
65                ciffile = 'file:'+urllib.pathname2url(filename)
66                #cf = cif.ReadCif(ciffile)
67                fp = open(ciffile,'r')             # patch: open file to avoid windows bug
68                cf = cif.ReadCif(fp)
69                fp.close()
70                self.DoneBusy()
71            # scan blocks for reflections
72            blklist = []
73            blktype = []
74            for blk in cf.keys():
75                blkkeys = [k.lower() for k in cf[blk].keys()]
76                gotFo = True
77                gotFo2 = True
78                for r in hklitems:
79                    if r not in blkkeys:
80                        gotFo = False
81                        gotFo2 = False
82                if '_refln_f_squared_meas' not in blkkeys:
83                    gotFo = False
84                if '_refln_f_squared_meas' not in blkkeys:
85                    gotFo2 = False
86                if gotFo or gotFo2:
87                    blklist.append(blk)
88                    blktype.append(gotFo2)
89            if not blklist:
90                selblk = None # no block to choose
91            elif len(blklist) == 1: # only one choice
92                selblk = 0
93            else:                       # choose from options
94                choice = []
95                for blknm in blklist:
96                    choice.append('')
97                    # accumumlate some info about this phase
98                    choice[-1] += blknm + ': '
99                    for i in phasenamefields: # get a name for the phase
100                        name = cf[blknm].get(i)
101                        if name is None or name == '?' or name == '.':
102                            continue
103                        else:
104                            choice[-1] += name.strip()[:20] + ', '
105                            break
106                    s = ''
107                    fmt = "%.2f,"
108                    for i,key in enumerate(cellitems):
109                        if i == 3: fmt = "%.f,"
110                        if i == 5: fmt = "%.f"
111                        val = cf[blknm].get(key)
112                        if val is None: break
113                        s += fmt % cif.get_number_with_esd(val)[0]
114                    if s: choice[-1] += ', cell: ' + s
115                    sg = cf[blknm].get("_symmetry_space_group_name_H-M")
116                    if sg: choice[-1] += ', (' + sg.strip() + ')'
117                choice.append('Import all of the above')
118                if self.repeat: # we were called to repeat the read
119                    selblk = self.repeatcount
120                    self.repeatcount += 1
121                    if self.repeatcount >= len(blklist): self.repeat = False
122                else:
123                    selblk = self.BlockSelector(
124                        choice,
125                        ParentFrame=ParentFrame,
126                        title='Select a dataset from one the CIF data_ blocks below',
127                        size=(600,100),
128                        header='Dataset Selector')
129            if selblk is None:
130                return False # no block selected or available
131            if selblk >= len(blklist): # all blocks selected
132                selblk = 0
133                self.repeat = True
134                if rdbuffer is not None:
135                    rdbuffer['lastcif'] = cf # save the parsed cif for the next loop
136                self.repeatcount = 1
137            blknm = blklist[selblk]
138            blk = cf[blklist[selblk]]
139            self.objname = os.path.basename(filename)+':'+str(blknm)
140            # read in reflections
141            refloop = blk.GetLoop('_refln_index_h')
142            itemkeys = {}
143            # prepare an index to the CIF reflection loop
144            for i,key in enumerate(refloop.keys()):
145                itemkeys[key.lower()] = i
146            if '_refln_f_squared_calc' in itemkeys:
147                FcalcPresent = True
148            elif '_refln_f_calc' in itemkeys:
149                FcalcPresent = True
150            else:
151                FcalcPresent = False
152            for item in refloop:
153                HKL = []
154                for i in hklitems: # ('_refln_index_h','_refln_index_k','_refln_index_l')
155                    num = itemkeys.get(i)
156                    try:
157                        HKL.append(int(item[num]))
158                    except:
159                        HKL.append('.')
160                #h,k,l,m,dsp,Fo2,sig,Fc2,Fot2,Fct2,phase,...
161                ref = HKL+[0,0,0,0,0,0,0,0,[],[],0,{}] 
162                if '_refln_f_squared_meas' in itemkeys:
163                    try:
164                        Fsq = float(item[itemkeys['_refln_f_squared_meas']])
165                        ref[8] = Fsq
166                        ref[5] = Fsq
167                    except:
168                        try:
169                            Fsq,Esd = item[itemkeys['_refln_f_squared_meas']].split('(')
170                            Fsq = float(Fsq)
171                            ref[8] = Fsq
172                            ref[5] = Fsq
173                            ref[6] = float(Esd[:-1])
174                        except:
175                            pass
176                    if  '_refln_f_squared_sigma' in itemkeys:
177                        try:
178                            ref[6] = float(item[itemkeys['_refln_f_squared_sigma']])
179                        except:
180                            pass                           
181                elif '_refln_f_meas' in itemkeys:
182                    try:
183                        Fsq = float(item[itemkeys['_refln_f_meas']])**2
184                        ref[8] = Fsq
185                        ref[5] = Fsq
186                    except:
187                        try:
188                            Fsq,Esd = item[itemkeys['_refln_f_squared_meas']].split('(')
189                            Fsq = float(Fsq)**2
190                            ref[8] = Fsq
191                            ref[5] = Fsq
192                            ref[6] = 2.0*sqrt(Fsq)*float(Esd[:-1])
193                        except:
194                            pass                               
195                    if  '_refln_f_sigma' in itemkeys:
196                        try:
197                            ref[6] = 2.*sqrt(ref[8])*float(item[itemkeys['_refln_f_sigma']])
198                        except:
199                            pass                               
200                if '_refln_f_squared_calc' in itemkeys:
201                    try:
202                        Fsq = float(item[itemkeys['_refln_f_squared_calc']])
203                        ref[9] = Fsq
204                        ref[7] = Fsq
205                    except:
206                        pass                               
207                elif '_refln_f_calc' in itemkeys:
208                    try:
209                        Fsq = float(item[itemkeys['_refln_f_calc']])**2
210                        ref[9] = Fsq
211                        ref[7] = Fsq
212                    except:
213                        pass                               
214                if '_refln_phase_calc' in itemkeys:
215                    try:
216                        ref[10] = float(item[itemkeys['_refln_phase_calc']])
217                    except:
218                        pass                               
219                self.RefList.append(ref)
220            self.UpdateControls(Type='Fosq',FcalcPresent=FcalcPresent) # set Fobs type & if Fcalc values are loaded
221            if blk.get('_diffrn_radiation_probe'):
222                if blk['_diffrn_radiation_probe'] == 'neutron':
223                    type = 'SNC'
224            else:
225                type = 'SXC'
226            if blk.get('_diffrn_radiation_wavelength'):
227                wave = float(blk['_diffrn_radiation_wavelength'])
228            else:
229                wave = None
230            self.UpdateParameters(Type=type,Wave=wave) # histogram type
231            return True
232        except Exception as detail:
233            print self.formatName+' read error:'+str(detail) # for testing
234            import traceback
235            traceback.print_exc(file=sys.stdout)
236        return False
Note: See TracBrowser for help on using the repository browser.