source: trunk/exports/G2cif.py @ 990

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

mac fix for gltext; update docs

  • Property svn:eol-style set to native
File size: 50.9 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
8#reload(G2IO)
9import GSASIIgrid as G2gd
10import GSASIIstrIO as G2stIO
11#reload(G2stIO)
12#import GSASIImapvars as G2mv
13import GSASIImath as G2mth
14reload(G2mth)
15import GSASIIlattice as G2lat
16import GSASIIspc as G2spg
17#reload(G2spg)
18
19def getCallerDocString(): # for development
20    "Return the calling function's doc string"
21    import inspect as ins
22    for item in ins.stack()[1][0].f_code.co_consts:
23        if type(item) is str:
24            return item
25    else:
26        return '?'
27
28class ExportCIF(G2IO.ExportBaseclass):
29    def __init__(self,G2frame):
30        super(self.__class__,self).__init__( # fancy way to say <parentclass>.__init__
31            G2frame=G2frame,
32            formatName = 'full CIF',
33            longFormatName = 'Export project as complete CIF'
34            )
35        self.author = ''
36
37    def export(self,mode='full'):
38        '''Export a CIF
39
40        :param str mode: "full" (default) to create a complete CIF of project,
41          "simple" for a simple CIF with only coordinates
42        '''
43   
44        def WriteCIFitem(name,value=''):
45            if value:
46                if "\n" in value or len(value)> 70:
47                    if name.strip(): print name
48                    print '; '+value
49                    print '; '
50                elif " " in value:
51                    if len(name)+len(value) > 65:
52                        print name,'\n   ','"' + str(value) + '"'
53                    else:
54                        print name,'  ','"' + str(value) + '"'
55                else:
56                    if len(name)+len(value) > 65:
57                        print name,'\n   ',value
58                    else:
59                        print name,'  ',value
60            else:
61                print name
62
63        def WriteAudit():
64            WriteCIFitem('_audit_creation_method',
65                         'created in GSAS-II')
66            WriteCIFitem('_audit_creation_date',self.CIFdate)
67            if self.author:
68                WriteCIFitem('_audit_author_name',self.author)
69            WriteCIFitem('_audit_update_record',
70                         self.CIFdate+'  Initial software-generated CIF')
71
72        def WriteOverall():
73            '''Write out overall refinement information.
74
75            More could be done here, but this is a good start.
76            '''
77            WriteCIFitem('_pd_proc_info_datetime', self.CIFdate)
78            WriteCIFitem('_pd_calc_method', 'Rietveld Refinement')
79            #WriteCIFitem('_refine_ls_shift/su_max',DAT1)
80            #WriteCIFitem('_refine_ls_shift/su_mean',DAT2)
81            WriteCIFitem('_computing_structure_refinement','GSAS-II')
82            try:
83                vars = str(len(self.OverallParms['Covariance']['varyList']))
84            except:
85                vars = '?'
86            WriteCIFitem('_refine_ls_number_parameters',vars)
87            try:
88                GOF = G2mth.ValEsd(self.OverallParms['Covariance']['Rvals']['GOF'],-0.009)
89            except:
90                GOF = '?'
91            WriteCIFitem('_refine_ls_goodness_of_fit_all',GOF)
92
93            # get restraint info
94            # restraintDict = self.OverallParms.get('Restraints',{})
95            # for i in  self.OverallParms['Constraints']:
96            #     print i
97            #     for j in self.OverallParms['Constraints'][i]:
98            #         print j
99            #WriteCIFitem('_refine_ls_number_restraints',TEXT)
100           
101            # other things to consider reporting
102            # _refine_ls_number_reflns
103            # _refine_ls_goodness_of_fit_obs
104            # _refine_ls_R_factor_all
105            # _refine_ls_R_factor_obs
106            # _refine_ls_wR_factor_all
107            # _refine_ls_wR_factor_obs
108            # _refine_ls_restrained_S_all
109            # _refine_ls_restrained_S_obs
110
111            # include an overall profile r-factor, if there is more than one powder histogram
112            if self.npowder > 1:
113                WriteCIFitem('\n# OVERALL POWDER R-FACTOR')
114                try:
115                    R = str(self.OverallParms['Covariance']['Rvals']['Rwp'])
116                except:
117                    R = '?'
118                WriteCIFitem('_pd_proc_ls_prof_wR_factor',R)
119                #WriteCIFitem('_pd_proc_ls_prof_R_factor',TEXT(11:20)) # who cares!
120            WriteCIFitem('_refine_ls_matrix_type','full')
121            #WriteCIFitem('_refine_ls_matrix_type','userblocks')
122
123        def WritePubTemplate():
124            '''TODO: insert the publication template ``template_publ.cif`` or some modified
125            version for this project. Store this in the GPX file?
126            '''
127            print getCallerDocString()
128
129        def WritePhaseTemplate():
130            '''TODO: insert the phase template ``template_phase.cif`` or some modified
131            version for this project
132            '''
133            print getCallerDocString()
134
135        def WritePowderTemplate():
136            '''TODO: insert the phase template ``template_instrument.cif`` or some modified
137            version for this project
138            '''
139            print getCallerDocString()
140
141        def WriteSnglXtalTemplate():
142            '''TODO: insert the single-crystal histogram template
143            for this project
144            '''
145            print getCallerDocString()
146
147        def FormatSH(phasenam):
148            'Format a full spherical harmonics texture description as a string'
149            phasedict = self.Phases[phasenam] # pointer to current phase info           
150            pfx = str(phasedict['pId'])+'::'
151            s = ""
152            textureData = phasedict['General']['SH Texture']   
153            if textureData.get('Order'):
154                s += "Spherical Harmonics correction. Order = "+str(textureData['Order'])
155                s += " Model: " + str(textureData['Model']) + "\n    Orientation angles: "
156                for name in ['omega','chi','phi']:
157                    aname = pfx+'SH '+name
158                    s += name + " = "
159                    sig = self.sigDict.get(aname,-0.09)
160                    s += G2mth.ValEsd(self.parmDict[aname],sig)
161                    s += "; "
162                s += "\n"
163                s1 = "    Coefficients:  "
164                for name in textureData['SH Coeff'][1]:
165                    aname = pfx+name
166                    if len(s1) > 60:
167                        s += s1 + "\n"
168                        s1 = "    "
169                    s1 += aname + ' = '
170                    sig = self.sigDict.get(aname,-0.0009)
171                    s1 += G2mth.ValEsd(self.parmDict[aname],sig)
172                    s1 += "; "
173                s += s1
174            return s
175
176        def FormatHAPpo(phasenam):
177            '''return the March-Dollase/SH correction for every
178            histogram in the current phase formatted into a
179            character string
180            '''
181            phasedict = self.Phases[phasenam] # pointer to current phase info           
182            s = ''
183            for histogram in sorted(phasedict['Histograms']):
184                if histogram.startswith("HKLF"): continue # powder only
185                Histogram = self.Histograms.get(histogram)
186                if not Histogram: continue
187                hapData = phasedict['Histograms'][histogram]
188                if hapData['Pref.Ori.'][0] == 'MD':
189                    aname = str(phasedict['pId'])+':'+str(Histogram['hId'])+':MD'
190                    if self.parmDict.get(aname,1.0) != 1.0: continue
191                    sig = self.sigDict.get(aname,-0.009)
192                    if s != "": s += '\n'
193                    s += 'March-Dollase correction'
194                    if self.npowder > 1:
195                        s += ', histogram '+str(Histogram['hId']+1)
196                    s += ' coef. = ' + G2mth.ValEsd(self.parmDict[aname],sig)
197                    s += ' axis = ' + str(hapData['Pref.Ori.'][3])
198                else: # must be SH
199                    if s != "": s += '\n'
200                    s += 'Simple spherical harmonic correction'
201                    if self.npowder > 1:
202                        s += ', histogram '+str(Histogram['hId']+1)
203                    s += ' Order = '+str(hapData['Pref.Ori.'][4])+'\n'
204                    s1 = "    Coefficients:  "
205                    for item in hapData['Pref.Ori.'][5]:
206                        print item
207                        aname = str(phasedict['pId'])+':'+str(Histogram['hId'])+':'+item
208                        print aname
209                        if len(s1) > 60:
210                            s += s1 + "\n"
211                            s1 = "    "
212                        s1 += aname + ' = '
213                        sig = self.sigDict.get(aname,-0.0009)
214                        s1 += G2mth.ValEsd(self.parmDict[aname],sig)
215                        s1 += "; "
216                    s += s1
217            return s
218        def FormatBackground(bkg):
219            '''Display the Background information as a descriptive text string.
220           
221            TODO: this needs to be expanded to show the diffuse peak and
222            Debye term information as well.
223
224            :returns: the text description (str)
225            '''
226            fxn, bkgdict = bkg
227            terms = fxn[2]
228            txt = 'Background function: "'+fxn[0]+'" function with '+str(terms)+' terms:\n'
229            l = "   "
230            for v in fxn[3:]:
231                if len(l) > 60:
232                    txt += l + '\n'
233                    l = '   '
234                l += G2mth.ValEsd(v,-.009)+', '
235            txt += l
236            return txt
237
238        def FormatInstProfile(instparmdict):
239            '''Format the instrumental profile parameters with a
240            string description. Will only be called on PWDR histograms
241            '''
242            #print instparmdict[0].keys()
243            return 'TODO: Instrument profile goes here'
244
245        def FormatPhaseProfile(phasenam):
246            '''Format the phase-related profile parameters (size/strain)
247            with a string description.
248            return an empty string or None there are no
249            powder histograms for this phase.
250            '''
251            s = ''
252            phasedict = self.Phases[phasenam] # pointer to current phase info           
253            for histogram in sorted(phasedict['Histograms']):
254                if histogram.startswith("HKLF"): continue # powder only
255                Histogram = self.Histograms.get(histogram)
256                if not Histogram: continue
257                hapData = phasedict['Histograms'][histogram]
258            return 'TODO: Phase profile goes here'
259       
260        def FmtAtomType(sym):
261            'Reformat a GSAS-II atom type symbol to match CIF rules'
262            sym = sym.replace('_','') # underscores are not allowed: no isotope designation?
263            # in CIF, oxidation state sign symbols come after, not before
264            if '+' in sym:
265                sym = sym.replace('+','') + '+'
266            elif '-' in sym:
267                sym = sym.replace('-','') + '-'
268            return sym
269           
270        def PutInCol(val,wid):
271            '''Pad a value to >=wid+1 columns by adding spaces at the end. Always
272            adds at least one space
273            '''
274            val = str(val).replace(' ','')
275            if not val: val = '?'
276            fmt = '{:' + str(wid) + '} '
277            return fmt.format(val)
278
279        def MakeUniqueLabel(lbl,labellist):
280            'Make sure that every atom label is unique'
281            lbl = lbl.strip()
282            if not lbl: # deal with a blank label
283                lbl = 'A_1'
284            if lbl not in labellist:
285                labellist.append(lbl)
286                return lbl
287            i = 1
288            prefix = lbl
289            if '_' in lbl:
290                prefix = lbl[:lbl.rfind('_')]
291                suffix = lbl[lbl.rfind('_')+1:]
292                try:
293                    i = int(suffix)+1
294                except:
295                    pass
296            while prefix+'_'+str(i) in labellist:
297                i += 1
298            else:
299                lbl = prefix+'_'+str(i)
300                labellist.append(lbl)
301
302        def WriteAtomsNuclear(phasenam):
303            'Write atom positions to CIF'
304            phasedict = self.Phases[phasenam] # pointer to current phase info
305            General = phasedict['General']
306            cx,ct,cs,cia = General['AtomPtrs']
307            Atoms = phasedict['Atoms']
308            cfrac = cx+3
309            fpfx = str(phasedict['pId'])+'::Afrac:'       
310            for i,at in enumerate(Atoms):
311                fval = self.parmDict.get(fpfx+str(i),at[cfrac])
312                if fval != 0.0:
313                    break
314            else:
315                WriteCIFitem('\n# PHASE HAS NO ATOMS!')
316                return
317               
318            WriteCIFitem('\n# ATOMIC COORDINATES AND DISPLACEMENT PARAMETERS')
319            WriteCIFitem('loop_ '+
320                         '\n\t_atom_site_label'+
321                         '\n\t_atom_site_type_symbol'+
322                         '\n\t_atom_site_fract_x'+
323                         '\n\t_atom_site_fract_y'+
324                         '\n\t_atom_site_fract_z'+
325                         '\n\t_atom_site_occupancy'+
326                         '\n\t_atom_site_adp_type'+
327                         '\n\t_atom_site_U_iso_or_equiv'+
328                         '\n\t_atom_site_symmetry_multiplicity')
329
330            varnames = {cx:'Ax',cx+1:'Ay',cx+2:'Az',cx+3:'Afrac',
331                        cia+1:'AUiso',cia+2:'AU11',cia+3:'AU22',cia+4:'AU33',
332                        cia+5:'AU12',cia+6:'AU13',cia+7:'AU23'}
333            self.labellist = []
334           
335            pfx = str(phasedict['pId'])+'::'
336            # loop over all atoms
337            naniso = 0
338            for i,at in enumerate(Atoms):
339                s = PutInCol(MakeUniqueLabel(at[ct-1],self.labellist),6) # label
340                fval = self.parmDict.get(fpfx+str(i),at[cfrac])
341                if fval == 0.0: continue # ignore any atoms that have a occupancy set to 0 (exact)
342                s += PutInCol(FmtAtomType(at[ct]),4) # type
343                if at[cia] == 'I':
344                    adp = 'Uiso '
345                else:
346                    adp = 'Uani '
347                    naniso += 1
348                    # compute Uequiv crudely
349                    # correct: Defined as "1/3 trace of diagonalized U matrix".
350                    # SEE cell2GS & Uij2Ueqv to GSASIIlattice. Former is needed to make the GS matrix used by the latter.
351                    t = 0.0
352                    for j in (2,3,4):
353                        var = pfx+varnames[cia+j]+":"+str(i)
354                        t += self.parmDict.get(var,at[cia+j])
355                for j in (cx,cx+1,cx+2,cx+3,cia+1):
356                    if j in (cx,cx+1,cx+2):
357                        dig = 11
358                        sigdig = -0.00009
359                    else:
360                        dig = 10
361                        sigdig = -0.009
362                    var = pfx+varnames[j]+":"+str(i)
363                    dvar = pfx+"d"+varnames[j]+":"+str(i)
364                    if dvar not in self.sigDict:
365                        dvar = var
366                    if j == cia+1 and adp == 'Uani ':
367                        val = t/3.
368                        sig = sigdig
369                    else:
370                        #print var,(var in self.parmDict),(var in self.sigDict)
371                        val = self.parmDict.get(var,at[j])
372                        sig = self.sigDict.get(dvar,sigdig)
373                    s += PutInCol(G2mth.ValEsd(val,sig),dig)
374                s += adp
375                s += PutInCol(at[cs+1],3)
376                WriteCIFitem(s)
377            if naniso == 0: return
378            # now loop over aniso atoms
379            WriteCIFitem('\nloop_' + '\n\t_atom_site_aniso_label' + 
380                         '\n\t_atom_site_aniso_U_11' + '\n\t_atom_site_aniso_U_12' +
381                         '\n\t_atom_site_aniso_U_13' + '\n\t_atom_site_aniso_U_22' +
382                         '\n\t_atom_site_aniso_U_23' + '\n\t_atom_site_aniso_U_33')
383            for i,at in enumerate(Atoms):
384                fval = self.parmDict.get(fpfx+str(i),at[cfrac])
385                if fval == 0.0: continue # ignore any atoms that have a occupancy set to 0 (exact)
386                if at[cia] == 'I': continue
387                s = PutInCol(self.labellist[i],6) # label
388                for j in (2,3,4,5,6,7):
389                    sigdig = -0.0009
390                    var = pfx+varnames[cia+j]+":"+str(i)
391                    val = self.parmDict.get(var,at[cia+j])
392                    sig = self.sigDict.get(var,sigdig)
393                    s += PutInCol(G2mth.ValEsd(val,sig),11)
394                WriteCIFitem(s)
395
396        def HillSortElements(elmlist):
397            '''Sort elements in "Hill" order: C, H, others, (where others
398            are alphabetical).
399
400            :params list elmlist: a list of element strings
401
402            :returns: a sorted list of element strings
403            '''
404            newlist = []
405            oldlist = elmlist[:]
406            for elm in ('C','H'):
407                if elm in elmlist:
408                    newlist.append(elm)
409                    oldlist.pop(oldlist.index(elm))
410            return newlist+sorted(oldlist)
411
412        def WriteComposition(phasenam):
413            '''determine the composition for the unit cell, crudely determine Z and
414            then compute the composition in formula units
415            '''
416            phasedict = self.Phases[phasenam] # pointer to current phase info
417            General = phasedict['General']
418            Z = General.get('cellZ',0.0)
419            cx,ct,cs,cia = General['AtomPtrs']
420            Atoms = phasedict['Atoms']
421            fpfx = str(phasedict['pId'])+'::Afrac:'       
422            cfrac = cx+3
423            cmult = cs+1
424            compDict = {} # combines H,D & T
425            sitemultlist = []
426            massDict = dict(zip(General['AtomTypes'],General['AtomMass']))
427            cellmass = 0
428            for i,at in enumerate(Atoms):
429                atype = at[ct].strip()
430                if atype.find('-') != -1: atype = atype.split('-')[0]
431                if atype.find('+') != -1: atype = atype.split('+')[0]
432                atype = atype[0].upper()+atype[1:2].lower() # force case conversion
433                if atype == "D" or atype == "D": atype = "H"
434                fvar = fpfx+str(i)
435                fval = self.parmDict.get(fvar,at[cfrac])
436                mult = at[cmult]
437                if not massDict.get(at[ct]):
438                    print 'No mass found for atom type '+at[ct]
439                    print 'Will not compute cell contents for phase '+phasenam
440                    return
441                cellmass += massDict[at[ct]]*mult*fval
442                compDict[atype] = compDict.get(atype,0.0) + mult*fval
443                if fval == 1: sitemultlist.append(mult)
444            if len(compDict.keys()) == 0: return # no elements!
445            if Z < 1: # Z has not been computed or set by user
446                Z = 1
447                for i in range(2,min(sitemultlist)+1):
448                    for m in sitemultlist:
449                        if m % i != 0:
450                            break
451                        else:
452                            Z = i
453                General['cellZ'] = Z # save it
454
455            # when scattering factors are included in the CIF, this needs to be
456            # added to the loop here but only in the one-block case.
457            # For multiblock CIFs, scattering factors go in the histogram
458            # blocks  (for all atoms in all appropriate phases)
459
460            #if oneblock: # add scattering factors for current phase here
461            WriteCIFitem('\nloop_  _atom_type_symbol _atom_type_number_in_cell')
462            formula = ''
463            reload(G2mth)
464            for elem in HillSortElements(compDict.keys()):
465                WriteCIFitem('  ' + PutInCol(elem,4) +
466                             G2mth.ValEsd(compDict[elem],-0.009,True))
467                if formula: formula += " "
468                formula += elem
469                if compDict[elem] == Z: continue
470                formula += G2mth.ValEsd(compDict[elem]/Z,-0.009,True)
471            WriteCIFitem( '\n# Note that Z affects _cell_formula_sum and _weight')
472            WriteCIFitem( '_cell_formula_units_Z',str(Z))
473            WriteCIFitem( '_chemical_formula_sum',formula)
474            WriteCIFitem( '_chemical_formula_weight',
475                          G2mth.ValEsd(cellmass/Z,-0.09,True))
476
477        def WriteDistances(phasenam,SymOpList,offsetList,symOpList,G2oprList):
478            '''Report bond distances and angles for the CIF
479
480            Note that _geom_*_symmetry_* fields are values of form
481            n_klm where n is the symmetry operation in SymOpList (counted
482            starting with 1) and (k-5, l-5, m-5) are translations to add
483            to (x,y,z). See
484            http://www.iucr.org/__data/iucr/cifdic_html/1/cif_core.dic/Igeom_angle_site_symmetry_.html
485
486            TODO: need a method to select publication flags for distances/angles
487            '''
488            phasedict = self.Phases[phasenam] # pointer to current phase info           
489            Atoms = phasedict['Atoms']
490            cx,ct,cs,cia = phasedict['General']['AtomPtrs']
491            fpfx = str(phasedict['pId'])+'::Afrac:'       
492            cfrac = cx+3
493            # loop over interatomic distances for this phase
494            WriteCIFitem('\n# MOLECULAR GEOMETRY')
495            WriteCIFitem('loop_' + 
496                         '\n\t_geom_bond_atom_site_label_1' +
497                         '\n\t_geom_bond_atom_site_label_2' + 
498                         '\n\t_geom_bond_distance' + 
499                         '\n\t_geom_bond_site_symmetry_1' + 
500                         '\n\t_geom_bond_site_symmetry_2' + 
501                         '\n\t_geom_bond_publ_flag')
502
503            # Note that labels should be read from self.labellist to correspond
504            # to the values reported in the atoms table and zero occupancy atoms
505            # should not be included
506            fpfx = str(phasedict['pId'])+'::Afrac:'       
507            for i,at in enumerate(Atoms):
508                if self.parmDict.get(fpfx+str(i),at[cfrac]) == 0.0: continue
509                lbl = self.labellist[i]
510
511
512            # loop over interatomic angles for this phase
513            WriteCIFitem('loop_' + 
514                         '\n\t_geom_angle_atom_site_label_1' + 
515                         '\n\t_geom_angle_atom_site_label_2' + 
516                         '\n\t_geom_angle_atom_site_label_3' + 
517                         '\n\t_geom_angle' + 
518                         '\n\t_geom_angle_site_symmetry_1' +
519                         '\n\t_geom_angle_site_symmetry_2' + 
520                         '\n\t_geom_angle_site_symmetry_3' + 
521                         '\n\t_geom_angle_publ_flag')
522
523
524        def WritePhaseInfo(phasenam):
525            WriteCIFitem('\n# phase info for '+str(phasenam) + ' follows')
526            phasedict = self.Phases[phasenam] # pointer to current phase info           
527            WriteCIFitem('_pd_phase_name', phasenam)
528            pfx = str(phasedict['pId'])+'::'
529            A,sigA = G2stIO.cellFill(pfx,phasedict['General']['SGData'],self.parmDict,self.sigDict)
530            cellSig = G2stIO.getCellEsd(pfx,
531                                       phasedict['General']['SGData'],A,
532                                       self.OverallParms['Covariance'])  # returns 7 vals, includes sigVol
533            cellList = G2lat.A2cell(A) + (G2lat.calc_V(A),)
534            defsigL = 3*[-0.00001] + 3*[-0.001] + [-0.01] # significance to use when no sigma
535            names = ['length_a','length_b','length_c',
536                     'angle_alpha','angle_beta ','angle_gamma',
537                     'volume']
538            prevsig = 0
539            for lbl,defsig,val,sig in zip(names,defsigL,cellList,cellSig):
540                if sig:
541                    txt = G2mth.ValEsd(val,sig)
542                    prevsig = -sig # use this as the significance for next value
543                else:
544                    txt = G2mth.ValEsd(val,min(defsig,prevsig),True)
545                WriteCIFitem('_cell_'+lbl,txt)
546                   
547            WriteCIFitem('_symmetry_cell_setting',
548                         phasedict['General']['SGData']['SGSys'])
549
550            spacegroup = phasedict['General']['SGData']['SpGrp'].strip()
551            # regularize capitalization and remove trailing H/R
552            spacegroup = spacegroup[0].upper() + spacegroup[1:].lower().rstrip('rh ')
553            WriteCIFitem('_symmetry_space_group_name_H-M',spacegroup)
554
555            # generate symmetry operations including centering and center of symmetry
556            SymOpList,offsetList,symOpList,G2oprList = G2spg.AllOps(
557                phasedict['General']['SGData'])
558            WriteCIFitem('loop_ _space_group_symop_id _space_group_symop_operation_xyz')
559            for i,op in enumerate(SymOpList,start=1):
560                WriteCIFitem('   {:3d}  {:}'.format(i,op.lower()))
561
562            # loop over histogram(s) used in this phase
563            if not oneblock and not self.quickmode:
564                # report pointers to the histograms used in this phase
565                histlist = []
566                for hist in self.Phases[phasenam]['Histograms']:
567                    if self.Phases[phasenam]['Histograms'][hist]['Use']:
568                        if phasebyhistDict.get(hist):
569                            phasebyhistDict[hist].append(phasenam)
570                        else:
571                            phasebyhistDict[hist] = [phasenam,]
572                        blockid = datablockidDict.get(hist)
573                        if not blockid:
574                            print "Internal error: no block for data. Phase "+str(
575                                phasenam)+" histogram "+str(hist)
576                            histlist = []
577                            break
578                        histlist.append(blockid)
579
580                if len(histlist) == 0:
581                    WriteCIFitem('# Note: phase has no associated data')
582                else:
583                    WriteCIFitem('loop_  _pd_block_diffractogram_id')
584
585            # report atom params
586            if phasedict['General']['Type'] == 'nuclear':        #this needs macromolecular variant, etc!
587                WriteAtomsNuclear(phasenam)
588            else:
589                raise Exception,"no export for mm coordinates implemented"
590            # report cell contents
591            WriteComposition(phasenam)
592            if not self.quickmode:      # report distances and angles
593                WriteDistances(phasenam,SymOpList,offsetList,symOpList,G2oprList)
594
595        def WritePowderData(histlbl):
596            text = '?'
597            histblk = self.Histograms[histlbl]
598            inst = histblk['Instrument Parameters'][0]
599            hId = histblk['hId']
600            pfx = ':' + str(hId) + ':'
601            print 'TODO: powder here data for',histblk["Sample Parameters"]['InstrName']
602            # see wrpowdhist.for & wrreflist.for
603           
604            #refprx = '_refln.' # mm
605            refprx = '_refln_' # normal
606
607            if 'Lam1' in inst:
608                ratio = self.parmDict.get('I(L2)/I(L1)',inst['I(L2)/I(L1)'][1])
609                sratio = self.sigDict.get('I(L2)/I(L1)',-0.0009)
610                lam1 = self.parmDict.get('Lam1',inst['Lam1'][1])
611                slam1 = self.sigDict.get('Lam1',-0.00009)
612                lam2 = self.parmDict.get('Lam2',inst['Lam2'][1])
613                slam2 = self.sigDict.get('Lam2',-0.00009)
614                # always assume Ka1 & Ka2 if two wavelengths are present
615                WriteCIFitem('loop_' + 
616                             '\n\t_diffrn_radiation_wavelength' +
617                             '\n\t_diffrn_radiation_wavelength_wt' + 
618                             '\n\t_diffrn_radiation_type' + 
619                             '\n\t_diffrn_radiation_wavelength_id')
620                WriteCIFitem('  ' + PutInCol(G2mth.ValEsd(lam1,slam1),15)+
621                             PutInCol('1.0',15) + 
622                             PutInCol('K\\a~1~',10) + 
623                             PutInCol('1',5))
624                WriteCIFitem('  ' + PutInCol(G2mth.ValEsd(lam2,slam2),15)+
625                             PutInCol(G2mth.ValEsd(ratio,sratio),15)+
626                             PutInCol('K\\a~2~',10) + 
627                             PutInCol('2',5))               
628            else:
629                lam1 = self.parmDict.get('Lam',inst['Lam'])
630                slam1 = self.sigDict.get('Lam',-0.00009)
631                WriteCIFitem('_diffrn_radiation_wavelength',G2mth.ValEsd(lam1,slam1))
632
633
634            if not oneblock:
635                if not phasebyhistDict.get(histlbl):
636                    WriteCIFitem('\n# No phases associated with this data set')
637                else:
638                    WriteCIFitem('\n# PHASE TABLE')
639                    WriteCIFitem('loop_' +
640                                 '\n\t_pd_phase_id' + 
641                                 '\n\t_pd_phase_block_id' + 
642                                 '\n\t_pd_phase_mass_%')
643                    wtFrSum = 0.
644                    for phasenam in phasebyhistDict.get(histlbl):
645                        hapData = self.Phases[phasenam]['Histograms'][histlbl]
646                        General = self.Phases[phasenam]['General']
647                        wtFrSum += hapData['Scale'][0]*General['Mass']
648
649                    for phasenam in phasebyhistDict.get(histlbl):
650                        hapData = self.Phases[phasenam]['Histograms'][histlbl]
651                        General = self.Phases[phasenam]['General']
652                        wtFr = hapData['Scale'][0]*General['Mass']/wtFrSum
653                        pfx = str(self.Phases[phasenam]['pId'])+':'+str(hId)+':'
654                        if pfx+'Scale' in self.sigDict:
655                            sig = self.sigDict[pfx+'Scale']*wtFr/hapData['Scale'][0]
656                        else:
657                            sig = -0.0001
658                        WriteCIFitem(
659                            '  '+
660                            str(self.Phases[phasenam]['pId']) +
661                            '  '+datablockidDict[phasenam]+
662                            '  '+G2mth.ValEsd(wtFr,sig)
663                            )
664
665            # TODO: this will need help from Bob
666            # WriteCIFitem('_pd_proc_ls_prof_R_factor','?')
667            # WriteCIFitem('_pd_proc_ls_prof_wR_factor','?')
668            # WriteCIFitem('_pd_proc_ls_prof_wR_expected','?')
669            # WriteCIFitem('_refine_ls_R_Fsqd_factor','?')
670
671            print histblk['Instrument Parameters'][0]['Type']
672           
673            if histblk['Instrument Parameters'][0]['Type'][1][1] == 'X':
674                WriteCIFitem('_diffrn_radiation_probe','x-ray')
675                pola = histblk['Instrument Parameters'][0].get('Polariz.')
676                if pola:
677                    pfx = ':' + str(hId) + ':'
678                    sig = self.sigDict.get(pfx+'Polariz.',-0.0009)
679                    txt = G2mth.ValEsd(pola[1],sig)
680                    WriteCIFitem('_diffrn_radiation_polarisn_ratio',txt)
681            elif histblk['Instrument Parameters'][0]['Type'][1][1] == 'N':
682                WriteCIFitem('_diffrn_radiation_probe','neutron')
683            # TOF (note that this may not be defined)
684            #if histblk['Instrument Parameters'][0]['Type'][1][2] == 'T':
685            #    WriteCIFitem('_pd_meas_2theta_fixed',text)
686           
687
688            # TODO: this will need help from Bob
689            #if not oneblock:
690            #WriteCIFitem('\n# SCATTERING FACTOR INFO')
691            #WriteCIFitem('loop_  _atom_type_symbol')
692            #if histblk['Instrument Parameters'][0]['Type'][1][1] == 'X':
693            #    WriteCIFitem('      _atom_type_scat_dispersion_real')
694            #    WriteCIFitem('      _atom_type_scat_dispersion_imag')
695            #    for lbl in ('a1','a2','a3', 'a4', 'b1', 'b2', 'b3', 'b4', 'c'):
696            #        WriteCIFitem('      _atom_type_scat_Cromer_Mann_'+lbl)
697            #elif histblk['Instrument Parameters'][0]['Type'][1][1] == 'N':
698            #    WriteCIFitem('      _atom_type_scat_length_neutron')
699            #WriteCIFitem('      _atom_type_scat_source')
700
701            WriteCIFitem('_pd_proc_ls_background_function',FormatBackground(histblk['Background']))
702
703            #WriteCIFitem('_exptl_absorpt_process_details','?')
704            #WriteCIFitem('_exptl_absorpt_correction_T_min','?')
705            #WriteCIFitem('_exptl_absorpt_correction_T_max','?')
706            #C extinction
707            #WRITE(IUCIF,'(A)') '# Extinction correction'
708            #CALL WRVAL(IUCIF,'_gsas_exptl_extinct_corr_T_min',TEXT(1:10))
709            #CALL WRVAL(IUCIF,'_gsas_exptl_extinct_corr_T_max',TEXT(11:20))
710
711            if not oneblock:
712                # instrumental profile terms go here
713                WriteCIFitem('_pd_proc_ls_profile_function','?')
714
715            raise Exception, "testing"
716            phasenam = self.Phases.keys()[0]
717            for key in self.Phases[phasenam]['Histograms']:
718                print key
719                print '------------'
720                print self.Phases[phasenam]['Histograms'][key]
721            print histblk.keys()
722            for key in histblk:
723                print key,histblk[key]
724            print inst
725            #print self.parmDict.keys()
726            #print self.sigDict.keys()
727
728            #print 'Data'
729            #for item in histblk['Data']:
730            #    print item
731                #try:
732                #    print key,histblk[key].keys()
733                #except:
734                #    print key
735                #    print histblk[key]
736            #print 'Background'
737            print histblk['Reflection Lists']['Garnet'][1]
738            for i in range(0,80):
739                for j in [0,1,2,13]:
740                    print histblk['Reflection Lists']['Garnet'][i][j],
741                print
742                #print histblk['Reflection Lists']['Garnet'][i][12].shape
743                #print histblk['Reflection Lists']['Garnet'][i][14]
744            #print histblk['Background'][0]
745            #print histblk['Background'][1]
746            import numpy as np
747            refList = np.array([refl[:11] for refl in histblk['Reflection Lists']['Garnet']])
748            #refList = histblk['Reflection Lists']['Garnet']
749            Icorr = np.array([refl[13] for refl in histblk['Reflection Lists']['Garnet']])
750            FO2 = np.array([refl[8] for refl in histblk['Reflection Lists']['Garnet']])
751            print Icorr
752            I100 = refList.T[8]*Icorr
753            print I100
754            print I100/max(I100)
755            Icorr = np.array([refl[13] for refl in histblk['Reflection Lists']['Garnet']]) * np.array([refl[8] for refl in histblk['Reflection Lists']['Garnet']])
756            print I100/max(I100)
757
758            WriteCIFitem('\n# STRUCTURE FACTOR TABLE')           
759            WriteCIFitem('loop_' + 
760                         '\n\t' + refprx + 'index_h' + 
761                         '\n\t' + refprx + 'index_k' + 
762                         '\n\t' + refprx + 'index_l' + 
763                         '\n\t_pd_refln_wavelength_id' +
764                         '\n\t_pd_refln_phase_id' + 
765                         '\n\t' + refprx + 'status' + 
766                         '\n\t' + refprx + 'F_squared_meas' + 
767                         '\n\t' + refprx + 'F_squared_sigma' + 
768                         '\n\t' + refprx + 'F_squared_calc' + 
769                         '\n\t' + refprx + 'phase_calc' + 
770                         '\n\t_pd_refln_d_spacing' + 
771                         '\n\t_gsas_i100_meas')
772
773            WriteCIFitem('_reflns_number_total', text)
774            WriteCIFitem('_reflns_limit_h_min', text)
775            WriteCIFitem('_reflns_limit_h_max', text)
776            WriteCIFitem('_reflns_limit_k_min', text)
777            WriteCIFitem('_reflns_limit_k_max', text)
778            WriteCIFitem('_reflns_limit_l_min', text)
779            WriteCIFitem('_reflns_limit_l_max', text)
780            WriteCIFitem('_reflns_d_resolution_high', text)
781            WriteCIFitem('_reflns_d_resolution_low', text)
782           
783            WriteCIFitem('\n# POWDER DATA TABLE')
784            # is data fixed step?
785            fixedstep = False
786            # are ESDs sqrt(I)
787            countsdata = False
788            zero = 0.01
789            if fixedstep:
790                WriteCIFitem('_pd_meas_2theta_range_min', text)
791                WriteCIFitem('_pd_meas_2theta_range_max', text)
792                WriteCIFitem('_pd_meas_2theta_range_inc', text)
793                # zero correct
794                if zero != 0.0:
795                    WriteCIFitem('_pd_proc_2theta_range_min', text)
796                    WriteCIFitem('_pd_proc_2theta_range_max', text)
797                    WriteCIFitem('_pd_proc_2theta_range_inc', text)
798            WriteCIFitem('loop_' +
799                         '\n\t_pd_proc_d_spacing')
800                         #'_pd_meas_time_of_flight'
801            if not fixedstep:
802                if zero != 0.0:
803                    WriteCIFitem('\t_pd_proc_2theta_corrected')
804                else:
805                    WriteCIFitem('\t_pd_meas_2theta_scan')
806            if countsdata:
807                WriteCIFitem('\t_pd_meas_counts_total')
808            else:
809                WriteCIFitem('\t_pd_meas_intensity_total')
810            WriteCIFitem('\t_pd_proc_ls_weight')
811            WriteCIFitem('\t_pd_proc_intensity_bkg_calc')
812            WriteCIFitem('\t_pd_calc_intensity_total')
813            if zero != 0.0:
814                WriteCIFitem('_pd_proc_number_of_points', text)
815            else:
816                WriteCIFitem('_pd_meas_number_of_points', text)
817                         
818        def WriteSingleXtalData(histlbl):
819            histblk = self.Histograms[histlbl]
820            print 'TODO: single xtal here data for',histblk["Instrument Parameters"][0]['InstrName']
821            # see wrreflist.for
822            refprx = '_refln.' # mm
823            refprx = '_refln_' # normal
824           
825            WriteCIFitem('\n# STRUCTURE FACTOR TABLE')           
826            WriteCIFitem('loop_' + 
827                         '\n\t' + refprx + 'index_h' + 
828                         '\n\t' + refprx + 'index_k' + 
829                         '\n\t' + refprx + 'index_l' + 
830                         '\n\t' + refprx + 'status' + 
831                         '\n\t' + refprx + 'F_squared_meas' + 
832                         '\n\t' + refprx + 'F_squared_sigma' + 
833                         '\n\t' + refprx + 'F_squared_calc' + 
834                         '\n\t' + refprx + 'phase_calc')
835            WriteCIFitem('_reflns_number_total', text)
836            WriteCIFitem('_reflns_number_observed', text)
837            WriteCIFitem('_reflns_limit_h_min', text)
838            WriteCIFitem('_reflns_limit_h_max', text)
839            WriteCIFitem('_reflns_limit_k_min', text)
840            WriteCIFitem('_reflns_limit_k_max', text)
841            WriteCIFitem('_reflns_limit_l_min', text)
842            WriteCIFitem('_reflns_limit_l_max', text)
843            WriteCIFitem('_reflns_d_resolution_high', text)
844            WriteCIFitem('_reflns_d_resolution_low', text)
845
846        #============================================================
847        # the export process starts here
848        # also load all of the tree into a set of dicts
849        self.loadTree()
850        #self.dumpTree()
851        # create a dict with refined values and their uncertainties
852        self.loadParmDict()
853        #
854
855        # get restraint info
856        #restraintDict = self.OverallParms.get('Restraints',{})
857        #for i in  self.OverallParms['Constraints']:
858        #    print i
859        #    for j in self.OverallParms['Constraints'][i]:
860        #        print j
861        #return
862
863        self.CIFdate = dt.datetime.strftime(dt.datetime.now(),"%Y-%m-%dT%H:%M")
864        # count phases, powder and single crystal histograms
865        self.nphase = len(self.Phases)
866        self.npowder = 0
867        self.nsingle = 0
868        for hist in self.Histograms:
869            if hist.startswith("PWDR"): 
870                self.npowder += 1
871            elif hist.startswith("HKLF"): 
872                self.nsingle += 1
873        # is there anything to export?
874        if self.nphase + self.npowder + self.nsingle == 0: 
875            self.G2frame.ErrorDialog(
876                'Empty project',
877                'No data or phases to include in CIF')
878            return
879        # is there a file name defined?
880        self.CIFname = os.path.splitext(
881            os.path.split(self.G2frame.GSASprojectfile)[1]
882            )[0]
883        self.CIFname = self.CIFname.replace(' ','')
884        if not self.CIFname:
885            self.G2frame.ErrorDialog(
886                'No GPX name',
887                'Please save the project to provide a name')
888            return
889        # test for quick CIF mode or no data
890        self.quickmode = False
891        phasenam = phasenum = None # include all phases
892        if mode != "full" or self.npowder + self.nsingle == 0:
893            self.quickmode = True
894            oneblock = True
895            if self.nphase == 0:
896                self.G2frame.ErrorDialog(
897                    'No phase present',
898                    'Cannot create a coordinates CIF with no phases')
899                return
900            elif self.nphase > 1: # quick mode: choose one phase
901                choices = sorted(self.Phases.keys())
902                phasenum = G2gd.ItemSelector(choices,self.G2frame)
903                if phasenum is None: return
904                phasenam = choices[phasenum]
905        # will this require a multiblock CIF?
906        elif self.nphase > 1:
907            oneblock = False
908        elif self.npowder + self.nsingle > 1:
909            oneblock = False
910        else: # one phase, one dataset, Full CIF
911            oneblock = True
912
913        # make sure needed infomation is present
914        # get CIF author name -- required for full CIFs
915        try:
916            self.author = self.OverallParms['Controls'].get("Author",'').strip()
917        except KeyError:
918            pass
919        while not (self.author or self.quickmode):
920            dlg = G2gd.SingleStringDialog(self.G2frame,'Get CIF Author','Provide CIF Author name (Last, First)')
921            if not dlg.Show(): return # cancel was pressed
922            self.author = dlg.GetValue()
923            dlg.Destroy()
924        try:
925            self.OverallParms['Controls']["Author"] = self.author # save for future
926        except KeyError:
927            pass
928        self.shortauthorname = self.author.replace(',','').replace(' ','')[:20]
929
930        # check the instrument name for every histogram
931        if not self.quickmode:
932            dictlist = []
933            keylist = []
934            lbllist = []
935            invalid = 0
936            key3 = 'InstrName'
937            for hist in self.Histograms:
938                if hist.startswith("PWDR"): 
939                    key2 = "Sample Parameters"
940                    d = self.Histograms[hist][key2]
941                elif hist.startswith("HKLF"): 
942                    key2 = "Instrument Parameters"
943                    d = self.Histograms[hist][key2][0]
944                   
945                lbllist.append(hist)
946                dictlist.append(d)
947                keylist.append(key3)
948                instrname = d.get(key3)
949                if instrname is None:
950                    d[key3] = ''
951                    invalid += 1
952                elif instrname.strip() == '':
953                    invalid += 1
954            if invalid:
955                msg = ""
956                if invalid > 3: msg = (
957                    "\n\nNote: it may be faster to set the name for\n"
958                    "one histogram for each instrument and use the\n"
959                    "File/Copy option to duplicate the name"
960                    )
961                if not G2gd.CallScrolledMultiEditor(
962                    self.G2frame,dictlist,keylist,
963                    prelbl=range(1,len(dictlist)+1),
964                    postlbl=lbllist,
965                    title='Instrument names',
966                    header="Edit instrument names. Note that a non-blank\nname is required for all histograms"+msg,
967                    ): return
968
969        if oneblock and not self.quickmode:
970            # select a dataset to use (there should only be one set in one block,
971            # but take whatever comes 1st
972            for hist in self.Histograms:
973                histblk = self.Histograms[hist]
974                if hist.startswith("PWDR"): 
975                    instnam = histblk["Sample Parameters"]['InstrName']
976                    break # ignore all but 1st data histogram
977                elif hist.startswith("HKLF"): 
978                    instnam = histblk["Instrument Parameters"][0]['InstrName']
979                    break # ignore all but 1st data histogram
980        #======================================================================
981        # Start writing the CIF - single block
982        #======================================================================
983        if oneblock:
984            WriteCIFitem('data_'+self.CIFname)
985            if phasenam is None: # if not already selected, select the first phase (should be one)
986                phasenam = self.Phases.keys()[0]
987            #print 'phasenam',phasenam
988            phaseblk = self.Phases[phasenam] # pointer to current phase info
989            if not self.quickmode:
990                instnam = instnam.replace(' ','')
991                WriteCIFitem('_pd_block_id',
992                             str(self.CIFdate) + "|" + str(self.CIFname) + "|" +
993                             str(self.shortauthorname) + "|" + instnam)
994                WriteAudit()
995                WritePubTemplate()
996                WriteOverall()
997                WritePhaseTemplate()
998            # report the phase info
999            WritePhaseInfo(phasenam)
1000            if hist.startswith("PWDR") and not self.quickmode:
1001                # preferred orientation
1002                SH = FormatSH(phasenam)
1003                MD = FormatHAPpo(phasenam)
1004                if SH and MD:
1005                    WriteCIFitem('_pd_proc_ls_pref_orient_corr', SH + '\n' + MD)
1006                elif SH or MD:
1007                    WriteCIFitem('_pd_proc_ls_pref_orient_corr', SH + MD)
1008                else:
1009                    WriteCIFitem('_pd_proc_ls_pref_orient_corr', 'none')
1010                    # report profile, since one-block: include both histogram and phase info
1011                WriteCIFitem('_pd_proc_ls_profile_function',
1012                             FormatInstProfile(histblk["Instrument Parameters"])
1013                             + '\n' +
1014                             FormatPhaseProfile(phasenam))
1015                WritePowderTemplate()
1016                WritePowderData(hist)
1017            elif hist.startswith("HKLF") and not self.quickmode:
1018                WriteSnglXtalTemplate()
1019                WriteSingleXtalData(hist)
1020        else:
1021        #======================================================================
1022        # Start writing the CIF - multiblock
1023        #======================================================================
1024            # publication info
1025            WriteCIFitem('\ndata_'+self.CIFname+'_publ')
1026            WriteAudit()
1027            WriteCIFitem('_pd_block_id',
1028                         str(self.CIFdate) + "|" + str(self.CIFname) + "|" +
1029                         str(self.shortauthorname) + "|Overall")
1030            WritePubTemplate()
1031            # overall info
1032            WriteCIFitem('data_'+str(self.CIFname)+'_overall')
1033            WriteOverall()
1034            #============================================================
1035            WriteCIFitem('# POINTERS TO PHASE AND HISTOGRAM BLOCKS')
1036            datablockidDict = {} # save block names here -- N.B. check for conflicts between phase & hist names (unlikely!)
1037            # loop over phase blocks
1038            if self.nphase > 1:
1039                loopprefix = ''
1040                WriteCIFitem('loop_   _pd_phase_block_id')
1041            else:
1042                loopprefix = '_pd_phase_block_id'
1043           
1044            for phasenam in sorted(self.Phases.keys()):
1045                i = self.Phases[phasenam]['pId']
1046                datablockidDict[phasenam] = (str(self.CIFdate) + "|" + str(self.CIFname) + "|" +
1047                             'phase_'+ str(i) + '|' + str(self.shortauthorname))
1048                WriteCIFitem(loopprefix,datablockidDict[phasenam])
1049            # loop over data blocks
1050            if self.npowder + self.nsingle > 1:
1051                loopprefix = ''
1052                WriteCIFitem('loop_   _pd_block_diffractogram_id')
1053            else:
1054                loopprefix = '_pd_block_diffractogram_id'
1055            for hist in self.Histograms:
1056                histblk = self.Histograms[hist]
1057                if hist.startswith("PWDR"): 
1058                    instnam = histblk["Sample Parameters"]['InstrName']
1059                elif hist.startswith("HKLF"): 
1060                    instnam = histblk["Instrument Parameters"][0]['InstrName']
1061                instnam = instnam.replace(' ','')
1062                i = histblk['hId']
1063                datablockidDict[hist] = (str(self.CIFdate) + "|" + str(self.CIFname) + "|" +
1064                                         str(self.shortauthorname) + "|" +
1065                                         instnam + "_hist_"+str(i))
1066                WriteCIFitem(loopprefix,datablockidDict[hist])
1067            #============================================================
1068            # loop over phases, exporting them
1069            phasebyhistDict = {} # create a cross-reference to phases by histogram
1070            for j,phasenam in enumerate(sorted(self.Phases.keys())):
1071                i = self.Phases[phasenam]['pId']
1072                WriteCIFitem('\ndata_'+self.CIFname+"_phase_"+str(i))
1073                print "debug, processing ",phasenam
1074                WriteCIFitem('# Information for phase '+str(i))
1075                WriteCIFitem('_pd_block_id',datablockidDict[phasenam])
1076                # report the phase
1077                WritePhaseTemplate()
1078                WritePhaseInfo(phasenam)
1079                # preferred orientation
1080                SH = FormatSH(phasenam)
1081                MD = FormatHAPpo(phasenam)
1082                if SH and MD:
1083                    WriteCIFitem('_pd_proc_ls_pref_orient_corr', SH + '\n' + MD)
1084                elif SH or MD:
1085                    WriteCIFitem('_pd_proc_ls_pref_orient_corr', SH + MD)
1086                else:
1087                    WriteCIFitem('_pd_proc_ls_pref_orient_corr', 'none')
1088                # report sample profile terms
1089                PP = FormatPhaseProfile(phasenam)
1090                if PP:
1091                    WriteCIFitem('_pd_proc_ls_profile_function',PP)
1092                   
1093            #============================================================
1094            # loop over histograms, exporting them
1095            for hist in self.Histograms:
1096                histblk = self.Histograms[hist]
1097                i = histblk['hId']
1098                if hist.startswith("PWDR"): 
1099                    WriteCIFitem('\ndata_'+self.CIFname+"_pwd_"+str(i))
1100                    #instnam = histblk["Sample Parameters"]['InstrName']
1101                    # report instrumental profile terms
1102                    WriteCIFitem('_pd_proc_ls_profile_function',
1103                                 FormatInstProfile(histblk["Instrument Parameters"]))
1104                    WriteCIFitem('# Information for histogram '+str(i)+': '+
1105                                 hist)
1106                    WriteCIFitem('_pd_block_id',datablockidDict[hist])
1107                    WritePowderTemplate()
1108                    WritePowderData(hist)
1109                elif hist.startswith("HKLF"): 
1110                    WriteCIFitem('\ndata_'+self.CIFname+"_sx_"+str(i))
1111                    #instnam = histblk["Instrument Parameters"][0]['InstrName']
1112                    WriteCIFitem('# Information for histogram '+str(i)+': '+
1113                                 hist)
1114                    WriteCIFitem('_pd_block_id',datablockidDict[hist])
1115                    WriteSnglXtalTemplate()
1116                    WriteSingleXtalData(hist)
1117
1118        WriteCIFitem('#--' + 15*'eof--' + '#')
1119
Note: See TracBrowser for help on using the repository browser.