source: trunk/imports/G2sfact_CIF.py @ 3136

Last change on this file since 3136 was 3136, checked in by vondreele, 4 years ago

make GSAS-II python 3.6 compliant & preserve python 2.7 use;changes:
do from future import division, print_function for all GSAS-II py sources
all menu items revised to be py 2.7/3.6 compliant
all wx.OPEN --> wx.FD_OPEN in file dialogs
all integer divides (typically for image pixel math) made explicit with ; ambiguous ones made floats as appropriate
all print "stuff" --> print (stuff)
all print >> pFile,'stuff' --> pFile.writeCIFtemplate('stuff')
all read file opens made explicit 'r' or 'rb'
all cPickle imports made for py2.7 or 3.6 as cPickle or _pickle; test for '2' platform.version_tuple[0] for py 2.7
define cPickleload to select load(fp) or load(fp,encoding='latin-1') for loading gpx files; provides cross compatibility between py 2.7/3.6 gpx files
make dict.keys() as explicit list(dict.keys()) as needed (NB: possible source of remaining py3.6 bugs)
make zip(a,b) as explicit list(zip(a,b)) as needed (NB: possible source of remaining py3.6 bugs)
select unichr/chr according test for '2' platform.version_tuple[0] for py 2.7 (G2pwdGUI * G2plot) for special characters
select wg.EVT_GRID_CELL_CHANGE (classic) or wg.EVT_GRID_CELL_CHANGED (phoenix) in grid Bind
maxint --> maxsize; used in random number stuff
raise Exception,"stuff" --> raise Exception("stuff")
wx 'classic' sizer.DeleteWindows?() or 'phoenix' sizer.Clear(True)
wx 'classic' SetToolTipString?(text) or 'phoenix' SetToolTip?(wx.ToolTip?(text)); define SetToolTipString?(self,text) to handle the choice in plots
status.SetFields? --> status.SetStatusText?
'classic' AddSimpleTool? or 'phoenix' self.AddTool? for plot toolbar; Bind different as well
define GetItemPydata? as it doesn't exist in wx 'phoenix'
allow python versions 2.7 & 3.6 to run GSAS-II
Bind override commented out - no logging capability (NB: remove all logging code?)
all import ContentsValidator? open filename & test if valid then close; filepointer removed from Reader
binary importers (mostly images) test for 'byte' type & convert as needed to satisfy py 3.6 str/byte rules

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