source: trunk/imports/G2sfact_CIF.py @ 1074

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

more CIF work

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