source: trunk/G2importsfact_CIF.py @ 612

Last change on this file since 612 was 607, checked in by toby, 13 years ago

revise help to include tutorials on tree only; add kw args to all readers; cache cif for multiple passes; start on powder 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 'no-parse'
61            if cf is None:
62                print 'parse'
63                self.ShowBusy() # this can take a while
64                ciffile = 'file:'+urllib.pathname2url(filename)
65                cf = cif.ReadCif(ciffile)
66                self.DoneBusy()
67            # scan blocks for reflections
68            blklist = []
69            blktype = []
70            for blk in cf.keys():
71                blkkeys = [k.lower() for k in cf[blk].keys()]
72                gotFo = True
73                gotFo2 = True
74                for r in hklitems:
75                    if r not in blkkeys:
76                        gotFo = False
77                        gotFo2 = False
78                if '_refln_f_squared_meas' not in blkkeys:
79                    gotFo = False
80                if '_refln_f_squared_meas' not in blkkeys:
81                    gotFo2 = False
82                if gotFo or gotFo2:
83                    blklist.append(blk)
84                    blktype.append(gotFo2)
85            if not blklist:
86                selblk = None # no block to choose
87            elif len(blklist) == 1: # only one choice
88                selblk = 0
89            else:                       # choose from options
90                choice = []
91                for blknm in blklist:
92                    choice.append('')
93                    # accumumlate some info about this phase
94                    choice[-1] += blknm + ': '
95                    for i in phasenamefields: # get a name for the phase
96                        name = cf[blknm].get(i)
97                        if name is None or name == '?' or name == '.':
98                            continue
99                        else:
100                            choice[-1] += name.strip()[:20] + ', '
101                            break
102                    s = ''
103                    fmt = "%.2f,"
104                    for i,key in enumerate(cellitems):
105                        if i == 3: fmt = "%.f,"
106                        if i == 5: fmt = "%.f"
107                        val = cf[blknm].get(key)
108                        if val is None: break
109                        s += fmt % cif.get_number_with_esd(
110                            )[0]
111                    if s: choice[-1] += ', cell: ' + s
112                    sg = cf[blknm].get("_symmetry_space_group_name_H-M")
113                    if sg: choice[-1] += ', (' + sg.strip() + ')'
114                choice.append('Import all of the above')
115                if self.repeat: # we were called to repeat the read
116                    selblk = self.repeatcount
117                    self.repeatcount += 1
118                    if self.repeatcount >= len(blklist): self.repeat = False
119                else:
120                    selblk = self.BlockSelector(
121                        choice,
122                        ParentFrame=ParentFrame,
123                        title='Select a dataset from one the CIF data_ blocks below',
124                        size=(600,100),
125                        header='Dataset Selector')
126            if selblk is None:
127                return False # no block selected or available
128            if selblk >= len(blklist): # all blocks selected
129                selblk = 0
130                self.repeat = True
131                if rdbuffer is not None:
132                    rdbuffer['lastcif'] = cf # save the parsed cif for the next loop
133                self.repeatcount = 1
134            blknm = blklist[selblk]
135            blk = cf[blklist[selblk]]
136            self.objname = os.path.basename(filename)+':'+str(blknm)
137            # read in reflections
138            refloop = blk.GetLoop('_refln_index_h')
139            itemkeys = {}
140            # prepare an index to the CIF reflection loop
141            for i,key in enumerate(refloop.keys()):
142                itemkeys[key.lower()] = i
143            if '_refln_f_squared_calc' in itemkeys:
144                FcalcPresent = True
145            elif '_refln_f_calc' in itemkeys:
146                FcalcPresent = True
147            else:
148                FcalcPresent = False
149            for item in refloop:
150                HKL = []
151                for i in hklitems: # ('_refln_index_h','_refln_index_k','_refln_index_l')
152                    num = itemkeys.get(i)
153                    try:
154                        HKL.append(int(item[num]))
155                    except:
156                        HKL.append('.')
157                ref = [HKL,0.,0.,0,0,0,0]  # HKL. Fo**2, sig(Fo**2), Fc, Fcp, Fcpp & phase
158                # get F or F**2 and sigma
159                if '_refln_f_squared_meas' in itemkeys:
160                    try:
161                        ref[1] = float(item[itemkeys['_refln_f_squared_meas']])
162                    except:
163                        pass
164                    if  '_refln_f_squared_sigma' in itemkeys:
165                        try:
166                            ref[2] = float(item[itemkeys['_refln_f_squared_sigma']])
167                        except:
168                            pass                           
169                elif '_refln_f_meas' in itemkeys:
170                    try:
171                        ref[1] = float(item[itemkeys['_refln_f_meas']])**2
172                    except:
173                        pass                               
174                    if  '_refln_f_sigma' in itemkeys:
175                        try:
176                            ref[2] = 2.*sqrt(ref[1])*float(item[itemkeys['_refln_f_sigma']])
177                        except:
178                            pass                               
179                if '_refln_f_squared_calc' in itemkeys:
180                    try:
181                        ref[3] = float(item[itemkeys['_refln_f_squared_calc']])
182                    except:
183                        pass                               
184                elif '_refln_f_calc' in itemkeys:
185                    try:
186                        ref[3] = float(item[itemkeys['_refln_f_calc']])**2
187                    except:
188                        pass                               
189                if '_refln_phase_calc' in itemkeys:
190                    try:
191                        ref[6] = float(item[itemkeys['_refln_phase_calc']])
192                    except:
193                        pass                               
194
195                self.RefList.append(ref)
196            self.UpdateControls(Type='Fosq',FcalcPresent=FcalcPresent) # set Fobs type & if Fcalc values are loaded
197            if blk.get('_diffrn_radiation_probe'):
198                if blk['_diffrn_radiation_probe'] == 'neutron':
199                    type = 'SNC'
200            else:
201                type = 'SXC'
202            if blk.get('_diffrn_radiation_wavelength'):
203                wave = blk['_diffrn_radiation_wavelength']
204            else:
205                wave = None
206            self.UpdateParameters(Type=type,Wave=wave) # histogram type
207            return True
208        except Exception as detail:
209            print self.formatName+' read error:'+str(detail) # for testing
210            import traceback
211            traceback.print_exc(file=sys.stdout)
212        return False
Note: See TracBrowser for help on using the repository browser.