1 | '''Development code to export a GSAS-II project as a CIF |
---|
2 | The heavy lifting is done in method export |
---|
3 | ''' |
---|
4 | |
---|
5 | import datetime as dt |
---|
6 | import os.path |
---|
7 | import GSASIIIO as G2IO |
---|
8 | import GSASIIgrid as G2gd |
---|
9 | #reload(G2gd) |
---|
10 | class ExportCIF(G2IO.ExportBaseclass): |
---|
11 | def __init__(self,G2frame): |
---|
12 | super(self.__class__,self).__init__( # fancy way to say <parentclass>.__init__ |
---|
13 | G2frame=G2frame, |
---|
14 | formatName = 'full CIF', |
---|
15 | longFormatName = 'Export project as complete CIF' |
---|
16 | ) |
---|
17 | self.author = '' |
---|
18 | |
---|
19 | def export(self,mode='full'): |
---|
20 | '''Export a CIF |
---|
21 | |
---|
22 | :param str mode: "full" (default) to create a complete CIF of project, |
---|
23 | "simple" for a simple CIF with only coordinates |
---|
24 | ''' |
---|
25 | def WriteCIFitem(name,value=''): |
---|
26 | if value: |
---|
27 | if "\n" in value or len(value)> 70: |
---|
28 | if name.strip(): print name |
---|
29 | print '; '+value |
---|
30 | print '; ' |
---|
31 | elif " " in value: |
---|
32 | if len(name)+len(value) > 65: |
---|
33 | print name,'\n ','"' + str(value) + '"' |
---|
34 | else: |
---|
35 | print name,' ','"' + str(value) + '"' |
---|
36 | else: |
---|
37 | if len(name)+len(value) > 65: |
---|
38 | print name,'\n ',value |
---|
39 | else: |
---|
40 | print name,' ',value |
---|
41 | else: |
---|
42 | print name |
---|
43 | |
---|
44 | def WriteAudit(): |
---|
45 | WriteCIFitem('_audit_creation_method', |
---|
46 | 'created in GSAS-II') |
---|
47 | WriteCIFitem('_audit_creation_date',self.CIFdate) |
---|
48 | if self.author: |
---|
49 | WriteCIFitem('_audit_author_name',self.author) |
---|
50 | WriteCIFitem('_audit_update_record', |
---|
51 | self.CIFdate+' Initial software-generated CIF') |
---|
52 | |
---|
53 | def WriteOverall(): |
---|
54 | '''TODO: Write out overall refinement information |
---|
55 | ''' |
---|
56 | WriteCIFitem('_pd_proc_info_datetime', self.CIFdate) |
---|
57 | WriteCIFitem('_pd_calc_method', 'Rietveld Refinement') |
---|
58 | #WriteCIFitem('_refine_ls_shift/su_max',DAT1) |
---|
59 | #WriteCIFitem('_refine_ls_shift/su_mean',DAT2) |
---|
60 | WriteCIFitem('_computing_structure_refinement','GSAS-II') |
---|
61 | #WriteCIFitem('_refine_ls_number_parameters',DAT1) |
---|
62 | #WriteCIFitem('_refine_ls_goodness_of_fit_all',DAT2) |
---|
63 | #WriteCIFitem('_refine_ls_number_restraints',TEXT(1:7)) |
---|
64 | # other things to consider reporting |
---|
65 | # _refine_ls_number_reflns |
---|
66 | # _refine_ls_goodness_of_fit_obs |
---|
67 | # _refine_ls_R_factor_all |
---|
68 | # _refine_ls_R_factor_obs |
---|
69 | # _refine_ls_wR_factor_all |
---|
70 | # _refine_ls_wR_factor_obs |
---|
71 | # _refine_ls_restrained_S_all |
---|
72 | # _refine_ls_restrained_S_obs |
---|
73 | |
---|
74 | # include an overall profile r-factor, if there is more than one powder histogram |
---|
75 | if self.npowder > 1: |
---|
76 | WriteCIFitem('\n# OVERALL POWDER R-FACTORS') |
---|
77 | #WriteCIFitem('_pd_proc_ls_prof_R_factor',TEXT(11:20)) |
---|
78 | #WriteCIFitem('_pd_proc_ls_prof_wR_factor',TEXT(1:10)) |
---|
79 | WriteCIFitem('_refine_ls_matrix_type','full') |
---|
80 | #WriteCIFitem('_refine_ls_matrix_type','userblocks') |
---|
81 | |
---|
82 | def WritePubTemplate(): |
---|
83 | '''TODO: insert the publication template ``template_publ.cif`` or some modified |
---|
84 | version for this project. Store this in the GPX file? |
---|
85 | ''' |
---|
86 | print "TODO: publication info goes here" |
---|
87 | |
---|
88 | def WritePhaseTemplate(): |
---|
89 | '''TODO: insert the phase template ``template_phase.cif`` or some modified |
---|
90 | version for this project |
---|
91 | ''' |
---|
92 | print "TODO: phase template info goes here" |
---|
93 | |
---|
94 | def WritePowderTemplate(): |
---|
95 | '''TODO: insert the phase template ``template_instrument.cif`` or some modified |
---|
96 | version for this project |
---|
97 | ''' |
---|
98 | print "TODO: powder histogram template info goes here" |
---|
99 | |
---|
100 | def WriteSnglXtalTemplate(): |
---|
101 | '''TODO: insert the single-crystal histogram template |
---|
102 | for this project |
---|
103 | ''' |
---|
104 | print "TODO: single-crystal histogram template info goes here" |
---|
105 | |
---|
106 | def WritePhaseInfo(phasenam): |
---|
107 | # see writepha.for |
---|
108 | print 'TODO: phase info for',phasenam,'goes here' |
---|
109 | # THINK: how to select publication flags for distances/angles? |
---|
110 | phasedict = self.GroupedParms['Phases'][phasenam] # pointer to current phase info |
---|
111 | WriteCIFitem('_pd_phase_name', phasenam) |
---|
112 | text = '?' |
---|
113 | for lbl in 'a','b','c': |
---|
114 | WriteCIFitem('_cell_length_'+lbl,text) |
---|
115 | for lbl in 'alpha','beta ','gamma': |
---|
116 | WriteCIFitem('_cell_angle_'+lbl,text) |
---|
117 | |
---|
118 | WriteCIFitem('_cell_volume',text) |
---|
119 | |
---|
120 | #print phasedict['Histograms'] |
---|
121 | # for key in phasedict['General']: |
---|
122 | # print key,'=',phasedict['General'][key] |
---|
123 | # print phasedict['pId'] |
---|
124 | |
---|
125 | #NSYS = (1,2,3,4,4,5,5,5,5,5,6,6,7,7) |
---|
126 | #SYST = ('','triclinic','monoclinic','orthorhombic','tetragonal','trigonal ','hexagonal','cubic') |
---|
127 | |
---|
128 | WriteCIFitem('_symmetry_cell_setting', |
---|
129 | phasedict['General']['SGData']['SGSys']) |
---|
130 | |
---|
131 | spacegroup = phasedict['General']['SGData']['SpGrp'].strip() |
---|
132 | # regularize capitalization and remove trailing H/R |
---|
133 | spacegroup = spacegroup[0].upper() + spacegroup[1:].lower().rstrip('rh ') |
---|
134 | WriteCIFitem('_symmetry_space_group_name_H-M',spacegroup) |
---|
135 | # generate symmetry operations including centering and center of symmetry |
---|
136 | WriteCIFitem('loop_ _symmetry_equiv_pos_site_id _symmetry_equiv_pos_as_xyz') |
---|
137 | |
---|
138 | # loop over histogram(s) used in this phase |
---|
139 | if not oneblock: |
---|
140 | # pointers to histograms used in this phase |
---|
141 | histlist = [] |
---|
142 | for hist in self.GroupedParms['Phases'][phasenam]['Histograms']: |
---|
143 | if self.GroupedParms['Phases'][phasenam]['Histograms'][hist]['Use']: |
---|
144 | if phasebyhistDict.get(hist): |
---|
145 | phasebyhistDict[hist].append(phasenam) |
---|
146 | else: |
---|
147 | phasebyhistDict[hist] = [phasenam,] |
---|
148 | blockid = datablockidDict.get(hist) |
---|
149 | if not blockid: |
---|
150 | print "Internal error: no block for data. Phase "+str( |
---|
151 | phasenam)+" histogram "+str(hist) |
---|
152 | histlist = [] |
---|
153 | break |
---|
154 | histlist.append(blockid) |
---|
155 | |
---|
156 | if len(histlist) == 0: |
---|
157 | WriteCIFitem('# Note: phase has no associated data') |
---|
158 | else: |
---|
159 | WriteCIFitem('loop_ _pd_block_diffractogram_id') |
---|
160 | for hist in histlist: |
---|
161 | WriteCIFitem('',hist) |
---|
162 | # TODO: sample/histogram profile information and other "HAP" info should be |
---|
163 | # reported in this loop, such as |
---|
164 | # _pd_proc_ls_pref_orient_corr |
---|
165 | # _pd_proc_ls_profile_function |
---|
166 | #txt = ' Spherical Harmonic ODF' + '\n spherical harmonic order='+'?' |
---|
167 | #IF ( ISAMSYM.EQ.1 ) THEN |
---|
168 | #txt += '\n No sample symmetry' |
---|
169 | #ELSE IF ( ISAMSYM.EQ.2 ) THEN |
---|
170 | #txt += ' The sample symmetry is: 2/m (shear texture)' |
---|
171 | #ELSE IF ( ISAMSYM.EQ.3 ) THEN |
---|
172 | #txt += ' The sample symmetry is: mmm (rolling texture)' |
---|
173 | #ELSE IF ( ISAMSYM.EQ.0 ) THEN |
---|
174 | #txt += ' The sample symmetry is: cylindrical (fiber texture)' |
---|
175 | #WriteCIFitem('_pd_proc_ls_pref_orient_corr',txt) |
---|
176 | else: |
---|
177 | # report all profile information here (include instrumental) |
---|
178 | # _pd_proc_ls_pref_orient_corr |
---|
179 | # _pd_proc_ls_profile_function |
---|
180 | pass |
---|
181 | |
---|
182 | WriteCIFitem('\n# ATOMIC COORDINATES AND DISPLACEMENT PARAMETERS') |
---|
183 | |
---|
184 | WriteCIFitem('loop_ '+ |
---|
185 | '\n\t_atom_site_type_symbol'+ |
---|
186 | '\n\t_atom_site_label'+ |
---|
187 | '\n\t_atom_site_fract_x'+ |
---|
188 | '\n\t_atom_site_fract_y'+ |
---|
189 | '\n\t_atom_site_fract_z'+ |
---|
190 | '\n\t_atom_site_occupancy'+ |
---|
191 | '\n\t_atom_site_thermal_displace_type'+ |
---|
192 | '\n\t_atom_site_U_iso_or_equiv'+ |
---|
193 | '\n\t_atom_site_symmetry_multiplicity') |
---|
194 | |
---|
195 | WriteCIFitem('loop_' + '\n\t_atom_site_aniso_label' + |
---|
196 | '\n\t_atom_site_aniso_U_11' + '\n\t_atom_site_aniso_U_12' + |
---|
197 | '\n\t_atom_site_aniso_U_13' + '\n\t_atom_site_aniso_U_22' + |
---|
198 | '\n\t_atom_site_aniso_U_23' + '\n\t_atom_site_aniso_U_33') |
---|
199 | |
---|
200 | # process the chemical formula: pick a Z value & generate molecular weight |
---|
201 | # find the maximum possible Z value |
---|
202 | |
---|
203 | # order the elements in "Hill" order: C, H, D, T & alphabetical or alphabetical |
---|
204 | if not oneblock: # in single block, this is combined with the scattering factors |
---|
205 | WriteCIFitem('loop_ _atom_type_symbol _atom_type_number_in_cell') |
---|
206 | |
---|
207 | WriteCIFitem('# If you change Z, be sure to change all 3 of the following') |
---|
208 | WriteCIFitem( '_chemical_formula_sum',text) |
---|
209 | #WRITE(TEXT,'(F15.2)') ATMASS |
---|
210 | WriteCIFitem( '_chemical_formula_weight',text) |
---|
211 | #WRITE(TEXT,'(I4)') Z |
---|
212 | WriteCIFitem( '_cell_formula_units_Z',text) |
---|
213 | |
---|
214 | #C now loop over interatomic distances for this phase |
---|
215 | WriteCIFitem('\n# MOLECULAR GEOMETRY') |
---|
216 | WriteCIFitem('loop_' + |
---|
217 | '\n\t_geom_bond_atom_site_label_1' + |
---|
218 | '\n\t_geom_bond_atom_site_label_2' + |
---|
219 | '\n\t_geom_bond_distance' + |
---|
220 | '\n\t_geom_bond_site_symmetry_1' + |
---|
221 | '\n\t_geom_bond_site_symmetry_2' + |
---|
222 | '\n\t_geom_bond_publ_flag') |
---|
223 | |
---|
224 | #C now loop over interatomic angles for this phase |
---|
225 | WriteCIFitem('loop_' + |
---|
226 | '\n\t_geom_angle_atom_site_label_1' + |
---|
227 | '\n\t_geom_angle_atom_site_label_2' + |
---|
228 | '\n\t_geom_angle_atom_site_label_3' + |
---|
229 | '\n\t_geom_angle' + |
---|
230 | '\n\t_geom_angle_site_symmetry_1' + |
---|
231 | '\n\t_geom_angle_site_symmetry_2' + |
---|
232 | '\n\t_geom_angle_site_symmetry_3' + |
---|
233 | '\n\t_geom_angle_publ_flag') |
---|
234 | |
---|
235 | def WritePowderData(histlbl): |
---|
236 | text = '?' |
---|
237 | histblk = self.GroupedParms['PWDR'][histlbl] |
---|
238 | print 'TODO: powder here data for',histblk["Sample Parameters"]['InstrName'] |
---|
239 | # see wrpowdhist.for & wrreflist.for |
---|
240 | |
---|
241 | refprx = '_refln.' # mm |
---|
242 | refprx = '_refln_' # normal |
---|
243 | |
---|
244 | if not oneblock: |
---|
245 | if not phasebyhistDict.get(histlbl): |
---|
246 | WriteCIFitem('\n# No phases associated with this data set') |
---|
247 | else: |
---|
248 | WriteCIFitem('\n# PHASE TABLE') |
---|
249 | WriteCIFitem('loop_' + |
---|
250 | '\n\t_pd_phase_id' + |
---|
251 | '\n\t_pd_phase_block_id' + |
---|
252 | '\n\t_pd_phase_mass_%') |
---|
253 | for phasenam in phasebyhistDict.get(histlbl): |
---|
254 | pass |
---|
255 | |
---|
256 | WriteCIFitem('\n# SCATTERING FACTOR INFO') |
---|
257 | WriteCIFitem('_diffrn_radiation_wavelength' ,text) |
---|
258 | #WriteCIFitem('_diffrn_radiation_type',text) |
---|
259 | #C always assume Ka1 & Ka2 if two wavelengths are present |
---|
260 | #WriteCIFitem('loop_' + |
---|
261 | # '\n\t_diffrn_radiation_wavelength' + |
---|
262 | # '\n\t_diffrn_radiation_wavelength_wt' + |
---|
263 | # '\n\t_diffrn_radiation_type' + |
---|
264 | # '\n\t_diffrn_radiation_wavelength_id') |
---|
265 | #WRITE LAM1,1.0,'K\\a~1~',1, LAM2,ratio,'K\\a~2~',2 |
---|
266 | |
---|
267 | WriteCIFitem('_pd_proc_ls_prof_R_factor','?') |
---|
268 | WriteCIFitem('_pd_proc_ls_prof_wR_factor','?') |
---|
269 | WriteCIFitem('_pd_proc_ls_prof_wR_expected','?') |
---|
270 | WriteCIFitem('_refine_ls_R_Fsqd_factor','?') |
---|
271 | |
---|
272 | #WriteCIFitem('_pd_meas_2theta_fixed',text) |
---|
273 | WriteCIFitem('_diffrn_radiation_probe','x-ray') |
---|
274 | WriteCIFitem('_diffrn_radiation_probe','neutron') |
---|
275 | WriteCIFitem('_diffrn_radiation_polarisn_ratio','?') |
---|
276 | |
---|
277 | WriteCIFitem('loop_ _atom_type_symbol') |
---|
278 | if oneblock: |
---|
279 | WriteCIFitem(' _atom_type_number_in_cell') |
---|
280 | #IF (HTYP(2:2) .eq. 'X' .AND. HTYP(3:3) .ne. 'E') THEN |
---|
281 | WriteCIFitem(' _atom_type_scat_dispersion_real') |
---|
282 | WriteCIFitem(' _atom_type_scat_dispersion_imag') |
---|
283 | for lbl in ('a1','a2','a3', 'a4', 'b1', 'b2', 'b3', 'b4', 'c'): |
---|
284 | WriteCIFitem(' _atom_type_scat_Cromer_Mann_'+lbl) |
---|
285 | #ELSEIF (HTYP(2:2) .eq. 'N') THEN |
---|
286 | WriteCIFitem(' _atom_type_scat_length_neutron') |
---|
287 | #ENDIF |
---|
288 | WriteCIFitem(' _atom_type_scat_source') |
---|
289 | |
---|
290 | #C document the background function used |
---|
291 | WriteCIFitem('_pd_proc_ls_background_function','?') |
---|
292 | |
---|
293 | WriteCIFitem('_exptl_absorpt_process_details','?') |
---|
294 | WriteCIFitem('_exptl_absorpt_correction_T_min','?') |
---|
295 | WriteCIFitem('_exptl_absorpt_correction_T_max','?') |
---|
296 | #C extinction |
---|
297 | #WRITE(IUCIF,'(A)') '# Extinction correction' |
---|
298 | #CALL WRVAL(IUCIF,'_gsas_exptl_extinct_corr_T_min',TEXT(1:10)) |
---|
299 | #CALL WRVAL(IUCIF,'_gsas_exptl_extinct_corr_T_max',TEXT(11:20)) |
---|
300 | |
---|
301 | if not oneblock: |
---|
302 | # instrumental profile terms go here |
---|
303 | WriteCIFitem('_pd_proc_ls_profile_function','?') |
---|
304 | |
---|
305 | WriteCIFitem('\n# STRUCTURE FACTOR TABLE') |
---|
306 | WriteCIFitem('loop_' + |
---|
307 | '\n\t' + refprx + 'index_h' + |
---|
308 | '\n\t' + refprx + 'index_k' + |
---|
309 | '\n\t' + refprx + 'index_l' + |
---|
310 | '\n\t_pd_refln_wavelength_id' + |
---|
311 | '\n\t_pd_refln_phase_id' + |
---|
312 | '\n\t' + refprx + 'status' + |
---|
313 | '\n\t' + refprx + 'F_squared_meas' + |
---|
314 | '\n\t' + refprx + 'F_squared_sigma' + |
---|
315 | '\n\t' + refprx + 'F_squared_calc' + |
---|
316 | '\n\t' + refprx + 'phase_calc' + |
---|
317 | '\n\t_pd_refln_d_spacing' + |
---|
318 | '\n\t_gsas_i100_meas') |
---|
319 | |
---|
320 | WriteCIFitem('_reflns_number_total', text) |
---|
321 | WriteCIFitem('_reflns_limit_h_min', text) |
---|
322 | WriteCIFitem('_reflns_limit_h_max', text) |
---|
323 | WriteCIFitem('_reflns_limit_k_min', text) |
---|
324 | WriteCIFitem('_reflns_limit_k_max', text) |
---|
325 | WriteCIFitem('_reflns_limit_l_min', text) |
---|
326 | WriteCIFitem('_reflns_limit_l_max', text) |
---|
327 | WriteCIFitem('_reflns_d_resolution_high', text) |
---|
328 | WriteCIFitem('_reflns_d_resolution_low', text) |
---|
329 | |
---|
330 | WriteCIFitem('\n# POWDER DATA TABLE') |
---|
331 | # is data fixed step? |
---|
332 | fixedstep = False |
---|
333 | # are ESDs sqrt(I) |
---|
334 | countsdata = False |
---|
335 | zero = 0.01 |
---|
336 | if fixedstep: |
---|
337 | WriteCIFitem('_pd_meas_2theta_range_min', text) |
---|
338 | WriteCIFitem('_pd_meas_2theta_range_max', text) |
---|
339 | WriteCIFitem('_pd_meas_2theta_range_inc', text) |
---|
340 | # zero correct |
---|
341 | if zero != 0.0: |
---|
342 | WriteCIFitem('_pd_proc_2theta_range_min', text) |
---|
343 | WriteCIFitem('_pd_proc_2theta_range_max', text) |
---|
344 | WriteCIFitem('_pd_proc_2theta_range_inc', text) |
---|
345 | WriteCIFitem('loop_' + |
---|
346 | '\n\t_pd_proc_d_spacing') |
---|
347 | #'_pd_meas_time_of_flight' |
---|
348 | if not fixedstep: |
---|
349 | if zero != 0.0: |
---|
350 | WriteCIFitem('\t_pd_proc_2theta_corrected') |
---|
351 | else: |
---|
352 | WriteCIFitem('\t_pd_meas_2theta_scan') |
---|
353 | if countsdata: |
---|
354 | WriteCIFitem('\t_pd_meas_counts_total') |
---|
355 | else: |
---|
356 | WriteCIFitem('\t_pd_meas_intensity_total') |
---|
357 | WriteCIFitem('\t_pd_proc_ls_weight') |
---|
358 | WriteCIFitem('\t_pd_proc_intensity_bkg_calc') |
---|
359 | WriteCIFitem('\t_pd_calc_intensity_total') |
---|
360 | if zero != 0.0: |
---|
361 | WriteCIFitem('_pd_proc_number_of_points', text) |
---|
362 | else: |
---|
363 | WriteCIFitem('_pd_meas_number_of_points', text) |
---|
364 | |
---|
365 | def WriteSingleXtalData(histlbl): |
---|
366 | histblk = self.GroupedParms['HKLF'][histlbl] |
---|
367 | print 'TODO: single xtal here data for',histblk["Instrument Parameters"][0]['InstrName'] |
---|
368 | # see wrreflist.for |
---|
369 | refprx = '_refln.' # mm |
---|
370 | refprx = '_refln_' # normal |
---|
371 | |
---|
372 | WriteCIFitem('\n# STRUCTURE FACTOR TABLE') |
---|
373 | WriteCIFitem('loop_' + |
---|
374 | '\n\t' + refprx + 'index_h' + |
---|
375 | '\n\t' + refprx + 'index_k' + |
---|
376 | '\n\t' + refprx + 'index_l' + |
---|
377 | '\n\t' + refprx + 'status' + |
---|
378 | '\n\t' + refprx + 'F_squared_meas' + |
---|
379 | '\n\t' + refprx + 'F_squared_sigma' + |
---|
380 | '\n\t' + refprx + 'F_squared_calc' + |
---|
381 | '\n\t' + refprx + 'phase_calc') |
---|
382 | WriteCIFitem('_reflns_number_total', text) |
---|
383 | WriteCIFitem('_reflns_number_observed', text) |
---|
384 | WriteCIFitem('_reflns_limit_h_min', text) |
---|
385 | WriteCIFitem('_reflns_limit_h_max', text) |
---|
386 | WriteCIFitem('_reflns_limit_k_min', text) |
---|
387 | WriteCIFitem('_reflns_limit_k_max', text) |
---|
388 | WriteCIFitem('_reflns_limit_l_min', text) |
---|
389 | WriteCIFitem('_reflns_limit_l_max', text) |
---|
390 | WriteCIFitem('_reflns_d_resolution_high', text) |
---|
391 | WriteCIFitem('_reflns_d_resolution_low', text) |
---|
392 | |
---|
393 | #============================================================ |
---|
394 | # the export process starts here |
---|
395 | self.loadTree() |
---|
396 | self.CIFdate = dt.datetime.strftime(dt.datetime.now(),"%Y-%m-%dT%H:%M") |
---|
397 | # count phases, powder and single crystal histograms |
---|
398 | self.nphase = len(self.GroupedParms.get("Phases",[])) |
---|
399 | self.npowder = len(self.GroupedParms.get("PWDR",[])) |
---|
400 | self.nsingle = len(self.GroupedParms.get("HKLF",[])) |
---|
401 | # is there anything to export? |
---|
402 | if self.nphase + self.npowder + self.nsingle == 0: |
---|
403 | self.G2frame.ErrorDialog( |
---|
404 | 'Empty project', |
---|
405 | 'No data or phases to include in CIF') |
---|
406 | return |
---|
407 | # is there a file name defined? |
---|
408 | self.CIFname = os.path.splitext( |
---|
409 | os.path.split(self.G2frame.GSASprojectfile)[1] |
---|
410 | )[0] |
---|
411 | self.CIFname = self.CIFname.replace(' ','') |
---|
412 | if not self.CIFname: |
---|
413 | self.G2frame.ErrorDialog( |
---|
414 | 'No GPX name', |
---|
415 | 'Please save the project to provide a name') |
---|
416 | return |
---|
417 | # test for quick CIF mode or no data |
---|
418 | self.quickmode = False |
---|
419 | phasenam = phasenum = None # include all phases |
---|
420 | if mode != "full" or self.npowder + self.nsingle == 0: |
---|
421 | self.quickmode = True |
---|
422 | oneblock = True |
---|
423 | if self.nphase == 0: |
---|
424 | self.G2frame.ErrorDialog( |
---|
425 | 'No phase present', |
---|
426 | 'Cannot create a coordinates CIF with no phases') |
---|
427 | return |
---|
428 | elif self.nphase > 1: # quick mode: choose one phase |
---|
429 | choices = sorted(self.GroupedParms['Phases'].keys()) |
---|
430 | phasenum = G2gd.ItemSelector(choices,self.G2frame) |
---|
431 | if phasenum is None: return |
---|
432 | phasenam = choices[phasenum] |
---|
433 | # will this require a multiblock CIF? |
---|
434 | elif self.nphase > 1: |
---|
435 | oneblock = False |
---|
436 | elif self.npowder + self.nsingle > 1: |
---|
437 | oneblock = False |
---|
438 | else: # one phase, one dataset, Full CIF |
---|
439 | oneblock = True |
---|
440 | |
---|
441 | # make sure needed infomation is present |
---|
442 | # get CIF author name -- required for full CIFs |
---|
443 | try: |
---|
444 | self.author = self.OverallParms['Controls'].get("Author",'').strip() |
---|
445 | except KeyError: |
---|
446 | pass |
---|
447 | while not (self.author or self.quickmode): |
---|
448 | dlg = G2gd.SingleStringDialog(self.G2frame,'Get CIF Author','Provide CIF Author name (Last, First)') |
---|
449 | if not dlg.Show(): return # cancel was pressed |
---|
450 | self.author = dlg.GetValue() |
---|
451 | dlg.Destroy() |
---|
452 | try: |
---|
453 | self.OverallParms['Controls']["Author"] = self.author # save for future |
---|
454 | except KeyError: |
---|
455 | pass |
---|
456 | self.shortauthorname = self.author.replace(',','').replace(' ','')[:20] |
---|
457 | |
---|
458 | # check the instrument name for every histogram |
---|
459 | if not self.quickmode: |
---|
460 | dictlist = [] |
---|
461 | keylist = [] |
---|
462 | lbllist = [] |
---|
463 | invalid = 0 |
---|
464 | key3 = 'InstrName' |
---|
465 | for key in self.GroupedParms: |
---|
466 | if key == 'Phases': continue |
---|
467 | for key1 in self.GroupedParms[key]: |
---|
468 | if key == "PWDR": |
---|
469 | key2 = "Sample Parameters" |
---|
470 | d = self.GroupedParms[key][key1][key2] |
---|
471 | elif key == "HKLF": |
---|
472 | key2 = "Instrument Parameters" |
---|
473 | d = self.GroupedParms[key][key1][key2][0] |
---|
474 | else: |
---|
475 | raise Exception,"Unexpected histogram type for CIF: "+str(key) |
---|
476 | |
---|
477 | lbllist.append(key1) |
---|
478 | dictlist.append(d) |
---|
479 | keylist.append(key3) |
---|
480 | instrname = d.get(key3) |
---|
481 | if instrname is None: |
---|
482 | d[key3] = '' |
---|
483 | invalid += 1 |
---|
484 | elif instrname.strip() == '': |
---|
485 | invalid += 1 |
---|
486 | if invalid: |
---|
487 | msg = "" |
---|
488 | if invalid > 1: msg = ( |
---|
489 | "\n\nNote: it may be faster to set the name for\n" |
---|
490 | "one histogram for each instrument and use the\n" |
---|
491 | "File/Copy option to duplicate the name" |
---|
492 | ) |
---|
493 | if not G2gd.CallScrolledMultiEditor( |
---|
494 | self.G2frame,dictlist,keylist, |
---|
495 | prelbl=range(1,len(dictlist)+1), |
---|
496 | postlbl=lbllist, |
---|
497 | title='Instrument names', |
---|
498 | header="Edit instrument names. Note that a non-blank\nname is required for all histograms"+msg, |
---|
499 | ): return |
---|
500 | |
---|
501 | #====================================================================== |
---|
502 | # Start writing the CIF - single block |
---|
503 | #====================================================================== |
---|
504 | if oneblock: |
---|
505 | if phasenam is None: # if not already selected, select the first phase (should be one) |
---|
506 | phasenam = self.GroupedParms['Phases'].keys()[0] |
---|
507 | #print 'phasenam',phasenam |
---|
508 | phaseblk = self.GroupedParms['Phases'][phasenam] # pointer to current phase info |
---|
509 | # select data, should only be one set, but take whatever comes 1st |
---|
510 | if not self.quickmode: |
---|
511 | for key in self.GroupedParms: |
---|
512 | if key == 'Phases': continue |
---|
513 | for key1 in self.GroupedParms[key]: |
---|
514 | histblk = self.GroupedParms[key][key1] |
---|
515 | histkey = key1 |
---|
516 | histtyp = key |
---|
517 | if key == "PWDR": |
---|
518 | instnam = histblk["Sample Parameters"]['InstrName'] |
---|
519 | elif key == "HKLF": |
---|
520 | instnam = histblk["Instrument Parameters"][0]['InstrName'] |
---|
521 | break |
---|
522 | break |
---|
523 | instnam = instnam.replace(' ','') |
---|
524 | WriteCIFitem('data_'+self.CIFname) |
---|
525 | if not self.quickmode: # publication information |
---|
526 | WriteCIFitem('_pd_block_id', |
---|
527 | str(self.CIFdate) + "|" + str(self.CIFname) + "|" + |
---|
528 | str(self.shortauthorname) + "|" + instnam) |
---|
529 | WriteAudit() |
---|
530 | WritePubTemplate() |
---|
531 | WriteOverall() |
---|
532 | # report the phase |
---|
533 | WritePhaseTemplate() |
---|
534 | WritePhaseInfo(phasenam) |
---|
535 | if not self.quickmode: |
---|
536 | if histtyp == "PWDR": |
---|
537 | WritePowderTemplate() |
---|
538 | WritePowderData(histkey) |
---|
539 | else: |
---|
540 | WriteSnglXtalTemplate() |
---|
541 | WriteSingleXtalData(histkey) |
---|
542 | else: |
---|
543 | #====================================================================== |
---|
544 | # Start writing the CIF - multiblock |
---|
545 | #====================================================================== |
---|
546 | # publication info |
---|
547 | WriteCIFitem('\ndata_'+self.CIFname+'_publ') |
---|
548 | WriteAudit() |
---|
549 | WriteCIFitem('_pd_block_id', |
---|
550 | str(self.CIFdate) + "|" + str(self.CIFname) + "|" + |
---|
551 | str(self.shortauthorname) + "|Overall") |
---|
552 | WritePubTemplate() |
---|
553 | # overall info |
---|
554 | WriteCIFitem('data_'+str(self.CIFname)+'_overall') |
---|
555 | WriteOverall() |
---|
556 | #============================================================ |
---|
557 | WriteCIFitem('# POINTERS TO PHASE AND HISTOGRAM BLOCKS') |
---|
558 | datablockidDict = {} # save block names here -- N.B. check for conflicts between phase & hist names (unlikely!) |
---|
559 | # loop over phase blocks |
---|
560 | if self.nphase > 1: |
---|
561 | loopprefix = '' |
---|
562 | WriteCIFitem('loop_ _pd_phase_block_id') |
---|
563 | else: |
---|
564 | loopprefix = '_pd_phase_block_id' |
---|
565 | |
---|
566 | for i,phasenam in enumerate(sorted(self.GroupedParms['Phases'].keys())): |
---|
567 | datablockidDict[phasenam] = (str(self.CIFdate) + "|" + str(self.CIFname) + "|" + |
---|
568 | 'phase_'+ str(i+1) + '|' + str(self.shortauthorname)) |
---|
569 | WriteCIFitem(loopprefix,datablockidDict[phasenam]) |
---|
570 | # loop over data blocks |
---|
571 | i = 0 |
---|
572 | if self.npowder + self.nsingle > 1: |
---|
573 | loopprefix = '' |
---|
574 | WriteCIFitem('loop_ _pd_block_diffractogram_id') |
---|
575 | else: |
---|
576 | loopprefix = '_pd_block_diffractogram_id' |
---|
577 | for key in self.GroupedParms: |
---|
578 | if key == 'Phases': continue |
---|
579 | for key1 in self.GroupedParms[key]: |
---|
580 | i += 1 |
---|
581 | histblk = self.GroupedParms[key][key1] |
---|
582 | if key == "PWDR": |
---|
583 | instnam = histblk["Sample Parameters"]['InstrName'] |
---|
584 | elif key == "HKLF": |
---|
585 | instnam = histblk["Instrument Parameters"][0]['InstrName'] |
---|
586 | instnam = instnam.replace(' ','') |
---|
587 | if datablockidDict.get(key1): |
---|
588 | print "Error: histogram name is duplicated: ",key1 |
---|
589 | return |
---|
590 | datablockidDict[key1] = (str(self.CIFdate) + "|" + str(self.CIFname) + "|" + |
---|
591 | str(self.shortauthorname) + "|" + |
---|
592 | instnam + "_hist_"+str(i)) |
---|
593 | WriteCIFitem(loopprefix,datablockidDict[key1]) |
---|
594 | #============================================================ |
---|
595 | # loop over phases, exporting them |
---|
596 | phasebyhistDict = {} # create a cross-reference to phases by histogram |
---|
597 | for j,phasenam in enumerate(sorted(self.GroupedParms['Phases'].keys())): |
---|
598 | i = j + 1 |
---|
599 | WriteCIFitem('\ndata_'+self.CIFname+"_phase_"+str(i)) |
---|
600 | print "debug, processing ",phasenam |
---|
601 | WriteCIFitem('# Information for phase '+str(i)) |
---|
602 | WriteCIFitem('_pd_block_id',datablockidDict[phasenam]) |
---|
603 | # report the phase |
---|
604 | WritePhaseTemplate() |
---|
605 | WritePhaseInfo(phasenam) |
---|
606 | |
---|
607 | #============================================================ |
---|
608 | # loop over histograms, exporting them |
---|
609 | i = 0 |
---|
610 | for key in self.GroupedParms: |
---|
611 | if key == 'Phases': continue |
---|
612 | for key1 in self.GroupedParms[key]: |
---|
613 | i += 1 |
---|
614 | histblk = self.GroupedParms[key][key1] |
---|
615 | if key == "PWDR": |
---|
616 | WriteCIFitem('\ndata_'+self.CIFname+"_pwd_"+str(i)) |
---|
617 | elif key == "HKLF": |
---|
618 | WriteCIFitem('\ndata_'+self.CIFname+"_sx_"+str(i)) |
---|
619 | WriteCIFitem('# Information for histogram '+str(i)+': '+ |
---|
620 | key1) |
---|
621 | WriteCIFitem('_pd_block_id',datablockidDict[key1]) |
---|
622 | if key == "PWDR": |
---|
623 | WritePowderTemplate() |
---|
624 | WritePowderData(key1) |
---|
625 | else: |
---|
626 | WriteSnglXtalTemplate() |
---|
627 | WriteSingleXtalData(key1) |
---|
628 | |
---|
629 | # TODO: how to report _pd_proc_ls_peak_cutoff? |
---|
630 | WriteCIFitem('#--' + 15*'eof--' + '#') |
---|
631 | |
---|