source: trunk/imports/G2sfact_CIF.py @ 1391

Last change on this file since 1391 was 1391, checked in by vondreele, 8 years ago

remove stray prints
Breit-Wigner & Lynn & Seeger neutron anomalous form factors for CW data
Add 'Ext' to HKLF reflection lists
make sure wave & tbar are in TOF HKLF reflection lists
add '_refln_f_sigma' & '_refln_f_squared_sigma' to possible cif reflection columns

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Author Revision URL Id
File size: 13.4 KB
Line 
1# -*- coding: utf-8 -*-
2########### SVN repository information ###################
3# $Date: 2014-06-20 18:43:42 +0000 (Fri, 20 Jun 2014) $
4# $Author: vondreele $
5# $Revision: 1391 $
6# $URL: trunk/imports/G2sfact_CIF.py $
7# $Id: G2sfact_CIF.py 1391 2014-06-20 18:43:42Z vondreele $
8########### SVN repository information ###################
9'''
10*Module G2sfact_CIF: CIF import*
11-----------------------------------
12Read structure factors from a CIF reflection table.
13
14'''
15# routines to read in structure factors from a CIF
16#
17import sys
18import numpy as np
19import os.path
20import GSASIIIO as G2IO
21import GSASIIpath
22GSASIIpath.SetVersionNumber("$Revision: 1391 $")
23import CifFile as cif # PyCifRW from James Hester
24
25class CIFhklReader(G2IO.ImportStructFactor):
26    'Routines to import Phase information from a CIF file'
27    def __init__(self):
28        super(self.__class__,self).__init__( # fancy way to self-reference
29            extensionlist = ('.CIF','.cif','.FCF','.fcf','.HKL','.hkl'),
30            strictExtension = False,
31            formatName = 'CIF',
32            longFormatName = 'CIF format structure factor file (.cif or .hkl)'
33            )
34    # Validate the contents
35    def ContentsValidator(self, filepointer):
36        'Use standard CIF validator'
37        return self.CIFValidator(filepointer)
38
39    def Reader(self, filename, filepointer, ParentFrame=None, **kwarg):
40        '''Read single crystal data from a CIF.
41        If multiple datasets are requested, use self.repeat and buffer caching.
42        '''
43        hklitems = [('_refln_index_h','_refln_index_k','_refln_index_l'),
44                    ('_refln.index_h','_refln.index_k','_refln.index_l')]
45        cellitems = [
46            ('_cell_length_a','_cell_length_b','_cell_length_c',
47             '_cell_angle_alpha','_cell_angle_beta','_cell_angle_gamma',),
48            ('_cell.length_a','_cell.length_b','_cell.length_c',
49             '_cell.angle_alpha','_cell.angle_beta','_cell.angle_gamma',),]
50
51        Fdatanames = ('_refln_f_meas','_refln.f_meas','_refln.f_meas_au',
52                      )
53       
54        F2datanames = ('_refln_f_squared_meas','_refln.f_squared_meas',
55                      )
56
57        Idatanames = ('_refln_intensity_meas','_refln.intensity_meas',
58                      ) # not used yet
59
60        Isignames = ('_refln_intensity_meas_sigma','_refln.intensity_meas_sigma',
61                      ) # not used yet
62
63        Fcalcnames = ('_refln_f_calc','_refln.f_calc','_refln.f_calc_au',
64                      )
65       
66        F2calcnames = ('_refln_f_squared_calc','_refln.f_squared_calc',
67                      )
68
69        Fsignames = ('_refln_f_meas_sigma','_refln.f_meas_sigma','_refln.f_meas_sigma_au',
70                    '_refln_f_sigma',
71                      )
72       
73        F2signames = ('_refln_f_squared_meas_sigma','_refln.f_squared_meas_sigma',
74                      '_refln_f_squared_sigma',
75                      )
76
77        phasenames = ('_refln_phase_calc','_refln.phase_calc',
78                      )
79
80
81        SGdataname = ('_symmetry_space_group_name_H-M', '_symmetry.space_group_name_H-M')
82                     
83        phasenamefields = (
84            '_chemical_name_common',
85            '_pd_phase_name',
86            '_chemical_formula_sum'
87            )
88        rdbuffer = kwarg.get('buffer')
89        cf = None
90        try:
91            if self.repeat and rdbuffer is not None:
92                cf = rdbuffer.get('lastcif')
93                print 'Reusing previously parsed CIF'
94            if cf is None:
95                self.ShowBusy() # this can take a while
96                try:
97                    cf = G2IO.ReadCIF(filename)
98                except Exception as detail:
99                    self.errors = "Parse or reading of file failed in pyCifRW; check syntax of file in enCIFer or CheckCIF"
100                    return False
101                finally:
102                    self.DoneBusy()
103            # scan blocks for reflections
104            self.errors = 'Error during scan of blocks for datasets'
105            blklist = []
106            for blk in cf.keys(): # scan for reflections, F or F2 values and cell lengths.
107                # Ignore blocks that do not have structure factors and a cell
108                blkkeys = [k.lower() for k in cf[blk].keys()]
109                gotFo = False
110                gotFo2 = False
111                for i in range(2):
112                    if hklitems[i][0] in blkkeys and hklitems[i][1] in blkkeys and hklitems[i][2] in blkkeys:
113                        dnIndex = i
114                        break
115                else:
116                    break # no reflections
117                for dn in Fdatanames: 
118                    if dn in blkkeys:
119                        blklist.append(blk)
120                        gotFo = True
121                        break
122                if gotFo: break
123                for dn in F2datanames: 
124                    if dn in blkkeys:
125                        blklist.append(blk)
126                        break
127                else:
128                    break
129            if not blklist:
130                selblk = None # no block to choose
131            elif len(blklist) == 1: # only one choice
132                selblk = 0
133            else:                       # choose from options
134                choice = []
135                for blknm in blklist:
136                    choice.append('')
137                    # accumumlate some info about this phase
138                    choice[-1] += blknm + ': '
139                    for i in phasenamefields: # get a name for the phase
140                        name = cf[blknm].get(i)
141                        if name is None or name == '?' or name == '.':
142                            continue
143                        else:
144                            choice[-1] += name.strip()[:20] + ', '
145                            break
146                    s = ''
147                    fmt = "%.2f,"
148                    for i,key in enumerate(cellitems[dnIndex]):
149                        if i == 3: fmt = "%.f,"
150                        if i == 5: fmt = "%.f"
151                        val = cf[blknm].get(key)
152                        if val is None: break
153                        s += fmt % cif.get_number_with_esd(val)[0]
154                    if s: choice[-1] += ', cell: ' + s
155                    for dn in SGdataname:
156                        sg = cf[blknm].get(dn)
157                        if sg: 
158                            choice[-1] += ', (' + sg.strip() + ')'
159                            break
160                choice.append('Import all of the above')
161                if self.repeat: # we were called to repeat the read
162                    selblk = self.repeatcount
163                    self.repeatcount += 1
164                    if self.repeatcount >= len(blklist): self.repeat = False
165                else:
166                    selblk = self.BlockSelector(
167                        choice,
168                        ParentFrame=ParentFrame,
169                        title='Select a dataset from one the CIF data_ blocks below',
170                        size=(600,100),
171                        header='Dataset Selector')
172            self.errors = 'Error during reading of selected block'
173            if selblk is None:
174                return False # no block selected or available
175            if selblk >= len(blklist): # all blocks selected
176                selblk = 0
177                self.repeat = True
178                if rdbuffer is not None:
179                    rdbuffer['lastcif'] = cf # save the parsed cif for the next loop
180                self.repeatcount = 1
181            blknm = blklist[selblk]
182            blk = cf[blklist[selblk]]
183            self.objname = os.path.basename(filename)+':'+str(blknm)
184            self.errors = 'Error during reading of reflections'
185            # read in reflections
186            try:
187                refloop = blk.GetLoop(hklitems[0][0])
188                dnIndex = 0
189            except KeyError:
190                try:
191                    refloop = blk.GetLoop(hklitems[1][0])
192                    dnIndex = 1
193                except KeyError:
194                    self.errors += "\nUnexpected: '_refln[-.]index_h not found!"
195                    return False
196            itemkeys = {}
197            # prepare an index to the CIF reflection loop
198            for i,key in enumerate(refloop.keys()):
199                itemkeys[key.lower()] = i
200               
201            # scan for data names:
202            F2dn = None
203            Fdn = None
204            F2cdn = None
205            Fcdn = None
206            F2sdn = None
207            Fsdn = None
208            Phdn = None
209            FcalcPresent = False
210            for dn in F2datanames:
211                if dn in itemkeys:
212                    F2dn = dn
213                    for dn in F2calcnames:
214                        if dn in itemkeys:
215                            F2cdn = dn
216                            FcalcPresent = True
217                            break
218                    for dn in F2signames:
219                        if dn in itemkeys:
220                            F2sdn = dn
221                            break
222                    break
223            else:
224                for dn in Fdatanames:
225                    if dn in itemkeys:
226                        Fdn = dn
227                        for dn in Fcalcnames:
228                            if dn in itemkeys:
229                                Fcdn = dn
230                                FcalcPresent = True
231                                break
232                        for dn in Fsignames:
233                            if dn in itemkeys:
234                                Fsdn = dn
235                                break
236                        break
237                else:
238                    msg = "\nno F or F2 loop value found in file\n"
239                    msg += "A CIF reflection file needs to have at least one of\n"
240                    for dn in F2datanames+Fdatanames:
241                        msg += dn + ', '
242                    self.errors += msg                       
243                    return False
244            for dn in phasenames:
245                if dn in itemkeys:
246                    Phdn = dn
247                    break
248               
249            # loop over all reflections
250            for item in refloop:
251                F2c = 0.0
252                sigF2 = 0.0
253                HKL = []
254                try:
255                    for i in hklitems[dnIndex]: # '_refln[._]index_[hkl]'
256                        num = itemkeys.get(i)
257                        try:
258                            HKL.append(int(item[num]))
259                        except:
260                            HKL.append('.')
261                    #h,k,l,m,dsp,Fo2,sig,Fc2,Fot2,Fct2,phase,Ext
262                    ref = HKL+[0,0,0,0,0, 0,0,0,0,0, 0] 
263                    if F2dn:
264                        F2 = item[itemkeys[F2dn]]
265                        if '(' in F2:
266                            F2, sigF2 = cif.get_number_with_esd(F2)
267                            F2 = float(F2)
268                            sigF2 = float(sigF2)
269                        elif F2sdn:
270                            F2 = float(F2)
271                            sigF2 = float(item[itemkeys[F2sdn]])
272                        else:
273                            F2 = float(F2)
274                        try:
275                            if F2cdn:
276                                F2c = float(item[itemkeys[F2cdn]])
277                        except:
278                            pass
279                    else:
280                        F = item[itemkeys[Fdn]]
281                        if '(' in F:
282                            F, sig = cif.get_number_with_esd(F)
283                        elif Fsdn:
284                            F = float(F)
285                            sig = float(item[itemkeys[Fsdn]])
286                        else:
287                            F = float(F)
288                            sig = 0.0
289                        F2 = F**2
290                        sigF2 = 2.0*F*sig
291                        try:
292                            if Fcdn:
293                                Fc = float(item[itemkeys[Fcdn]])
294                                F2c = Fc*Fc
295                        except:
296                            pass
297                               
298                    ref[8] = F2
299                    ref[5] = F2
300                    ref[6] = sigF2
301                    ref[9] = F2c
302                    ref[7] = F2c
303                    try:
304                        if Phdn:
305                            ref[10] = float(item[itemkeys[Phdn]])
306                    except:
307                        pass
308                except:
309                    continue # skip over incompletely parsed reflections
310                self.RefDict['RefList'].append(ref)
311                self.RefDict['FF'].append({})
312            self.RefDict['RefList'] = np.array(self.RefDict['RefList'])
313            self.errors = 'Error during reading of dataset parameters'
314            if blk.get('_diffrn_radiation_probe'):
315                if blk['_diffrn_radiation_probe'] == 'neutron':
316                    type = 'SNC'
317            elif blk.get('_diffrn_radiation.probe'):
318                if blk['_diffrn_radiation.probe'] == 'neutron':
319                    type = 'SNC'
320            else:
321                type = 'SXC'
322            if blk.get('_diffrn_radiation_wavelength'):
323                wave = float(blk['_diffrn_radiation_wavelength'])
324            elif blk.get('_diffrn_radiation.wavelength'):
325                wave = float(blk['_diffrn_radiation.wavelength'])
326            else:
327                wave = None
328            self.UpdateParameters(Type=type,Wave=wave) # histogram type
329            return True
330        except Exception as detail:
331            self.errors += '\n  '+str(detail)
332            print self.formatName+' read error:'+str(detail) # for testing
333            import traceback
334            traceback.print_exc(file=sys.stdout)
335        return False
Note: See TracBrowser for help on using the repository browser.