source: trunk/exports/G2cif.py @ 941

Last change on this file since 941 was 941, checked in by toby, 10 years ago

fix Matts mac bug on switching phase tabs; start doc of phase contents; get major CIF data names (but not yet values) into export

  • Property svn:eol-style set to native
File size: 29.3 KB
Line 
1'''Development code to export a GSAS-II project as a CIF
2The heavy lifting is done in method export
3'''
4
5import datetime as dt
6import os.path
7import GSASIIIO as G2IO
8import GSASIIgrid as G2gd
9#reload(G2gd)
10class 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
Note: See TracBrowser for help on using the repository browser.