source: trunk/exports/G2cif.py @ 946

Last change on this file since 946 was 946, checked in by toby, 9 years ago

update self-docs, start work on constraints object

  • Property svn:eol-style set to native
File size: 30.8 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        # ====== move this later ==================================================
397        #for key in self.OverallParms['Covariance']:
398        #    print key
399        #    print type(self.OverallParms['Covariance'][key])
400        sigDict = dict(zip(
401            self.OverallParms['Covariance']['varyList'],
402            self.OverallParms['Covariance']['sig'])
403                       )
404        # get restraint info
405        #restraintDict = self.OverallParms.get('Restraints',{})
406        for i in  self.OverallParms['Constraints']:
407            print i
408            for j in self.OverallParms['Constraints'][i]:
409                print j
410        return
411        parmDict = {}
412        #G2mv.InitVars()
413        # do constraint processing
414        #try:
415        #    groups,parmlist = G2mv.GroupConstraints(constrDict)
416        #    G2mv.GenerateConstraints(groups,parmlist,varyList,constrDict,fixedList)
417        #except:
418        #    import GSASIIstrIO as G2stIO
419        #    print ' *** ERROR - your constraints are internally inconsistent ***'
420        #    errmsg, warnmsg = G2stIO.CheckConstraints(varyList,constrDict,fixedList)
421        #    print 'Errors',errmsg
422        #    if warnmsg: print 'Warnings',warnmsg
423        #    raise Exception(' *** CIF creation aborted ***')
424       
425        # add the uncertainties into the esd dictionary (sigDict)
426        #sigDict.update(G2mv.ComputeDepESD(
427        #    self.OverallParms['Covariance']['covMatrix'],
428        #    self.OverallParms['Covariance']['varyList'],
429        #    parmDict))
430
431        return
432
433        self.CIFdate = dt.datetime.strftime(dt.datetime.now(),"%Y-%m-%dT%H:%M")
434        # count phases, powder and single crystal histograms
435        self.nphase = len(self.GroupedParms.get("Phases",[]))
436        self.npowder = len(self.GroupedParms.get("PWDR",[]))
437        self.nsingle = len(self.GroupedParms.get("HKLF",[]))
438        # is there anything to export?
439        if self.nphase + self.npowder + self.nsingle == 0: 
440            self.G2frame.ErrorDialog(
441                'Empty project',
442                'No data or phases to include in CIF')
443            return
444        # is there a file name defined?
445        self.CIFname = os.path.splitext(
446            os.path.split(self.G2frame.GSASprojectfile)[1]
447            )[0]
448        self.CIFname = self.CIFname.replace(' ','')
449        if not self.CIFname:
450            self.G2frame.ErrorDialog(
451                'No GPX name',
452                'Please save the project to provide a name')
453            return
454        # test for quick CIF mode or no data
455        self.quickmode = False
456        phasenam = phasenum = None # include all phases
457        if mode != "full" or self.npowder + self.nsingle == 0:
458            self.quickmode = True
459            oneblock = True
460            if self.nphase == 0:
461                self.G2frame.ErrorDialog(
462                    'No phase present',
463                    'Cannot create a coordinates CIF with no phases')
464                return
465            elif self.nphase > 1: # quick mode: choose one phase
466                choices = sorted(self.GroupedParms['Phases'].keys())
467                phasenum = G2gd.ItemSelector(choices,self.G2frame)
468                if phasenum is None: return
469                phasenam = choices[phasenum]
470        # will this require a multiblock CIF?
471        elif self.nphase > 1:
472            oneblock = False
473        elif self.npowder + self.nsingle > 1:
474            oneblock = False
475        else: # one phase, one dataset, Full CIF
476            oneblock = True
477
478        # make sure needed infomation is present
479        # get CIF author name -- required for full CIFs
480        try:
481            self.author = self.OverallParms['Controls'].get("Author",'').strip()
482        except KeyError:
483            pass
484        while not (self.author or self.quickmode):
485            dlg = G2gd.SingleStringDialog(self.G2frame,'Get CIF Author','Provide CIF Author name (Last, First)')
486            if not dlg.Show(): return # cancel was pressed
487            self.author = dlg.GetValue()
488            dlg.Destroy()
489        try:
490            self.OverallParms['Controls']["Author"] = self.author # save for future
491        except KeyError:
492            pass
493        self.shortauthorname = self.author.replace(',','').replace(' ','')[:20]
494
495        # check the instrument name for every histogram
496        if not self.quickmode:
497            dictlist = []
498            keylist = []
499            lbllist = []
500            invalid = 0
501            key3 = 'InstrName'
502            for key in self.GroupedParms:
503                if key == 'Phases': continue
504                for key1 in self.GroupedParms[key]:
505                    if key == "PWDR":
506                        key2 = "Sample Parameters"
507                        d = self.GroupedParms[key][key1][key2]
508                    elif key == "HKLF":
509                        key2 = "Instrument Parameters"
510                        d = self.GroupedParms[key][key1][key2][0]
511                    else:
512                        raise Exception,"Unexpected histogram type for CIF: "+str(key)
513                       
514                    lbllist.append(key1)
515                    dictlist.append(d)
516                    keylist.append(key3)
517                    instrname = d.get(key3)
518                    if instrname is None:
519                        d[key3] = ''
520                        invalid += 1
521                    elif instrname.strip() == '':
522                        invalid += 1
523            if invalid:
524                msg = ""
525                if invalid > 1: msg = (
526                    "\n\nNote: it may be faster to set the name for\n"
527                    "one histogram for each instrument and use the\n"
528                    "File/Copy option to duplicate the name"
529                    )
530                if not G2gd.CallScrolledMultiEditor(
531                    self.G2frame,dictlist,keylist,
532                    prelbl=range(1,len(dictlist)+1),
533                    postlbl=lbllist,
534                    title='Instrument names',
535                    header="Edit instrument names. Note that a non-blank\nname is required for all histograms"+msg,
536                    ): return
537
538        #======================================================================
539        # Start writing the CIF - single block
540        #======================================================================
541        if oneblock:
542            if phasenam is None: # if not already selected, select the first phase (should be one)
543                phasenam = self.GroupedParms['Phases'].keys()[0]
544            #print 'phasenam',phasenam
545            phaseblk = self.GroupedParms['Phases'][phasenam] # pointer to current phase info
546            # select data, should only be one set, but take whatever comes 1st
547            if not self.quickmode:
548                for key in self.GroupedParms:
549                    if key == 'Phases': continue
550                    for key1 in self.GroupedParms[key]:
551                        histblk = self.GroupedParms[key][key1]
552                        histkey = key1
553                        histtyp = key
554                        if key == "PWDR":
555                            instnam = histblk["Sample Parameters"]['InstrName']
556                        elif key == "HKLF":
557                            instnam = histblk["Instrument Parameters"][0]['InstrName']
558                        break
559                    break
560                instnam = instnam.replace(' ','')
561            WriteCIFitem('data_'+self.CIFname)
562            if not self.quickmode: # publication information
563                WriteCIFitem('_pd_block_id',
564                             str(self.CIFdate) + "|" + str(self.CIFname) + "|" +
565                             str(self.shortauthorname) + "|" + instnam)
566                WriteAudit()
567                WritePubTemplate()
568                WriteOverall()
569            # report the phase
570            WritePhaseTemplate()
571            WritePhaseInfo(phasenam)
572            if not self.quickmode:
573                if histtyp == "PWDR":
574                    WritePowderTemplate()
575                    WritePowderData(histkey)
576                else:
577                    WriteSnglXtalTemplate()
578                    WriteSingleXtalData(histkey)
579        else:
580        #======================================================================
581        # Start writing the CIF - multiblock
582        #======================================================================
583            # publication info
584            WriteCIFitem('\ndata_'+self.CIFname+'_publ')
585            WriteAudit()
586            WriteCIFitem('_pd_block_id',
587                         str(self.CIFdate) + "|" + str(self.CIFname) + "|" +
588                         str(self.shortauthorname) + "|Overall")
589            WritePubTemplate()
590            # overall info
591            WriteCIFitem('data_'+str(self.CIFname)+'_overall')
592            WriteOverall()
593            #============================================================
594            WriteCIFitem('# POINTERS TO PHASE AND HISTOGRAM BLOCKS')
595            datablockidDict = {} # save block names here -- N.B. check for conflicts between phase & hist names (unlikely!)
596            # loop over phase blocks
597            if self.nphase > 1:
598                loopprefix = ''
599                WriteCIFitem('loop_   _pd_phase_block_id')
600            else:
601                loopprefix = '_pd_phase_block_id'
602           
603            for i,phasenam in enumerate(sorted(self.GroupedParms['Phases'].keys())):
604                datablockidDict[phasenam] = (str(self.CIFdate) + "|" + str(self.CIFname) + "|" +
605                             'phase_'+ str(i+1) + '|' + str(self.shortauthorname))
606                WriteCIFitem(loopprefix,datablockidDict[phasenam])
607            # loop over data blocks
608            i = 0
609            if self.npowder + self.nsingle > 1:
610                loopprefix = ''
611                WriteCIFitem('loop_   _pd_block_diffractogram_id')
612            else:
613                loopprefix = '_pd_block_diffractogram_id'
614            for key in self.GroupedParms:
615                if key == 'Phases': continue
616                for key1 in self.GroupedParms[key]:
617                    i += 1
618                    histblk = self.GroupedParms[key][key1]
619                    if key == "PWDR":
620                        instnam = histblk["Sample Parameters"]['InstrName']
621                    elif key == "HKLF":
622                        instnam = histblk["Instrument Parameters"][0]['InstrName']
623                    instnam = instnam.replace(' ','')
624                    if datablockidDict.get(key1):
625                        print "Error: histogram name is duplicated: ",key1
626                        return
627                    datablockidDict[key1] = (str(self.CIFdate) + "|" + str(self.CIFname) + "|" +
628                                             str(self.shortauthorname) + "|" +
629                                             instnam + "_hist_"+str(i))
630                    WriteCIFitem(loopprefix,datablockidDict[key1])
631            #============================================================
632            # loop over phases, exporting them
633            phasebyhistDict = {} # create a cross-reference to phases by histogram
634            for j,phasenam in enumerate(sorted(self.GroupedParms['Phases'].keys())):
635                i = j + 1
636                WriteCIFitem('\ndata_'+self.CIFname+"_phase_"+str(i))
637                print "debug, processing ",phasenam
638                WriteCIFitem('# Information for phase '+str(i))
639                WriteCIFitem('_pd_block_id',datablockidDict[phasenam])
640                # report the phase
641                WritePhaseTemplate()
642                WritePhaseInfo(phasenam)
643
644            #============================================================
645            # loop over histograms, exporting them
646            i = 0
647            for key in self.GroupedParms:
648                if key == 'Phases': continue
649                for key1 in self.GroupedParms[key]:
650                    i += 1
651                    histblk = self.GroupedParms[key][key1]
652                    if key == "PWDR":
653                        WriteCIFitem('\ndata_'+self.CIFname+"_pwd_"+str(i))
654                    elif key == "HKLF":
655                        WriteCIFitem('\ndata_'+self.CIFname+"_sx_"+str(i))
656                    WriteCIFitem('# Information for histogram '+str(i)+': '+
657                                 key1)
658                    WriteCIFitem('_pd_block_id',datablockidDict[key1])
659                    if key == "PWDR":
660                        WritePowderTemplate()
661                        WritePowderData(key1)
662                    else:
663                        WriteSnglXtalTemplate()
664                        WriteSingleXtalData(key1)
665
666        # TODO: how to report _pd_proc_ls_peak_cutoff?
667        WriteCIFitem('#--' + 15*'eof--' + '#')
668
Note: See TracBrowser for help on using the repository browser.