Changeset 3011
- Timestamp:
- Aug 16, 2017 4:16:55 PM (5 years ago)
- Location:
- trunk
- Files:
-
- 1 added
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/GSASIIscriptable.py
r3009 r3011 33 33 from __future__ import division, print_function # needed? 34 34 import os.path as ospath 35 import datetime as dt 35 36 import sys 36 37 import cPickle … … 377 378 generalData['Mass'] = G2mth.getMass(generalData) 378 379 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 379 390 def make_empty_project(author=None, filename=None): 380 391 """Creates an dictionary in the style of GSASIIscriptable, for an empty … … 1485 1496 return G2obj.PhaseRanIdLookup[self.ranId] 1486 1497 1487 def cell_dict(self):1498 def get_cell(self): 1488 1499 """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' 1490 1501 1491 1502 :returns: a dict""" 1492 1503 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 1496 1590 1497 1591 def set_refinements(self, refs): … … 1682 1776 1683 1777 1778 # TODO SUBPARSERS 1779 1684 1780 def create(*args): 1685 1781 """The create subcommand. 1686 1782 1687 1783 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) 1689 1795 1690 1796 isPhase = False … … 1724 1830 def dump(*args): 1725 1831 """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: 1742 1846 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: 1745 1850 proj, nameList = LoadDictFromProjFile(fname) 1746 1851 print("file:", fname) … … 1751 1856 else: 1752 1857 proj = G2Project(fname) 1753 if histograms:1858 if results.histograms: 1754 1859 hists = proj.histograms() 1755 1860 for h in hists: 1756 1861 print(fname, "hist", h.id, h.name) 1757 if phases:1862 if results.phases: 1758 1863 phase_list = proj.phases() 1759 1864 for p in phase_list: … … 1776 1881 """The refine subcommand""" 1777 1882 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) 1779 1892 1780 1893 … … 1787 1900 """The export subcommand""" 1788 1901 # 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) 1790 1906 1791 1907 … … 1799 1915 1800 1916 def 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` 1802 1935 ''' 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 1816 1960 # arg = sys.argv 1817 1961 # print(arg) -
trunk/exports/G2export_CIF.py
r3000 r3011 15 15 entire project in a complete CIF intended for submission as a 16 16 publication. In addition, there are three subclasses of :class:`ExportCIF`: 17 :class:`ExportProjectCIF`, 17 :class:`ExportProjectCIF`, 18 18 :class:`ExportPhaseCIF` and :class:`ExportDataCIF` where extra parameters 19 19 for the _Exporter() determine if a project, single phase or data set are written. … … 43 43 CIFdic = None 44 44 45 # Refactored over here to allow access by GSASIIscriptable.py 46 def 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 70 def 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 174 def 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 198 def 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 210 def 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 218 def 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 45 301 class ExportCIF(G2IO.ExportBaseclass): 46 302 '''Base class for CIF exports … … 64 320 'Unicode not valid for CIF') 65 321 return True 66 322 67 323 def _Exporter(self,event=None,phaseOnly=None,histOnly=None,IncludeOnlyHist=None): 68 324 '''Basic code to export a CIF. Export can be full or simple, as set by … … 76 332 77 333 #***** 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 pass84 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 += c90 else:91 s += '.'92 name = s93 s = ''94 for c in value:95 if ord(c) < 128:96 s += c97 else:98 s += '.'99 value = s100 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 120 334 def WriteAudit(): 121 335 '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', 123 337 'created in GSAS-II') 124 WriteCIFitem( '_audit_creation_date',self.CIFdate)338 WriteCIFitem(self.fp, '_audit_creation_date',self.CIFdate) 125 339 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', 128 342 self.CIFdate+' Initial software-generated CIF') 129 343 … … 134 348 ''' 135 349 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)') 141 355 if self.ifHKLF: 142 356 controls = self.OverallParms['Controls'] … … 145 359 else: 146 360 thresh = 'F>%.1fu(F)'%(controls['minF/sig']) 147 WriteCIFitem( '_reflns_threshold_expression', thresh)361 WriteCIFitem(self.fp, '_reflns_threshold_expression', thresh) 148 362 try: 149 363 vars = str(len(self.OverallParms['Covariance']['varyList'])) 150 364 except: 151 365 vars = '?' 152 WriteCIFitem( '_refine_ls_number_parameters',vars)366 WriteCIFitem(self.fp, '_refine_ls_number_parameters',vars) 153 367 try: 154 368 GOF = G2mth.ValEsd(self.OverallParms['Covariance']['Rvals']['GOF'],-0.009) 155 369 except: 156 370 GOF = '?' 157 WriteCIFitem( '_refine_ls_goodness_of_fit_all',GOF)371 WriteCIFitem(self.fp, '_refine_ls_goodness_of_fit_all',GOF) 158 372 159 373 # get restraint info … … 163 377 # for j in self.OverallParms['Constraints'][i]: 164 378 # print j 165 #WriteCIFitem( '_refine_ls_number_restraints',TEXT)379 #WriteCIFitem(self.fp, '_refine_ls_number_restraints',TEXT) 166 380 # other things to consider reporting 167 381 # _refine_ls_number_reflns … … 173 387 # include an overall profile r-factor, if there is more than one powder histogram 174 388 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) 177 391 # _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') 181 395 182 396 def writeCIFtemplate(G2dict,tmplate,defaultname=''): 183 397 '''Write out the selected or edited CIF template 184 398 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. 186 400 In all cases the initial data_ header is stripped (there should only be one!) 187 401 ''' … … 221 435 txt = "# GSAS-II edited template follows "+txt[txt.index("data_")+5:] 222 436 #txt = txt.replace('data_','#') 223 WriteCIFitem( txt)437 WriteCIFitem(self.fp, txt) 224 438 225 439 def FormatSH(phasenam): 226 440 '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 228 442 pfx = str(phasedict['pId'])+'::' 229 443 s = "" 230 textureData = phasedict['General']['SH Texture'] 444 textureData = phasedict['General']['SH Texture'] 231 445 if textureData.get('Order'): 232 446 s += "Spherical Harmonics correction. Order = "+str(textureData['Order']) … … 257 471 character string 258 472 ''' 259 phasedict = self.Phases[phasenam] # pointer to current phase info 473 phasedict = self.Phases[phasenam] # pointer to current phase info 260 474 s = '' 261 475 for histogram in sorted(phasedict['Histograms']): … … 292 506 s += s1 293 507 return s 294 508 295 509 def FormatBackground(bkg,hId): 296 510 '''Display the Background information as a descriptive text string. 297 511 298 512 TODO: this needs to be expanded to show the diffuse peak and 299 513 Debye term information as well. (Bob) … … 349 563 name = hfx+item 350 564 sig = self.sigDict.get(name,-0.009) 351 s += G2mth.ValEsd(inst[item][1],sig)+', ' 565 s += G2mth.ValEsd(inst[item][1],sig)+', ' 352 566 elif 'T' in inst['Type'][0]: #to be tested after TOF Rietveld done 353 567 s = 'Von Dreele-Jorgenson-Windsor function parameters\n'+ \ … … 367 581 s = '' 368 582 phasedict = self.Phases[phasenam] # pointer to current phase info 369 SGData = phasedict['General'] ['SGData'] 583 SGData = phasedict['General'] ['SGData'] 370 584 for histogram in sorted(phasedict['Histograms']): 371 585 if histogram.startswith("HKLF"): continue # powder only … … 387 601 else: 388 602 s += ' Crystallite size model "%s" for %s (microns)\n '%(size[0],phasenam) 389 603 390 604 names = ['Size;i','Size;mx'] 391 605 if 'uniax' in size[0]: … … 404 618 s += G2mth.ValEsd(size[4][i],sig)+', ' 405 619 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)+', ' 407 621 else: #isotropic 408 622 s += 'parameters: Size, G/L mix\n ' … … 412 626 sig = self.sigDict.get(name,-0.009) 413 627 s += G2mth.ValEsd(size[1][i],sig)+', ' 414 i = 2 #skip the aniso value 628 i = 2 #skip the aniso value 415 629 s += '\n Mustrain model "%s" for %s (10^6^)\n '%(mustrain[0],phasenam) 416 630 names = ['Mustrain;i','Mustrain;mx'] … … 439 653 txt = '' 440 654 txt += G2mth.ValEsd(mustrain[4][i],sig)+', ' 441 s += txt 655 s += txt 442 656 sig = self.sigDict.get(phfx+'Mustrain;mx',-0.009) 443 657 s += G2mth.ValEsd(mustrain[1][2],sig)+', ' 444 658 445 659 else: #isotropic 446 660 s += ' parameters: Mustrain, G/L mix\n ' … … 450 664 sig = self.sigDict.get(name,-0.009) 451 665 s += G2mth.ValEsd(mustrain[1][i],sig)+', ' 452 i = 2 #skip the aniso value 666 i = 2 #skip the aniso value 453 667 s1 = ' \n Macrostrain parameters: ' 454 668 names = G2spc.HStrainNames(SGData) … … 468 682 s += '\n' 469 683 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 before475 if '+' in sym:476 sym = sym.replace('+','') + '+'477 elif '-' in sym:478 sym = sym.replace('-','') + '-'479 return sym480 481 def PutInCol(val,wid):482 '''Pad a value to >=wid+1 columns by adding spaces at the end. Always483 adds at least one space484 '''485 val = str(val).replace(' ','')486 if not val: val = '?'487 fmt = '{:' + str(wid) + '} '488 return fmt.format(val)489 684 490 685 def MakeUniqueLabel(lbl,labellist): … … 511 706 labellist.append(lbl) 512 707 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) 612 809 613 810 def HillSortElements(elmlist): … … 627 824 return newlist+sorted(oldlist) 628 825 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?: 679 879 #loop_ 680 # _at om_type_symbol681 # _at om_type_description682 # _at om_type_scat_dispersion_real683 # _at om_type_scat_dispersion_imag684 # _at om_type_scat_source685 # 'C' 'C' 0.0033 0.0016686 # 'International Tables Vol C Tables 4.2.6.8 and 6.1.1.4'687 # 'H' 'H' 0.0000 0.0000688 # 'International Tables Vol C Tables 4.2.6.8 and 6.1.1.4'689 # 'P' 'P' 0.1023 0.0942690 # 'International Tables Vol C Tables 4.2.6.8 and 6.1.1.4'691 # 'Cl ' 'Cl' 0.1484 0.1585692 # 'International Tables Vol C Tables 4.2.6.8 and 6.1.1.4'693 # 'Cu ' 'Cu' 0.3201 1.2651694 # 'International Tables Vol C Tables 4.2.6.8 and 6.1.1.4'695 696 #if oneblock: # add scattering factors for current phase here697 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 += elem705 if compDict[elem] == Z: continue706 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)) 712 912 713 913 def WriteDistances(phasenam,SymOpList,offsetList,symOpList,G2oprList): … … 722 922 TODO: need a method to select publication flags for distances/angles 723 923 ''' 724 phasedict = self.Phases[phasenam] # pointer to current phase info 924 phasedict = self.Phases[phasenam] # pointer to current phase info 725 925 Atoms = phasedict['Atoms'] 726 926 generalData = phasedict['General'] … … 731 931 cx,ct,cs,cia = phasedict['General']['AtomPtrs'] 732 932 cn = ct-1 733 fpfx = str(phasedict['pId'])+'::Afrac:' 933 fpfx = str(phasedict['pId'])+'::Afrac:' 734 934 cfrac = cx+3 735 935 DisAglData = {} 736 936 # create a list of atoms, but skip atoms with zero occupancy 737 937 xyz = [] 738 fpfx = str(phasedict['pId'])+'::Afrac:' 938 fpfx = str(phasedict['pId'])+'::Afrac:' 739 939 for i,atom in enumerate(Atoms): 740 940 if self.parmDict.get(fpfx+str(i),atom[cfrac]) == 0.0: continue … … 776 976 except KeyError: # inside DistAngle for missing atom types in DisAglCtls 777 977 print('**** ERROR - try again but do "Reset" to fill in missing atom types ****') 778 978 779 979 # 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_' + 782 982 '\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' + 787 987 '\n _geom_bond_publ_flag') 788 988 … … 802 1002 else: 803 1003 line += " yes" 804 WriteCIFitem( line)1004 WriteCIFitem(self.fp, line) 805 1005 806 1006 # 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' + 812 1012 '\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' + 815 1015 '\n _geom_angle_publ_flag') 816 1016 … … 836 1036 else: 837 1037 line += " yes" 838 WriteCIFitem( line)1038 WriteCIFitem(self.fp, line) 839 1039 840 1040 def WritePhaseInfo(phasenam,hist=None): 841 1041 '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) 845 1045 cellList,cellSig = self.GetCell(phasenam) 846 1046 defsigL = 3*[-0.00001] + 3*[-0.001] + [-0.01] # significance to use when no sigma … … 855 1055 else: 856 1056 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', 860 1060 phasedict['General']['SGData']['SGSys']) 861 1061 … … 863 1063 # regularize capitalization and remove trailing H/R 864 1064 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) 866 1066 867 1067 # generate symmetry operations including centering and center of symmetry 868 1068 SymOpList,offsetList,symOpList,G2oprList,G2opcodes = G2spc.AllOps( 869 1069 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') 871 1071 for i,op in enumerate(SymOpList,start=1): 872 WriteCIFitem( ' {:3d} {:}'.format(i,op.lower()))1072 WriteCIFitem(self.fp, ' {:3d} {:}'.format(i,op.lower())) 873 1073 874 1074 # loop over histogram(s) used in this phase … … 891 1091 892 1092 if len(histlist) == 0: 893 WriteCIFitem( '# Note: phase has no associated data')1093 WriteCIFitem(self.fp, '# Note: phase has no associated data') 894 1094 895 1095 # report atom params 896 1096 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) 898 1103 else: 899 1104 raise Exception,"no export for "+str(phasedict['General']['Type'])+" coordinates implemented" 900 1105 # report cell contents 901 WriteComposition( phasenam)1106 WriteComposition(self.fp, self.Phases[phasenam], phasenam, self.parmDict) 902 1107 if not self.quickmode and phasedict['General']['Type'] == 'nuclear': # report distances and angles 903 1108 WriteDistances(phasenam,SymOpList,offsetList,symOpList,G2oprList) 904 1109 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') 906 1111 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 910 1115 def Yfmt(ndec,val): 911 1116 'Format intensity values' … … 913 1118 out = out.rstrip('0') # strip zeros to right of decimal 914 1119 return out.rstrip('.') # and decimal place when not needed 915 1120 916 1121 def WriteReflStat(refcount,hklmin,hklmax,dmin,dmax,nRefSets=1): 917 1122 'Write reflection statistics' 918 WriteCIFitem( '_reflns_number_total', str(refcount))1123 WriteCIFitem(self.fp, '_reflns_number_total', str(refcount)) 919 1124 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]))) 926 1131 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)) 929 1134 930 1135 def WritePowderData(histlbl): … … 934 1139 hId = histblk['hId'] 935 1140 pfx = ':' + str(hId) + ':' 936 1141 937 1142 if 'Lam1' in inst: 938 1143 ratio = self.parmDict.get('I(L2)/I(L1)',inst['I(L2)/I(L1)'][1]) … … 943 1148 slam2 = self.sigDict.get('Lam2',-0.00009) 944 1149 # 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_' + 947 1152 '\n _diffrn_radiation_wavelength' + 948 '\n _diffrn_radiation_wavelength_wt' + 1153 '\n _diffrn_radiation_wavelength_wt' + 949 1154 '\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) + 952 1157 PutInCol('1',5)) 953 WriteCIFitem( ' ' + PutInCol(G2mth.ValEsd(lam2,slam2),15)+1158 WriteCIFitem(self.fp, ' ' + PutInCol(G2mth.ValEsd(lam2,slam2),15)+ 954 1159 PutInCol(G2mth.ValEsd(ratio,sratio),15)+ 955 PutInCol('2',5)) 1160 PutInCol('2',5)) 956 1161 elif 'Lam' in inst: 957 1162 lam1 = self.parmDict.get('Lam',inst['Lam'][1]) 958 1163 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)) 960 1165 961 1166 if not oneblock: 962 1167 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') 964 1169 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' + 969 1174 '\n _pd_phase_mass_%') 970 1175 wtFrSum = 0. … … 983 1188 else: 984 1189 sig = -0.0001 985 WriteCIFitem( 1190 WriteCIFitem(self.fp, 986 1191 ' '+ 987 1192 str(self.Phases[phasenam]['pId']) + … … 989 1194 ' '+G2mth.ValEsd(wtFr,sig) 990 1195 ) 991 WriteCIFitem( 'loop_' +1196 WriteCIFitem(self.fp, 'loop_' + 992 1197 '\n _gsas_proc_phase_R_F_factor' + 993 1198 '\n _gsas_proc_phase_R_Fsqd_factor' + … … 996 1201 for phasenam in phasebyhistDict.get(histlbl): 997 1202 pfx = str(self.Phases[phasenam]['pId'])+':'+str(hId)+':' 998 WriteCIFitem( 1203 WriteCIFitem(self.fp, 999 1204 ' '+ 1000 1205 ' '+G2mth.ValEsd(histblk[pfx+'Rf']/100.,-.00009) + … … 1006 1211 # single phase in this histogram 1007 1212 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.)) 1016 1221 1017 1222 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') 1019 1224 pola = histblk['Instrument Parameters'][0].get('Polariz.') 1020 1225 if pola: … … 1022 1227 sig = self.sigDict.get(pfx+'Polariz.',-0.0009) 1023 1228 txt = G2mth.ValEsd(pola[1],sig) 1024 WriteCIFitem( '_diffrn_radiation_polarisn_ratio',txt)1229 WriteCIFitem(self.fp, '_diffrn_radiation_polarisn_ratio',txt) 1025 1230 elif histblk['Instrument Parameters'][0]['Type'][1][1] == 'N': 1026 WriteCIFitem( '_diffrn_radiation_probe','neutron')1231 WriteCIFitem(self.fp, '_diffrn_radiation_probe','neutron') 1027 1232 if 'T' in inst['Type'][0]: 1028 1233 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) 1030 1235 1031 1236 # TODO: this will need help from Bob 1032 1237 #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') 1035 1240 #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') 1038 1243 # 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) 1040 1245 #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'])) 1045 1250 1046 1251 # 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','?') 1050 1255 #C extinction 1051 1256 #WRITE(IUCIF,'(A)') '# Extinction correction' … … 1054 1259 1055 1260 if not oneblock: # instrumental profile terms go here 1056 WriteCIFitem( '_pd_proc_ls_profile_function',1261 WriteCIFitem(self.fp, '_pd_proc_ls_profile_function', 1057 1262 FormatInstProfile(histblk["Instrument Parameters"],histblk['hId'])) 1058 1263 … … 1060 1265 refprx = '_refln_' # normal 1061 1266 # data collection parameters for the powder dataset 1062 1267 1063 1268 temperature = histblk['Sample Parameters'].get('Temperature') # G2 uses K 1064 1269 if not temperature: … … 1066 1271 else: 1067 1272 T = G2mth.ValEsd(temperature,-0.009,True) # CIF uses K 1068 WriteCIFitem( '_diffrn_ambient_temperature',T)1273 WriteCIFitem(self.fp, '_diffrn_ambient_temperature',T) 1069 1274 1070 1275 pressure = histblk['Sample Parameters'].get('Pressure') #G2 uses mega-Pascal … … 1073 1278 else: 1074 1279 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') 1078 1283 # compute maximum intensity reflection 1079 1284 Imax = 0 … … 1087 1292 Imax = max(Imax,max(I100)) 1088 1293 1089 WriteCIFitem( 'loop_')1294 WriteCIFitem(self.fp, 'loop_') 1090 1295 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' + 1098 1303 '\n _pd_refln_d_spacing') 1099 1304 if Imax > 0: 1100 WriteCIFitem( ' _gsas_i100_meas')1305 WriteCIFitem(self.fp, ' _gsas_i100_meas') 1101 1306 1102 1307 refcount = 0 … … 1135 1340 if Imax > 0: 1136 1341 s += PutInCol(G2mth.ValEsd(100.*I100[j]/Imax,-0.09),6) 1137 WriteCIFitem( " "+s)1342 WriteCIFitem(self.fp, " "+s) 1138 1343 1139 1344 WriteReflStat(refcount,hklmin,hklmax,dmin,dmax,len(histblk['Reflection Lists'])) 1140 WriteCIFitem( '\n# POWDER DATA TABLE')1345 WriteCIFitem(self.fp, '\n# POWDER DATA TABLE') 1141 1346 # is data fixed step? If the step varies by <0.01% treat as fixed step 1142 1347 steps = histblk['Data'][0][1:] - histblk['Data'][0][:-1] … … 1148 1353 zero = None 1149 1354 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)) 1153 1358 # zero correct, if defined 1154 1359 zerolst = histblk['Instrument Parameters'][0].get('Zero') … … 1156 1361 zero = self.parmDict.get('Zero',zero) 1157 1362 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 1162 1367 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]))) 1164 1369 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 this1370 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 1168 1373 if not fixedstep: 1169 1374 if zero: 1170 WriteCIFitem( ' _pd_proc_2theta_corrected')1375 WriteCIFitem(self.fp, ' _pd_proc_2theta_corrected') 1171 1376 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') 1173 1378 else: 1174 WriteCIFitem( ' _pd_meas_2theta_scan')1379 WriteCIFitem(self.fp, ' _pd_meas_2theta_scan') 1175 1380 # at least for now, always report weights. 1176 1381 #if countsdata: 1177 # WriteCIFitem( ' _pd_meas_counts_total')1382 # WriteCIFitem(self.fp, ' _pd_meas_counts_total') 1178 1383 #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') 1183 1388 maxY = max(histblk['Data'][1].max(),histblk['Data'][3].max()) 1184 1389 if maxY < 0: maxY *= -10 # this should never happen, but... … … 1191 1396 if DEBUG: 1192 1397 print('DEBUG: skipping profile list') 1193 else: 1398 else: 1194 1399 for x,yobs,yw,ycalc,ybkg in zip(histblk['Data'][0], 1195 1400 histblk['Data'][1], … … 1201 1406 else: 1202 1407 yw = 0.0 # show the point is not in use 1203 1408 1204 1409 if fixedstep: 1205 1410 s = "" … … 1212 1417 s += PutInCol(Yfmt(ndec,ybkg),11) 1213 1418 s += PutInCol(Yfmt(ndecSU,yw),9) 1214 WriteCIFitem( " "+s)1419 WriteCIFitem(self.fp, " "+s) 1215 1420 1216 1421 def WriteSingleXtalData(histlbl): … … 1221 1426 refprx = '_refln_' # normal 1222 1427 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' + 1227 1432 '\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' + 1231 1436 '\n ' + refprx + 'phase_calc' 1232 1437 ) … … 1262 1467 dmax = max(dmax,ref[4]) 1263 1468 dmin = min(dmin,ref[4]) 1264 WriteCIFitem(s )1469 WriteCIFitem(self.fp, s) 1265 1470 if not self.quickmode: # statistics only in a full CIF 1266 1471 WriteReflStat(refcount,hklmin,hklmax,dmin,dmax) … … 1270 1475 extType,extModel,extParms = self.Phases[phasenam]['Histograms'][histlbl]['Extinction'] 1271 1476 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)) 1274 1479 sig = -1.e-3 1275 1480 if extModel == 'Primary': … … 1298 1503 sig = self.sigDict[phfx+'Es']*1.e5 1299 1504 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.)) 1306 1511 def EditAuthor(event=None): 1307 1512 'dialog to edit the CIF author info' … … 1329 1534 lbllist = [] 1330 1535 for hist in self.Histograms: 1331 if hist.startswith("PWDR"): 1536 if hist.startswith("PWDR"): 1332 1537 key2 = "Sample Parameters" 1333 1538 d = self.Histograms[hist][key2] 1334 elif hist.startswith("HKLF"): 1539 elif hist.startswith("HKLF"): 1335 1540 key2 = "Instrument Parameters" 1336 1541 d = self.Histograms[hist][key2][0] 1337 1542 1338 1543 lbllist.append(hist) 1339 1544 dictlist.append(d) … … 1349 1554 header="Edit instrument names. Note that a non-blank\nname is required for all histograms", 1350 1555 CopyButton=True,ASCIIonly=True) 1351 1556 1352 1557 def EditRanges(event): 1353 1558 '''Edit the bond distance/angle search range; phase is determined from … … 1359 1564 dlg = G2G.DisAglDialog( 1360 1565 self.G2frame, 1361 phasedict['General']['DisAglCtls'], # edited 1566 phasedict['General']['DisAglCtls'], # edited 1362 1567 phasedict['General'], # defaults 1363 1568 ) … … 1365 1570 phasedict['General']['DisAglCtls'] = dlg.GetData() 1366 1571 dlg.Destroy() 1367 1572 1368 1573 def EditCIFDefaults(): 1369 1574 '''Fills the CIF Defaults window with controls for editing various CIF export … … 1382 1587 cpnl = wxscroll.ScrolledPanel(self.cifdefs,size=(300,300)) 1383 1588 cbox = wx.BoxSizer(wx.VERTICAL) 1384 G2G.HorizontalLine(cbox,cpnl) 1589 G2G.HorizontalLine(cbox,cpnl) 1385 1590 cbox.Add( 1386 1591 CIFtemplateSelect(self.cifdefs, … … 1391 1596 0,wx.EXPAND|wx.ALIGN_LEFT|wx.ALL) 1392 1597 for phasenam in sorted(self.Phases.keys()): 1393 G2G.HorizontalLine(cbox,cpnl) 1598 G2G.HorizontalLine(cbox,cpnl) 1394 1599 title = 'Phase '+phasenam 1395 phasedict = self.Phases[phasenam] # pointer to current phase info 1600 phasedict = self.Phases[phasenam] # pointer to current phase info 1396 1601 cbox.Add( 1397 1602 CIFtemplateSelect(self.cifdefs, … … 1402 1607 0,wx.EXPAND|wx.ALIGN_LEFT|wx.ALL) 1403 1608 cpnl.SetSizer(cbox) 1404 if phasedict['General']['Type'] == 'nuclear': 1609 if phasedict['General']['Type'] == 'nuclear': 1405 1610 but = wx.Button(cpnl, wx.ID_ANY,'Edit distance/angle ranges') 1406 1611 cbox.Add(but,0,wx.ALIGN_LEFT,0) … … 1409 1614 but.Bind(wx.EVT_BUTTON,EditRanges) # phase bond/angle ranges 1410 1615 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 1412 1617 but.Bind(wx.EVT_BUTTON,SelectDisAglFlags) # phase bond/angle ranges 1413 1618 cbox.Add(but,0,wx.ALIGN_LEFT,0) 1414 1619 cbox.Add((-1,2)) 1415 1620 for i in sorted(self.powderDict.keys()): 1416 G2G.HorizontalLine(cbox,cpnl) 1621 G2G.HorizontalLine(cbox,cpnl) 1417 1622 hist = self.powderDict[i] 1418 1623 histblk = self.Histograms[hist] … … 1426 1631 0,wx.EXPAND|wx.ALIGN_LEFT|wx.ALL) 1427 1632 for i in sorted(self.xtalDict.keys()): 1428 G2G.HorizontalLine(cbox,cpnl) 1633 G2G.HorizontalLine(cbox,cpnl) 1429 1634 hist = self.xtalDict[i] 1430 1635 histblk = self.Histograms[hist] … … 1455 1660 vbox.Fit(self.cifdefs) 1456 1661 self.cifdefs.Layout() 1457 1662 1458 1663 def OnToggleButton(event): 1459 1664 'Respond to press of ToggleButton in SelectDisAglFlags' 1460 1665 but = event.GetEventObject() 1461 if but.GetValue(): 1666 if but.GetValue(): 1462 1667 but.DisAglSel[but.key] = True 1463 1668 else: … … 1470 1675 def keepFalse(event): 1471 1676 event.GetEventObject().SetValue(False) 1472 1677 1473 1678 def SelectDisAglFlags(event): 1474 1679 'Select Distance/Angle use flags for the selected phase' … … 1488 1693 # create a list of atoms, but skip atoms with zero occupancy 1489 1694 xyz = [] 1490 fpfx = str(phasedict['pId'])+'::Afrac:' 1695 fpfx = str(phasedict['pId'])+'::Afrac:' 1491 1696 for i,atom in enumerate(phasedict['Atoms']): 1492 1697 if self.parmDict.get(fpfx+str(i),atom[cfrac]) == 0.0: continue … … 1542 1747 wx.EndBusyCursor() 1543 1748 txt.SetLabel('Set publication flags for distances and angles in\nphase '+phasenam) 1544 vbox.Add((5,5)) 1749 vbox.Add((5,5)) 1545 1750 vbox.Add(wx.StaticText(dlg,wx.ID_ANY, 1546 1751 'The default is to flag all distances and angles as to be'+ … … 1557 1762 hbox.Add(but) 1558 1763 but.SetValue(True) 1559 G2G.HorizontalLine(vbox,dlg) 1560 1764 G2G.HorizontalLine(vbox,dlg) 1765 1561 1766 cpnl = wxscroll.ScrolledPanel(dlg,size=(400,300)) 1562 1767 cbox = wx.BoxSizer(wx.VERTICAL) … … 1574 1779 dbox.Add(wx.StaticText(cpnl,wx.ID_ANY,AtomLabels[D[0]]), 1575 1780 (i+1,0) 1576 ) 1781 ) 1577 1782 dbox.Add(wx.StaticText(cpnl,wx.ID_ANY,sym), 1578 1783 (i+1,1) … … 1604 1809 ) 1605 1810 cbox.Add(dbox) 1606 G2G.HorizontalLine(cbox,cpnl) 1811 G2G.HorizontalLine(cbox,cpnl) 1607 1812 cpnl.SetSizer(cbox) 1608 1813 cpnl.SetAutoLayout(1) … … 1622 1827 vbox.Fit(dlg) 1623 1828 dlg.Layout() 1624 1829 1625 1830 dlg.CenterOnParent() 1626 1831 dlg.ShowModal() 1627 1832 1628 1833 #================================================================================= 1629 1834 #===== end of function definitions for _Exporter ================================= … … 1631 1836 # make sure required information is present 1632 1837 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). 1634 1839 if not self.G2frame.GSASprojectfile: 1635 1840 self.G2frame.OnFileSaveas(None) … … 1653 1858 pass 1654 1859 #================================================================= 1655 # write quick CIFs 1860 # write quick CIFs 1656 1861 #================================================================= 1657 1862 if phaseOnly: #====Phase only CIF ================================ … … 1662 1867 self.Write(' ') 1663 1868 self.Write(70*'#') 1664 WriteCIFitem( 'data_'+self.CIFname)1869 WriteCIFitem(self.fp, 'data_'+self.CIFname) 1665 1870 #phaseblk = self.Phases[phaseOnly] # pointer to current phase info 1666 1871 # report the phase info … … 1680 1885 self.Write(70*'#') 1681 1886 #phasenam = self.Phases.keys()[0] 1682 WriteCIFitem( 'data_'+self.CIFname)1887 WriteCIFitem(self.fp, 'data_'+self.CIFname) 1683 1888 #print 'phasenam',phasenam 1684 1889 #phaseblk = self.Phases[phasenam] # pointer to current phase info 1685 1890 #instnam = instnam.replace(' ','') 1686 #WriteCIFitem( '_pd_block_id',1891 #WriteCIFitem(self.fp, '_pd_block_id', 1687 1892 # str(self.CIFdate) + "|" + str(self.CIFname) + "|" + 1688 1893 # str(self.shortauthorname) + "|" + instnam + '|' + histname) … … 1697 1902 #MD = FormatHAPpo(phasenam) 1698 1903 #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) 1700 1905 #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) 1702 1907 #else: 1703 # WriteCIFitem( '_pd_proc_ls_pref_orient_corr', 'none')1908 # WriteCIFitem(self.fp, '_pd_proc_ls_pref_orient_corr', 'none') 1704 1909 # 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', 1706 1911 # FormatInstProfile(histblk["Instrument Parameters"],histblk['hId']) 1707 1912 # +'\n'+FormatPhaseProfile(phasenam)) … … 1713 1918 #elif IncludeOnlyHist is not None: # truncate histogram list to only selected (for sequential export) 1714 1919 # self.Histograms = {IncludeOnlyHist:self.Histograms[IncludeOnlyHist]} 1715 1920 1716 1921 #=============================================================================== 1717 1922 # the export process for a full CIF starts here … … 1764 1969 self.ifHKLF = True 1765 1970 key2 = "Instrument Parameters" 1766 d = self.Histograms[hist][key2][0] 1971 d = self.Histograms[hist][key2][0] 1767 1972 instrname = d.get(key3) 1768 1973 if instrname is None: … … 1779 1984 # ) 1780 1985 if not EditInstNames(): return 1781 1986 1782 1987 # check for a distance-angle range search range for each phase 1783 1988 for phasenam in sorted(self.Phases.keys()): 1784 1989 #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 1786 1991 if 'DisAglCtls' not in phasedict['General']: 1787 1992 dlg = G2G.DisAglDialog( … … 1799 2004 default = 0 1800 2005 for hist in self.Histograms: 1801 if hist.startswith("PWDR"): 2006 if hist.startswith("PWDR"): 1802 2007 key2 = "Sample Parameters" 1803 2008 T = self.Histograms[hist][key2].get('Temperature') … … 1825 2030 for hist in self.Histograms: 1826 2031 histblk = self.Histograms[hist] 1827 if hist.startswith("PWDR"): 2032 if hist.startswith("PWDR"): 1828 2033 instnam = histblk["Sample Parameters"]['InstrName'] 1829 2034 break # ignore all but 1st data histogram 1830 elif hist.startswith("HKLF"): 2035 elif hist.startswith("HKLF"): 1831 2036 instnam = histblk["Instrument Parameters"][0]['InstrName'] 1832 2037 break # ignore all but 1st data histogram … … 1858 2063 hist = self.histnam[0] 1859 2064 self.CIFname = hist[5:40].replace(' ','') 1860 WriteCIFitem( 'data_'+self.CIFname)2065 WriteCIFitem(self.fp, 'data_'+self.CIFname) 1861 2066 if hist.startswith("PWDR"): 1862 2067 WritePowderData(hist) … … 1867 2072 elif oneblock: 1868 2073 #====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) 1871 2076 phasenam = self.Phases.keys()[0] 1872 2077 #print 'phasenam',phasenam 1873 2078 #phaseblk = self.Phases[phasenam] # pointer to current phase info 1874 2079 instnam = instnam.replace(' ','') 1875 WriteCIFitem( '_pd_block_id',2080 WriteCIFitem(self.fp, '_pd_block_id', 1876 2081 str(self.CIFdate) + "|" + str(self.CIFname) + "|" + 1877 2082 str(self.shortauthorname) + "|" + instnam) … … 1887 2092 MD = FormatHAPpo(phasenam) 1888 2093 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) 1890 2095 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) 1892 2097 else: 1893 WriteCIFitem( '_pd_proc_ls_pref_orient_corr', 'none')2098 WriteCIFitem(self.fp, '_pd_proc_ls_pref_orient_corr', 'none') 1894 2099 # 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', 1896 2101 FormatInstProfile(histblk["Instrument Parameters"],histblk['hId']) 1897 2102 +'\n'+FormatPhaseProfile(phasenam)) … … 1915 2120 step = 1 1916 2121 dlg.Update(step,"Exporting overall section") 1917 WriteCIFitem( '\ndata_'+self.CIFname+'_publ')2122 WriteCIFitem(self.fp, '\ndata_'+self.CIFname+'_publ') 1918 2123 WriteAudit() 1919 WriteCIFitem( '_pd_block_id',2124 WriteCIFitem(self.fp, '_pd_block_id', 1920 2125 str(self.CIFdate) + "|" + str(self.CIFname) + "|" + 1921 2126 str(self.shortauthorname) + "|Overall") … … 1923 2128 # ``template_publ.cif`` or a modified version 1924 2129 # overall info 1925 WriteCIFitem( 'data_'+str(self.CIFname)+'_overall')2130 WriteCIFitem(self.fp, 'data_'+str(self.CIFname)+'_overall') 1926 2131 WriteOverall() 1927 2132 #============================================================ 1928 WriteCIFitem( '# POINTERS TO PHASE AND HISTOGRAM BLOCKS')2133 WriteCIFitem(self.fp, '# POINTERS TO PHASE AND HISTOGRAM BLOCKS') 1929 2134 datablockidDict = {} # save block names here -- N.B. check for conflicts between phase & hist names (unlikely!) 1930 2135 # loop over phase blocks 1931 2136 if len(self.Phases) > 1: 1932 2137 loopprefix = '' 1933 WriteCIFitem( 'loop_ _pd_phase_block_id')2138 WriteCIFitem(self.fp, 'loop_ _pd_phase_block_id') 1934 2139 else: 1935 2140 loopprefix = '_pd_phase_block_id' … … 1939 2144 datablockidDict[phasenam] = (str(self.CIFdate) + "|" + str(self.CIFname) + "|" + 1940 2145 'phase_'+ str(i) + '|' + str(self.shortauthorname)) 1941 WriteCIFitem( loopprefix,datablockidDict[phasenam])2146 WriteCIFitem(self.fp, loopprefix,datablockidDict[phasenam]) 1942 2147 # loop over data blocks 1943 2148 if len(self.powderDict) + len(self.xtalDict) > 1: 1944 2149 loopprefix = '' 1945 WriteCIFitem( 'loop_ _pd_block_diffractogram_id')2150 WriteCIFitem(self.fp, 'loop_ _pd_block_diffractogram_id') 1946 2151 else: 1947 2152 loopprefix = '_pd_block_diffractogram_id' … … 1955 2160 str(self.shortauthorname) + "|" + 1956 2161 instnam + "_hist_"+str(j)) 1957 WriteCIFitem( loopprefix,datablockidDict[hist])2162 WriteCIFitem(self.fp, loopprefix,datablockidDict[hist]) 1958 2163 for i in sorted(self.xtalDict.keys()): 1959 2164 hist = self.xtalDict[i] … … 1965 2170 str(self.shortauthorname) + "|" + 1966 2171 instnam + "_hist_"+str(i)) 1967 WriteCIFitem( loopprefix,datablockidDict[hist])2172 WriteCIFitem(self.fp, loopprefix,datablockidDict[hist]) 1968 2173 #============================================================ 1969 2174 # loop over phases, exporting them … … 1973 2178 dlg.Update(step,"Exporting phase "+phasenam+' (#'+str(j+1)+')') 1974 2179 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]) 1978 2183 # report the phase 1979 2184 writeCIFtemplate(self.Phases[phasenam]['General'],'phase',phasenam) # write phase template … … 1984 2189 MD = FormatHAPpo(phasenam) 1985 2190 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) 1987 2192 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) 1989 2194 else: 1990 WriteCIFitem( '_pd_proc_ls_pref_orient_corr', 'none')2195 WriteCIFitem(self.fp, '_pd_proc_ls_pref_orient_corr', 'none') 1991 2196 # report sample profile terms 1992 2197 PP = FormatPhaseProfile(phasenam) 1993 2198 if PP: 1994 WriteCIFitem( '_pd_proc_ls_profile_function',PP)2199 WriteCIFitem(self.fp, '_pd_proc_ls_profile_function',PP) 1995 2200 1996 2201 #============================================================ … … 1999 2204 hist = self.powderDict[i] 2000 2205 histblk = self.Histograms[hist] 2001 if hist.startswith("PWDR"): 2206 if hist.startswith("PWDR"): 2002 2207 step += 1 2003 2208 dlg.Update(step,"Exporting "+hist.strip()) 2004 WriteCIFitem( '\ndata_'+self.CIFname+"_pwd_"+str(i))2209 WriteCIFitem(self.fp, '\ndata_'+self.CIFname+"_pwd_"+str(i)) 2005 2210 #instnam = histblk["Sample Parameters"]['InstrName'] 2006 2211 # report instrumental profile terms 2007 WriteCIFitem( '_pd_proc_ls_profile_function',2212 WriteCIFitem(self.fp, '_pd_proc_ls_profile_function', 2008 2213 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]) 2011 2216 histprm = self.Histograms[hist]["Sample Parameters"] 2012 2217 writeCIFtemplate(histprm,'powder',histprm['InstrName']) # powder template … … 2015 2220 hist = self.xtalDict[i] 2016 2221 histblk = self.Histograms[hist] 2017 if hist.startswith("HKLF"): 2222 if hist.startswith("HKLF"): 2018 2223 step += 1 2019 2224 dlg.Update(step,"Exporting "+hist.strip()) 2020 WriteCIFitem( '\ndata_'+self.CIFname+"_sx_"+str(i))2225 WriteCIFitem(self.fp, '\ndata_'+self.CIFname+"_sx_"+str(i)) 2021 2226 #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]) 2024 2229 histprm = self.Histograms[hist]["Instrument Parameters"][0] 2025 2230 writeCIFtemplate(histprm,'single',histprm['InstrName']) # single crystal template … … 2028 2233 dlg.Destroy() 2029 2234 2030 WriteCIFitem( '#--' + 15*'eof--' + '#')2235 WriteCIFitem(self.fp, '#--' + 15*'eof--' + '#') 2031 2236 #self.CloseFile() 2032 2237 print("...export completed") … … 2047 2252 ) 2048 2253 self.exporttype = ['project'] 2049 2254 2050 2255 def Exporter(self,event=None): 2051 2256 self._Exporter(event=event) … … 2066 2271 # print('CIF written to file '+self.fullpath) 2067 2272 # self.CloseFile() 2068 2273 2069 2274 class ExportPhaseCIF(ExportCIF): 2070 2275 '''Used to create a simple CIF with one phase. Uses exact same code as … … 2155 2360 print('CIF written to file '+self.fullpath) 2156 2361 self.CloseFile() 2157 2362 2158 2363 class ExportHKLCIF(ExportCIF): 2159 2364 '''Used to create a simple CIF containing diffraction data only. Uses exact same code as … … 2187 2392 ): return 2188 2393 self._Exporter(event=event,histOnly=self.histnam[0]) 2189 2394 2190 2395 #=============================================================================== 2191 2396 # misc CIF utilities … … 2200 2405 :param str fil: file name of CIF dictionary, will usually end 2201 2406 in .dic 2202 :returns: the dict with the definitions 2407 :returns: the dict with the definitions 2203 2408 ''' 2204 2409 import CifFile as cif # PyCifRW from James Hester … … 2238 2443 cif_core.dic and/or cif_pd.dic are read. 2239 2444 2240 :returns: the dict with the definitions 2445 :returns: the dict with the definitions 2241 2446 ''' 2242 2447 cifdic = {} … … 2301 2506 :returns: cifblk, loopstructure where cifblk is a dict with 2302 2507 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. 2304 2509 ''' 2305 2510 blk = cf.keys()[0] # assume templates are a single CIF block, use the 1st … … 2332 2537 Defaults to 'Template' 2333 2538 2334 :returns: the newly created PyCifRW CIF object 2539 :returns: the newly created PyCifRW CIF object 2335 2540 ''' 2336 2541 … … 2354 2559 # create a CIF and add the block 2355 2560 newcf = cif.CifFile() 2356 newcf[blockname] = newblk 2561 newcf[blockname] = newblk 2357 2562 return newcf 2358 2563 … … 2362 2567 placed in cifblk. If the CIF is saved as a file, the name of that file 2363 2568 is saved as ``self.newfile``. 2364 2569 2365 2570 :param wx.Frame parent: parent frame or None 2366 2571 :param cifblk: dict or PyCifRW block containing values for each CIF item … … 2378 2583 Note that the values for each looped CIF item, such as _a, 2379 2584 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 2382 2587 saving the CIF. 2383 2588 ''' … … 2387 2592 self.loopstructure = loopstructure 2388 2593 self.newfile = None 2389 self.defaultname = defaultname 2594 self.defaultname = defaultname 2390 2595 global CIFdic # once this is loaded, keep it around 2391 2596 if CIFdic is None: … … 2419 2624 def Post(self): 2420 2625 '''Display the dialog 2421 2626 2422 2627 :returns: True unless Cancel has been pressed. 2423 2628 ''' … … 2504 2709 but = wx.Button(self,wx.ID_ANY,"Add row") 2505 2710 self.AddDict[but]=lnum 2506 2507 hbox.Add(but) 2711 2712 hbox.Add(but) 2508 2713 but.Bind(wx.EVT_BUTTON,self.OnAddRow) 2509 2714 fbox = wx.GridBagSizer(0, 0) … … 2541 2746 line = wx.StaticLine(self,wx.ID_ANY, size=(-1,3), style=wx.LI_HORIZONTAL) 2542 2747 vbox.Add(line, 0, wx.EXPAND|wx.ALIGN_CENTER|wx.ALL, 10) 2543 2748 2544 2749 # post the non-looped CIF items 2545 2750 for item in sorted(self.cifblk.keys()): … … 2571 2776 self.DoLayout after the current operations are complete using 2572 2777 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. 2574 2779 ''' 2575 2780 if self.LayoutCalled: return # call already queued … … 2616 2821 for btn in self.parentOKbuttons: 2617 2822 btn.Disable() 2618 2823 2619 2824 def CIFEntryWidget(self,dct,item,dataname): 2620 2825 '''Create an entry widget for a CIF item. Use a validated entry for numb values … … 2622 2827 At present this does not allow entry of the special CIF values of "." and "?" for 2623 2828 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. 2625 2830 ''' 2626 2831 if self.cifdic.get(dataname): … … 2658 2863 class CIFtemplateSelect(wx.BoxSizer): 2659 2864 '''Create a set of buttons to show, select and edit a CIF template 2660 2865 2661 2866 :param frame: wx.Frame object of parent 2662 2867 :param panel: wx.Panel object where widgets should be placed … … 2666 2871 "CIF_template" will be used to store either a list or a string. 2667 2872 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. 2669 2874 :param function repaint: reference to a routine to be called to repaint 2670 2875 the frame after a change has been made 2671 2876 :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 2673 2878 saving the CIF. 2674 2879 ''' … … 2686 2891 else: 2687 2892 self.defaultname = '' 2688 2893 2689 2894 txt = wx.StaticText(panel,wx.ID_ANY,title) 2690 2895 self.Add(txt,0,wx.ALIGN_CENTER) … … 2776 2981 self.repaint() #EditCIFDefaults() # note that this does a dlg.Destroy() 2777 2982 else: 2778 dlg.Destroy() 2983 dlg.Destroy() 2779 2984 2780 2985 #===============================================================================
Note: See TracChangeset
for help on using the changeset viewer.