source: trunk/imports/G2sfact_CIF.py @ 2927

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

major revision - move all importers to GSASIIobj & make them independent of wx so they can be used in a scripting environment.
Still to move are PhaseSelector?, and 3 BlockSelector? dialogs

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Author Revision URL Id
File size: 12.4 KB
Line 
1# -*- coding: utf-8 -*-
2########### SVN repository information ###################
3# $Date: 2017-05-02 15:03:41 +0000 (Tue, 02 May 2017) $
4# $Author: vondreele $
5# $Revision: 2817 $
6# $URL: trunk/imports/G2sfact_CIF.py $
7# $Id: G2sfact_CIF.py 2817 2017-05-02 15:03:41Z 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 numpy as np
18import os.path
19import GSASIIobj as G2obj
20import GSASIIIO as G2IO
21import GSASIIpath
22GSASIIpath.SetVersionNumber("$Revision: 2817 $")
23import CifFile as cif # PyCifRW from James Hester
24
25class CIFhklReader(G2obj.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','_refln_index_m_1'),
44                    ('_refln.index_h','_refln.index_k','_refln.index_l','_refln.index_m_1')]
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            '_refln_intensity_meas','_refln.intensity_meas',
56                      )
57
58#        Idatanames = ('_refln_intensity_meas','_refln.intensity_meas',
59#                      ) # not used yet
60#
61#        Isignames = ('_refln_intensity_meas_sigma','_refln.intensity_meas_sigma',
62#                      ) # not used yet
63
64        Fcalcnames = ('_refln_f_calc','_refln.f_calc','_refln.f_calc_au',
65                      )
66       
67        F2calcnames = ('_refln_f_squared_calc','_refln.f_squared_calc',
68                      )
69
70        Fsignames = ('_refln_f_meas_sigma','_refln.f_meas_sigma','_refln.f_meas_sigma_au',
71                    '_refln_f_sigma',
72                      )
73       
74        F2signames = ('_refln_f_squared_meas_sigma','_refln.f_squared_meas_sigma',
75                      '_refln_f_squared_sigma',
76                      '_refln_intensity_meas_sigma','_refln.intensity_meas_sigma',
77                      '_refln.intensity_sigma',)
78
79        phasenames = ('_refln_phase_calc','_refln.phase_calc',
80                      )
81
82
83        SGdataname = ('_symmetry_space_group_name_H-M', '_symmetry.space_group_name_H-M')
84                     
85        phasenamefields = (
86            '_chemical_name_common',
87            '_pd_phase_name',
88            '_chemical_formula_sum'
89            )
90        rdbuffer = kwarg.get('buffer')
91        cf = None
92        if self.repeat and rdbuffer is not None:
93            cf = rdbuffer.get('lastcif')
94            print 'Reusing previously parsed CIF'
95        if cf is None:
96            cf = G2obj.ReadCIF(filename)
97        # scan blocks for reflections
98        self.errors = 'Error during scan of blocks for datasets'
99        blklist = []
100        for blk in cf.keys(): # scan for reflections, F or F2 values and cell lengths.
101            # Ignore blocks that do not have structure factors and a cell
102            blkkeys = [k.lower() for k in cf[blk].keys()]
103            gotFo = False
104            im = 0
105            for i in range(2):
106                if hklitems[i][3] in blkkeys:   #Super lattice reflections h,k,l,m
107                    im = 1
108                if hklitems[i][0] in blkkeys and hklitems[i][1] in blkkeys and hklitems[i][2] in blkkeys:
109                    dnIndex = i
110                    break
111            else:
112                break # no reflections
113            for dn in Fdatanames: 
114                if dn in blkkeys:
115                    blklist.append(blk)
116                    gotFo = True
117                    break
118            if gotFo: break
119            for dn in F2datanames: 
120                if dn in blkkeys:
121                    blklist.append(blk)
122                    break
123            else:
124                break
125        if not blklist:
126            selblk = None # no block to choose
127        elif len(blklist) == 1: # only one choice
128            selblk = 0
129        else:                       # choose from options
130            choice = []
131            for blknm in blklist:
132                choice.append('')
133                # accumulate some info about this phase
134                choice[-1] += blknm + ': '
135                for i in phasenamefields: # get a name for the phase
136                    name = cf[blknm].get(i)
137                    if name is None or name == '?' or name == '.':
138                        continue
139                    else:
140                        choice[-1] += name.strip()[:20] + ', '
141                        break
142                s = ''
143                fmt = "%.2f,"
144                for i,key in enumerate(cellitems[dnIndex]):
145                    if i == 3: fmt = "%.f,"
146                    if i == 5: fmt = "%.f"
147                    val = cf[blknm].get(key)
148                    if val is None: break
149                    s += fmt % cif.get_number_with_esd(val)[0]
150                if s: choice[-1] += ', cell: ' + s
151                for dn in SGdataname:
152                    sg = cf[blknm].get(dn)
153                    if sg: 
154                        choice[-1] += ', (' + sg.strip() + ')'
155                        break
156            choice.append('Import all of the above')
157            if self.repeat: # we were called to repeat the read
158                selblk = self.repeatcount
159                self.repeatcount += 1
160                if self.repeatcount >= len(blklist): self.repeat = False
161            else:
162                selblk = G2IO.BlockSelector(
163                    choice,
164                    ParentFrame=ParentFrame,
165                    title='Select a dataset from one the CIF data_ blocks below',
166                    size=(600,100),
167                    header='Dataset Selector')
168        self.errors = 'Error during reading of selected block'
169        if selblk is None:
170            return False # no block selected or available
171        if selblk >= len(blklist): # all blocks selected
172            selblk = 0
173            self.repeat = True
174            if rdbuffer is not None:
175                rdbuffer['lastcif'] = cf # save the parsed cif for the next loop
176            self.repeatcount = 1
177        blknm = blklist[selblk]
178        blk = cf[blklist[selblk]]
179        self.objname = os.path.basename(filename)+':'+str(blknm)
180        self.errors = 'Error during reading of reflections'
181        # read in reflections
182        try:
183            refloop = blk.GetLoop(hklitems[0][0])
184            dnIndex = 0
185        except KeyError:
186            try:
187                refloop = blk.GetLoop(hklitems[1][0])
188                dnIndex = 1
189            except KeyError:
190                self.errors += "\nUnexpected: '_refln[-.]index_h not found!"
191                return False
192        itemkeys = {}
193        # prepare an index to the CIF reflection loop
194        for i,key in enumerate(refloop.keys()):
195            itemkeys[key.lower()] = i
196           
197        # scan for data names:
198        F2dn = None
199        Fdn = None
200        F2cdn = None
201        Fcdn = None
202        F2sdn = None
203        Fsdn = None
204        Phdn = None
205        FcalcPresent = False
206        for dn in F2datanames:
207            if dn in itemkeys:
208                F2dn = dn
209                for dm in F2calcnames:
210                    if dm in itemkeys:
211                        F2cdn = dm
212                        FcalcPresent = True
213                        break
214                for dm in F2signames:
215                    if dm in itemkeys:
216                        F2sdn = dm
217                        break
218                break
219        else:
220            for dn in Fdatanames:
221                if dn in itemkeys:
222                    Fdn = dn
223                    for dm in Fcalcnames:
224                        if dm in itemkeys:
225                            Fcdn = dm
226                            break
227                    for dm in Fsignames:
228                        if dm in itemkeys:
229                            Fsdn = dm
230                            break
231                    break
232            else:
233                msg = "\nno F or F2 loop value found in file\n"
234                msg += "A CIF reflection file needs to have at least one of\n"
235                for dn in F2datanames+Fdatanames:
236                    msg += dn + ', '
237                self.errors += msg                       
238                return False
239        for dn in phasenames:
240            if dn in itemkeys:
241                Phdn = dn
242                break
243           
244        # loop over all reflections
245        for item in refloop:
246            F2c = 0.0
247            sigF2 = 0.0
248            HKL = []
249            try:
250                for i in hklitems[dnIndex][:3+im]: # '_refln[._]index_[hkl]'
251                    num = itemkeys.get(i)
252                    try:
253                        HKL.append(int(item[num]))
254                    except:
255                        HKL.append('.')
256                #h,k,l,tw,dsp,Fo2,sig,Fc2,Fot2,Fct2,phase,Ext
257                if im:
258                    ref = HKL+[1,0,0,0,1, 0,0,0,0,0, 0,0] 
259                else:
260                    ref = HKL+[1,0,0,1,0, 0,0,0,0,0, 0] 
261                if F2dn:
262                    F2 = item[itemkeys[F2dn]]
263                    if '(' in F2:
264                        F2, sigF2 = cif.get_number_with_esd(F2)
265                        F2 = float(F2)
266                        sigF2 = float(sigF2)
267                    elif F2sdn:
268                        F2 = float(F2)
269                        sigF2 = float(item[itemkeys[F2sdn]])
270                    else:
271                        F2 = float(F2)
272                    try:
273                        if F2cdn:
274                            F2c = float(item[itemkeys[F2cdn]])
275                    except:
276                        pass
277                else:
278                    F = item[itemkeys[Fdn]]
279                    if '(' in F:
280                        F, sig = cif.get_number_with_esd(F)
281                    elif Fsdn:
282                        F = float(F)
283                        sig = float(item[itemkeys[Fsdn]])
284                    else:
285                        F = float(F)
286                        sig = 0.0
287                    F2 = F**2
288                    sigF2 = 2.0*F*sig
289                    try:
290                        if Fcdn:
291                            Fc = float(item[itemkeys[Fcdn]])
292                            F2c = Fc*Fc
293                    except:
294                        pass
295                           
296                ref[8+im] = F2
297                ref[5+im] = F2
298                ref[6+im] = sigF2
299                ref[9+im] = F2c
300                ref[7+im] = F2c
301                try:
302                    if Phdn:
303                        ref[10+im] = float(item[itemkeys[Phdn]])
304                except:
305                    pass
306            except:
307                continue # skip over incompletely parsed reflections
308            self.RefDict['RefList'].append(ref)
309#                self.RefDict['FF'].append({})
310        self.RefDict['RefList'] = np.array(self.RefDict['RefList'])
311        self.errors = 'Error during reading of dataset parameters'
312        Type = 'SXC'
313        if blk.get('_diffrn_radiation_probe'):
314            if blk['_diffrn_radiation_probe'] == 'neutron':
315                Type = 'SNC'
316        elif blk.get('_diffrn_radiation.probe'):
317            if blk['_diffrn_radiation.probe'] == 'neutron':
318                Type = 'SNC'
319        self.RefDict['Type'] = Type
320        self.RefDict['Super'] = im
321        if blk.get('_diffrn_radiation_wavelength'):
322            wave = float(blk['_diffrn_radiation_wavelength'])
323        elif blk.get('_diffrn_radiation.wavelength'):
324            wave = float(blk['_diffrn_radiation.wavelength'])
325        else:
326            wave = 0.70926
327        self.UpdateParameters(Type=Type,Wave=wave) # histogram type
328        return True
Note: See TracBrowser for help on using the repository browser.