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 | # |
---|
11 | import sys |
---|
12 | import numpy as np |
---|
13 | import os.path |
---|
14 | import GSASIIIO as G2IO |
---|
15 | import CifFile as cif # PyCifRW from James Hester |
---|
16 | import urllib |
---|
17 | |
---|
18 | class 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 |
---|