Changeset 3011


Ignore:
Timestamp:
Aug 16, 2017 4:16:55 PM (4 years ago)
Author:
odonnell
Message:

CIF export. changelist:

  • Start using argparse module in GSASIIscriptable.py
  • G2Phase now has export_CIF method
  • GSASIIscriptable export method now works
  • refactoring of exports/G2export_CIF.py to reduce code duplication
Location:
trunk
Files:
1 added
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/GSASIIscriptable.py

    r3009 r3011  
    3333from __future__ import division, print_function # needed?
    3434import os.path as ospath
     35import datetime as dt
    3536import sys
    3637import cPickle
     
    377378    generalData['Mass'] = G2mth.getMass(generalData)
    378379
     380
     381############################################
     382############ CIF export helpers ############
     383############################################
     384## These functions are translated from
     385## exports/G2export_CIF.py
     386## They are used in G2Phase.export_CIF
     387
     388
     389
    379390def make_empty_project(author=None, filename=None):
    380391    """Creates an dictionary in the style of GSASIIscriptable, for an empty
     
    14851496        return G2obj.PhaseRanIdLookup[self.ranId]
    14861497
    1487     def cell_dict(self):
     1498    def get_cell(self):
    14881499        """Returns a dictionary of the cell parameters, with keys:
    1489             'a', 'b', 'c', 'alpha', 'beta', 'gamma', 'vol'
     1500            'length_a', 'length_b', 'length_c', 'angle_alpha', 'angle_beta', 'angle_gamma', 'volume'
    14901501
    14911502        :returns: a dict"""
    14921503        cell = self['General']['Cell']
    1493         return {'a': cell[1], 'b': cell[2], 'c': cell[3],
    1494                 'alpha': cell[4], 'beta': cell[5], 'gamma': cell[6],
    1495                 'vol': cell[7]}
     1504        return {'length_a': cell[1], 'length_b': cell[2], 'length_c': cell[3],
     1505                'angle_alpha': cell[4], 'angle_beta': cell[5], 'angle_gamma': cell[6],
     1506                'volume': cell[7]}
     1507
     1508    def export_CIF(self, outputname, quickmode=True):
     1509        """Write this phase to a .cif file named outputname
     1510
     1511        :param str outputname: The name of the .cif file to write to
     1512        :param bool quickmode: Currently ignored. Carryover from exports.G2export_CIF"""
     1513        # This code is all taken from exports/G2export_CIF.py
     1514        # Functions copied have the same names
     1515        import GSASIImath as G2mth
     1516        import GSASIImapvars as G2mv
     1517        from exports import G2export_CIF as cif
     1518
     1519        CIFdate = dt.datetime.strftime(dt.datetime.now(),"%Y-%m-%dT%H:%M")
     1520        CIFname = os.path.splitext(self.proj.filename)[0]
     1521        CIFname = os.path.split(CIFname)[1]
     1522        CIFname = ''.join([c if ord(c) < 128 else ''
     1523                           for c in CIFname.replace(' ', '_')])
     1524        try:
     1525            author = self.proj['Controls'].get('Author','').strip()
     1526        except KeyError:
     1527            pass
     1528        oneblock = True
     1529
     1530        covDict = self.proj['Covariance']
     1531        parmDict = dict(zip(covDict.get('varyList',[]),
     1532                            covDict.get('variables',[])))
     1533        sigDict = dict(zip(covDict.get('varyList',[]),
     1534                           covDict.get('sig',[])))
     1535
     1536        if covDict.get('covMatrix') is not None:
     1537            sigDict.update(G2mv.ComputeDepESD(covDict['covMatrix'],
     1538                                              covDict['varyList'],
     1539                                              parmDict))
     1540
     1541        with open(outputname, 'w') as fp:
     1542            fp.write(' \n' + 70*'#' + '\n')
     1543            cif.WriteCIFitem(fp, 'data_' + CIFname)
     1544            # from exports.G2export_CIF.WritePhaseInfo
     1545            cif.WriteCIFitem(fp, '\n# phase info for '+str(self.name) + ' follows')
     1546            cif.WriteCIFitem(fp, '_pd_phase_name', self.name)
     1547            # TODO get esds
     1548            cellDict = self.get_cell()
     1549            defsigL = 3*[-0.00001] + 3*[-0.001] + [-0.01] # significance to use when no sigma
     1550            names = ['length_a','length_b','length_c',
     1551                     'angle_alpha','angle_beta ','angle_gamma',
     1552                     'volume']
     1553            for key, val in cellDict.items():
     1554                cif.WriteCIFitem(fp, '_cell_' + key, G2mth.ValEsd(val))
     1555
     1556            cif.WriteCIFitem(fp, '_symmetry_cell_setting',
     1557                         self['General']['SGData']['SGSys'])
     1558
     1559            spacegroup = self['General']['SGData']['SpGrp'].strip()
     1560            # regularize capitalization and remove trailing H/R
     1561            spacegroup = spacegroup[0].upper() + spacegroup[1:].lower().rstrip('rh ')
     1562            cif.WriteCIFitem(fp, '_symmetry_space_group_name_H-M', spacegroup)
     1563
     1564            # generate symmetry operations including centering and center of symmetry
     1565            SymOpList, offsetList, symOpList, G2oprList, G2opcodes = G2spc.AllOps(
     1566                self['General']['SGData'])
     1567            cif.WriteCIFitem(fp, 'loop_\n    _space_group_symop_id\n    _space_group_symop_operation_xyz')
     1568            for i, op in enumerate(SymOpList,start=1):
     1569                cif.WriteCIFitem(fp, '   {:3d}  {:}'.format(i,op.lower()))
     1570
     1571            # TODO skipped histograms, exports/G2export_CIF.py:880
     1572
     1573            # report atom params
     1574            if self['General']['Type'] in ['nuclear','macromolecular']:        #this needs macromolecular variant, etc!
     1575                cif.WriteAtomsNuclear(fp, self.data, self.name, parmDict, sigDict, [])
     1576                # self._WriteAtomsNuclear(fp, parmDict, sigDict)
     1577            else:
     1578                raise Exception,"no export for "+str(self['General']['Type'])+" coordinates implemented"
     1579            # report cell contents
     1580            cif.WriteComposition(fp, self.data, self.name, parmDict)
     1581            if not quickmode and self['General']['Type'] == 'nuclear':      # report distances and angles
     1582                # WriteDistances(fp,self.name,SymOpList,offsetList,symOpList,G2oprList)
     1583                raise NotImplementedError("only quickmode currently supported")
     1584            if 'Map' in self['General'] and 'minmax' in self['General']['Map']:
     1585                cif.WriteCIFitem(fp,'\n# Difference density results')
     1586                MinMax = self['General']['Map']['minmax']
     1587                cif.WriteCIFitem(fp,'_refine_diff_density_max',G2mth.ValEsd(MinMax[0],-0.009))
     1588                cif.WriteCIFitem(fp,'_refine_diff_density_min',G2mth.ValEsd(MinMax[1],-0.009))
     1589
    14961590
    14971591    def set_refinements(self, refs):
     
    16821776
    16831777
     1778# TODO SUBPARSERS
     1779
    16841780def create(*args):
    16851781    """The create subcommand.
    16861782
    16871783    Should be passed all the command-line arguments after `create`"""
    1688     proj = G2Project(filename=args[0])
     1784    import argparse
     1785    parser = argparse.ArgumentParser(prog=' '.join([sys.argv[0], sys.argv[1]]))
     1786    parser.add_argument('filename',
     1787                        help='the project file to create. should end in .gpx')
     1788    parser.add_argument('-g', '--histograms', nargs='+',
     1789                        help='list of histograms to add')
     1790    parser.add_argument('-p', '--phases', nargs='+',
     1791                        help='list of phases to add')
     1792    results = parser.parse_args(args)
     1793
     1794    proj = G2Project(filename=filename)
    16891795
    16901796    isPhase = False
     
    17241830def dump(*args):
    17251831    """The dump subcommand"""
    1726     raw = True
    1727     histograms = False
    1728     phases = False
    1729     filenames = []
    1730     for arg in args:
    1731         if arg in ['-h', '--histograms']:
    1732             histograms = True
    1733             raw = False
    1734         elif arg in ['-p', '--phases']:
    1735             phases = True
    1736             raw = False
    1737         elif arg in ['-r', '--raw']:
    1738             raw = True
    1739         else:
    1740             filenames.append(arg)
    1741     if raw:
     1832    import argparse
     1833    parser = argparse.ArgumentParser(prog=' '.join([sys.argv[0], sys.argv[1]]))
     1834    parser.add_argument('-g', '--histograms', action='store_true',
     1835                        help='list histograms in files, overrides --raw')
     1836    parser.add_argument('-p', '--phases', action='store_true',
     1837                        help='list phases in files, overrides --raw')
     1838    parser.add_argument('-r', '--raw', action='store_true',
     1839                        help='dump raw file contents')
     1840    parser.add_argument('files', nargs='*')
     1841    results = parser.parse_args(args)
     1842
     1843    if not results.histograms and not results.phases:
     1844        results.raw = True
     1845    if results.raw:
    17421846        import IPython.lib.pretty as pretty
    1743     for fname in filenames:
    1744         if raw:
     1847
     1848    for fname in results.files:
     1849        if results.raw:
    17451850            proj, nameList = LoadDictFromProjFile(fname)
    17461851            print("file:", fname)
     
    17511856        else:
    17521857            proj = G2Project(fname)
    1753             if histograms:
     1858            if results.histograms:
    17541859                hists = proj.histograms()
    17551860                for h in hists:
    17561861                    print(fname, "hist", h.id, h.name)
    1757             if phases:
     1862            if results.phases:
    17581863                phase_list = proj.phases()
    17591864                for p in phase_list:
     
    17761881    """The refine subcommand"""
    17771882    proj = G2Project(args[0])
    1778     proj.refine()
     1883    if len(args) == 1:
     1884        proj.refine()
     1885    elif len(args) == 2:
     1886        import json
     1887        with open(args[1]) as refs:
     1888            refs = json.load(refs)
     1889        proj.do_refinements(refs['refinements'])
     1890    else:
     1891        print("Refine not sure what to do with args:", args)
    17791892
    17801893
     
    17871900    """The export subcommand"""
    17881901    # Export CIF or Structure or ...
    1789     raise NotImplementedError("export is not yet implemented")
     1902    gpxfile, phase, exportfile = args
     1903    proj = G2Project(gpxfile)
     1904    phase = proj.phase(phase)
     1905    phase.export_CIF(exportfile)
    17901906
    17911907
     
    17991915
    18001916def main():
    1801     '''TODO: the command-line options need some thought
     1917    '''The command line interface for GSASIIscriptable.
     1918
     1919    Executes one of the following subcommands:
     1920
     1921        * :func:`create`
     1922        * :func:`dump`
     1923        * :func:`refine`
     1924        * :func:`seqrefine`
     1925        * :func:`export`
     1926        * :func:`browse`
     1927
     1928    .. seealso::
     1929        :func:`create`
     1930        :func:`dump`
     1931        :func:`refine`
     1932        :func:`seqrefine`
     1933        :func:`export`
     1934        :func:`browse`
    18021935    '''
    1803     argv = sys.argv
    1804     if len(argv) > 1 and argv[1] in subcommands:
    1805         subcommands[argv[1]](*argv[2:])
    1806     elif len(argv) == 1 or argv[1] in ('help', '--help', '-h'):
    1807         # TODO print usage
    1808         subcommand_names = ' | '.join(sorted(subcommands.keys()))
    1809         print("USAGE: {} [ {} ] ...".format(argv[0], subcommand_names))
    1810     else:
    1811         print("Unknown subcommand: {}".format(argv[1]))
    1812         print("Available subcommands:")
    1813         for name in sorted(subcommands.keys()):
    1814             print("\t{}".format(name))
    1815         sys.exit(-1)
     1936    import argparse
     1937    parser = argparse.ArgumentParser()
     1938    parser.add_argument('subcommand', choices=sorted(subcommands.keys()),
     1939                        help='The subcommand to be executed')
     1940
     1941    result = parser.parse_args(sys.argv[1:2])
     1942    sub = result.subcommand
     1943    subcommands[sub](*sys.argv[2:])
     1944
     1945    # argv = sys.argv
     1946    # if len(argv) > 1 and argv[1] in subcommands:
     1947    #     subcommands[argv[1]](*argv[2:])
     1948    # elif len(argv) == 1 or argv[1] in ('help', '--help', '-h'):
     1949    #     # TODO print usage
     1950    #     subcommand_names = ' | '.join(sorted(subcommands.keys()))
     1951    #     print("USAGE: {} [ {} ] ...".format(argv[0], subcommand_names))
     1952    # else:
     1953    #     print("Unknown subcommand: {}".format(argv[1]))
     1954    #     print("Available subcommands:")
     1955    #     for name in sorted(subcommands.keys()):
     1956    #         print("\t{}".format(name))
     1957    #     sys.exit(-1)
     1958    # sys.exit(0)
     1959
    18161960    # arg = sys.argv
    18171961    # print(arg)
  • trunk/exports/G2export_CIF.py

    r3000 r3011  
    1515entire project in a complete CIF intended for submission as a
    1616publication. In addition, there are three subclasses of :class:`ExportCIF`:
    17 :class:`ExportProjectCIF`, 
     17:class:`ExportProjectCIF`,
    1818:class:`ExportPhaseCIF` and :class:`ExportDataCIF` where extra parameters
    1919for the _Exporter() determine if a project, single phase or data set are written.
     
    4343CIFdic = None
    4444
     45# Refactored over here to allow access by GSASIIscriptable.py
     46def WriteCIFitem(fp, name, value=''):
     47    '''Helper function for writing CIF output. Translated from exports/G2export_CIF.py'''
     48    # Ignore unicode issues
     49    if value:
     50        if "\n" in value or len(value)> 70:
     51            if name.strip():
     52                fp.write(name+'\n')
     53            fp.write('; '+value+'\n')
     54            fp.write('; '+'\n')
     55        elif " " in value:
     56            if len(name)+len(value) > 65:
     57                fp.write(name + '\n   ' + '"' + str(value) + '"'+'\n')
     58            else:
     59                fp.write(name + '  ' + '"' + str(value) + '"'+'\n')
     60        else:
     61            if len(name)+len(value) > 65:
     62                fp.write(name+'\n   ' + value+'\n')
     63            else:
     64                fp.write(name+'  ' + value+'\n')
     65    else:
     66        fp.write(name+'\n')
     67
     68
     69# Refactored over here to allow access by GSASIIscriptable.py
     70def WriteAtomsNuclear(fp, phasedict, phasenam, parmDict, sigDict, labellist):
     71    'Write atom positions to CIF'
     72    # phasedict = self.Phases[phasenam] # pointer to current phase info
     73    General = phasedict['General']
     74    cx,ct,cs,cia = General['AtomPtrs']
     75    Atoms = phasedict['Atoms']
     76    cfrac = cx+3
     77    fpfx = str(phasedict['pId'])+'::Afrac:'
     78    for i,at in enumerate(Atoms):
     79        fval = parmDict.get(fpfx+str(i),at[cfrac])
     80        if fval != 0.0:
     81            break
     82    else:
     83        WriteCIFitem(fp, '\n# PHASE HAS NO ATOMS!')
     84        return
     85
     86    WriteCIFitem(fp, '\n# ATOMIC COORDINATES AND DISPLACEMENT PARAMETERS')
     87    WriteCIFitem(fp, 'loop_ '+
     88                 '\n   _atom_site_label'+
     89                 '\n   _atom_site_type_symbol'+
     90                 '\n   _atom_site_fract_x'+
     91                 '\n   _atom_site_fract_y'+
     92                 '\n   _atom_site_fract_z'+
     93                 '\n   _atom_site_occupancy'+
     94                 '\n   _atom_site_adp_type'+
     95                 '\n   _atom_site_U_iso_or_equiv'+
     96                 '\n   _atom_site_symmetry_multiplicity')
     97
     98    varnames = {cx:'Ax',cx+1:'Ay',cx+2:'Az',cx+3:'Afrac',
     99                cia+1:'AUiso',cia+2:'AU11',cia+3:'AU22',cia+4:'AU33',
     100                cia+5:'AU12',cia+6:'AU13',cia+7:'AU23'}
     101    # Empty the labellist
     102    while labellist:
     103        labellist.pop()
     104
     105    pfx = str(phasedict['pId'])+'::'
     106    # loop over all atoms
     107    naniso = 0
     108    for i,at in enumerate(Atoms):
     109        if phasedict['General']['Type'] == 'macromolecular':
     110            label = '%s_%s_%s_%s'%(at[ct-1],at[ct-3],at[ct-4],at[ct-2])
     111            s = PutInCol(MakeUniqueLabel(label,labellist),15) # label
     112        else:
     113            s = PutInCol(MakeUniqueLabel(at[ct-1],labellist),6) # label
     114        fval = parmDict.get(fpfx+str(i),at[cfrac])
     115        if fval == 0.0: continue # ignore any atoms that have a occupancy set to 0 (exact)
     116        s += PutInCol(FmtAtomType(at[ct]),4) # type
     117        if at[cia] == 'I':
     118            adp = 'Uiso '
     119        else:
     120            adp = 'Uani '
     121            naniso += 1
     122            # compute Uequiv crudely
     123            # correct: Defined as "1/3 trace of diagonalized U matrix".
     124            # SEE cell2GS & Uij2Ueqv to GSASIIlattice. Former is needed to make the GS matrix used by the latter.
     125            t = 0.0
     126            for j in (2,3,4):
     127                var = pfx+varnames[cia+j]+":"+str(i)
     128                t += parmDict.get(var,at[cia+j])
     129        for j in (cx,cx+1,cx+2,cx+3,cia,cia+1):
     130            if j in (cx,cx+1,cx+2):
     131                dig = 11
     132                sigdig = -0.00009
     133            else:
     134                dig = 10
     135                sigdig = -0.009
     136            if j == cia:
     137                s += adp
     138            else:
     139                var = pfx+varnames[j]+":"+str(i)
     140                dvar = pfx+"d"+varnames[j]+":"+str(i)
     141                if dvar not in sigDict:
     142                    dvar = var
     143                if j == cia+1 and adp == 'Uani ':
     144                    val = t/3.
     145                    sig = sigdig
     146                else:
     147                    #print var,(var in parmDict),(var in sigDict)
     148                    val = parmDict.get(var,at[j])
     149                    sig = sigDict.get(dvar,sigdig)
     150                s += PutInCol(G2mth.ValEsd(val,sig),dig)
     151        s += PutInCol(at[cs+1],3)
     152        WriteCIFitem(fp, s)
     153    if naniso == 0: return
     154    # now loop over aniso atoms
     155    WriteCIFitem(fp, '\nloop_' + '\n   _atom_site_aniso_label' +
     156                 '\n   _atom_site_aniso_U_11' + '\n   _atom_site_aniso_U_22' +
     157                 '\n   _atom_site_aniso_U_33' + '\n   _atom_site_aniso_U_12' +
     158                 '\n   _atom_site_aniso_U_13' + '\n   _atom_site_aniso_U_23')
     159    for i,at in enumerate(Atoms):
     160        fval = parmDict.get(fpfx+str(i),at[cfrac])
     161        if fval == 0.0: continue # ignore any atoms that have a occupancy set to 0 (exact)
     162        if at[cia] == 'I': continue
     163        s = PutInCol(labellist[i],6) # label
     164        for j in (2,3,4,5,6,7):
     165            sigdig = -0.0009
     166            var = pfx+varnames[cia+j]+":"+str(i)
     167            val = parmDict.get(var,at[cia+j])
     168            sig = sigDict.get(var,sigdig)
     169            s += PutInCol(G2mth.ValEsd(val,sig),11)
     170        WriteCIFitem(fp, s)
     171
     172
     173# Refactored over here to allow access by GSASIIscriptable.py
     174def MakeUniqueLabel(lbl, labellist):
     175    lbl = lbl.strip()
     176    if not lbl: # deal with a blank label
     177        lbl = 'A_1'
     178    if lbl not in labellist:
     179        labellist.append(lbl)
     180        return lbl
     181    i = 1
     182    prefix = lbl
     183    if '_' in lbl:
     184        prefix = lbl[:lbl.rfind('_')]
     185        suffix = lbl[lbl.rfind('_')+1:]
     186        try:
     187            i = int(suffix)+1
     188        except:
     189            pass
     190    while prefix+'_'+str(i) in labellist:
     191        i += 1
     192    else:
     193        lbl = prefix+'_'+str(i)
     194        labellist.append(lbl)
     195
     196
     197# Refactored over here to allow access by GSASIIscriptable.py
     198def FmtAtomType(sym):
     199    'Reformat a GSAS-II atom type symbol to match CIF rules'
     200    sym = sym.replace('_','') # underscores are not allowed: no isotope designation?
     201    # in CIF, oxidation state sign symbols come after, not before
     202    if '+' in sym:
     203        sym = sym.replace('+','') + '+'
     204    elif '-' in sym:
     205        sym = sym.replace('-','') + '-'
     206    return sym
     207
     208
     209# Refactored over here to allow access by GSASIIscriptable.py
     210def PutInCol(val, wid):
     211    val = str(val).replace(' ', '')
     212    if not val: val = '?'
     213    fmt = '{:' + str(wid) + '} '
     214    return fmt.format(val)
     215
     216
     217# Refactored over here to allow access by GSASIIscriptable.py
     218def WriteComposition(fp, phasedict, phasenam, parmDict):
     219    '''determine the composition for the unit cell, crudely determine Z and
     220    then compute the composition in formula units
     221    '''
     222    General = phasedict['General']
     223    Z = General.get('cellZ',0.0)
     224    cx,ct,cs,cia = General['AtomPtrs']
     225    Atoms = phasedict['Atoms']
     226    fpfx = str(phasedict['pId'])+'::Afrac:'
     227    cfrac = cx+3
     228    cmult = cs+1
     229    compDict = {} # combines H,D & T
     230    sitemultlist = []
     231    massDict = dict(zip(General['AtomTypes'],General['AtomMass']))
     232    cellmass = 0
     233    for i,at in enumerate(Atoms):
     234        atype = at[ct].strip()
     235        if atype.find('-') != -1: atype = atype.split('-')[0]
     236        if atype.find('+') != -1: atype = atype.split('+')[0]
     237        atype = atype[0].upper()+atype[1:2].lower() # force case conversion
     238        if atype == "D" or atype == "D": atype = "H"
     239        fvar = fpfx+str(i)
     240        fval = parmDict.get(fvar,at[cfrac])
     241        mult = at[cmult]
     242        if not massDict.get(at[ct]):
     243            print('Error: No mass found for atom type '+at[ct])
     244            print('Will not compute cell contents for phase '+phasenam)
     245            return
     246        cellmass += massDict[at[ct]]*mult*fval
     247        compDict[atype] = compDict.get(atype,0.0) + mult*fval
     248        if fval == 1: sitemultlist.append(mult)
     249    if len(compDict.keys()) == 0: return # no elements!
     250    if Z < 1: # Z has not been computed or set by user
     251        Z = 1
     252        if not sitemultlist:
     253            General['cellZ'] = 1
     254            return
     255        for i in range(2,min(sitemultlist)+1):
     256            for m in sitemultlist:
     257                if m % i != 0:
     258                    break
     259                else:
     260                    Z = i
     261        General['cellZ'] = Z # save it
     262
     263    # when scattering factors are included in the CIF, this needs to be
     264    # added to the loop here but only in the one-block case.
     265    # For multiblock CIFs, scattering factors go in the histogram
     266    # blocks  (for all atoms in all appropriate phases) - an example?:
     267    #loop_
     268    #    _atom_type_symbol
     269    #    _atom_type_description
     270    #    _atom_type_scat_dispersion_real
     271    #    _atom_type_scat_dispersion_imag
     272    #    _atom_type_scat_source
     273    #    'C' 'C' 0.0033 0.0016
     274    #                         'International Tables Vol C Tables 4.2.6.8 and 6.1.1.4'
     275    #    'H' 'H' 0.0000 0.0000
     276    #                         'International Tables Vol C Tables 4.2.6.8 and 6.1.1.4'
     277    #    'P' 'P' 0.1023 0.0942
     278    #                         'International Tables Vol C Tables 4.2.6.8 and 6.1.1.4'
     279    #    'Cl' 'Cl' 0.1484 0.1585
     280    #                         'International Tables Vol C Tables 4.2.6.8 and 6.1.1.4'
     281    #    'Cu' 'Cu' 0.3201 1.2651
     282    #                         'International Tables Vol C Tables 4.2.6.8 and 6.1.1.4'
     283
     284    #if oneblock: # add scattering factors for current phase here
     285    WriteCIFitem(fp, '\nloop_  _atom_type_symbol _atom_type_number_in_cell')
     286    formula = ''
     287    reload(G2mth)
     288    for elem in HillSortElements(compDict.keys()):
     289        WriteCIFitem(fp, '  ' + PutInCol(elem,4) +
     290                     G2mth.ValEsd(compDict[elem],-0.009,True))
     291        if formula: formula += " "
     292        formula += elem
     293        if compDict[elem] == Z: continue
     294        formula += G2mth.ValEsd(compDict[elem]/Z,-0.009,True)
     295    WriteCIFitem(fp,  '\n# Note that Z affects _cell_formula_sum and _weight')
     296    WriteCIFitem(fp,  '_cell_formula_units_Z',str(Z))
     297    WriteCIFitem(fp,  '_chemical_formula_sum',formula)
     298    WriteCIFitem(fp,  '_chemical_formula_weight',
     299                  G2mth.ValEsd(cellmass/Z,-0.09,True))
     300
    45301class ExportCIF(G2IO.ExportBaseclass):
    46302    '''Base class for CIF exports
     
    64320                             'Unicode not valid for CIF')
    65321            return True
    66                      
     322
    67323    def _Exporter(self,event=None,phaseOnly=None,histOnly=None,IncludeOnlyHist=None):
    68324        '''Basic code to export a CIF. Export can be full or simple, as set by
     
    76332
    77333#***** define functions for export method =======================================
    78         def WriteCIFitem(name,value=''):
    79             '''Write CIF data items to the file. Formats values as needed.
    80             Also used without a value for loops, comments, loop headers, etc.
    81             '''
    82             if all(ord(c) < 128 for c in value) and all(ord(c) < 128 for c in name):
    83                 pass
    84             else:
    85                 print('Warning: unicode stripped from CIF item with name='+name+' value='+value)
    86                 s = ''
    87                 for c in name:
    88                     if ord(c) < 128:
    89                         s += c
    90                     else:
    91                         s += '.'
    92                 name = s
    93                 s = ''
    94                 for c in value:
    95                     if ord(c) < 128:
    96                         s += c
    97                     else:
    98                         s += '.'
    99                 value = s
    100                 print('...changed to name='+name+' value='+value)
    101                
    102             if value:
    103                 if "\n" in value or len(value)> 70:
    104                     if name.strip(): self.fp.write(name+'\n')
    105                     self.fp.write('; '+value+'\n')
    106                     self.fp.write('; '+'\n')
    107                 elif " " in value:
    108                     if len(name)+len(value) > 65:
    109                         self.fp.write(name + '\n   ' + '"' + str(value) + '"'+'\n')
    110                     else:
    111                         self.fp.write(name + '  ' + '"' + str(value) + '"'+'\n')
    112                 else:
    113                     if len(name)+len(value) > 65:
    114                         self.fp.write(name+'\n   ' + value+'\n')
    115                     else:
    116                         self.fp.write(name+'  ' + value+'\n')
    117             else:
    118                 self.fp.write(name+'\n')
    119 
    120334        def WriteAudit():
    121335            'Write the CIF audit values. Perhaps should be in a single element loop.'
    122             WriteCIFitem('_audit_creation_method',
     336            WriteCIFitem(self.fp, '_audit_creation_method',
    123337                         'created in GSAS-II')
    124             WriteCIFitem('_audit_creation_date',self.CIFdate)
     338            WriteCIFitem(self.fp, '_audit_creation_date',self.CIFdate)
    125339            if self.author:
    126                 WriteCIFitem('_audit_author_name',self.author)
    127             WriteCIFitem('_audit_update_record',
     340                WriteCIFitem(self.fp, '_audit_author_name',self.author)
     341            WriteCIFitem(self.fp, '_audit_update_record',
    128342                         self.CIFdate+'  Initial software-generated CIF')
    129343
     
    134348            '''
    135349            if self.ifPWDR:
    136                 WriteCIFitem('_pd_proc_info_datetime', self.CIFdate)
    137                 WriteCIFitem('_pd_calc_method', 'Rietveld Refinement')
    138             #WriteCIFitem('_refine_ls_shift/su_max',DAT1)
    139             #WriteCIFitem('_refine_ls_shift/su_mean',DAT2)
    140             WriteCIFitem('_computing_structure_refinement','GSAS-II (Toby & Von Dreele, J. Appl. Cryst. 46, 544-549, 2013)')
     350                WriteCIFitem(self.fp, '_pd_proc_info_datetime', self.CIFdate)
     351                WriteCIFitem(self.fp, '_pd_calc_method', 'Rietveld Refinement')
     352            #WriteCIFitem(self.fp, '_refine_ls_shift/su_max',DAT1)
     353            #WriteCIFitem(self.fp, '_refine_ls_shift/su_mean',DAT2)
     354            WriteCIFitem(self.fp, '_computing_structure_refinement','GSAS-II (Toby & Von Dreele, J. Appl. Cryst. 46, 544-549, 2013)')
    141355            if self.ifHKLF:
    142356                controls = self.OverallParms['Controls']
     
    145359                else:
    146360                    thresh = 'F>%.1fu(F)'%(controls['minF/sig'])
    147                 WriteCIFitem('_reflns_threshold_expression', thresh)               
     361                WriteCIFitem(self.fp, '_reflns_threshold_expression', thresh)
    148362            try:
    149363                vars = str(len(self.OverallParms['Covariance']['varyList']))
    150364            except:
    151365                vars = '?'
    152             WriteCIFitem('_refine_ls_number_parameters',vars)
     366            WriteCIFitem(self.fp, '_refine_ls_number_parameters',vars)
    153367            try:
    154368                GOF = G2mth.ValEsd(self.OverallParms['Covariance']['Rvals']['GOF'],-0.009)
    155369            except:
    156370                GOF = '?'
    157             WriteCIFitem('_refine_ls_goodness_of_fit_all',GOF)
     371            WriteCIFitem(self.fp, '_refine_ls_goodness_of_fit_all',GOF)
    158372
    159373            # get restraint info
     
    163377            #     for j in self.OverallParms['Constraints'][i]:
    164378            #         print j
    165             #WriteCIFitem('_refine_ls_number_restraints',TEXT)
     379            #WriteCIFitem(self.fp, '_refine_ls_number_restraints',TEXT)
    166380            # other things to consider reporting
    167381            # _refine_ls_number_reflns
     
    173387            # include an overall profile r-factor, if there is more than one powder histogram
    174388            R = '%.5f'%(self.OverallParms['Covariance']['Rvals']['Rwp']/100.)
    175             WriteCIFitem('\n# OVERALL WEIGHTED R-FACTOR')
    176             WriteCIFitem('_refine_ls_wR_factor_obs',R)
     389            WriteCIFitem(self.fp, '\n# OVERALL WEIGHTED R-FACTOR')
     390            WriteCIFitem(self.fp, '_refine_ls_wR_factor_obs',R)
    177391                # _refine_ls_R_factor_all
    178                 # _refine_ls_R_factor_obs               
    179             WriteCIFitem('_refine_ls_matrix_type','full')
    180             #WriteCIFitem('_refine_ls_matrix_type','userblocks')
     392                # _refine_ls_R_factor_obs
     393            WriteCIFitem(self.fp, '_refine_ls_matrix_type','full')
     394            #WriteCIFitem(self.fp, '_refine_ls_matrix_type','userblocks')
    181395
    182396        def writeCIFtemplate(G2dict,tmplate,defaultname=''):
    183397            '''Write out the selected or edited CIF template
    184398            An unedited CIF template file is copied, comments intact; an edited
    185             CIF template is written out from PyCifRW which of course strips comments. 
     399            CIF template is written out from PyCifRW which of course strips comments.
    186400            In all cases the initial data_ header is stripped (there should only be one!)
    187401            '''
     
    221435            txt = "# GSAS-II edited template follows "+txt[txt.index("data_")+5:]
    222436            #txt = txt.replace('data_','#')
    223             WriteCIFitem(txt)
     437            WriteCIFitem(self.fp, txt)
    224438
    225439        def FormatSH(phasenam):
    226440            'Format a full spherical harmonics texture description as a string'
    227             phasedict = self.Phases[phasenam] # pointer to current phase info           
     441            phasedict = self.Phases[phasenam] # pointer to current phase info
    228442            pfx = str(phasedict['pId'])+'::'
    229443            s = ""
    230             textureData = phasedict['General']['SH Texture']   
     444            textureData = phasedict['General']['SH Texture']
    231445            if textureData.get('Order'):
    232446                s += "Spherical Harmonics correction. Order = "+str(textureData['Order'])
     
    257471            character string
    258472            '''
    259             phasedict = self.Phases[phasenam] # pointer to current phase info           
     473            phasedict = self.Phases[phasenam] # pointer to current phase info
    260474            s = ''
    261475            for histogram in sorted(phasedict['Histograms']):
     
    292506                    s += s1
    293507            return s
    294        
     508
    295509        def FormatBackground(bkg,hId):
    296510            '''Display the Background information as a descriptive text string.
    297            
     511
    298512            TODO: this needs to be expanded to show the diffuse peak and
    299513            Debye term information as well. (Bob)
     
    349563                    name = hfx+item
    350564                    sig = self.sigDict.get(name,-0.009)
    351                     s += G2mth.ValEsd(inst[item][1],sig)+', '                   
     565                    s += G2mth.ValEsd(inst[item][1],sig)+', '
    352566            elif 'T' in inst['Type'][0]:    #to be tested after TOF Rietveld done
    353567                s = 'Von Dreele-Jorgenson-Windsor function parameters\n'+ \
     
    367581            s = ''
    368582            phasedict = self.Phases[phasenam] # pointer to current phase info
    369             SGData = phasedict['General'] ['SGData']         
     583            SGData = phasedict['General'] ['SGData']
    370584            for histogram in sorted(phasedict['Histograms']):
    371585                if histogram.startswith("HKLF"): continue # powder only
     
    387601                else:
    388602                    s += '  Crystallite size model "%s" for %s (microns)\n  '%(size[0],phasenam)
    389                
     603
    390604                names = ['Size;i','Size;mx']
    391605                if 'uniax' in size[0]:
     
    404618                        s += G2mth.ValEsd(size[4][i],sig)+', '
    405619                    sig = self.sigDict.get(phfx+'Size;mx',-0.009)
    406                     s += G2mth.ValEsd(size[1][2],sig)+', '                                           
     620                    s += G2mth.ValEsd(size[1][2],sig)+', '
    407621                else:       #isotropic
    408622                    s += 'parameters: Size, G/L mix\n    '
     
    412626                        sig = self.sigDict.get(name,-0.009)
    413627                        s += G2mth.ValEsd(size[1][i],sig)+', '
    414                         i = 2    #skip the aniso value               
     628                        i = 2    #skip the aniso value
    415629                s += '\n  Mustrain model "%s" for %s (10^6^)\n  '%(mustrain[0],phasenam)
    416630                names = ['Mustrain;i','Mustrain;mx']
     
    439653                            txt = ''
    440654                        txt += G2mth.ValEsd(mustrain[4][i],sig)+', '
    441                     s += txt                                           
     655                    s += txt
    442656                    sig = self.sigDict.get(phfx+'Mustrain;mx',-0.009)
    443657                    s += G2mth.ValEsd(mustrain[1][2],sig)+', '
    444                    
     658
    445659                else:       #isotropic
    446660                    s += '  parameters: Mustrain, G/L mix\n    '
     
    450664                        sig = self.sigDict.get(name,-0.009)
    451665                        s += G2mth.ValEsd(mustrain[1][i],sig)+', '
    452                         i = 2    #skip the aniso value               
     666                        i = 2    #skip the aniso value
    453667                s1 = '  \n  Macrostrain parameters: '
    454668                names = G2spc.HStrainNames(SGData)
     
    468682                    s += '\n'
    469683            return s
    470        
    471         def FmtAtomType(sym):
    472             'Reformat a GSAS-II atom type symbol to match CIF rules'
    473             sym = sym.replace('_','') # underscores are not allowed: no isotope designation?
    474             # in CIF, oxidation state sign symbols come after, not before
    475             if '+' in sym:
    476                 sym = sym.replace('+','') + '+'
    477             elif '-' in sym:
    478                 sym = sym.replace('-','') + '-'
    479             return sym
    480            
    481         def PutInCol(val,wid):
    482             '''Pad a value to >=wid+1 columns by adding spaces at the end. Always
    483             adds at least one space
    484             '''
    485             val = str(val).replace(' ','')
    486             if not val: val = '?'
    487             fmt = '{:' + str(wid) + '} '
    488             return fmt.format(val)
    489684
    490685        def MakeUniqueLabel(lbl,labellist):
     
    511706                labellist.append(lbl)
    512707
    513         def WriteAtomsNuclear(phasenam):
    514             'Write atom positions to CIF'
    515             phasedict = self.Phases[phasenam] # pointer to current phase info
    516             General = phasedict['General']
    517             cx,ct,cs,cia = General['AtomPtrs']
    518             Atoms = phasedict['Atoms']
    519             cfrac = cx+3
    520             fpfx = str(phasedict['pId'])+'::Afrac:'       
    521             for i,at in enumerate(Atoms):
    522                 fval = self.parmDict.get(fpfx+str(i),at[cfrac])
    523                 if fval != 0.0:
    524                     break
    525             else:
    526                 WriteCIFitem('\n# PHASE HAS NO ATOMS!')
    527                 return
    528                
    529             WriteCIFitem('\n# ATOMIC COORDINATES AND DISPLACEMENT PARAMETERS')
    530             WriteCIFitem('loop_ '+
    531                          '\n   _atom_site_label'+
    532                          '\n   _atom_site_type_symbol'+
    533                          '\n   _atom_site_fract_x'+
    534                          '\n   _atom_site_fract_y'+
    535                          '\n   _atom_site_fract_z'+
    536                          '\n   _atom_site_occupancy'+
    537                          '\n   _atom_site_adp_type'+
    538                          '\n   _atom_site_U_iso_or_equiv'+
    539                          '\n   _atom_site_symmetry_multiplicity')
    540 
    541             varnames = {cx:'Ax',cx+1:'Ay',cx+2:'Az',cx+3:'Afrac',
    542                         cia+1:'AUiso',cia+2:'AU11',cia+3:'AU22',cia+4:'AU33',
    543                         cia+5:'AU12',cia+6:'AU13',cia+7:'AU23'}
    544             self.labellist = []
    545            
    546             pfx = str(phasedict['pId'])+'::'
    547             # loop over all atoms
    548             naniso = 0
    549             for i,at in enumerate(Atoms):
    550                 if phasedict['General']['Type'] == 'macromolecular':
    551                     label = '%s_%s_%s_%s'%(at[ct-1],at[ct-3],at[ct-4],at[ct-2])
    552                     s = PutInCol(MakeUniqueLabel(label,self.labellist),15) # label
    553                 else:
    554                     s = PutInCol(MakeUniqueLabel(at[ct-1],self.labellist),6) # label
    555                 fval = self.parmDict.get(fpfx+str(i),at[cfrac])
    556                 if fval == 0.0: continue # ignore any atoms that have a occupancy set to 0 (exact)
    557                 s += PutInCol(FmtAtomType(at[ct]),4) # type
    558                 if at[cia] == 'I':
    559                     adp = 'Uiso '
    560                 else:
    561                     adp = 'Uani '
    562                     naniso += 1
    563                     # compute Uequiv crudely
    564                     # correct: Defined as "1/3 trace of diagonalized U matrix".
    565                     # SEE cell2GS & Uij2Ueqv to GSASIIlattice. Former is needed to make the GS matrix used by the latter.
    566                     t = 0.0
    567                     for j in (2,3,4):
    568                         var = pfx+varnames[cia+j]+":"+str(i)
    569                         t += self.parmDict.get(var,at[cia+j])
    570                 for j in (cx,cx+1,cx+2,cx+3,cia,cia+1):
    571                     if j in (cx,cx+1,cx+2):
    572                         dig = 11
    573                         sigdig = -0.00009
    574                     else:
    575                         dig = 10
    576                         sigdig = -0.009
    577                     if j == cia:
    578                         s += adp
    579                     else:
    580                         var = pfx+varnames[j]+":"+str(i)
    581                         dvar = pfx+"d"+varnames[j]+":"+str(i)
    582                         if dvar not in self.sigDict:
    583                             dvar = var
    584                         if j == cia+1 and adp == 'Uani ':
    585                             val = t/3.
    586                             sig = sigdig
    587                         else:
    588                             #print var,(var in self.parmDict),(var in self.sigDict)
    589                             val = self.parmDict.get(var,at[j])
    590                             sig = self.sigDict.get(dvar,sigdig)
    591                         s += PutInCol(G2mth.ValEsd(val,sig),dig)
    592                 s += PutInCol(at[cs+1],3)
    593                 WriteCIFitem(s)
    594             if naniso == 0: return
    595             # now loop over aniso atoms
    596             WriteCIFitem('\nloop_' + '\n   _atom_site_aniso_label' +
    597                          '\n   _atom_site_aniso_U_11' + '\n   _atom_site_aniso_U_22' +
    598                          '\n   _atom_site_aniso_U_33' + '\n   _atom_site_aniso_U_12' +
    599                          '\n   _atom_site_aniso_U_13' + '\n   _atom_site_aniso_U_23')
    600             for i,at in enumerate(Atoms):
    601                 fval = self.parmDict.get(fpfx+str(i),at[cfrac])
    602                 if fval == 0.0: continue # ignore any atoms that have a occupancy set to 0 (exact)
    603                 if at[cia] == 'I': continue
    604                 s = PutInCol(self.labellist[i],6) # label
    605                 for j in (2,3,4,5,6,7):
    606                     sigdig = -0.0009
    607                     var = pfx+varnames[cia+j]+":"+str(i)
    608                     val = self.parmDict.get(var,at[cia+j])
    609                     sig = self.sigDict.get(var,sigdig)
    610                     s += PutInCol(G2mth.ValEsd(val,sig),11)
    611                 WriteCIFitem(s)
     708        # Factored out to above by Jack O'Donnell, so it
     709        # could be accessed by GSASIIscriptable.py
     710        #  def WriteAtomsNuclear(phasenam):
     711        #      'Write atom positions to CIF'
     712        #      phasedict = self.Phases[phasenam] # pointer to current phase info
     713        #      General = phasedict['General']
     714        #      cx,ct,cs,cia = General['AtomPtrs']
     715        #      Atoms = phasedict['Atoms']
     716        #      cfrac = cx+3
     717        #      fpfx = str(phasedict['pId'])+'::Afrac:'
     718        #      for i,at in enumerate(Atoms):
     719        #          fval = self.parmDict.get(fpfx+str(i),at[cfrac])
     720        #          if fval != 0.0:
     721        #              break
     722        #      else:
     723        #          WriteCIFitem(self.fp, '\n# PHASE HAS NO ATOMS!')
     724        #          return
     725
     726        #      WriteCIFitem(self.fp, '\n# ATOMIC COORDINATES AND DISPLACEMENT PARAMETERS')
     727        #      WriteCIFitem(self.fp, 'loop_ '+
     728        #                   '\n   _atom_site_label'+
     729        #                   '\n   _atom_site_type_symbol'+
     730        #                   '\n   _atom_site_fract_x'+
     731        #                   '\n   _atom_site_fract_y'+
     732        #                   '\n   _atom_site_fract_z'+
     733        #                   '\n   _atom_site_occupancy'+
     734        #                   '\n   _atom_site_adp_type'+
     735        #                   '\n   _atom_site_U_iso_or_equiv'+
     736        #                   '\n   _atom_site_symmetry_multiplicity')
     737
     738        #      varnames = {cx:'Ax',cx+1:'Ay',cx+2:'Az',cx+3:'Afrac',
     739        #                  cia+1:'AUiso',cia+2:'AU11',cia+3:'AU22',cia+4:'AU33',
     740        #                  cia+5:'AU12',cia+6:'AU13',cia+7:'AU23'}
     741        #      self.labellist = []
     742
     743        #      pfx = str(phasedict['pId'])+'::'
     744        #      # loop over all atoms
     745        #      naniso = 0
     746        #      for i,at in enumerate(Atoms):
     747        #          if phasedict['General']['Type'] == 'macromolecular':
     748        #              label = '%s_%s_%s_%s'%(at[ct-1],at[ct-3],at[ct-4],at[ct-2])
     749        #              s = PutInCol(MakeUniqueLabel(label,self.labellist),15) # label
     750        #          else:
     751        #              s = PutInCol(MakeUniqueLabel(at[ct-1],self.labellist),6) # label
     752        #          fval = self.parmDict.get(fpfx+str(i),at[cfrac])
     753        #          if fval == 0.0: continue # ignore any atoms that have a occupancy set to 0 (exact)
     754        #          s += PutInCol(FmtAtomType(at[ct]),4) # type
     755        #          if at[cia] == 'I':
     756        #              adp = 'Uiso '
     757        #          else:
     758        #              adp = 'Uani '
     759        #              naniso += 1
     760        #              # compute Uequiv crudely
     761        #              # correct: Defined as "1/3 trace of diagonalized U matrix".
     762        #              # SEE cell2GS & Uij2Ueqv to GSASIIlattice. Former is needed to make the GS matrix used by the latter.
     763        #              t = 0.0
     764        #              for j in (2,3,4):
     765        #                  var = pfx+varnames[cia+j]+":"+str(i)
     766        #                  t += self.parmDict.get(var,at[cia+j])
     767        #          for j in (cx,cx+1,cx+2,cx+3,cia,cia+1):
     768        #              if j in (cx,cx+1,cx+2):
     769        #                  dig = 11
     770        #                  sigdig = -0.00009
     771        #              else:
     772        #                  dig = 10
     773        #                  sigdig = -0.009
     774        #              if j == cia:
     775        #                  s += adp
     776        #              else:
     777        #                  var = pfx+varnames[j]+":"+str(i)
     778        #                  dvar = pfx+"d"+varnames[j]+":"+str(i)
     779        #                  if dvar not in self.sigDict:
     780        #                      dvar = var
     781        #                  if j == cia+1 and adp == 'Uani ':
     782        #                      val = t/3.
     783        #                      sig = sigdig
     784        #                  else:
     785        #                      #print var,(var in self.parmDict),(var in self.sigDict)
     786        #                      val = self.parmDict.get(var,at[j])
     787        #                      sig = self.sigDict.get(dvar,sigdig)
     788        #                  s += PutInCol(G2mth.ValEsd(val,sig),dig)
     789        #          s += PutInCol(at[cs+1],3)
     790        #          WriteCIFitem(self.fp, s)
     791        #      if naniso == 0: return
     792        #      # now loop over aniso atoms
     793        #      WriteCIFitem(self.fp, '\nloop_' + '\n   _atom_site_aniso_label' +
     794        #                   '\n   _atom_site_aniso_U_11' + '\n   _atom_site_aniso_U_22' +
     795        #                   '\n   _atom_site_aniso_U_33' + '\n   _atom_site_aniso_U_12' +
     796        #                   '\n   _atom_site_aniso_U_13' + '\n   _atom_site_aniso_U_23')
     797        #      for i,at in enumerate(Atoms):
     798        #          fval = self.parmDict.get(fpfx+str(i),at[cfrac])
     799        #          if fval == 0.0: continue # ignore any atoms that have a occupancy set to 0 (exact)
     800        #          if at[cia] == 'I': continue
     801        #          s = PutInCol(self.labellist[i],6) # label
     802        #          for j in (2,3,4,5,6,7):
     803        #              sigdig = -0.0009
     804        #              var = pfx+varnames[cia+j]+":"+str(i)
     805        #              val = self.parmDict.get(var,at[cia+j])
     806        #              sig = self.sigDict.get(var,sigdig)
     807        #              s += PutInCol(G2mth.ValEsd(val,sig),11)
     808        #          WriteCIFitem(self.fp, s)
    612809
    613810        def HillSortElements(elmlist):
     
    627824            return newlist+sorted(oldlist)
    628825
    629         def WriteComposition(phasenam):
    630             '''determine the composition for the unit cell, crudely determine Z and
    631             then compute the composition in formula units
    632             '''
    633             phasedict = self.Phases[phasenam] # pointer to current phase info
    634             General = phasedict['General']
    635             Z = General.get('cellZ',0.0)
    636             cx,ct,cs,cia = General['AtomPtrs']
    637             Atoms = phasedict['Atoms']
    638             fpfx = str(phasedict['pId'])+'::Afrac:'       
    639             cfrac = cx+3
    640             cmult = cs+1
    641             compDict = {} # combines H,D & T
    642             sitemultlist = []
    643             massDict = dict(zip(General['AtomTypes'],General['AtomMass']))
    644             cellmass = 0
    645             for i,at in enumerate(Atoms):
    646                 atype = at[ct].strip()
    647                 if atype.find('-') != -1: atype = atype.split('-')[0]
    648                 if atype.find('+') != -1: atype = atype.split('+')[0]
    649                 atype = atype[0].upper()+atype[1:2].lower() # force case conversion
    650                 if atype == "D" or atype == "D": atype = "H"
    651                 fvar = fpfx+str(i)
    652                 fval = self.parmDict.get(fvar,at[cfrac])
    653                 mult = at[cmult]
    654                 if not massDict.get(at[ct]):
    655                     print('Error: No mass found for atom type '+at[ct])
    656                     print('Will not compute cell contents for phase '+phasenam)
    657                     return
    658                 cellmass += massDict[at[ct]]*mult*fval
    659                 compDict[atype] = compDict.get(atype,0.0) + mult*fval
    660                 if fval == 1: sitemultlist.append(mult)
    661             if len(compDict.keys()) == 0: return # no elements!
    662             if Z < 1: # Z has not been computed or set by user
    663                 Z = 1
    664                 if not sitemultlist:
    665                     General['cellZ'] = 1
    666                     return
    667                 for i in range(2,min(sitemultlist)+1):
    668                     for m in sitemultlist:
    669                         if m % i != 0:
    670                             break
    671                         else:
    672                             Z = i
    673                 General['cellZ'] = Z # save it
    674 
    675             # when scattering factors are included in the CIF, this needs to be
    676             # added to the loop here but only in the one-block case.
    677             # For multiblock CIFs, scattering factors go in the histogram
    678             # blocks  (for all atoms in all appropriate phases) - an example?:
     826        # Factored out to above by Jackson O'Donnell
     827        # so that it can be accessed by GSASIIscriptable
     828
     829        # def WriteComposition(phasenam):
     830        #     '''determine the composition for the unit cell, crudely determine Z and
     831        #     then compute the composition in formula units
     832        #     '''
     833        #     phasedict = self.Phases[phasenam] # pointer to current phase info
     834        #     General = phasedict['General']
     835        #     Z = General.get('cellZ',0.0)
     836        #     cx,ct,cs,cia = General['AtomPtrs']
     837        #     Atoms = phasedict['Atoms']
     838        #     fpfx = str(phasedict['pId'])+'::Afrac:'
     839        #     cfrac = cx+3
     840        #     cmult = cs+1
     841        #     compDict = {} # combines H,D & T
     842        #     sitemultlist = []
     843        #     massDict = dict(zip(General['AtomTypes'],General['AtomMass']))
     844        #     cellmass = 0
     845        #     for i,at in enumerate(Atoms):
     846        #         atype = at[ct].strip()
     847        #         if atype.find('-') != -1: atype = atype.split('-')[0]
     848        #         if atype.find('+') != -1: atype = atype.split('+')[0]
     849        #         atype = atype[0].upper()+atype[1:2].lower() # force case conversion
     850        #         if atype == "D" or atype == "D": atype = "H"
     851        #         fvar = fpfx+str(i)
     852        #         fval = self.parmDict.get(fvar,at[cfrac])
     853        #         mult = at[cmult]
     854        #         if not massDict.get(at[ct]):
     855        #             print('Error: No mass found for atom type '+at[ct])
     856        #             print('Will not compute cell contents for phase '+phasenam)
     857        #             return
     858        #         cellmass += massDict[at[ct]]*mult*fval
     859        #         compDict[atype] = compDict.get(atype,0.0) + mult*fval
     860        #         if fval == 1: sitemultlist.append(mult)
     861        #     if len(compDict.keys()) == 0: return # no elements!
     862        #     if Z < 1: # Z has not been computed or set by user
     863        #         Z = 1
     864        #         if not sitemultlist:
     865        #             General['cellZ'] = 1
     866        #             return
     867        #         for i in range(2,min(sitemultlist)+1):
     868        #             for m in sitemultlist:
     869        #                 if m % i != 0:
     870        #                     break
     871        #                 else:
     872        #                     Z = i
     873        #         General['cellZ'] = Z # save it
     874
     875        #     # when scattering factors are included in the CIF, this needs to be
     876        #     # added to the loop here but only in the one-block case.
     877        #     # For multiblock CIFs, scattering factors go in the histogram
     878        #     # blocks  (for all atoms in all appropriate phases) - an example?:
    679879#loop_
    680 #    _atom_type_symbol
    681 #    _atom_type_description
    682 #    _atom_type_scat_dispersion_real
    683 #    _atom_type_scat_dispersion_imag
    684 #    _atom_type_scat_source
    685 #    'C' 'C' 0.0033 0.0016
    686 #                         'International Tables Vol C Tables 4.2.6.8 and 6.1.1.4'
    687 #    'H' 'H' 0.0000 0.0000
    688 #                         'International Tables Vol C Tables 4.2.6.8 and 6.1.1.4'
    689 #    'P' 'P' 0.1023 0.0942
    690 #                         'International Tables Vol C Tables 4.2.6.8 and 6.1.1.4'
    691 #    'Cl' 'Cl' 0.1484 0.1585
    692 #                         'International Tables Vol C Tables 4.2.6.8 and 6.1.1.4'
    693 #    'Cu' 'Cu' 0.3201 1.2651
    694 #                         'International Tables Vol C Tables 4.2.6.8 and 6.1.1.4'
    695 
    696             #if oneblock: # add scattering factors for current phase here
    697             WriteCIFitem('\nloop_  _atom_type_symbol _atom_type_number_in_cell')
    698             formula = ''
    699             reload(G2mth)
    700             for elem in HillSortElements(compDict.keys()):
    701                 WriteCIFitem('  ' + PutInCol(elem,4) +
    702                              G2mth.ValEsd(compDict[elem],-0.009,True))
    703                 if formula: formula += " "
    704                 formula += elem
    705                 if compDict[elem] == Z: continue
    706                 formula += G2mth.ValEsd(compDict[elem]/Z,-0.009,True)
    707             WriteCIFitem( '\n# Note that Z affects _cell_formula_sum and _weight')
    708             WriteCIFitem( '_cell_formula_units_Z',str(Z))
    709             WriteCIFitem( '_chemical_formula_sum',formula)
    710             WriteCIFitem( '_chemical_formula_weight',
    711                           G2mth.ValEsd(cellmass/Z,-0.09,True))
     880#    _at# om_type_symbol
     881#    _at# om_type_description
     882#    _at# om_type_scat_dispersion_real
     883#    _at# om_type_scat_dispersion_imag
     884#    _at# om_type_scat_source
     885#    'C'# 'C' 0.0033 0.0016
     886#       #                   'International Tables Vol C Tables 4.2.6.8 and 6.1.1.4'
     887#    'H'# 'H' 0.0000 0.0000
     888#       #                   'International Tables Vol C Tables 4.2.6.8 and 6.1.1.4'
     889#    'P'# 'P' 0.1023 0.0942
     890#       #                   'International Tables Vol C Tables 4.2.6.8 and 6.1.1.4'
     891#    'Cl# ' 'Cl' 0.1484 0.1585
     892#       #                   'International Tables Vol C Tables 4.2.6.8 and 6.1.1.4'
     893#    'Cu# ' 'Cu' 0.3201 1.2651
     894#       #                   'International Tables Vol C Tables 4.2.6.8 and 6.1.1.4'
     895
     896        #     #if oneblock: # add scattering factors for current phase here
     897        #     WriteCIFitem(self.fp, '\nloop_  _atom_type_symbol _atom_type_number_in_cell')
     898        #     formula = ''
     899        #     reload(G2mth)
     900        #     for elem in HillSortElements(compDict.keys()):
     901        #         WriteCIFitem(self.fp, '  ' + PutInCol(elem,4) +
     902        #                      G2mth.ValEsd(compDict[elem],-0.009,True))
     903        #         if formula: formula += " "
     904        #         formula += elem
     905        #         if compDict[elem] == Z: continue
     906        #         formula += G2mth.ValEsd(compDict[elem]/Z,-0.009,True)
     907        #     WriteCIFitem(self.fp, '\n# Note that Z affects _cell_formula_sum and _weight')
     908        #     WriteCIFitem(self.fp, '_cell_formula_units_Z',str(Z))
     909        #     WriteCIFitem(self.fp, '_chemical_formula_sum',formula)
     910        #     WriteCIFitem(self.fp, '_chemical_formula_weight',
     911        #                   G2mth.ValEsd(cellmass/Z,-0.09,True))
    712912
    713913        def WriteDistances(phasenam,SymOpList,offsetList,symOpList,G2oprList):
     
    722922            TODO: need a method to select publication flags for distances/angles
    723923            '''
    724             phasedict = self.Phases[phasenam] # pointer to current phase info           
     924            phasedict = self.Phases[phasenam] # pointer to current phase info
    725925            Atoms = phasedict['Atoms']
    726926            generalData = phasedict['General']
     
    731931            cx,ct,cs,cia = phasedict['General']['AtomPtrs']
    732932            cn = ct-1
    733             fpfx = str(phasedict['pId'])+'::Afrac:'       
     933            fpfx = str(phasedict['pId'])+'::Afrac:'
    734934            cfrac = cx+3
    735935            DisAglData = {}
    736936            # create a list of atoms, but skip atoms with zero occupancy
    737937            xyz = []
    738             fpfx = str(phasedict['pId'])+'::Afrac:'       
     938            fpfx = str(phasedict['pId'])+'::Afrac:'
    739939            for i,atom in enumerate(Atoms):
    740940                if self.parmDict.get(fpfx+str(i),atom[cfrac]) == 0.0: continue
     
    776976            except KeyError:        # inside DistAngle for missing atom types in DisAglCtls
    777977                print('**** ERROR - try again but do "Reset" to fill in missing atom types ****')
    778                    
     978
    779979            # loop over interatomic distances for this phase
    780             WriteCIFitem('\n# MOLECULAR GEOMETRY')
    781             WriteCIFitem('loop_' +
     980            WriteCIFitem(self.fp, '\n# MOLECULAR GEOMETRY')
     981            WriteCIFitem(self.fp, 'loop_' +
    782982                         '\n   _geom_bond_atom_site_label_1' +
    783                          '\n   _geom_bond_atom_site_label_2' + 
    784                          '\n   _geom_bond_distance' + 
    785                          '\n   _geom_bond_site_symmetry_1' + 
    786                          '\n   _geom_bond_site_symmetry_2' + 
     983                         '\n   _geom_bond_atom_site_label_2' +
     984                         '\n   _geom_bond_distance' +
     985                         '\n   _geom_bond_site_symmetry_1' +
     986                         '\n   _geom_bond_site_symmetry_2' +
    787987                         '\n   _geom_bond_publ_flag')
    788988
     
    8021002                    else:
    8031003                        line += " yes"
    804                     WriteCIFitem(line)
     1004                    WriteCIFitem(self.fp, line)
    8051005
    8061006            # loop over interatomic angles for this phase
    807             WriteCIFitem('\nloop_' +
    808                          '\n   _geom_angle_atom_site_label_1' + 
    809                          '\n   _geom_angle_atom_site_label_2' + 
    810                          '\n   _geom_angle_atom_site_label_3' + 
    811                          '\n   _geom_angle' + 
     1007            WriteCIFitem(self.fp, '\nloop_' +
     1008                         '\n   _geom_angle_atom_site_label_1' +
     1009                         '\n   _geom_angle_atom_site_label_2' +
     1010                         '\n   _geom_angle_atom_site_label_3' +
     1011                         '\n   _geom_angle' +
    8121012                         '\n   _geom_angle_site_symmetry_1' +
    813                          '\n   _geom_angle_site_symmetry_2' + 
    814                          '\n   _geom_angle_site_symmetry_3' + 
     1013                         '\n   _geom_angle_site_symmetry_2' +
     1014                         '\n   _geom_angle_site_symmetry_3' +
    8151015                         '\n   _geom_angle_publ_flag')
    8161016
     
    8361036                    else:
    8371037                        line += " yes"
    838                     WriteCIFitem(line)
     1038                    WriteCIFitem(self.fp, line)
    8391039
    8401040        def WritePhaseInfo(phasenam,hist=None):
    8411041            'Write out the phase information for the selected phase'
    842             WriteCIFitem('\n# phase info for '+str(phasenam) + ' follows')
    843             phasedict = self.Phases[phasenam] # pointer to current phase info           
    844             WriteCIFitem('_pd_phase_name', phasenam)
     1042            WriteCIFitem(self.fp, '\n# phase info for '+str(phasenam) + ' follows')
     1043            phasedict = self.Phases[phasenam] # pointer to current phase info
     1044            WriteCIFitem(self.fp, '_pd_phase_name', phasenam)
    8451045            cellList,cellSig = self.GetCell(phasenam)
    8461046            defsigL = 3*[-0.00001] + 3*[-0.001] + [-0.01] # significance to use when no sigma
     
    8551055                else:
    8561056                    txt = G2mth.ValEsd(val,min(defsig,prevsig),True)
    857                 WriteCIFitem('_cell_'+lbl,txt)
    858                    
    859             WriteCIFitem('_symmetry_cell_setting',
     1057                WriteCIFitem(self.fp, '_cell_'+lbl,txt)
     1058
     1059            WriteCIFitem(self.fp, '_symmetry_cell_setting',
    8601060                         phasedict['General']['SGData']['SGSys'])
    8611061
     
    8631063            # regularize capitalization and remove trailing H/R
    8641064            spacegroup = spacegroup[0].upper() + spacegroup[1:].lower().rstrip('rh ')
    865             WriteCIFitem('_symmetry_space_group_name_H-M',spacegroup)
     1065            WriteCIFitem(self.fp, '_symmetry_space_group_name_H-M',spacegroup)
    8661066
    8671067            # generate symmetry operations including centering and center of symmetry
    8681068            SymOpList,offsetList,symOpList,G2oprList,G2opcodes = G2spc.AllOps(
    8691069                phasedict['General']['SGData'])
    870             WriteCIFitem('loop_\n    _space_group_symop_id\n    _space_group_symop_operation_xyz')
     1070            WriteCIFitem(self.fp, 'loop_\n    _space_group_symop_id\n    _space_group_symop_operation_xyz')
    8711071            for i,op in enumerate(SymOpList,start=1):
    872                 WriteCIFitem('   {:3d}  {:}'.format(i,op.lower()))
     1072                WriteCIFitem(self.fp, '   {:3d}  {:}'.format(i,op.lower()))
    8731073
    8741074            # loop over histogram(s) used in this phase
     
    8911091
    8921092                if len(histlist) == 0:
    893                     WriteCIFitem('# Note: phase has no associated data')
     1093                    WriteCIFitem(self.fp, '# Note: phase has no associated data')
    8941094
    8951095            # report atom params
    8961096            if phasedict['General']['Type'] in ['nuclear','macromolecular']:        #this needs macromolecular variant, etc!
    897                 WriteAtomsNuclear(phasenam)
     1097                try:
     1098                    self.labellist
     1099                except AttributeError:
     1100                    self.labellist = []
     1101                WriteAtomsNuclear(self.fp, self.Phases[phasenam], phasenam,
     1102                                  self.parmDict, self.sigDict, self.labellist)
    8981103            else:
    8991104                raise Exception,"no export for "+str(phasedict['General']['Type'])+" coordinates implemented"
    9001105            # report cell contents
    901             WriteComposition(phasenam)
     1106            WriteComposition(self.fp, self.Phases[phasenam], phasenam, self.parmDict)
    9021107            if not self.quickmode and phasedict['General']['Type'] == 'nuclear':      # report distances and angles
    9031108                WriteDistances(phasenam,SymOpList,offsetList,symOpList,G2oprList)
    9041109            if 'Map' in phasedict['General'] and 'minmax' in phasedict['General']['Map']:
    905                 WriteCIFitem('\n# Difference density results')
     1110                WriteCIFitem(self.fp, '\n# Difference density results')
    9061111                MinMax = phasedict['General']['Map']['minmax']
    907                 WriteCIFitem('_refine_diff_density_max',G2mth.ValEsd(MinMax[0],-0.009))
    908                 WriteCIFitem('_refine_diff_density_min',G2mth.ValEsd(MinMax[1],-0.009))
    909                
     1112                WriteCIFitem(self.fp, '_refine_diff_density_max',G2mth.ValEsd(MinMax[0],-0.009))
     1113                WriteCIFitem(self.fp, '_refine_diff_density_min',G2mth.ValEsd(MinMax[1],-0.009))
     1114
    9101115        def Yfmt(ndec,val):
    9111116            'Format intensity values'
     
    9131118            out = out.rstrip('0')  # strip zeros to right of decimal
    9141119            return out.rstrip('.')  # and decimal place when not needed
    915            
     1120
    9161121        def WriteReflStat(refcount,hklmin,hklmax,dmin,dmax,nRefSets=1):
    9171122            'Write reflection statistics'
    918             WriteCIFitem('_reflns_number_total', str(refcount))
     1123            WriteCIFitem(self.fp, '_reflns_number_total', str(refcount))
    9191124            if hklmin is not None and nRefSets == 1: # hkl range has no meaning with multiple phases
    920                 WriteCIFitem('_reflns_limit_h_min', str(int(hklmin[0])))
    921                 WriteCIFitem('_reflns_limit_h_max', str(int(hklmax[0])))
    922                 WriteCIFitem('_reflns_limit_k_min', str(int(hklmin[1])))
    923                 WriteCIFitem('_reflns_limit_k_max', str(int(hklmax[1])))
    924                 WriteCIFitem('_reflns_limit_l_min', str(int(hklmin[2])))
    925                 WriteCIFitem('_reflns_limit_l_max', str(int(hklmax[2])))
     1125                WriteCIFitem(self.fp, '_reflns_limit_h_min', str(int(hklmin[0])))
     1126                WriteCIFitem(self.fp, '_reflns_limit_h_max', str(int(hklmax[0])))
     1127                WriteCIFitem(self.fp, '_reflns_limit_k_min', str(int(hklmin[1])))
     1128                WriteCIFitem(self.fp, '_reflns_limit_k_max', str(int(hklmax[1])))
     1129                WriteCIFitem(self.fp, '_reflns_limit_l_min', str(int(hklmin[2])))
     1130                WriteCIFitem(self.fp, '_reflns_limit_l_max', str(int(hklmax[2])))
    9261131            if hklmin is not None:
    927                 WriteCIFitem('_reflns_d_resolution_low  ', G2mth.ValEsd(dmax,-0.009))
    928                 WriteCIFitem('_reflns_d_resolution_high ', G2mth.ValEsd(dmin,-0.009))
     1132                WriteCIFitem(self.fp, '_reflns_d_resolution_low  ', G2mth.ValEsd(dmax,-0.009))
     1133                WriteCIFitem(self.fp, '_reflns_d_resolution_high ', G2mth.ValEsd(dmin,-0.009))
    9291134
    9301135        def WritePowderData(histlbl):
     
    9341139            hId = histblk['hId']
    9351140            pfx = ':' + str(hId) + ':'
    936            
     1141
    9371142            if 'Lam1' in inst:
    9381143                ratio = self.parmDict.get('I(L2)/I(L1)',inst['I(L2)/I(L1)'][1])
     
    9431148                slam2 = self.sigDict.get('Lam2',-0.00009)
    9441149                # always assume Ka1 & Ka2 if two wavelengths are present
    945                 WriteCIFitem('_diffrn_radiation_type','K\\a~1,2~')
    946                 WriteCIFitem('loop_' +
     1150                WriteCIFitem(self.fp, '_diffrn_radiation_type','K\\a~1,2~')
     1151                WriteCIFitem(self.fp, 'loop_' +
    9471152                             '\n   _diffrn_radiation_wavelength' +
    948                              '\n   _diffrn_radiation_wavelength_wt' + 
     1153                             '\n   _diffrn_radiation_wavelength_wt' +
    9491154                             '\n   _diffrn_radiation_wavelength_id')
    950                 WriteCIFitem('  ' + PutInCol(G2mth.ValEsd(lam1,slam1),15)+
    951                              PutInCol('1.0',15) + 
     1155                WriteCIFitem(self.fp, '  ' + PutInCol(G2mth.ValEsd(lam1,slam1),15)+
     1156                             PutInCol('1.0',15) +
    9521157                             PutInCol('1',5))
    953                 WriteCIFitem('  ' + PutInCol(G2mth.ValEsd(lam2,slam2),15)+
     1158                WriteCIFitem(self.fp, '  ' + PutInCol(G2mth.ValEsd(lam2,slam2),15)+
    9541159                             PutInCol(G2mth.ValEsd(ratio,sratio),15)+
    955                              PutInCol('2',5))               
     1160                             PutInCol('2',5))
    9561161            elif 'Lam' in inst:
    9571162                lam1 = self.parmDict.get('Lam',inst['Lam'][1])
    9581163                slam1 = self.sigDict.get('Lam',-0.00009)
    959                 WriteCIFitem('_diffrn_radiation_wavelength',G2mth.ValEsd(lam1,slam1))
     1164                WriteCIFitem(self.fp, '_diffrn_radiation_wavelength',G2mth.ValEsd(lam1,slam1))
    9601165
    9611166            if not oneblock:
    9621167                if not phasebyhistDict.get(histlbl):
    963                     WriteCIFitem('\n# No phases associated with this data set')
     1168                    WriteCIFitem(self.fp, '\n# No phases associated with this data set')
    9641169                else:
    965                     WriteCIFitem('\n# PHASE TABLE')
    966                     WriteCIFitem('loop_' +
    967                                  '\n   _pd_phase_id' + 
    968                                  '\n   _pd_phase_block_id' + 
     1170                    WriteCIFitem(self.fp, '\n# PHASE TABLE')
     1171                    WriteCIFitem(self.fp, 'loop_' +
     1172                                 '\n   _pd_phase_id' +
     1173                                 '\n   _pd_phase_block_id' +
    9691174                                 '\n   _pd_phase_mass_%')
    9701175                    wtFrSum = 0.
     
    9831188                        else:
    9841189                            sig = -0.0001
    985                         WriteCIFitem(
     1190                        WriteCIFitem(self.fp,
    9861191                            '  '+
    9871192                            str(self.Phases[phasenam]['pId']) +
     
    9891194                            '  '+G2mth.ValEsd(wtFr,sig)
    9901195                            )
    991                     WriteCIFitem('loop_' +
     1196                    WriteCIFitem(self.fp, 'loop_' +
    9921197                                 '\n   _gsas_proc_phase_R_F_factor' +
    9931198                                 '\n   _gsas_proc_phase_R_Fsqd_factor' +
     
    9961201                    for phasenam in phasebyhistDict.get(histlbl):
    9971202                        pfx = str(self.Phases[phasenam]['pId'])+':'+str(hId)+':'
    998                         WriteCIFitem(
     1203                        WriteCIFitem(self.fp,
    9991204                            '  '+
    10001205                            '  '+G2mth.ValEsd(histblk[pfx+'Rf']/100.,-.00009) +
     
    10061211                # single phase in this histogram
    10071212                pfx = '0:'+str(hId)+':'
    1008                 WriteCIFitem('_refine_ls_R_F_factor      ','%.5f'%(histblk[pfx+'Rf']/100.))
    1009                 WriteCIFitem('_refine_ls_R_Fsqd_factor   ','%.5f'%(histblk[pfx+'Rf^2']/100.))
    1010                
    1011             WriteCIFitem('_pd_proc_ls_prof_R_factor   ','%.5f'%(histblk['R']/100.))
    1012             WriteCIFitem('_pd_proc_ls_prof_wR_factor  ','%.5f'%(histblk['wR']/100.))
    1013             WriteCIFitem('_gsas_proc_ls_prof_R_B_factor ','%.5f'%(histblk['Rb']/100.))
    1014             WriteCIFitem('_gsas_proc_ls_prof_wR_B_factor','%.5f'%(histblk['wRb']/100.))
    1015             WriteCIFitem('_pd_proc_ls_prof_wR_expected','%.5f'%(histblk['wRmin']/100.))
     1213                WriteCIFitem(self.fp, '_refine_ls_R_F_factor      ','%.5f'%(histblk[pfx+'Rf']/100.))
     1214                WriteCIFitem(self.fp, '_refine_ls_R_Fsqd_factor   ','%.5f'%(histblk[pfx+'Rf^2']/100.))
     1215
     1216            WriteCIFitem(self.fp, '_pd_proc_ls_prof_R_factor   ','%.5f'%(histblk['R']/100.))
     1217            WriteCIFitem(self.fp, '_pd_proc_ls_prof_wR_factor  ','%.5f'%(histblk['wR']/100.))
     1218            WriteCIFitem(self.fp, '_gsas_proc_ls_prof_R_B_factor ','%.5f'%(histblk['Rb']/100.))
     1219            WriteCIFitem(self.fp, '_gsas_proc_ls_prof_wR_B_factor','%.5f'%(histblk['wRb']/100.))
     1220            WriteCIFitem(self.fp, '_pd_proc_ls_prof_wR_expected','%.5f'%(histblk['wRmin']/100.))
    10161221
    10171222            if histblk['Instrument Parameters'][0]['Type'][1][1] == 'X':
    1018                 WriteCIFitem('_diffrn_radiation_probe','x-ray')
     1223                WriteCIFitem(self.fp, '_diffrn_radiation_probe','x-ray')
    10191224                pola = histblk['Instrument Parameters'][0].get('Polariz.')
    10201225                if pola:
     
    10221227                    sig = self.sigDict.get(pfx+'Polariz.',-0.0009)
    10231228                    txt = G2mth.ValEsd(pola[1],sig)
    1024                     WriteCIFitem('_diffrn_radiation_polarisn_ratio',txt)
     1229                    WriteCIFitem(self.fp, '_diffrn_radiation_polarisn_ratio',txt)
    10251230            elif histblk['Instrument Parameters'][0]['Type'][1][1] == 'N':
    1026                 WriteCIFitem('_diffrn_radiation_probe','neutron')
     1231                WriteCIFitem(self.fp, '_diffrn_radiation_probe','neutron')
    10271232            if 'T' in inst['Type'][0]:
    10281233                txt = G2mth.ValEsd(inst['2-theta'][0],-0.009)
    1029                 WriteCIFitem('_pd_meas_2theta_fixed',txt)
     1234                WriteCIFitem(self.fp, '_pd_meas_2theta_fixed',txt)
    10301235
    10311236            # TODO: this will need help from Bob
    10321237            #if not oneblock:
    1033             #WriteCIFitem('\n# SCATTERING FACTOR INFO')
    1034             #WriteCIFitem('loop_  _atom_type_symbol')
     1238            #WriteCIFitem(self.fp, '\n# SCATTERING FACTOR INFO')
     1239            #WriteCIFitem(self.fp, 'loop_  _atom_type_symbol')
    10351240            #if histblk['Instrument Parameters'][0]['Type'][1][1] == 'X':
    1036             #    WriteCIFitem('      _atom_type_scat_dispersion_real')
    1037             #    WriteCIFitem('      _atom_type_scat_dispersion_imag')
     1241            #    WriteCIFitem(self.fp, '      _atom_type_scat_dispersion_real')
     1242            #    WriteCIFitem(self.fp, '      _atom_type_scat_dispersion_imag')
    10381243            #    for lbl in ('a1','a2','a3', 'a4', 'b1', 'b2', 'b3', 'b4', 'c'):
    1039             #        WriteCIFitem('      _atom_type_scat_Cromer_Mann_'+lbl)
     1244            #        WriteCIFitem(self.fp, '      _atom_type_scat_Cromer_Mann_'+lbl)
    10401245            #elif histblk['Instrument Parameters'][0]['Type'][1][1] == 'N':
    1041             #    WriteCIFitem('      _atom_type_scat_length_neutron')
    1042             #WriteCIFitem('      _atom_type_scat_source')
    1043 
    1044             WriteCIFitem('_pd_proc_ls_background_function',FormatBackground(histblk['Background'],histblk['hId']))
     1246            #    WriteCIFitem(self.fp, '      _atom_type_scat_length_neutron')
     1247            #WriteCIFitem(self.fp, '      _atom_type_scat_source')
     1248
     1249            WriteCIFitem(self.fp, '_pd_proc_ls_background_function',FormatBackground(histblk['Background'],histblk['hId']))
    10451250
    10461251            # TODO: this will need help from Bob
    1047             #WriteCIFitem('_exptl_absorpt_process_details','?')
    1048             #WriteCIFitem('_exptl_absorpt_correction_T_min','?')
    1049             #WriteCIFitem('_exptl_absorpt_correction_T_max','?')
     1252            #WriteCIFitem(self.fp, '_exptl_absorpt_process_details','?')
     1253            #WriteCIFitem(self.fp, '_exptl_absorpt_correction_T_min','?')
     1254            #WriteCIFitem(self.fp, '_exptl_absorpt_correction_T_max','?')
    10501255            #C extinction
    10511256            #WRITE(IUCIF,'(A)') '# Extinction correction'
     
    10541259
    10551260            if not oneblock:                 # instrumental profile terms go here
    1056                 WriteCIFitem('_pd_proc_ls_profile_function',
     1261                WriteCIFitem(self.fp, '_pd_proc_ls_profile_function',
    10571262                    FormatInstProfile(histblk["Instrument Parameters"],histblk['hId']))
    10581263
     
    10601265            refprx = '_refln_' # normal
    10611266            # data collection parameters for the powder dataset
    1062            
     1267
    10631268            temperature = histblk['Sample Parameters'].get('Temperature') # G2 uses K
    10641269            if not temperature:
     
    10661271            else:
    10671272                T = G2mth.ValEsd(temperature,-0.009,True) # CIF uses K
    1068             WriteCIFitem('_diffrn_ambient_temperature',T)
     1273            WriteCIFitem(self.fp, '_diffrn_ambient_temperature',T)
    10691274
    10701275            pressure = histblk['Sample Parameters'].get('Pressure') #G2 uses mega-Pascal
     
    10731278            else:
    10741279                P = G2mth.ValEsd(pressure*1000,-0.09,True) # CIF uses kilopascal
    1075             WriteCIFitem('_diffrn_ambient_pressure',P)
    1076 
    1077             WriteCIFitem('\n# STRUCTURE FACTOR TABLE')           
     1280            WriteCIFitem(self.fp, '_diffrn_ambient_pressure',P)
     1281
     1282            WriteCIFitem(self.fp, '\n# STRUCTURE FACTOR TABLE')
    10781283            # compute maximum intensity reflection
    10791284            Imax = 0
     
    10871292                Imax = max(Imax,max(I100))
    10881293
    1089             WriteCIFitem('loop_')
     1294            WriteCIFitem(self.fp, 'loop_')
    10901295            if len(histblk['Reflection Lists'].keys()) > 1:
    1091                 WriteCIFitem('   _pd_refln_phase_id')
    1092             WriteCIFitem('   ' + refprx + 'index_h' +
    1093                          '\n   ' + refprx + 'index_k' + 
    1094                          '\n   ' + refprx + 'index_l' + 
    1095                          '\n   ' + refprx + 'F_squared_meas' + 
    1096                          '\n   ' + refprx + 'F_squared_calc' + 
    1097                          '\n   ' + refprx + 'phase_calc' + 
     1296                WriteCIFitem(self.fp, '   _pd_refln_phase_id')
     1297            WriteCIFitem(self.fp, '   ' + refprx + 'index_h' +
     1298                         '\n   ' + refprx + 'index_k' +
     1299                         '\n   ' + refprx + 'index_l' +
     1300                         '\n   ' + refprx + 'F_squared_meas' +
     1301                         '\n   ' + refprx + 'F_squared_calc' +
     1302                         '\n   ' + refprx + 'phase_calc' +
    10981303                         '\n   _pd_refln_d_spacing')
    10991304            if Imax > 0:
    1100                 WriteCIFitem('   _gsas_i100_meas')
     1305                WriteCIFitem(self.fp, '   _gsas_i100_meas')
    11011306
    11021307            refcount = 0
     
    11351340                    if Imax > 0:
    11361341                        s += PutInCol(G2mth.ValEsd(100.*I100[j]/Imax,-0.09),6)
    1137                     WriteCIFitem("  "+s)
     1342                    WriteCIFitem(self.fp, "  "+s)
    11381343
    11391344            WriteReflStat(refcount,hklmin,hklmax,dmin,dmax,len(histblk['Reflection Lists']))
    1140             WriteCIFitem('\n# POWDER DATA TABLE')
     1345            WriteCIFitem(self.fp, '\n# POWDER DATA TABLE')
    11411346            # is data fixed step? If the step varies by <0.01% treat as fixed step
    11421347            steps = histblk['Data'][0][1:] - histblk['Data'][0][:-1]
     
    11481353            zero = None
    11491354            if fixedstep and 'T' not in inst['Type'][0]: # and not TOF
    1150                 WriteCIFitem('_pd_meas_2theta_range_min', G2mth.ValEsd(histblk['Data'][0][0],-0.00009))
    1151                 WriteCIFitem('_pd_meas_2theta_range_max', G2mth.ValEsd(histblk['Data'][0][-1],-0.00009))
    1152                 WriteCIFitem('_pd_meas_2theta_range_inc', G2mth.ValEsd(steps.sum()/len(steps),-0.00009))
     1355                WriteCIFitem(self.fp, '_pd_meas_2theta_range_min', G2mth.ValEsd(histblk['Data'][0][0],-0.00009))
     1356                WriteCIFitem(self.fp, '_pd_meas_2theta_range_max', G2mth.ValEsd(histblk['Data'][0][-1],-0.00009))
     1357                WriteCIFitem(self.fp, '_pd_meas_2theta_range_inc', G2mth.ValEsd(steps.sum()/len(steps),-0.00009))
    11531358                # zero correct, if defined
    11541359                zerolst = histblk['Instrument Parameters'][0].get('Zero')
     
    11561361                zero = self.parmDict.get('Zero',zero)
    11571362                if zero:
    1158                     WriteCIFitem('_pd_proc_2theta_range_min', G2mth.ValEsd(histblk['Data'][0][0]-zero,-0.00009))
    1159                     WriteCIFitem('_pd_proc_2theta_range_max', G2mth.ValEsd(histblk['Data'][0][-1]-zero,-0.00009))
    1160                     WriteCIFitem('_pd_proc_2theta_range_inc', G2mth.ValEsd(steps.sum()/len(steps),-0.00009))
    1161                
     1363                    WriteCIFitem(self.fp, '_pd_proc_2theta_range_min', G2mth.ValEsd(histblk['Data'][0][0]-zero,-0.00009))
     1364                    WriteCIFitem(self.fp, '_pd_proc_2theta_range_max', G2mth.ValEsd(histblk['Data'][0][-1]-zero,-0.00009))
     1365                    WriteCIFitem(self.fp, '_pd_proc_2theta_range_inc', G2mth.ValEsd(steps.sum()/len(steps),-0.00009))
     1366
    11621367            if zero:
    1163                 WriteCIFitem('_pd_proc_number_of_points', str(len(histblk['Data'][0])))
     1368                WriteCIFitem(self.fp, '_pd_proc_number_of_points', str(len(histblk['Data'][0])))
    11641369            else:
    1165                 WriteCIFitem('_pd_meas_number_of_points', str(len(histblk['Data'][0])))
    1166             WriteCIFitem('\nloop_')
    1167             #            WriteCIFitem('   _pd_proc_d_spacing') # need easy way to get this
     1370                WriteCIFitem(self.fp, '_pd_meas_number_of_points', str(len(histblk['Data'][0])))
     1371            WriteCIFitem(self.fp, '\nloop_')
     1372            #            WriteCIFitem(self.fp, '   _pd_proc_d_spacing') # need easy way to get this
    11681373            if not fixedstep:
    11691374                if zero:
    1170                     WriteCIFitem('   _pd_proc_2theta_corrected')
     1375                    WriteCIFitem(self.fp, '   _pd_proc_2theta_corrected')
    11711376                elif 'T' in inst['Type'][0]: # and not TOF
    1172                     WriteCIFitem('   _pd_meas_time_of_flight')
     1377                    WriteCIFitem(self.fp, '   _pd_meas_time_of_flight')
    11731378                else:
    1174                     WriteCIFitem('   _pd_meas_2theta_scan')
     1379                    WriteCIFitem(self.fp, '   _pd_meas_2theta_scan')
    11751380            # at least for now, always report weights.
    11761381            #if countsdata:
    1177             #    WriteCIFitem('   _pd_meas_counts_total')
     1382            #    WriteCIFitem(self.fp, '   _pd_meas_counts_total')
    11781383            #else:
    1179             WriteCIFitem('   _pd_meas_intensity_total')
    1180             WriteCIFitem('   _pd_calc_intensity_total')
    1181             WriteCIFitem('   _pd_proc_intensity_bkg_calc')
    1182             WriteCIFitem('   _pd_proc_ls_weight')
     1384            WriteCIFitem(self.fp, '   _pd_meas_intensity_total')
     1385            WriteCIFitem(self.fp, '   _pd_calc_intensity_total')
     1386            WriteCIFitem(self.fp, '   _pd_proc_intensity_bkg_calc')
     1387            WriteCIFitem(self.fp, '   _pd_proc_ls_weight')
    11831388            maxY = max(histblk['Data'][1].max(),histblk['Data'][3].max())
    11841389            if maxY < 0: maxY *= -10 # this should never happen, but...
     
    11911396            if DEBUG:
    11921397                print('DEBUG: skipping profile list')
    1193             else:   
     1398            else:
    11941399                for x,yobs,yw,ycalc,ybkg in zip(histblk['Data'][0],
    11951400                                                histblk['Data'][1],
     
    12011406                    else:
    12021407                        yw = 0.0 # show the point is not in use
    1203    
     1408
    12041409                    if fixedstep:
    12051410                        s = ""
     
    12121417                    s += PutInCol(Yfmt(ndec,ybkg),11)
    12131418                    s += PutInCol(Yfmt(ndecSU,yw),9)
    1214                     WriteCIFitem("  "+s)
     1419                    WriteCIFitem(self.fp, "  "+s)
    12151420
    12161421        def WriteSingleXtalData(histlbl):
     
    12211426            refprx = '_refln_' # normal
    12221427
    1223             WriteCIFitem('\n# STRUCTURE FACTOR TABLE')           
    1224             WriteCIFitem('loop_' +
    1225                          '\n   ' + refprx + 'index_h' + 
    1226                          '\n   ' + refprx + 'index_k' + 
     1428            WriteCIFitem(self.fp, '\n# STRUCTURE FACTOR TABLE')
     1429            WriteCIFitem(self.fp, 'loop_' +
     1430                         '\n   ' + refprx + 'index_h' +
     1431                         '\n   ' + refprx + 'index_k' +
    12271432                         '\n   ' + refprx + 'index_l' +
    1228                          '\n   ' + refprx + 'F_squared_meas' + 
    1229                          '\n   ' + refprx + 'F_squared_sigma' + 
    1230                          '\n   ' + refprx + 'F_squared_calc' + 
     1433                         '\n   ' + refprx + 'F_squared_meas' +
     1434                         '\n   ' + refprx + 'F_squared_sigma' +
     1435                         '\n   ' + refprx + 'F_squared_calc' +
    12311436                         '\n   ' + refprx + 'phase_calc'
    12321437                         )
     
    12621467                dmax = max(dmax,ref[4])
    12631468                dmin = min(dmin,ref[4])
    1264                 WriteCIFitem(s)
     1469                WriteCIFitem(self.fp, s)
    12651470            if not self.quickmode: # statistics only in a full CIF
    12661471                WriteReflStat(refcount,hklmin,hklmax,dmin,dmax)
     
    12701475                extType,extModel,extParms = self.Phases[phasenam]['Histograms'][histlbl]['Extinction']
    12711476                if extModel != 'None':
    1272                     WriteCIFitem('# Extinction scaled by 1.e5')
    1273                     WriteCIFitem('_refine_ls_extinction_method','Becker-Coppens %s %s'%(extModel,extType))
     1477                    WriteCIFitem(self.fp, '# Extinction scaled by 1.e5')
     1478                    WriteCIFitem(self.fp, '_refine_ls_extinction_method','Becker-Coppens %s %s'%(extModel,extType))
    12741479                    sig = -1.e-3
    12751480                    if extModel == 'Primary':
     
    12981503                            sig = self.sigDict[phfx+'Es']*1.e5
    12991504                        text += G2mth.ValEsd(parm,sig)
    1300                     WriteCIFitem('_refine_ls_extinction_coef',text)
    1301                     WriteCIFitem('_refine_ls_extinction_expression','Becker & Coppens (1974). Acta Cryst. A30, 129-147')
    1302 
    1303                 WriteCIFitem('_refine_ls_wR_factor_gt    ','%.4f'%(histblk['wR']/100.))
    1304                 WriteCIFitem('_refine_ls_R_factor_gt     ','%.4f'%(histblk[hfx+'Rf']/100.))
    1305                 WriteCIFitem('_refine_ls_R_Fsqd_factor   ','%.4f'%(histblk[hfx+'Rf^2']/100.))
     1505                    WriteCIFitem(self.fp, '_refine_ls_extinction_coef',text)
     1506                    WriteCIFitem(self.fp, '_refine_ls_extinction_expression','Becker & Coppens (1974). Acta Cryst. A30, 129-147')
     1507
     1508                WriteCIFitem(self.fp, '_refine_ls_wR_factor_gt    ','%.4f'%(histblk['wR']/100.))
     1509                WriteCIFitem(self.fp, '_refine_ls_R_factor_gt     ','%.4f'%(histblk[hfx+'Rf']/100.))
     1510                WriteCIFitem(self.fp, '_refine_ls_R_Fsqd_factor   ','%.4f'%(histblk[hfx+'Rf^2']/100.))
    13061511        def EditAuthor(event=None):
    13071512            'dialog to edit the CIF author info'
     
    13291534            lbllist = []
    13301535            for hist in self.Histograms:
    1331                 if hist.startswith("PWDR"): 
     1536                if hist.startswith("PWDR"):
    13321537                    key2 = "Sample Parameters"
    13331538                    d = self.Histograms[hist][key2]
    1334                 elif hist.startswith("HKLF"): 
     1539                elif hist.startswith("HKLF"):
    13351540                    key2 = "Instrument Parameters"
    13361541                    d = self.Histograms[hist][key2][0]
    1337                    
     1542
    13381543                lbllist.append(hist)
    13391544                dictlist.append(d)
     
    13491554                header="Edit instrument names. Note that a non-blank\nname is required for all histograms",
    13501555                CopyButton=True,ASCIIonly=True)
    1351            
     1556
    13521557        def EditRanges(event):
    13531558            '''Edit the bond distance/angle search range; phase is determined from
     
    13591564            dlg = G2G.DisAglDialog(
    13601565                self.G2frame,
    1361                 phasedict['General']['DisAglCtls'], # edited 
     1566                phasedict['General']['DisAglCtls'], # edited
    13621567                phasedict['General'], # defaults
    13631568                )
     
    13651570                phasedict['General']['DisAglCtls'] = dlg.GetData()
    13661571            dlg.Destroy()
    1367            
     1572
    13681573        def EditCIFDefaults():
    13691574            '''Fills the CIF Defaults window with controls for editing various CIF export
     
    13821587            cpnl = wxscroll.ScrolledPanel(self.cifdefs,size=(300,300))
    13831588            cbox = wx.BoxSizer(wx.VERTICAL)
    1384             G2G.HorizontalLine(cbox,cpnl)         
     1589            G2G.HorizontalLine(cbox,cpnl)
    13851590            cbox.Add(
    13861591                CIFtemplateSelect(self.cifdefs,
     
    13911596                0,wx.EXPAND|wx.ALIGN_LEFT|wx.ALL)
    13921597            for phasenam in sorted(self.Phases.keys()):
    1393                 G2G.HorizontalLine(cbox,cpnl)         
     1598                G2G.HorizontalLine(cbox,cpnl)
    13941599                title = 'Phase '+phasenam
    1395                 phasedict = self.Phases[phasenam] # pointer to current phase info           
     1600                phasedict = self.Phases[phasenam] # pointer to current phase info
    13961601                cbox.Add(
    13971602                    CIFtemplateSelect(self.cifdefs,
     
    14021607                    0,wx.EXPAND|wx.ALIGN_LEFT|wx.ALL)
    14031608                cpnl.SetSizer(cbox)
    1404                 if phasedict['General']['Type'] == 'nuclear': 
     1609                if phasedict['General']['Type'] == 'nuclear':
    14051610                    but = wx.Button(cpnl, wx.ID_ANY,'Edit distance/angle ranges')
    14061611                    cbox.Add(but,0,wx.ALIGN_LEFT,0)
     
    14091614                    but.Bind(wx.EVT_BUTTON,EditRanges)     # phase bond/angle ranges
    14101615                    but = wx.Button(cpnl, wx.ID_ANY,'Set distance/angle publication flags')
    1411                     but.phase = phasenam  # set a pointer to current phase info     
     1616                    but.phase = phasenam  # set a pointer to current phase info
    14121617                    but.Bind(wx.EVT_BUTTON,SelectDisAglFlags)     # phase bond/angle ranges
    14131618                    cbox.Add(but,0,wx.ALIGN_LEFT,0)
    14141619                cbox.Add((-1,2))
    14151620            for i in sorted(self.powderDict.keys()):
    1416                 G2G.HorizontalLine(cbox,cpnl)         
     1621                G2G.HorizontalLine(cbox,cpnl)
    14171622                hist = self.powderDict[i]
    14181623                histblk = self.Histograms[hist]
     
    14261631                    0,wx.EXPAND|wx.ALIGN_LEFT|wx.ALL)
    14271632            for i in sorted(self.xtalDict.keys()):
    1428                 G2G.HorizontalLine(cbox,cpnl)         
     1633                G2G.HorizontalLine(cbox,cpnl)
    14291634                hist = self.xtalDict[i]
    14301635                histblk = self.Histograms[hist]
     
    14551660            vbox.Fit(self.cifdefs)
    14561661            self.cifdefs.Layout()
    1457            
     1662
    14581663        def OnToggleButton(event):
    14591664            'Respond to press of ToggleButton in SelectDisAglFlags'
    14601665            but = event.GetEventObject()
    1461             if but.GetValue():                   
     1666            if but.GetValue():
    14621667                but.DisAglSel[but.key] = True
    14631668            else:
     
    14701675        def keepFalse(event):
    14711676            event.GetEventObject().SetValue(False)
    1472                
     1677
    14731678        def SelectDisAglFlags(event):
    14741679            'Select Distance/Angle use flags for the selected phase'
     
    14881693            # create a list of atoms, but skip atoms with zero occupancy
    14891694            xyz = []
    1490             fpfx = str(phasedict['pId'])+'::Afrac:'       
     1695            fpfx = str(phasedict['pId'])+'::Afrac:'
    14911696            for i,atom in enumerate(phasedict['Atoms']):
    14921697                if self.parmDict.get(fpfx+str(i),atom[cfrac]) == 0.0: continue
     
    15421747            wx.EndBusyCursor()
    15431748            txt.SetLabel('Set publication flags for distances and angles in\nphase '+phasenam)
    1544             vbox.Add((5,5)) 
     1749            vbox.Add((5,5))
    15451750            vbox.Add(wx.StaticText(dlg,wx.ID_ANY,
    15461751                                   'The default is to flag all distances and angles as to be'+
     
    15571762            hbox.Add(but)
    15581763            but.SetValue(True)
    1559             G2G.HorizontalLine(vbox,dlg)         
    1560            
     1764            G2G.HorizontalLine(vbox,dlg)
     1765
    15611766            cpnl = wxscroll.ScrolledPanel(dlg,size=(400,300))
    15621767            cbox = wx.BoxSizer(wx.VERTICAL)
     
    15741779                    dbox.Add(wx.StaticText(cpnl,wx.ID_ANY,AtomLabels[D[0]]),
    15751780                             (i+1,0)
    1576                              )                   
     1781                             )
    15771782                    dbox.Add(wx.StaticText(cpnl,wx.ID_ANY,sym),
    15781783                             (i+1,1)
     
    16041809                                 )
    16051810                cbox.Add(dbox)
    1606                 G2G.HorizontalLine(cbox,cpnl)         
     1811                G2G.HorizontalLine(cbox,cpnl)
    16071812            cpnl.SetSizer(cbox)
    16081813            cpnl.SetAutoLayout(1)
     
    16221827            vbox.Fit(dlg)
    16231828            dlg.Layout()
    1624            
     1829
    16251830            dlg.CenterOnParent()
    16261831            dlg.ShowModal()
    1627            
     1832
    16281833#=================================================================================
    16291834#===== end of function definitions for _Exporter =================================
     
    16311836        # make sure required information is present
    16321837        self.CIFdate = dt.datetime.strftime(dt.datetime.now(),"%Y-%m-%dT%H:%M")
    1633         if not self.CIFname: # Get a name for the CIF. If not defined, use the GPX name (save, if that is needed). 
     1838        if not self.CIFname: # Get a name for the CIF. If not defined, use the GPX name (save, if that is needed).
    16341839            if not self.G2frame.GSASprojectfile:
    16351840                self.G2frame.OnFileSaveas(None)
     
    16531858            pass
    16541859        #=================================================================
    1655         # write quick CIFs 
     1860        # write quick CIFs
    16561861        #=================================================================
    16571862        if phaseOnly: #====Phase only CIF ================================
     
    16621867            self.Write(' ')
    16631868            self.Write(70*'#')
    1664             WriteCIFitem('data_'+self.CIFname)
     1869            WriteCIFitem(self.fp, 'data_'+self.CIFname)
    16651870            #phaseblk = self.Phases[phaseOnly] # pointer to current phase info
    16661871            # report the phase info
     
    16801885            self.Write(70*'#')
    16811886            #phasenam = self.Phases.keys()[0]
    1682             WriteCIFitem('data_'+self.CIFname)
     1887            WriteCIFitem(self.fp, 'data_'+self.CIFname)
    16831888            #print 'phasenam',phasenam
    16841889            #phaseblk = self.Phases[phasenam] # pointer to current phase info
    16851890            #instnam = instnam.replace(' ','')
    1686             #WriteCIFitem('_pd_block_id',
     1891            #WriteCIFitem(self.fp, '_pd_block_id',
    16871892            #             str(self.CIFdate) + "|" + str(self.CIFname) + "|" +
    16881893            #             str(self.shortauthorname) + "|" + instnam + '|' + histname)
     
    16971902            #MD = FormatHAPpo(phasenam)
    16981903            #if SH and MD:
    1699             #    WriteCIFitem('_pd_proc_ls_pref_orient_corr', SH + '\n' + MD)
     1904            #    WriteCIFitem(self.fp, '_pd_proc_ls_pref_orient_corr', SH + '\n' + MD)
    17001905            #elif SH or MD:
    1701             #    WriteCIFitem('_pd_proc_ls_pref_orient_corr', SH + MD)
     1906            #    WriteCIFitem(self.fp, '_pd_proc_ls_pref_orient_corr', SH + MD)
    17021907            #else:
    1703             #    WriteCIFitem('_pd_proc_ls_pref_orient_corr', 'none')
     1908            #    WriteCIFitem(self.fp, '_pd_proc_ls_pref_orient_corr', 'none')
    17041909            # report profile, since one-block: include both histogram and phase info
    1705             #WriteCIFitem('_pd_proc_ls_profile_function',
     1910            #WriteCIFitem(self.fp, '_pd_proc_ls_profile_function',
    17061911            #    FormatInstProfile(histblk["Instrument Parameters"],histblk['hId'])
    17071912            #        +'\n'+FormatPhaseProfile(phasenam))
     
    17131918        #elif IncludeOnlyHist is not None: # truncate histogram list to only selected (for sequential export)
    17141919        #    self.Histograms = {IncludeOnlyHist:self.Histograms[IncludeOnlyHist]}
    1715        
     1920
    17161921        #===============================================================================
    17171922        # the export process for a full CIF starts here
     
    17641969                self.ifHKLF = True
    17651970                key2 = "Instrument Parameters"
    1766                 d = self.Histograms[hist][key2][0]                   
     1971                d = self.Histograms[hist][key2][0]
    17671972            instrname = d.get(key3)
    17681973            if instrname is None:
     
    17791984            #    )
    17801985            if not EditInstNames(): return
    1781            
     1986
    17821987        # check for a distance-angle range search range for each phase
    17831988        for phasenam in sorted(self.Phases.keys()):
    17841989            #i = self.Phases[phasenam]['pId']
    1785             phasedict = self.Phases[phasenam] # pointer to current phase info           
     1990            phasedict = self.Phases[phasenam] # pointer to current phase info
    17861991            if 'DisAglCtls' not in phasedict['General']:
    17871992                dlg = G2G.DisAglDialog(
     
    17992004        default = 0
    18002005        for hist in self.Histograms:
    1801             if hist.startswith("PWDR"): 
     2006            if hist.startswith("PWDR"):
    18022007                key2 = "Sample Parameters"
    18032008                T = self.Histograms[hist][key2].get('Temperature')
     
    18252030            for hist in self.Histograms:
    18262031                histblk = self.Histograms[hist]
    1827                 if hist.startswith("PWDR"): 
     2032                if hist.startswith("PWDR"):
    18282033                    instnam = histblk["Sample Parameters"]['InstrName']
    18292034                    break # ignore all but 1st data histogram
    1830                 elif hist.startswith("HKLF"): 
     2035                elif hist.startswith("HKLF"):
    18312036                    instnam = histblk["Instrument Parameters"][0]['InstrName']
    18322037                    break # ignore all but 1st data histogram
     
    18582063            hist = self.histnam[0]
    18592064            self.CIFname = hist[5:40].replace(' ','')
    1860             WriteCIFitem('data_'+self.CIFname)
     2065            WriteCIFitem(self.fp, 'data_'+self.CIFname)
    18612066            if hist.startswith("PWDR"):
    18622067                WritePowderData(hist)
     
    18672072        elif oneblock:
    18682073            #====Single block, data & phase CIF ===================================
    1869             WriteCIFitem('data_'+self.CIFname)
    1870             if phasenam is None: # if not already selected, select the first phase (should be one) 
     2074            WriteCIFitem(self.fp, 'data_'+self.CIFname)
     2075            if phasenam is None: # if not already selected, select the first phase (should be one)
    18712076                phasenam = self.Phases.keys()[0]
    18722077            #print 'phasenam',phasenam
    18732078            #phaseblk = self.Phases[phasenam] # pointer to current phase info
    18742079            instnam = instnam.replace(' ','')
    1875             WriteCIFitem('_pd_block_id',
     2080            WriteCIFitem(self.fp, '_pd_block_id',
    18762081                         str(self.CIFdate) + "|" + str(self.CIFname) + "|" +
    18772082                         str(self.shortauthorname) + "|" + instnam)
     
    18872092                MD = FormatHAPpo(phasenam)
    18882093                if SH and MD:
    1889                     WriteCIFitem('_pd_proc_ls_pref_orient_corr', SH + '\n' + MD)
     2094                    WriteCIFitem(self.fp, '_pd_proc_ls_pref_orient_corr', SH + '\n' + MD)
    18902095                elif SH or MD:
    1891                     WriteCIFitem('_pd_proc_ls_pref_orient_corr', SH + MD)
     2096                    WriteCIFitem(self.fp, '_pd_proc_ls_pref_orient_corr', SH + MD)
    18922097                else:
    1893                     WriteCIFitem('_pd_proc_ls_pref_orient_corr', 'none')
     2098                    WriteCIFitem(self.fp, '_pd_proc_ls_pref_orient_corr', 'none')
    18942099                    # report profile, since one-block: include both histogram and phase info
    1895                 WriteCIFitem('_pd_proc_ls_profile_function',
     2100                WriteCIFitem(self.fp, '_pd_proc_ls_profile_function',
    18962101                    FormatInstProfile(histblk["Instrument Parameters"],histblk['hId'])
    18972102                    +'\n'+FormatPhaseProfile(phasenam))
     
    19152120            step = 1
    19162121            dlg.Update(step,"Exporting overall section")
    1917             WriteCIFitem('\ndata_'+self.CIFname+'_publ')
     2122            WriteCIFitem(self.fp, '\ndata_'+self.CIFname+'_publ')
    19182123            WriteAudit()
    1919             WriteCIFitem('_pd_block_id',
     2124            WriteCIFitem(self.fp, '_pd_block_id',
    19202125                         str(self.CIFdate) + "|" + str(self.CIFname) + "|" +
    19212126                         str(self.shortauthorname) + "|Overall")
     
    19232128            # ``template_publ.cif`` or a modified version
    19242129            # overall info
    1925             WriteCIFitem('data_'+str(self.CIFname)+'_overall')
     2130            WriteCIFitem(self.fp, 'data_'+str(self.CIFname)+'_overall')
    19262131            WriteOverall()
    19272132            #============================================================
    1928             WriteCIFitem('# POINTERS TO PHASE AND HISTOGRAM BLOCKS')
     2133            WriteCIFitem(self.fp, '# POINTERS TO PHASE AND HISTOGRAM BLOCKS')
    19292134            datablockidDict = {} # save block names here -- N.B. check for conflicts between phase & hist names (unlikely!)
    19302135            # loop over phase blocks
    19312136            if len(self.Phases) > 1:
    19322137                loopprefix = ''
    1933                 WriteCIFitem('loop_   _pd_phase_block_id')
     2138                WriteCIFitem(self.fp, 'loop_   _pd_phase_block_id')
    19342139            else:
    19352140                loopprefix = '_pd_phase_block_id'
     
    19392144                datablockidDict[phasenam] = (str(self.CIFdate) + "|" + str(self.CIFname) + "|" +
    19402145                             'phase_'+ str(i) + '|' + str(self.shortauthorname))
    1941                 WriteCIFitem(loopprefix,datablockidDict[phasenam])
     2146                WriteCIFitem(self.fp, loopprefix,datablockidDict[phasenam])
    19422147            # loop over data blocks
    19432148            if len(self.powderDict) + len(self.xtalDict) > 1:
    19442149                loopprefix = ''
    1945                 WriteCIFitem('loop_   _pd_block_diffractogram_id')
     2150                WriteCIFitem(self.fp, 'loop_   _pd_block_diffractogram_id')
    19462151            else:
    19472152                loopprefix = '_pd_block_diffractogram_id'
     
    19552160                                         str(self.shortauthorname) + "|" +
    19562161                                         instnam + "_hist_"+str(j))
    1957                 WriteCIFitem(loopprefix,datablockidDict[hist])
     2162                WriteCIFitem(self.fp, loopprefix,datablockidDict[hist])
    19582163            for i in sorted(self.xtalDict.keys()):
    19592164                hist = self.xtalDict[i]
     
    19652170                                         str(self.shortauthorname) + "|" +
    19662171                                         instnam + "_hist_"+str(i))
    1967                 WriteCIFitem(loopprefix,datablockidDict[hist])
     2172                WriteCIFitem(self.fp, loopprefix,datablockidDict[hist])
    19682173            #============================================================
    19692174            # loop over phases, exporting them
     
    19732178                dlg.Update(step,"Exporting phase "+phasenam+' (#'+str(j+1)+')')
    19742179                i = self.Phases[phasenam]['pId']
    1975                 WriteCIFitem('\ndata_'+self.CIFname+"_phase_"+str(i))
    1976                 WriteCIFitem('# Information for phase '+str(i))
    1977                 WriteCIFitem('_pd_block_id',datablockidDict[phasenam])
     2180                WriteCIFitem(self.fp, '\ndata_'+self.CIFname+"_phase_"+str(i))
     2181                WriteCIFitem(self.fp, '# Information for phase '+str(i))
     2182                WriteCIFitem(self.fp, '_pd_block_id',datablockidDict[phasenam])
    19782183                # report the phase
    19792184                writeCIFtemplate(self.Phases[phasenam]['General'],'phase',phasenam) # write phase template
     
    19842189                    MD = FormatHAPpo(phasenam)
    19852190                    if SH and MD:
    1986                         WriteCIFitem('_pd_proc_ls_pref_orient_corr', SH + '\n' + MD)
     2191                        WriteCIFitem(self.fp, '_pd_proc_ls_pref_orient_corr', SH + '\n' + MD)
    19872192                    elif SH or MD:
    1988                         WriteCIFitem('_pd_proc_ls_pref_orient_corr', SH + MD)
     2193                        WriteCIFitem(self.fp, '_pd_proc_ls_pref_orient_corr', SH + MD)
    19892194                    else:
    1990                         WriteCIFitem('_pd_proc_ls_pref_orient_corr', 'none')
     2195                        WriteCIFitem(self.fp, '_pd_proc_ls_pref_orient_corr', 'none')
    19912196                # report sample profile terms
    19922197                PP = FormatPhaseProfile(phasenam)
    19932198                if PP:
    1994                     WriteCIFitem('_pd_proc_ls_profile_function',PP)
     2199                    WriteCIFitem(self.fp, '_pd_proc_ls_profile_function',PP)
    19952200
    19962201            #============================================================
     
    19992204                hist = self.powderDict[i]
    20002205                histblk = self.Histograms[hist]
    2001                 if hist.startswith("PWDR"): 
     2206                if hist.startswith("PWDR"):
    20022207                    step += 1
    20032208                    dlg.Update(step,"Exporting "+hist.strip())
    2004                     WriteCIFitem('\ndata_'+self.CIFname+"_pwd_"+str(i))
     2209                    WriteCIFitem(self.fp, '\ndata_'+self.CIFname+"_pwd_"+str(i))
    20052210                    #instnam = histblk["Sample Parameters"]['InstrName']
    20062211                    # report instrumental profile terms
    2007                     WriteCIFitem('_pd_proc_ls_profile_function',
     2212                    WriteCIFitem(self.fp, '_pd_proc_ls_profile_function',
    20082213                        FormatInstProfile(histblk["Instrument Parameters"],histblk['hId']))
    2009                     WriteCIFitem('# Information for histogram '+str(i)+': '+hist)
    2010                     WriteCIFitem('_pd_block_id',datablockidDict[hist])
     2214                    WriteCIFitem(self.fp, '# Information for histogram '+str(i)+': '+hist)
     2215                    WriteCIFitem(self.fp, '_pd_block_id',datablockidDict[hist])
    20112216                    histprm = self.Histograms[hist]["Sample Parameters"]
    20122217                    writeCIFtemplate(histprm,'powder',histprm['InstrName']) # powder template
     
    20152220                hist = self.xtalDict[i]
    20162221                histblk = self.Histograms[hist]
    2017                 if hist.startswith("HKLF"): 
     2222                if hist.startswith("HKLF"):
    20182223                    step += 1
    20192224                    dlg.Update(step,"Exporting "+hist.strip())
    2020                     WriteCIFitem('\ndata_'+self.CIFname+"_sx_"+str(i))
     2225                    WriteCIFitem(self.fp, '\ndata_'+self.CIFname+"_sx_"+str(i))
    20212226                    #instnam = histblk["Instrument Parameters"][0]['InstrName']
    2022                     WriteCIFitem('# Information for histogram '+str(i)+': '+hist)
    2023                     WriteCIFitem('_pd_block_id',datablockidDict[hist])
     2227                    WriteCIFitem(self.fp, '# Information for histogram '+str(i)+': '+hist)
     2228                    WriteCIFitem(self.fp, '_pd_block_id',datablockidDict[hist])
    20242229                    histprm = self.Histograms[hist]["Instrument Parameters"][0]
    20252230                    writeCIFtemplate(histprm,'single',histprm['InstrName']) # single crystal template
     
    20282233            dlg.Destroy()
    20292234
    2030         WriteCIFitem('#--' + 15*'eof--' + '#')
     2235        WriteCIFitem(self.fp, '#--' + 15*'eof--' + '#')
    20312236        #self.CloseFile()
    20322237        print("...export completed")
     
    20472252            )
    20482253        self.exporttype = ['project']
    2049        
     2254
    20502255    def Exporter(self,event=None):
    20512256        self._Exporter(event=event)
     
    20662271    #         print('CIF written to file '+self.fullpath)
    20672272    #     self.CloseFile()
    2068        
     2273
    20692274class ExportPhaseCIF(ExportCIF):
    20702275    '''Used to create a simple CIF with one phase. Uses exact same code as
     
    21552360            print('CIF written to file '+self.fullpath)
    21562361        self.CloseFile()
    2157        
     2362
    21582363class ExportHKLCIF(ExportCIF):
    21592364    '''Used to create a simple CIF containing diffraction data only. Uses exact same code as
     
    21872392            ): return
    21882393        self._Exporter(event=event,histOnly=self.histnam[0])
    2189                
     2394
    21902395#===============================================================================
    21912396# misc CIF utilities
     
    22002405    :param str fil: file name of CIF dictionary, will usually end
    22012406      in .dic
    2202     :returns: the dict with the definitions 
     2407    :returns: the dict with the definitions
    22032408    '''
    22042409    import CifFile as cif # PyCifRW from James Hester
     
    22382443    cif_core.dic and/or cif_pd.dic are read.
    22392444
    2240     :returns: the dict with the definitions 
     2445    :returns: the dict with the definitions
    22412446    '''
    22422447    cifdic = {}
     
    23012506    :returns: cifblk, loopstructure where cifblk is a dict with
    23022507      CIF items and loopstructure is a list of lists that defines
    2303       which items are in which loops. 
     2508      which items are in which loops.
    23042509    '''
    23052510    blk = cf.keys()[0] # assume templates are a single CIF block, use the 1st
     
    23322537      Defaults to 'Template'
    23332538
    2334     :returns: the newly created PyCifRW CIF object 
     2539    :returns: the newly created PyCifRW CIF object
    23352540    '''
    23362541
     
    23542559    # create a CIF and add the block
    23552560    newcf = cif.CifFile()
    2356     newcf[blockname] = newblk   
     2561    newcf[blockname] = newblk
    23572562    return newcf
    23582563
     
    23622567    placed in cifblk. If the CIF is saved as a file, the name of that file
    23632568    is saved as ``self.newfile``.
    2364    
     2569
    23652570    :param wx.Frame parent: parent frame or None
    23662571    :param cifblk: dict or PyCifRW block containing values for each CIF item
     
    23782583      Note that the values for each looped CIF item, such as _a,
    23792584      are contained in a list, for example as cifblk["_a"]
    2380      
    2381     :param str defaultname: specifies the default file name to be used for 
     2585
     2586    :param str defaultname: specifies the default file name to be used for
    23822587      saving the CIF.
    23832588    '''
     
    23872592        self.loopstructure = loopstructure
    23882593        self.newfile = None
    2389         self.defaultname = defaultname       
     2594        self.defaultname = defaultname
    23902595        global CIFdic  # once this is loaded, keep it around
    23912596        if CIFdic is None:
     
    24192624    def Post(self):
    24202625        '''Display the dialog
    2421        
     2626
    24222627        :returns: True unless Cancel has been pressed.
    24232628        '''
     
    25042709            but = wx.Button(self,wx.ID_ANY,"Add row")
    25052710            self.AddDict[but]=lnum
    2506            
    2507             hbox.Add(but)           
     2711
     2712            hbox.Add(but)
    25082713            but.Bind(wx.EVT_BUTTON,self.OnAddRow)
    25092714            fbox = wx.GridBagSizer(0, 0)
     
    25412746            line = wx.StaticLine(self,wx.ID_ANY, size=(-1,3), style=wx.LI_HORIZONTAL)
    25422747            vbox.Add(line, 0, wx.EXPAND|wx.ALIGN_CENTER|wx.ALL, 10)
    2543                
     2748
    25442749        # post the non-looped CIF items
    25452750        for item in sorted(self.cifblk.keys()):
     
    25712776        self.DoLayout after the current operations are complete using
    25722777        CallAfter. This is called only once, according to flag
    2573         self.LayoutCalled, which is cleared in self.DoLayout. 
     2778        self.LayoutCalled, which is cleared in self.DoLayout.
    25742779        '''
    25752780        if self.LayoutCalled: return # call already queued
     
    26162821            for btn in self.parentOKbuttons:
    26172822                btn.Disable()
    2618        
     2823
    26192824    def CIFEntryWidget(self,dct,item,dataname):
    26202825        '''Create an entry widget for a CIF item. Use a validated entry for numb values
     
    26222827        At present this does not allow entry of the special CIF values of "." and "?" for
    26232828        numerical values and highlights them as invalid.
    2624         Use a selection widget when there are specific enumerated values for a string.       
     2829        Use a selection widget when there are specific enumerated values for a string.
    26252830        '''
    26262831        if self.cifdic.get(dataname):
     
    26582863class CIFtemplateSelect(wx.BoxSizer):
    26592864    '''Create a set of buttons to show, select and edit a CIF template
    2660    
     2865
    26612866    :param frame: wx.Frame object of parent
    26622867    :param panel: wx.Panel object where widgets should be placed
     
    26662871      "CIF_template" will be used to store either a list or a string.
    26672872      If a list, it will contain a dict and a list defining loops. If
    2668       an str, it will contain a file name.   
     2873      an str, it will contain a file name.
    26692874    :param function repaint: reference to a routine to be called to repaint
    26702875      the frame after a change has been made
    26712876    :param str title: A line of text to show at the top of the window
    2672     :param str defaultname: specifies the default file name to be used for 
     2877    :param str defaultname: specifies the default file name to be used for
    26732878      saving the CIF.
    26742879    '''
     
    26862891        else:
    26872892            self.defaultname = ''
    2688            
     2893
    26892894        txt = wx.StaticText(panel,wx.ID_ANY,title)
    26902895        self.Add(txt,0,wx.ALIGN_CENTER)
     
    27762981            self.repaint() #EditCIFDefaults() # note that this does a dlg.Destroy()
    27772982        else:
    2778             dlg.Destroy()       
     2983            dlg.Destroy()
    27792984
    27802985#===============================================================================
Note: See TracChangeset for help on using the changeset viewer.