source: trunk/imports/G2sfact_CIF.py @ 1956

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

fix (again) fill unit cell, dynamic SS drawing & GenAtom? issues - now all OK
fixes to get SS structure factors to compute & twins in SS data issues

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Author Revision URL Id
File size: 14.0 KB
Line 
1# -*- coding: utf-8 -*-
2########### SVN repository information ###################
3# $Date: 2015-08-12 18:30:41 +0000 (Wed, 12 Aug 2015) $
4# $Author: vondreele $
5# $Revision: 1956 $
6# $URL: trunk/imports/G2sfact_CIF.py $
7# $Id: G2sfact_CIF.py 1956 2015-08-12 18:30: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 sys
18import numpy as np
19import os.path
20import GSASIIIO as G2IO
21import GSASIIpath
22GSASIIpath.SetVersionNumber("$Revision: 1956 $")
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','_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        try:
93            if self.repeat and rdbuffer is not None:
94                cf = rdbuffer.get('lastcif')
95                print 'Reusing previously parsed CIF'
96            if cf is None:
97                self.ShowBusy() # this can take a while
98                try:
99                    cf = G2IO.ReadCIF(filename)
100                except Exception as detail:
101                    self.errors = "Parse or reading of file failed in pyCifRW; check syntax of file in enCIFer or CheckCIF"
102                    return False
103                finally:
104                    self.DoneBusy()
105            # scan blocks for reflections
106            self.errors = 'Error during scan of blocks for datasets'
107            blklist = []
108            for blk in cf.keys(): # scan for reflections, F or F2 values and cell lengths.
109                # Ignore blocks that do not have structure factors and a cell
110                blkkeys = [k.lower() for k in cf[blk].keys()]
111                gotFo = False
112                gotFo2 = False
113                im = 0
114                for i in range(2):
115                    if hklitems[i][3] in blkkeys:   #Super lattice reflections h,k,l,m
116                        im = 1
117                    if hklitems[i][0] in blkkeys and hklitems[i][1] in blkkeys and hklitems[i][2] in blkkeys:
118                        dnIndex = i
119                        break
120                else:
121                    break # no reflections
122                for dn in Fdatanames: 
123                    if dn in blkkeys:
124                        blklist.append(blk)
125                        gotFo = True
126                        break
127                if gotFo: break
128                for dn in F2datanames: 
129                    if dn in blkkeys:
130                        blklist.append(blk)
131                        break
132                else:
133                    break
134            if not blklist:
135                selblk = None # no block to choose
136            elif len(blklist) == 1: # only one choice
137                selblk = 0
138            else:                       # choose from options
139                choice = []
140                for blknm in blklist:
141                    choice.append('')
142                    # accumulate some info about this phase
143                    choice[-1] += blknm + ': '
144                    for i in phasenamefields: # get a name for the phase
145                        name = cf[blknm].get(i)
146                        if name is None or name == '?' or name == '.':
147                            continue
148                        else:
149                            choice[-1] += name.strip()[:20] + ', '
150                            break
151                    s = ''
152                    fmt = "%.2f,"
153                    for i,key in enumerate(cellitems[dnIndex]):
154                        if i == 3: fmt = "%.f,"
155                        if i == 5: fmt = "%.f"
156                        val = cf[blknm].get(key)
157                        if val is None: break
158                        s += fmt % cif.get_number_with_esd(val)[0]
159                    if s: choice[-1] += ', cell: ' + s
160                    for dn in SGdataname:
161                        sg = cf[blknm].get(dn)
162                        if sg: 
163                            choice[-1] += ', (' + sg.strip() + ')'
164                            break
165                choice.append('Import all of the above')
166                if self.repeat: # we were called to repeat the read
167                    selblk = self.repeatcount
168                    self.repeatcount += 1
169                    if self.repeatcount >= len(blklist): self.repeat = False
170                else:
171                    selblk = self.BlockSelector(
172                        choice,
173                        ParentFrame=ParentFrame,
174                        title='Select a dataset from one the CIF data_ blocks below',
175                        size=(600,100),
176                        header='Dataset Selector')
177            self.errors = 'Error during reading of selected block'
178            if selblk is None:
179                return False # no block selected or available
180            if selblk >= len(blklist): # all blocks selected
181                selblk = 0
182                self.repeat = True
183                if rdbuffer is not None:
184                    rdbuffer['lastcif'] = cf # save the parsed cif for the next loop
185                self.repeatcount = 1
186            blknm = blklist[selblk]
187            blk = cf[blklist[selblk]]
188            self.objname = os.path.basename(filename)+':'+str(blknm)
189            self.errors = 'Error during reading of reflections'
190            # read in reflections
191            try:
192                refloop = blk.GetLoop(hklitems[0][0])
193                dnIndex = 0
194            except KeyError:
195                try:
196                    refloop = blk.GetLoop(hklitems[1][0])
197                    dnIndex = 1
198                except KeyError:
199                    self.errors += "\nUnexpected: '_refln[-.]index_h not found!"
200                    return False
201            itemkeys = {}
202            # prepare an index to the CIF reflection loop
203            for i,key in enumerate(refloop.keys()):
204                itemkeys[key.lower()] = i
205               
206            # scan for data names:
207            F2dn = None
208            Fdn = None
209            F2cdn = None
210            Fcdn = None
211            F2sdn = None
212            Fsdn = None
213            Phdn = None
214            FcalcPresent = False
215            for dn in F2datanames:
216                if dn in itemkeys:
217                    F2dn = dn
218                    for dm in F2calcnames:
219                        if dm in itemkeys:
220                            F2cdn = dm
221                            FcalcPresent = True
222                            break
223                    for dm in F2signames:
224                        if dm in itemkeys:
225                            F2sdn = dm
226                            break
227                    break
228            else:
229                for dn in Fdatanames:
230                    if dn in itemkeys:
231                        Fdn = dn
232                        for dm in Fcalcnames:
233                            if dm in itemkeys:
234                                Fcdn = dm
235                                FcalcPresent = True
236                                break
237                        for dm in Fsignames:
238                            if dm in itemkeys:
239                                Fsdn = dm
240                                break
241                        break
242                else:
243                    msg = "\nno F or F2 loop value found in file\n"
244                    msg += "A CIF reflection file needs to have at least one of\n"
245                    for dn in F2datanames+Fdatanames:
246                        msg += dn + ', '
247                    self.errors += msg                       
248                    return False
249            for dn in phasenames:
250                if dn in itemkeys:
251                    Phdn = dn
252                    break
253               
254            # loop over all reflections
255            for item in refloop:
256                F2c = 0.0
257                sigF2 = 0.0
258                HKL = []
259                try:
260                    for i in hklitems[dnIndex][:3+im]: # '_refln[._]index_[hkl]'
261                        num = itemkeys.get(i)
262                        try:
263                            HKL.append(int(item[num]))
264                        except:
265                            HKL.append('.')
266                    #h,k,l,m,dsp,Fo2,sig,Fc2,Fot2,Fct2,phase,Ext
267                    if im:
268                        ref = HKL+[1,0,0,0,1, 0,0,0,0,0, 0,0] 
269                    else:
270                        ref = HKL+[1,0,0,1,0, 0,0,0,0,0, 0] 
271                    if F2dn:
272                        F2 = item[itemkeys[F2dn]]
273                        if '(' in F2:
274                            F2, sigF2 = cif.get_number_with_esd(F2)
275                            F2 = float(F2)
276                            sigF2 = float(sigF2)
277                        elif F2sdn:
278                            F2 = float(F2)
279                            sigF2 = float(item[itemkeys[F2sdn]])
280                        else:
281                            F2 = float(F2)
282                        try:
283                            if F2cdn:
284                                F2c = float(item[itemkeys[F2cdn]])
285                        except:
286                            pass
287                    else:
288                        F = item[itemkeys[Fdn]]
289                        if '(' in F:
290                            F, sig = cif.get_number_with_esd(F)
291                        elif Fsdn:
292                            F = float(F)
293                            sig = float(item[itemkeys[Fsdn]])
294                        else:
295                            F = float(F)
296                            sig = 0.0
297                        F2 = F**2
298                        sigF2 = 2.0*F*sig
299                        try:
300                            if Fcdn:
301                                Fc = float(item[itemkeys[Fcdn]])
302                                F2c = Fc*Fc
303                        except:
304                            pass
305                               
306                    ref[8+im] = F2
307                    ref[5+im] = F2
308                    ref[6+im] = sigF2
309                    ref[9+im] = F2c
310                    ref[7+im] = F2c
311                    try:
312                        if Phdn:
313                            ref[10+im] = float(item[itemkeys[Phdn]])
314                    except:
315                        pass
316                except:
317                    continue # skip over incompletely parsed reflections
318                self.RefDict['RefList'].append(ref)
319#                self.RefDict['FF'].append({})
320            self.RefDict['RefList'] = np.array(self.RefDict['RefList'])
321            self.errors = 'Error during reading of dataset parameters'
322            if blk.get('_diffrn_radiation_probe'):
323                if blk['_diffrn_radiation_probe'] == 'neutron':
324                    Type = 'SNC'
325            elif blk.get('_diffrn_radiation.probe'):
326                if blk['_diffrn_radiation.probe'] == 'neutron':
327                    Type = 'SNC'
328            else:
329                Type = 'SXC'
330            self.RefDict['Type'] = Type
331            self.RefDict['Super'] = im
332            if blk.get('_diffrn_radiation_wavelength'):
333                wave = float(blk['_diffrn_radiation_wavelength'])
334            elif blk.get('_diffrn_radiation.wavelength'):
335                wave = float(blk['_diffrn_radiation.wavelength'])
336            else:
337                wave = 0.70926
338            self.UpdateParameters(Type=Type,Wave=wave) # histogram type
339            return True
340        except Exception as detail:
341            self.errors += '\n  '+str(detail)
342            print self.formatName+' read error:'+str(detail) # for testing
343            import traceback
344            traceback.print_exc(file=sys.stdout)
345        return False
Note: See TracBrowser for help on using the repository browser.