source: trunk/imports/G2sfact_CIF.py @ 614

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

import GSAS powder data tested; import routines moved to imports

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(
109                            )[0]
110                    if s: choice[-1] += ', cell: ' + s
111                    sg = cf[blknm].get("_symmetry_space_group_name_H-M")
112                    if sg: choice[-1] += ', (' + sg.strip() + ')'
113                choice.append('Import all of the above')
114                if self.repeat: # we were called to repeat the read
115                    selblk = self.repeatcount
116                    self.repeatcount += 1
117                    if self.repeatcount >= len(blklist): self.repeat = False
118                else:
119                    selblk = self.BlockSelector(
120                        choice,
121                        ParentFrame=ParentFrame,
122                        title='Select a dataset from one the CIF data_ blocks below',
123                        size=(600,100),
124                        header='Dataset Selector')
125            if selblk is None:
126                return False # no block selected or available
127            if selblk >= len(blklist): # all blocks selected
128                selblk = 0
129                self.repeat = True
130                if rdbuffer is not None:
131                    rdbuffer['lastcif'] = cf # save the parsed cif for the next loop
132                self.repeatcount = 1
133            blknm = blklist[selblk]
134            blk = cf[blklist[selblk]]
135            self.objname = os.path.basename(filename)+':'+str(blknm)
136            # read in reflections
137            refloop = blk.GetLoop('_refln_index_h')
138            itemkeys = {}
139            # prepare an index to the CIF reflection loop
140            for i,key in enumerate(refloop.keys()):
141                itemkeys[key.lower()] = i
142            if '_refln_f_squared_calc' in itemkeys:
143                FcalcPresent = True
144            elif '_refln_f_calc' in itemkeys:
145                FcalcPresent = True
146            else:
147                FcalcPresent = False
148            for item in refloop:
149                HKL = []
150                for i in hklitems: # ('_refln_index_h','_refln_index_k','_refln_index_l')
151                    num = itemkeys.get(i)
152                    try:
153                        HKL.append(int(item[num]))
154                    except:
155                        HKL.append('.')
156                ref = [HKL,0.,0.,0,0,0,0]  # HKL. Fo**2, sig(Fo**2), Fc, Fcp, Fcpp & phase
157                # get F or F**2 and sigma
158                if '_refln_f_squared_meas' in itemkeys:
159                    try:
160                        ref[1] = float(item[itemkeys['_refln_f_squared_meas']])
161                    except:
162                        pass
163                    if  '_refln_f_squared_sigma' in itemkeys:
164                        try:
165                            ref[2] = float(item[itemkeys['_refln_f_squared_sigma']])
166                        except:
167                            pass                           
168                elif '_refln_f_meas' in itemkeys:
169                    try:
170                        ref[1] = float(item[itemkeys['_refln_f_meas']])**2
171                    except:
172                        pass                               
173                    if  '_refln_f_sigma' in itemkeys:
174                        try:
175                            ref[2] = 2.*sqrt(ref[1])*float(item[itemkeys['_refln_f_sigma']])
176                        except:
177                            pass                               
178                if '_refln_f_squared_calc' in itemkeys:
179                    try:
180                        ref[3] = float(item[itemkeys['_refln_f_squared_calc']])
181                    except:
182                        pass                               
183                elif '_refln_f_calc' in itemkeys:
184                    try:
185                        ref[3] = float(item[itemkeys['_refln_f_calc']])**2
186                    except:
187                        pass                               
188                if '_refln_phase_calc' in itemkeys:
189                    try:
190                        ref[6] = float(item[itemkeys['_refln_phase_calc']])
191                    except:
192                        pass                               
193
194                self.RefList.append(ref)
195            self.UpdateControls(Type='Fosq',FcalcPresent=FcalcPresent) # set Fobs type & if Fcalc values are loaded
196            if blk.get('_diffrn_radiation_probe'):
197                if blk['_diffrn_radiation_probe'] == 'neutron':
198                    type = 'SNC'
199            else:
200                type = 'SXC'
201            if blk.get('_diffrn_radiation_wavelength'):
202                wave = blk['_diffrn_radiation_wavelength']
203            else:
204                wave = None
205            self.UpdateParameters(Type=type,Wave=wave) # histogram type
206            return True
207        except Exception as detail:
208            print self.formatName+' read error:'+str(detail) # for testing
209            import traceback
210            traceback.print_exc(file=sys.stdout)
211        return False
Note: See TracBrowser for help on using the repository browser.