source: trunk/imports/G2sfact_CIF.py @ 615

Last change on this file since 615 was 615, checked in by toby, 11 years ago

add powder CIF importer, minor other updates to readers

File size: 9.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 CifFile as cif # PyCifRW from James Hester
16import urllib
17
18class CIFhklReader(G2IO.ImportStructFactor):
19    'Routines to import Phase information from a CIF file'
20    def __init__(self):
21        super(self.__class__,self).__init__( # fancy way to self-reference
22            extensionlist=('.CIF','.cif'),
23            strictExtension=False,
24            formatName = 'CIF',
25            longFormatName = 'Reflections from CIF'
26            )
27    # Validate the contents
28    def ContentsValidator(self, filepointer):
29        for i,line in enumerate(filepointer):
30            if i >= 1000: break
31            ''' Encountered only blank lines or comments in first 1000
32            lines. This is unlikely, but assume it is CIF since we are
33            even less likely to find a file with nothing but hashes and
34            blank lines'''
35            line = line.strip()
36            if len(line) == 0:
37                continue # ignore blank lines
38            elif line.startswith('#'):
39                continue # ignore comments
40            elif line.startswith('data_'):
41                return True
42            else:
43                return False # found something else
44        return True
45    def Reader(self,filename,filepointer, ParentFrame=None, **kwarg):
46        hklitems = ('_refln_index_h','_refln_index_k','_refln_index_l')
47        cellitems = (
48            '_cell_length_a','_cell_length_b','_cell_length_c',
49            '_cell_angle_alpha','_cell_angle_beta','_cell_angle_gamma',)
50        phasenamefields = (
51            '_chemical_name_common',
52            '_pd_phase_name',
53            '_chemical_formula_sum'
54            )
55        rdbuffer = kwarg.get('buffer')
56        cf = None
57        try:
58            if self.repeat and rdbuffer is not None:
59                cf = rdbuffer.get('lastcif')
60                print 'Reuse previously parsed CIF'
61            if cf is None:
62                self.ShowBusy() # this can take a while
63                ciffile = 'file:'+urllib.pathname2url(filename)
64                cf = cif.ReadCif(ciffile)
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                ref = [HKL,0.,0.,0,0,0,0]  # HKL. Fo**2, sig(Fo**2), Fc, Fcp, Fcpp & phase
156                # get F or F**2 and sigma
157                if '_refln_f_squared_meas' in itemkeys:
158                    try:
159                        ref[1] = float(item[itemkeys['_refln_f_squared_meas']])
160                    except:
161                        pass
162                    if  '_refln_f_squared_sigma' in itemkeys:
163                        try:
164                            ref[2] = float(item[itemkeys['_refln_f_squared_sigma']])
165                        except:
166                            pass                           
167                elif '_refln_f_meas' in itemkeys:
168                    try:
169                        ref[1] = float(item[itemkeys['_refln_f_meas']])**2
170                    except:
171                        pass                               
172                    if  '_refln_f_sigma' in itemkeys:
173                        try:
174                            ref[2] = 2.*sqrt(ref[1])*float(item[itemkeys['_refln_f_sigma']])
175                        except:
176                            pass                               
177                if '_refln_f_squared_calc' in itemkeys:
178                    try:
179                        ref[3] = float(item[itemkeys['_refln_f_squared_calc']])
180                    except:
181                        pass                               
182                elif '_refln_f_calc' in itemkeys:
183                    try:
184                        ref[3] = float(item[itemkeys['_refln_f_calc']])**2
185                    except:
186                        pass                               
187                if '_refln_phase_calc' in itemkeys:
188                    try:
189                        ref[6] = float(item[itemkeys['_refln_phase_calc']])
190                    except:
191                        pass                               
192
193                self.RefList.append(ref)
194            self.UpdateControls(Type='Fosq',FcalcPresent=FcalcPresent) # set Fobs type & if Fcalc values are loaded
195            if blk.get('_diffrn_radiation_probe'):
196                if blk['_diffrn_radiation_probe'] == 'neutron':
197                    type = 'SNC'
198            else:
199                type = 'SXC'
200            if blk.get('_diffrn_radiation_wavelength'):
201                wave = blk['_diffrn_radiation_wavelength']
202            else:
203                wave = None
204            self.UpdateParameters(Type=type,Wave=wave) # histogram type
205            return True
206        except Exception as detail:
207            print self.formatName+' read error:'+str(detail) # for testing
208            import traceback
209            traceback.print_exc(file=sys.stdout)
210        return False
Note: See TracBrowser for help on using the repository browser.