- Timestamp:
- Aug 6, 2017 3:08:30 PM (6 years ago)
- Location:
- branch/2frame
- Files:
-
- 1 added
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
branch/2frame/GSASIIIO.py
r2915 r2963 79 79 ''' 80 80 return re.sub('\s+', ' ', val).strip() 81 82 def makeInstDict(names,data,codes):83 inst = dict(zip(names,zip(data,data,codes)))84 for item in inst:85 inst[item] = list(inst[item])86 return inst87 81 88 82 def FileDlgFixExt(dlg,file): -
branch/2frame/GSASIIdataGUI.py
r2957 r2963 40 40 import GSASIImath as G2mth 41 41 import GSASIIIO as G2IO 42 import GSASIIfiles as G2fil 42 43 import GSASIIstrIO as G2stIO 43 44 import GSASIIlattice as G2lat … … 392 393 self.SetTopWindow(self.main) 393 394 # save the current package versions 394 self.main.PackageVersions = [] 395 self.main.PackageVersions.append(['Python',sys.version.split()[0]]) 396 for p in (wx,mpl,np,sp,ogl): 397 self.main.PackageVersions.append([p.__name__,p.__version__]) 398 # TODO: not sure how this works with pillow 399 try: 400 from PIL import Image 401 try: 402 from PIL import PILLOW_VERSION 403 self.main.PackageVersions.append([Image.__name__,PILLOW_VERSION]) 404 except: 405 self.main.PackageVersions.append([Image.__name__,Image.VERSION]) 406 except ImportError: 407 try: 408 import Image 409 self.main.PackageVersions.append([Image.__name__,Image.VERSION]) 410 except ImportError: 411 pass 412 self.main.PackageVersions.append(['Platform',sys.platform+' '+platform.architecture()[0]+' '+platform.machine()]) 395 self.main.PackageVersions = G2fil.get_python_versions([wx, mpl, np, sp, ogl]) 413 396 414 397 return True … … 578 561 ''' 579 562 580 self.ImportPhaseReaderlist = [] 581 self._init_Import_routines('phase',self.ImportPhaseReaderlist,'Phase') 582 self.ImportSfactReaderlist = [] 583 self._init_Import_routines('sfact',self.ImportSfactReaderlist,'Struct_Factor') 584 self.ImportPowderReaderlist = [] 585 self._init_Import_routines('pwd',self.ImportPowderReaderlist,'Powder_Data') 586 self.ImportSmallAngleReaderlist = [] 587 self._init_Import_routines('sad',self.ImportSmallAngleReaderlist,'SmallAngle_Data') 588 self.ImportReflectometryReaderlist = [] 589 self._init_Import_routines('rfd',self.ImportReflectometryReaderlist,'Reflectometry_Data') 590 self.ImportPDFReaderlist = [] 591 self._init_Import_routines('pdf',self.ImportPDFReaderlist,'PDF_Data') 592 self.ImportImageReaderlist = [] 593 self._init_Import_routines('img',self.ImportImageReaderlist,'Images') 563 self.ImportPhaseReaderlist = G2fil.LoadImportRoutines('phase','Phase') 564 self.ImportSfactReaderlist = G2fil.LoadImportRoutines('sfact','Struct_Factor') 565 self.ImportPowderReaderlist = G2fil.LoadImportRoutines('pwd','Powder_Data') 566 self.ImportSmallAngleReaderlist = G2fil.LoadImportRoutines('sad','SmallAngle_Data') 567 self.ImportReflectometryReaderlist = G2fil.LoadImportRoutines('rfd','Reflectometry_Data') 568 self.ImportPDFReaderlist = G2fil.LoadImportRoutines('pdf','PDF_Data') 569 self.ImportImageReaderlist = G2fil.LoadImportRoutines('img','Images') 594 570 self.ImportMenuId = {} 595 596 def _init_Import_routines(self,prefix,readerlist,errprefix):597 '''import all the import readers matching the prefix598 '''599 #path2GSAS2 = os.path.dirname(os.path.realpath(__file__)) # location of this file600 #pathlist = sys.path[:]601 #if path2GSAS2 not in pathlist: pathlist.append(path2GSAS2)602 #path2GSAS2 = os.path.join(603 # os.path.dirname(os.path.realpath(__file__)), # location of this file604 # 'imports')605 pathlist = sys.path[:]606 #if path2GSAS2 not in pathlist: pathlist.append(path2GSAS2)607 if '.' not in pathlist: pathlist.append('.') # insert the directory where G2 is started608 609 filelist = []610 for path in pathlist:611 for filename in glob.iglob(os.path.join(612 path,613 "G2"+prefix+"*.py")):614 filelist.append(filename)615 #print 'debug: found',filename616 filelist = sorted(list(set(filelist))) # remove duplicates617 for filename in filelist:618 path,rootname = os.path.split(filename)619 pkg = os.path.splitext(rootname)[0]620 try:621 fp = None622 fp, fppath,desc = imp.find_module(pkg,[path,])623 pkg = imp.load_module(pkg,fp,fppath,desc)624 for clss in inspect.getmembers(pkg): # find classes defined in package625 if clss[0].startswith('_'): continue626 if inspect.isclass(clss[1]):627 # check if we have the required methods628 for m in 'Reader','ExtensionValidator','ContentsValidator':629 if not hasattr(clss[1],m): break630 if not callable(getattr(clss[1],m)): break631 else:632 reader = clss[1]() # create an import instance633 if reader.UseReader:634 readerlist.append(reader)635 except AttributeError:636 print 'Import_'+errprefix+': Attribute Error '+ filename637 #except ImportError:638 # print 'Import_'+errprefix+': Error importing file '+ filename639 except Exception,errmsg:640 print('\nImport_'+errprefix+': Error importing file '+ filename)641 print(u'Error message: {}\n'.format(errmsg))642 if fp: fp.close()643 571 644 572 def EnableSeqRefineMenu(self): … … 1311 1239 finds matching bank no. to load - problem with nonmatches? 1312 1240 1241 Note that this routine performs a similar role to :func:`GSASIIfiles.ReadPowderInstprm`, 1242 but this will call a GUI routine for selection when needed. TODO: refactor to combine 1243 1313 1244 :param list instLines: strings from GSAS-II parameter file; can be concatenated with ';' 1314 1245 :param int bank: bank number to check when instprm file has '#BANK n:...' strings … … 1391 1322 newVals.append(val) 1392 1323 il += 1 1393 return [G2 IO.makeInstDict(newItems,newVals,len(newVals)*[False,]),{}]1324 return [G2fil.makeInstDict(newItems,newVals,len(newVals)*[False,]),{}] 1394 1325 1395 1326 def ReadPowderIparm(self,instfile,bank,databanks,rd): … … 1466 1397 :returns: a list of two dicts, the first containing instrument parameters 1467 1398 and the second used for TOF lookup tables for profile coeff. 1468 1469 1399 ''' 1470 def SetPowderInstParms(Iparm, rd):1471 '''extracts values from instrument parameters in rd.instdict1472 or in array Iparm.1473 Create and return the contents of the instrument parameter tree entry.1474 '''1475 Irads = {0:' ',1:'CrKa',2:'FeKa',3:'CuKa',4:'MoKa',5:'AgKa',6:'TiKa',7:'CoKa'}1476 DataType = Iparm['INS HTYPE '].strip()[:3] # take 1st 3 chars1477 # override inst values with values read from data file1478 Bank = rd.powderentry[2] #should be used in multibank iparm files1479 if rd.instdict.get('type'):1480 DataType = rd.instdict.get('type')1481 data = [DataType,]1482 instname = Iparm.get('INS 1INAME ')1483 irad = int(Iparm.get('INS 1 IRAD ','0'))1484 if instname:1485 rd.Sample['InstrName'] = instname.strip()1486 if 'C' in DataType:1487 wave1 = None1488 wave2 = 0.01489 if rd.instdict.get('wave'):1490 wl = rd.instdict.get('wave')1491 wave1 = wl[0]1492 if len(wl) > 1: wave2 = wl[1]1493 s = Iparm['INS 1 ICONS']1494 if not wave1:1495 wave1 = G2IO.sfloat(s[:10])1496 wave2 = G2IO.sfloat(s[10:20])1497 v = (wave1,wave2,1498 G2IO.sfloat(s[20:30])/100.,G2IO.sfloat(s[55:65]),G2IO.sfloat(s[40:50])) #get lam1, lam2, zero, pola & ratio1499 if not v[1]:1500 names = ['Type','Lam','Zero','Polariz.','U','V','W','X','Y','SH/L','Azimuth']1501 v = (v[0],v[2],v[4])1502 codes = [0,0,0,0]1503 rd.Sample.update({'Type':'Debye-Scherrer','Absorption':[0.,False],'DisplaceX':[0.,False],'DisplaceY':[0.,False]})1504 else:1505 names = ['Type','Lam1','Lam2','Zero','I(L2)/I(L1)','Polariz.','U','V','W','X','Y','SH/L','Azimuth']1506 codes = [0,0,0,0,0,0]1507 rd.Sample.update({'Type':'Bragg-Brentano','Shift':[0.,False],'Transparency':[0.,False],1508 'SurfRoughA':[0.,False],'SurfRoughB':[0.,False]})1509 data.extend(v)1510 if 'INS 1PRCF ' in Iparm:1511 v1 = Iparm['INS 1PRCF '].split()1512 v = Iparm['INS 1PRCF 1'].split()1513 data.extend([float(v[0]),float(v[1]),float(v[2])]) #get GU, GV & GW - always here1514 azm = float(Iparm.get('INS 1DETAZM','0.0'))1515 v = Iparm['INS 1PRCF 2'].split()1516 if v1[0] == 3:1517 data.extend([float(v[0]),float(v[1]),float(v[2])+float(v[3],azm)]) #get LX, LY, S+H/L & azimuth1518 else:1519 data.extend([0.0,0.0,0.002,azm]) #OK defaults if fxn #3 not 1st in iprm file1520 else:1521 v1 = Iparm['INS 1PRCF1 '].split()1522 v = Iparm['INS 1PRCF11'].split()1523 data.extend([float(v[0]),float(v[1]),float(v[2])]) #get GU, GV & GW - always here1524 azm = float(Iparm.get('INS 1DETAZM','0.0'))1525 v = Iparm['INS 1PRCF12'].split()1526 if v1[0] == 3:1527 data.extend([float(v[0]),float(v[1]),float(v[2])+float(v[3],azm)]) #get LX, LY, S+H/L & azimuth1528 else:1529 data.extend([0.0,0.0,0.002,azm]) #OK defaults if fxn #3 not 1st in iprm file1530 codes.extend([0,0,0,0,0,0,0])1531 Iparm1 = G2IO.makeInstDict(names,data,codes)1532 Iparm1['Source'] = [Irads[irad],Irads[irad]]1533 Iparm1['Bank'] = [Bank,Bank,0]1534 return [Iparm1,{}]1535 elif 'T' in DataType:1536 names = ['Type','fltPath','2-theta','difC','difA', 'difB','Zero','alpha','beta-0','beta-1',1537 'beta-q','sig-0','sig-1','sig-2','sig-q', 'X','Y','Azimuth',]1538 codes = [0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,]1539 azm = 0.1540 if 'INS 1DETAZM' in Iparm:1541 azm = float(Iparm['INS 1DETAZM'])1542 rd.Sample['Azimuth'] = azm1543 fltPath0 = 20. #arbitrary1544 if 'INS FPATH1' in Iparm:1545 s = Iparm['INS FPATH1'].split()1546 fltPath0 = G2IO.sfloat(s[0])1547 if 'INS 1BNKPAR' not in Iparm: #bank missing from Iparm file1548 return []1549 s = Iparm['INS 1BNKPAR'].split()1550 fltPath1 = G2IO.sfloat(s[0])1551 data.extend([fltPath0+fltPath1,]) #Flight path source-sample-detector1552 data.extend([G2IO.sfloat(s[1]),]) #2-theta for bank1553 s = Iparm['INS 1 ICONS'].split()1554 data.extend([G2IO.sfloat(s[0]),G2IO.sfloat(s[1]),0.0,G2IO.sfloat(s[2])]) #difC,difA,difB,Zero1555 if 'INS 1PRCF ' in Iparm:1556 s = Iparm['INS 1PRCF '].split()1557 pfType = int(s[0])1558 s = Iparm['INS 1PRCF 1'].split()1559 if abs(pfType) == 1:1560 data.extend([G2IO.sfloat(s[1]),G2IO.sfloat(s[2]),G2IO.sfloat(s[3])]) #alpha, beta-0, beta-11561 s = Iparm['INS 1PRCF 2'].split()1562 data.extend([0.0,0.0,G2IO.sfloat(s[1]),G2IO.sfloat(s[2]),0.0,0.0,0.0,azm]) #beta-q, sig-0, sig-1, sig-2, sig-q, X, Y1563 elif abs(pfType) in [3,4,5]:1564 data.extend([G2IO.sfloat(s[0]),G2IO.sfloat(s[1]),G2IO.sfloat(s[2])]) #alpha, beta-0, beta-11565 if abs(pfType) == 4:1566 data.extend([0.0,0.0,G2IO.sfloat(s[3]),0.0,0.0,0.0,0.0,azm]) #beta-q, sig-0, sig-1, sig-2, sig-q, X, Y1567 else:1568 s = Iparm['INS 1PRCF 2'].split()1569 data.extend([0.0,0.0,G2IO.sfloat(s[0]),G2IO.sfloat(s[1]),0.0,0.0,0.0,azm]) #beta-q, sig-0, sig-1, sig-2, sig-q, X, Y1570 elif abs(pfType) == 2:1571 data.extend([G2IO.sfloat(s[1]),0.0,1./G2IO.sfloat(s[3])]) #alpha, beta-0, beta-11572 data.extend([0.0,0.0,G2IO.sfloat(s[1]),0.0,0.0,0.0,0.0,azm]) #beta-q, sig-0, sig-1, sig-2, sig-q, X, Y1573 else:1574 s = Iparm['INS 1PRCF1 '].split()1575 pfType = int(s[0])1576 s = Iparm['INS 1PRCF11'].split()1577 if abs(pfType) == 1:1578 data.extend([G2IO.sfloat(s[1]),G2IO.sfloat(s[2]),G2IO.sfloat(s[3])]) #alpha, beta-0, beta-11579 s = Iparm['INS 1PRCF12'].split()1580 data.extend([0.0,0.0,G2IO.sfloat(s[1]),G2IO.sfloat(s[2]),0.0,0.0,0.0,azm]) #beta-q, sig-0, sig-1, sig-2, sig-q, X, Y1581 elif abs(pfType) in [3,4,5]:1582 data.extend([G2IO.sfloat(s[0]),G2IO.sfloat(s[1]),G2IO.sfloat(s[2])]) #alpha, beta-0, beta-11583 if abs(pfType) == 4:1584 data.extend([0.0,0.0,G2IO.sfloat(s[3]),0.0,0.0,0.0,0.0,azm]) #beta-q, sig-0, sig-1, sig-2, sig-q, X, Y1585 else:1586 s = Iparm['INS 1PRCF12'].split()1587 data.extend([0.0,0.0,G2IO.sfloat(s[0]),G2IO.sfloat(s[1]),0.0,0.0,0.0,azm]) #beta-q, sig-0, sig-1, sig-2, sig-q, X, Y1588 Inst1 = G2IO.makeInstDict(names,data,codes)1589 Inst1['Bank'] = [Bank,Bank,0]1590 Inst2 = {}1591 if pfType < 0:1592 Ipab = 'INS 1PAB'+str(-pfType)1593 Npab = int(Iparm[Ipab+' '].strip())1594 Inst2['Pdabc'] = []1595 for i in range(Npab):1596 k = Ipab+str(i+1).rjust(2)1597 s = Iparm[k].split()1598 Inst2['Pdabc'].append([float(t) for t in s])1599 Inst2['Pdabc'] = np.array(Inst2['Pdabc'])1600 Inst2['Pdabc'].T[3] += Inst2['Pdabc'].T[0]*Inst1['difC'][0] #turn 3rd col into TOF1601 if 'INS 1I ITYP' in Iparm:1602 s = Iparm['INS 1I ITYP'].split()1603 Ityp = int(s[0])1604 Tminmax = [float(s[1])*1000.,float(s[2])*1000.]1605 Itypes = ['Exponential','Maxwell/Exponential','','Maxwell/Chebyschev','']1606 if Ityp in [1,2,4]:1607 Inst2['Itype'] = Itypes[Ityp-1]1608 Inst2['Tminmax'] = Tminmax1609 Icoeff = []1610 Iesd = []1611 Icovar = []1612 for i in range(3):1613 s = Iparm['INS 1ICOFF'+str(i+1)].split()1614 Icoeff += [float(S) for S in s]1615 s = Iparm['INS 1IECOF'+str(i+1)].split()1616 Iesd += [float(S) for S in s]1617 NT = 101618 for i in range(8):1619 s = Iparm['INS 1IECOR'+str(i+1)]1620 if i == 7:1621 NT = 81622 Icovar += [float(s[6*j:6*j+6]) for j in range(NT)]1623 Inst2['Icoeff'] = Icoeff1624 Inst2['Iesd'] = Iesd1625 Inst2['Icovar'] = Icovar1626 return [Inst1,Inst2]1627 1400 1628 1401 def GetDefaultParms(self,rd): … … 1704 1477 rd.instfile = instfile 1705 1478 rd.instmsg = instfile + ' bank ' + str(rd.instbank) 1706 return SetPowderInstParms(Iparm,rd)1479 return G2fil.SetPowderInstParms(Iparm,rd) 1707 1480 else: 1708 1481 #print 'debug: open/read failed',instfile … … 1733 1506 rd.instfile = instfile 1734 1507 rd.instmsg = instfile + ' bank ' + str(rd.instbank) 1735 instParmList = SetPowderInstParms(Iparm,rd) #this is [Inst1,Inst2] a pair of dicts1508 instParmList = G2fil.SetPowderInstParms(Iparm,rd) #this is [Inst1,Inst2] a pair of dicts 1736 1509 if 'list' in str(type(instParmList)): #record stuff & return stuff 1737 1510 rd.instfile = instfile … … 1779 1552 rd.instfile = instfile 1780 1553 rd.instmsg = instfile + ' bank ' + str(rd.instbank) 1781 return SetPowderInstParms(Iparm,rd)1554 return G2fil.SetPowderInstParms(Iparm,rd) 1782 1555 else: 1783 1556 self.ErrorDialog('Read Error', … … 3187 2960 names = ['Type','Lam','Zero'] 3188 2961 codes = [0,0,0] 3189 inst = [G2 IO.makeInstDict(names,data,codes),{}]2962 inst = [G2fil.makeInstDict(names,data,codes),{}] 3190 2963 self.GPXtree.SetItemPyData(self.GPXtree.AppendItem(Id,text='Instrument Parameters'),inst) 3191 2964 self.GPXtree.SetItemPyData(self.GPXtree.AppendItem(Id,text='Comments'),comments) … … 7357 7130 G2frame.dataWindow.currentGrids = [] 7358 7131 G2frame.dataDisplay = G2G.GSGrid(parent=G2frame.dataWindow) 7132 G2frame.dataDisplay.SetScrollRate(1,1) 7359 7133 G2frame.dataWindow.GetSizer().Add(G2frame.dataDisplay,1,wx.ALL|wx.EXPAND) 7360 7134 G2frame.SeqTable = G2G.Table([list(cl) for cl in zip(*G2frame.colList)], # convert from columns to rows -
branch/2frame/GSASIIpwdGUI.py
r2960 r2963 32 32 import GSASIIpwd as G2pwd 33 33 import GSASIIIO as G2IO 34 import GSASIIfiles as G2fil 34 35 import GSASIIobj as G2obj 35 36 import GSASIIlattice as G2lat … … 1470 1471 if 'Bank' not in Inst: #patch for old .instprm files - may cause faults for TOF data 1471 1472 Inst['Bank'] = [1,1,0] 1472 data = G2 IO.makeInstDict(newItems,newVals,len(newVals)*[False,])1473 data = G2fil.makeInstDict(newItems,newVals,len(newVals)*[False,]) 1473 1474 G2frame.GPXtree.SetItemPyData(G2gd.GetGPXtreeItemId(G2frame,G2frame.PatternId,'Instrument Parameters'),[data,Inst2]) 1474 1475 RefreshInstrumentGrid(event,doAnyway=True) #to get peaks updated -
branch/2frame/GSASIIscriptable.py
r2895 r2963 10 10 11 11 """ 12 from __future__ import division, print_function # needed? 12 13 import os.path as ospath 13 14 import sys … … 15 16 import imp 16 17 import copy 18 import platform 19 import os 20 import random as ran 21 import json 22 23 import numpy.ma as ma 24 import scipy.interpolate as si 25 import numpy as np 26 import scipy as sp 27 import matplotlib as mpl 28 17 29 import GSASIIpath 30 GSASIIpath.SetBinaryPath() # would rather have this in __name__ == '__main__' stanza 31 import GSASIIIO as G2IO 32 import GSASIIfiles as G2fil 18 33 import GSASIIobj as G2obj 34 import GSASIIpwd as G2pwd 35 import GSASIIstrIO as G2strIO 36 import GSASIIspc as G2spc 37 import GSASIIstrMain as G2strMain 38 import GSASIImath as G2mth 39 import GSASIIElem as G2elem 19 40 20 41 def LoadDictFromProjFile(ProjFile): 21 ''' 'Read a GSAS-II project file and load items to dictionary42 '''Read a GSAS-II project file and load items to dictionary 22 43 :param: str ProjFile: GSAS-II project (name.gpx) full file name 23 44 :returns: dict Project: representation of gpx file following the GSAS-II tree struture … … 25 46 data dict = {'data':item data whch may be list, dict or None,'subitems':subdata (if any)} 26 47 :returns: list nameList: names of main tree entries & subentries used to reconstruct project file 48 27 49 Example for fap.gpx: 28 50 Project = { #NB:dict order is not tree order … … 60 82 return 61 83 file = open(ProjFile,'rb') 62 print 'loading from file: ',ProjFile84 print('loading from file: {}'.format(ProjFile)) 63 85 Project = {} 64 86 nameList = [] … … 90 112 ''' 91 113 file = open(ProjFile,'wb') 92 print 'save to file: ',ProjFile114 print('save to file: {}'.format(ProjFile)) 93 115 for name in nameList: 94 116 data = [] … … 118 140 rd = rdclass.GSAS_ReaderClass() 119 141 if not rd.scriptable: 120 print '**** ERROR: ',reader,' is not a scriptable reader'142 print(u'**** ERROR: '+reader+u' is not a scriptable reader') 121 143 return None 122 144 fl = open(filename,'rb') … … 137 159 repeat = True 138 160 return rdlist 139 print rd.errors161 print(rd.errors) 140 162 return None 141 163 164 def SetDefaultDData(dType,histoName,NShkl=0,NDij=0): 165 '''Create an initial Histogram dictionary 166 167 Author: Jackson O'Donnell jacksonhodonnell@gmail.com 168 ''' 169 if dType in ['SXC','SNC']: 170 return {'Histogram':histoName,'Show':False,'Scale':[1.0,True], 171 'Babinet':{'BabA':[0.0,False],'BabU':[0.0,False]}, 172 'Extinction':['Lorentzian','None', {'Tbar':0.1,'Cos2TM':0.955, 173 'Eg':[1.e-10,False],'Es':[1.e-10,False],'Ep':[1.e-10,False]}], 174 'Flack':[0.0,False]} 175 elif dType == 'SNT': 176 return {'Histogram':histoName,'Show':False,'Scale':[1.0,True], 177 'Babinet':{'BabA':[0.0,False],'BabU':[0.0,False]}, 178 'Extinction':['Lorentzian','None', { 179 'Eg':[1.e-10,False],'Es':[1.e-10,False],'Ep':[1.e-10,False]}]} 180 elif 'P' in dType: 181 return {'Histogram':histoName,'Show':False,'Scale':[1.0,False], 182 'Pref.Ori.':['MD',1.0,False,[0,0,1],0,{},[],0.1], 183 'Size':['isotropic',[1.,1.,1.],[False,False,False],[0,0,1], 184 [1.,1.,1.,0.,0.,0.],6*[False,]], 185 'Mustrain':['isotropic',[1000.0,1000.0,1.0],[False,False,False],[0,0,1], 186 NShkl*[0.01,],NShkl*[False,]], 187 'HStrain':[NDij*[0.0,],NDij*[False,]], 188 'Extinction':[0.0,False],'Babinet':{'BabA':[0.0,False],'BabU':[0.0,False]}} 189 190 191 def PreSetup(data): 192 '''Create part of an initial (empty) phase dictionary 193 194 from GSASIIphsGUI.py, near end of UpdatePhaseData 195 Author: Jackson O'Donnell jacksonhodonnell@gmail.com 196 ''' 197 if 'RBModels' not in data: 198 data['RBModels'] = {} 199 if 'MCSA' not in data: 200 data['MCSA'] = {'Models':[{'Type':'MD','Coef':[1.0,False,[.8,1.2],],'axis':[0,0,1]}],'Results':[],'AtInfo':{}} 201 if 'dict' in str(type(data['MCSA']['Results'])): 202 data['MCSA']['Results'] = [] 203 if 'Modulated' not in data['General']: 204 data['General']['Modulated'] = False 205 if 'modulated' in data['General']['Type']: 206 data['General']['Modulated'] = True 207 data['General']['Type'] = 'nuclear' 208 209 210 def SetupGeneral(data, dirname): 211 """Helps initialize phase data. 212 213 From GSASIIphsGui.py, function of the same name. Minor changes for imports etc. 214 Author: Jackson O'Donnell jacksonhodonnell@gmail.com 215 """ 216 mapDefault = {'MapType':'','RefList':'','Resolution':0.5,'Show bonds':True, 217 'rho':[],'rhoMax':0.,'mapSize':10.0,'cutOff':50.,'Flip':False} 218 generalData = data['General'] 219 atomData = data['Atoms'] 220 generalData['AtomTypes'] = [] 221 generalData['Isotopes'] = {} 222 223 if 'Isotope' not in generalData: 224 generalData['Isotope'] = {} 225 if 'Data plot type' not in generalData: 226 generalData['Data plot type'] = 'Mustrain' 227 if 'POhkl' not in generalData: 228 generalData['POhkl'] = [0,0,1] 229 if 'Map' not in generalData: 230 generalData['Map'] = mapDefault.copy() 231 if 'Flip' not in generalData: 232 generalData['Flip'] = {'RefList':'','Resolution':0.5,'Norm element':'None', 233 'k-factor':0.1,'k-Max':20.,} 234 if 'testHKL' not in generalData['Flip']: 235 generalData['Flip']['testHKL'] = [[0,0,2],[2,0,0],[1,1,1],[0,2,0],[1,2,3]] 236 if 'doPawley' not in generalData: 237 generalData['doPawley'] = False #ToDo: change to '' 238 if 'Pawley dmin' not in generalData: 239 generalData['Pawley dmin'] = 1.0 240 if 'Pawley neg wt' not in generalData: 241 generalData['Pawley neg wt'] = 0.0 242 if 'Algolrithm' in generalData.get('MCSA controls',{}) or \ 243 'MCSA controls' not in generalData: 244 generalData['MCSA controls'] = {'Data source':'','Annealing':[50.,0.001,50], 245 'dmin':2.0,'Algorithm':'log','Jump coeff':[0.95,0.5],'boltzmann':1.0, 246 'fast parms':[1.0,1.0,1.0],'log slope':0.9,'Cycles':1,'Results':[],'newDmin':True} 247 if 'AtomPtrs' not in generalData: 248 generalData['AtomPtrs'] = [3,1,7,9] 249 if generalData['Type'] == 'macromolecular': 250 generalData['AtomPtrs'] = [6,4,10,12] 251 elif generalData['Type'] == 'magnetic': 252 generalData['AtomPtrs'] = [3,1,10,12] 253 if generalData['Type'] in ['modulated',]: 254 generalData['Modulated'] = True 255 generalData['Type'] = 'nuclear' 256 if 'Super' not in generalData: 257 generalData['Super'] = 1 258 generalData['SuperVec'] = [[0,0,.1],False,4] 259 generalData['SSGData'] = {} 260 if '4DmapData' not in generalData: 261 generalData['4DmapData'] = mapDefault.copy() 262 generalData['4DmapData'].update({'MapType':'Fobs'}) 263 if 'Modulated' not in generalData: 264 generalData['Modulated'] = False 265 if 'HydIds' not in generalData: 266 generalData['HydIds'] = {} 267 cx,ct,cs,cia = generalData['AtomPtrs'] 268 generalData['NoAtoms'] = {} 269 generalData['BondRadii'] = [] 270 generalData['AngleRadii'] = [] 271 generalData['vdWRadii'] = [] 272 generalData['AtomMass'] = [] 273 generalData['Color'] = [] 274 if generalData['Type'] == 'magnetic': 275 generalData['MagDmin'] = generalData.get('MagDmin',1.0) 276 landeg = generalData.get('Lande g',[]) 277 generalData['Mydir'] = dirname 278 badList = {} 279 for iat,atom in enumerate(atomData): 280 atom[ct] = atom[ct].lower().capitalize() #force to standard form 281 if generalData['AtomTypes'].count(atom[ct]): 282 generalData['NoAtoms'][atom[ct]] += atom[cx+3]*float(atom[cs+1]) 283 elif atom[ct] != 'UNK': 284 Info = G2elem.GetAtomInfo(atom[ct]) 285 if not Info: 286 if atom[ct] not in badList: 287 badList[atom[ct]] = 0 288 badList[atom[ct]] += 1 289 atom[ct] = 'UNK' 290 continue 291 atom[ct] = Info['Symbol'] # N.B. symbol might be changed by GetAtomInfo 292 generalData['AtomTypes'].append(atom[ct]) 293 generalData['Z'] = Info['Z'] 294 generalData['Isotopes'][atom[ct]] = Info['Isotopes'] 295 generalData['BondRadii'].append(Info['Drad']) 296 generalData['AngleRadii'].append(Info['Arad']) 297 generalData['vdWRadii'].append(Info['Vdrad']) 298 if atom[ct] in generalData['Isotope']: 299 if generalData['Isotope'][atom[ct]] not in generalData['Isotopes'][atom[ct]]: 300 isotope = generalData['Isotopes'][atom[ct]].keys()[-1] 301 generalData['Isotope'][atom[ct]] = isotope 302 generalData['AtomMass'].append(Info['Isotopes'][generalData['Isotope'][atom[ct]]]['Mass']) 303 else: 304 generalData['Isotope'][atom[ct]] = 'Nat. Abund.' 305 if 'Nat. Abund.' not in generalData['Isotopes'][atom[ct]]: 306 isotope = generalData['Isotopes'][atom[ct]].keys()[-1] 307 generalData['Isotope'][atom[ct]] = isotope 308 generalData['AtomMass'].append(Info['Mass']) 309 generalData['NoAtoms'][atom[ct]] = atom[cx+3]*float(atom[cs+1]) 310 generalData['Color'].append(Info['Color']) 311 if generalData['Type'] == 'magnetic': 312 if len(landeg) < len(generalData['AtomTypes']): 313 landeg.append(2.0) 314 if generalData['Type'] == 'magnetic': 315 generalData['Lande g'] = landeg[:len(generalData['AtomTypes'])] 316 317 if badList: 318 msg = 'Warning: element symbol(s) not found:' 319 for key in badList: 320 msg += '\n\t' + key 321 if badList[key] > 1: 322 msg += ' (' + str(badList[key]) + ' times)' 323 raise Exception("Phase error:\n" + msg) 324 # wx.MessageBox(msg,caption='Element symbol error') 325 F000X = 0. 326 F000N = 0. 327 for i,elem in enumerate(generalData['AtomTypes']): 328 F000X += generalData['NoAtoms'][elem]*generalData['Z'] 329 isotope = generalData['Isotope'][elem] 330 F000N += generalData['NoAtoms'][elem]*generalData['Isotopes'][elem][isotope]['SL'][0] 331 generalData['F000X'] = F000X 332 generalData['F000N'] = F000N 333 generalData['Mass'] = G2mth.getMass(generalData) 334 335 def make_empty_project(author=None, filename=None): 336 """Creates an dictionary in the style of GSASIIscriptable, for an empty 337 project. 338 339 If no author name or filename is supplied, 'no name' and 340 <current dir>/test_output.gpx are used , respectively. 341 342 Returns: project dictionary, name list 343 Author: Jackson O'Donnell jacksonhodonnell@gmail.com 344 """ 345 if not filename: 346 filename = os.path.join(os.getcwd(), 'test_output.gpx') 347 else: 348 filename = os.path.abspath(filename) 349 gsasii_version = str(GSASIIpath.GetVersionNumber()) 350 python_library_versions = G2fil.get_python_versions([mpl, np, sp]) 351 352 controls_data = dict(G2obj.DefaultControls) 353 controls_data['LastSavedAs'] = unicode(filename) 354 controls_data['LastSavedUsing'] = gsasii_version 355 controls_data['PythonVersions'] = python_library_versions 356 if author: 357 controls_data['Author'] = author 358 359 output = {'Constraints': {'data': {'HAP': [], 'Hist': [], 'Phase': [], 360 'Global': []}}, 361 'Controls': {'data': controls_data}, 362 u'Covariance': {'data': {}}, 363 u'Notebook': {'data': ['']}, 364 u'Restraints': {'data': {}}, 365 u'Rigid bodies': {'data': {'RBIds': {'Residue': [], 'Vector': []}, 366 'Residue': {'AtInfo': {}}, 367 'Vector': {'AtInfo': {}}}}} 368 369 names = [[u'Notebook'], [u'Controls'], [u'Covariance'], 370 [u'Constraints'], [u'Restraints'], [u'Rigid bodies']] 371 372 return output, names 373 374 375 class G2ImportException(Exception): 376 pass 377 378 379 def import_generic(filename, readerlist): 380 """Attempt to import a filename, using a list of reader objects. 381 382 Returns the first reader object which worked.""" 383 # Translated from OnImportGeneric method in GSASII.py 384 primaryReaders, secondaryReaders = [], [] 385 for reader in readerlist: 386 flag = reader.ExtensionValidator(filename) 387 if flag is None: 388 secondaryReaders.append(reader) 389 elif flag: 390 primaryReaders.append(reader) 391 if not secondaryReaders and not primaryReaders: 392 raise G2ImportException("Could not read file: ", filename) 393 394 with open(filename, 'Ur') as fp: 395 rd_list = [] 396 397 for rd in primaryReaders + secondaryReaders: 398 # Initialize reader 399 rd.selections = [] 400 rd.dnames = [] 401 rd.ReInitialize() 402 # Rewind file 403 fp.seek(0) 404 rd.errors = "" 405 if not rd.ContentsValidator(fp): 406 # Report error 407 pass 408 if len(rd.selections) > 1: 409 # Select data? 410 # GSASII.py:543 411 raise G2ImportException("Not sure what data to select") 412 413 block = 0 414 rdbuffer = {} 415 fp.seek(0) 416 repeat = True 417 while repeat: 418 repeat = False 419 block += 1 420 rd.objname = os.path.basename(filename) 421 flag = rd.Reader(filename, fp, buffer=rdbuffer, blocknum=block) 422 if flag: 423 # Omitting image loading special cases 424 rd.readfilename = filename 425 rd_list.append(copy.deepcopy(rd)) 426 repeat = rd.repeat 427 else: 428 raise G2ImportException("{}.Reader() returned:".format(rd), 429 flag) 430 431 if rd_list: 432 if rd.warnings: 433 print("Read warning by", rd.formatName, "reader:", 434 rd.warnings, file=sys.stderr) 435 return rd_list 436 raise G2ImportException("No reader could read file: " + filename) 437 438 439 def load_iprms(instfile, reader): 440 """Loads instrument parameters from a file, and edits the 441 given reader. 442 443 Returns a 2-tuple of (Iparm1, Iparm2) parameters 444 """ 445 ext = os.path.splitext(instfile)[1] 446 447 if ext.lower() == '.instprm': 448 # New GSAS File, load appropriately 449 with open(instfile) as f: 450 lines = f.readlines() 451 bank = reader.powderentry[2] 452 numbanks = reader.numbanks 453 iparms = G2fil.ReadPowderInstprm(lines, bank, numbanks, reader) 454 455 reader.instfile = instfile 456 reader.instmsg = 'GSAS-II file' + instfile 457 return iparms 458 elif ext.lower() not in ('.prm', '.inst', '.ins'): 459 raise ValueError('Expected .prm file, found: ', instfile) 460 461 # It's an old GSAS file, load appropriately 462 Iparm = {} 463 with open(instfile, 'Ur') as fp: 464 for line in fp: 465 if '#' in line: 466 continue 467 Iparm[line[:12]] = line[12:-1] 468 ibanks = int(Iparm.get('INS BANK ', '1').strip()) 469 if ibanks == 1: 470 reader.instbank = 1 471 reader.powderentry[2] = 1 472 reader.instfile = instfile 473 reader.instmsg = instfile + ' bank ' + str(reader.instbank) 474 return G2fil.SetPowderInstParms(Iparm, reader) 475 # TODO handle >1 banks 476 raise NotImplementedError("Check GSASIIfiles.py: ReadPowderInstprm") 477 478 def load_pwd_from_reader(reader, instprm, existingnames=[]): 479 """Loads powder data from a reader object, and assembles it into a GSASII data tree. 480 481 Returns: (name, tree) - 2-tuple of the histogram name (str), and data 482 Author: Jackson O'Donnell jacksonhodonnell@gmail.com 483 """ 484 HistName = 'PWDR ' + G2obj.StripUnicode(reader.idstring, '_') 485 HistName = unicode(G2obj.MakeUniqueLabel(HistName, existingnames)) 486 487 try: 488 Iparm1, Iparm2 = instprm 489 except ValueError: 490 # TODO load_iprms 491 Iparm1, Iparm2 = load_iprms(instprm, reader) 492 493 Ymin = np.min(reader.powderdata[1]) 494 Ymax = np.max(reader.powderdata[1]) 495 valuesdict = {'wtFactor': 1.0, 496 'Dummy': False, 497 'ranId': ran.randint(0, sys.maxint), 498 'Offset': [0.0, 0.0], 'delOffset': 0.02*Ymax, 499 'refOffset': -0.1*Ymax, 'refDelt': 0.1*Ymax, 500 'qPlot': False, 'dPlot': False, 'sqrtPlot': False, 501 'Yminmax': [Ymin, Ymax]} 502 reader.Sample['ranId'] = valuesdict['ranId'] 503 504 # Ending keys: 505 # [u'Reflection Lists', 506 # u'Limits', 507 # 'data', 508 # u'Index Peak List', 509 # u'Comments', 510 # u'Unit Cells List', 511 # u'Sample Parameters', 512 # u'Peak List', 513 # u'Background', 514 # u'Instrument Parameters'] 515 Tmin = np.min(reader.powderdata[0]) 516 Tmax = np.max(reader.powderdata[0]) 517 518 default_background = [['chebyschev', False, 3, 1.0, 0.0, 0.0], 519 {'nDebye': 0, 'debyeTerms': [], 'nPeaks': 0, 'peaksList': []}] 520 521 output_dict = {u'Reflection Lists': {}, 522 u'Limits': reader.pwdparms.get('Limits', [(Tmin, Tmax), [Tmin, Tmax]]), 523 u'data': [valuesdict, reader.powderdata, HistName], 524 u'Index Peak List': [[], []], 525 u'Comments': reader.comments, 526 u'Unit Cells List': [], 527 u'Sample Parameters': reader.Sample, 528 u'Peak List': {'peaks': [], 'sigDict': {}}, 529 u'Background': reader.pwdparms.get('Background', default_background), 530 u'Instrument Parameters': [Iparm1, Iparm2], 531 } 532 533 names = [u'Comments', 534 u'Limits', 535 u'Background', 536 u'Instrument Parameters', 537 u'Sample Parameters', 538 u'Peak List', 539 u'Index Peak List', 540 u'Unit Cells List', 541 u'Reflection Lists'] 542 543 # TODO controls?? GSASII.py:1664-7 544 545 return HistName, [HistName] + names, output_dict 546 547 548 def _deep_copy_into(from_, into): 549 """Helper function for reloading .gpx file. See G2Project.reload() 550 Author: Jackson O'Donnell jacksonhodonnell@gmail.com 551 """ 552 if isinstance(from_, dict) and isinstance(into, dict): 553 combined_keys = set(from_.keys()).union(into.keys()) 554 for key in combined_keys: 555 if key in from_ and key in into: 556 both_dicts = (isinstance(from_[key], dict) 557 and isinstance(into[key], dict)) 558 both_lists = (isinstance(from_[key], list) 559 and isinstance(into[key], list)) 560 if both_dicts or both_lists: 561 _deep_copy_into(from_[key], into[key]) 562 else: 563 into[key] = from_[key] 564 elif key in from_: 565 into[key] = from_[key] 566 else: # key in into 567 del into[key] 568 elif isinstance(from_, list) and isinstance(into, list): 569 if len(from_) == len(into): 570 for i in xrange(len(from_)): 571 both_dicts = (isinstance(from_[i], dict) 572 and isinstance(into[i], dict)) 573 both_lists = (isinstance(from_[i], list) 574 and isinstance(into[i], list)) 575 if both_dicts or both_lists: 576 _deep_copy_into(from_[i], into[i]) 577 else: 578 into[i] = from_[i] 579 else: 580 into[:] = from_ 581 582 583 class G2ObjectWrapper(object): 584 """Base class for all GSAS-II object wrappers 585 Author: Jackson O'Donnell jacksonhodonnell@gmail.com 586 """ 587 def __init__(self, datadict): 588 self.data = datadict 589 590 def __getitem__(self, key): 591 return self.data[key] 592 593 def __setitem__(self, key, value): 594 self.data[key] = value 595 596 def __contains__(self, key): 597 return key in self.data 598 599 def get(self, k, d=None): 600 return self.data.get(k, d) 601 602 def keys(self): 603 return self.data.keys() 604 605 def values(self): 606 return self.data.values() 607 608 def items(self): 609 return self.data.items() 610 611 612 class G2Project(G2ObjectWrapper): 613 def __init__(self, gpxfile=None, author=None, filename=None): 614 """Loads a GSAS-II project from a specified filename. 615 616 :param str gpxfile: Existing .gpx file to be loaded. If nonexistent, 617 creates an empty project. 618 :param str author: Author's name. Optional. 619 :param str filename: The filename the project should be saved to in 620 the future. If both filename and gpxfile are present, the project is 621 loaded from the gpxfile, then set to save to filename in the future""" 622 if gpxfile is None: 623 self.filename = filename 624 self.data, self.names = make_empty_project(author=author, filename=filename) 625 elif isinstance(gpxfile, str): 626 # TODO set author, filename 627 self.filename = gpxfile 628 self.data, self.names = LoadDictFromProjFile(gpxfile) 629 self.index_ids() 630 else: 631 raise ValueError("Not sure what to do with gpxfile") 632 633 @classmethod 634 def from_dict_and_names(cls, gpxdict, names, filename=None): 635 out = cls() 636 if filename: 637 out.filename = filename 638 gpxdict['Controls']['data']['LastSavedAs'] = filename 639 else: 640 try: 641 out.filename = gpxdict['Controls']['data']['LastSavedAs'] 642 except KeyError: 643 out.filename = None 644 out.data = gpxdict 645 out.names = names 646 647 def save(self, filename=None): 648 """Saves the project, either to the current filename, or to a new file. 649 650 Updates self.filename if a new filename provided""" 651 # TODO update LastSavedUsing ? 652 if filename: 653 self.data['Controls']['data']['LastSavedAs'] = filename 654 self.filename = filename 655 elif not self.filename: 656 raise AttributeError("No file name to save to") 657 SaveDictToProjFile(self.data, self.names, self.filename) 658 659 def add_powder_histogram(self, datafile, iparams): 660 """Loads a powder data histogram into the project. 661 662 Automatically checks for an instrument parameter file, or one can be 663 provided.""" 664 pwdrreaders = import_generic(datafile, PwdrDataReaders) 665 histname, new_names, pwdrdata = load_pwd_from_reader( 666 pwdrreaders[0], iparams, 667 list(self.histogram_names())) 668 if histname in self.data: 669 print("Warning - redefining histogram", histname) 670 else: 671 if self.names[-1][0] == 'Phases': 672 self.names.insert(-1, new_names) 673 else: 674 self.names.append(new_names) 675 self.data[histname] = pwdrdata 676 return self.histogram(histname) 677 678 def add_phase(self, phasefile, phasename=None, histograms=[]): 679 """Loads a phase into the project from a .cif file 680 681 :returns: A :class:`gpx_manipulations.G2Phase` object representing the 682 new phase.""" 683 # TODO handle multiple phases in a file 684 phasereaders = import_generic(phasefile, PhaseReaders) 685 phasereader = phasereaders[0] 686 687 phasename = phasename or phasereader.Phase['General']['Name'] 688 phaseNameList = list(self.phase_names()) 689 phasename = G2obj.MakeUniqueLabel(phasename, phaseNameList) 690 phasereader.Phase['General']['Name'] = phasename 691 692 if 'Phases' not in self.data: 693 self.data[u'Phases'] = { 'data': None } 694 assert phasename not in self.data['Phases'], "phase names should be unique" 695 self.data['Phases'][phasename] = phasereader.Phase 696 697 if phasereader.Constraints: 698 Constraints = self.data['Constraints'] 699 for i in phasereader.Constraints: 700 if isinstance(i, dict): 701 if '_Explain' not in Constraints: 702 Constraints['_Explain'] = {} 703 Constraints['_Explain'].update(i) 704 else: 705 Constraints['Phase'].append(i) 706 707 data = self.data['Phases'][phasename] 708 generalData = data['General'] 709 SGData = generalData['SGData'] 710 NShkl = len(G2spc.MustrainNames(SGData)) 711 NDij = len(G2spc.HStrainNames(SGData)) 712 Super = generalData.get('Super', 0) 713 if Super: 714 SuperVec = np.array(generalData['SuperVec'][0]) 715 else: 716 SuperVec = [] 717 UseList = data['Histograms'] 718 719 for histname in histograms: 720 if histname.startswith('HKLF '): 721 raise NotImplementedError("Does not support HKLF yet") 722 elif histname.startswith('PWDR '): 723 hist = self.histogram(histname) 724 hist['Reflection Lists'][generalData['Name']] = {} 725 UseList[histname] = SetDefaultDData('PWDR', histname, NShkl=NShkl, NDij=NDij) 726 for key, val in [('Use', True), ('LeBail', False), 727 ('newLeBail', True), 728 ('Babinet', {'BabA': [0.0, False], 729 'BabU': [0.0, False]})]: 730 if key not in UseList[histname]: 731 UseList[histname][key] = val 732 else: 733 raise NotImplementedError("Unexpected histogram" + histname) 734 735 for obj in self.names: 736 if obj[0] == 'Phases': 737 phasenames = obj 738 break 739 else: 740 phasenames = [u'Phases'] 741 self.names.append(phasenames) 742 phasenames.append(unicode(phasename)) 743 744 # TODO should it be self.filename, not phasefile? 745 SetupGeneral(data, os.path.dirname(phasefile)) 746 self.index_ids() 747 748 return self.phase(phasename) 749 750 def reload(self): 751 """Reload self from self.filename""" 752 data, names = LoadDictFromProjFile(self.filename) 753 self.names = names 754 # Need to deep copy the new data file data into the current tree, 755 # so that any existing G2Phase, or G2PwdrData objects will still be 756 # valid 757 _deep_copy_into(from_=data, into=self.data) 758 759 def refine(self, newfile=None, printFile=None): 760 # index_ids will automatically save the project 761 self.index_ids() 762 # TODO G2strMain does not properly use printFile 763 G2strMain.Refine(self.filename) 764 # Reload yourself 765 self.reload() 766 767 def histogram_names(self): 768 """Gives an iterator of the names of each histogram in the project.""" 769 for obj in self.names: 770 if len(obj) > 1 and obj[0] != u'Phases': 771 yield obj[0] 772 773 def histogram(self, histname): 774 """Returns the histogram named histname, or None if it does not exist.""" 775 if histname in self.data: 776 return G2PwdrData(self.data[histname]) 777 return None 778 779 def histograms(self): 780 """Return a list of all histograms, as 781 :class:`gpx_manipulations.G2PwdrData` objects""" 782 return [self.histogram(name) for name in self.histogram_names()] 783 784 def phase_names(self): 785 """Gives an iterator of the names of each phase in the project.""" 786 for obj in self.names: 787 if obj[0] == 'Phases': 788 for name in obj[1:]: 789 yield name 790 break 791 792 def phase(self, phasename): 793 return G2Phase(self.data['Phases'][phasename]) 794 795 def phases(self): 796 return [self.phase(name) for name in self.phase_names()] 797 798 def do_refinements(self, refinements, histogram='all', phase='all', 799 outputnames=None): 800 """Conducts a series of refinements.""" 801 if outputnames: 802 if len(refinements) != len(outputnames): 803 raise ValueError("Should have same number of outuputs to" 804 "refinements") 805 else: 806 outputnames = [None for r in refinements] 807 808 for output, refinement in zip(outputnames, refinements): 809 self.set_refinement(refinement, histogram) 810 # Handle 'once' args - refinements that are disabled after this 811 # refinement 812 if 'once' in refinement: 813 temp = {'set': refinement['once']} 814 self.set_refinement(temp, histogram, phase) 815 816 if output: 817 self.save(output) 818 819 self.refine() # newFile=output) 820 821 # Handle 'once' args - refinements that are disabled after this 822 # refinement 823 if 'once' in refinement: 824 temp = {'clear': refinement['once']} 825 self.set_refinement(temp, histogram, phase) 826 827 def set_refinement(self, refinement, histogram='all', phase='all'): 828 """Apply specified refinements to a given histogram(s) or phase(s). 829 830 :param dict refinement: The refinements to be conducted 831 :param histogram: Either a name of a histogram (str), a list of 832 histogram names, or 'all' (default) 833 :param phase: Either a name of a phase (str), a list of phase names, or 834 'all' (default)""" 835 if histogram == 'all': 836 hists = [self.histogram(name) 837 for name in self.histogram_names()] 838 elif isinstance(histogram, str): 839 hists = [self.histogram(histogram)] 840 else: 841 hists = [self.histogram(name) for name in histogram] 842 843 if phase == 'all': 844 phases = [self.phase(name) for name in self.phase_names()] 845 elif isinstance(phase, str): 846 phases = [self.phase(phase)] 847 else: 848 phases = [self.phase(name) for name in phase] 849 850 for key, val in refinement.get('set', {}).items(): 851 # Apply refinement options 852 if G2PwdrData.is_valid_refinement_key(key): 853 for hist in hists: 854 hist.set_refinement(key, val) 855 elif G2Phase.is_valid_refinement_key(key): 856 for phase in phases: 857 phase.set_refinement(key, val) 858 else: 859 print("Unknown refinement key:", key) 860 861 for key, val in refinement.get('clear', {}).items(): 862 # Clear refinement options 863 if G2PwdrData.is_valid_refinement_key(key): 864 for hist in hists: 865 hist.clear_refinement(key, val) 866 elif G2Phase.is_valid_refinement_key(key): 867 for phase in phases: 868 phase.clear_refinement(key, val) 869 else: 870 print("Unknown refinement key:", key) 871 872 def index_ids(self): 873 self.save() 874 return G2strIO.GetUsedHistogramsAndPhases(self.filename) 875 876 def add_constraint_raw(self, cons_scope, constr): 877 """Adds a constraint of type consType to the project. 878 cons_scope should be one of "Hist", "Phase", "HAP", or "Global". 879 880 WARNING it does not check the constraint is well-constructed""" 881 constrs = self['Constraints']['data'] 882 if 'Global' not in constrs: 883 constrs['Global'] = [] 884 constrs[cons_scope].append(constr) 885 886 def hold_many(self, vars, type): 887 """Apply holds for all the variables in vars, for constraint of a given type. 888 889 type is passed directly to add_constraint_raw as consType 890 891 :param list vars: A list of variables to hold. Either G2obj.G2VarObj objects, 892 string variable specifiers, or arguments for :meth:`make_var_obj` 893 :param str type: A string constraint type specifier. See 894 :meth:`add_constraint_raw`""" 895 for var in vars: 896 if isinstance(var, str): 897 var = self.make_var_obj(var) 898 elif not isinstance(var, G2obj.G2VarObj): 899 var = self.make_var_obj(*var) 900 self.add_constraint_raw(type, [[1.0, var], None, None, 'h']) 901 902 def make_var_obj(self, phase=None, hist=None, varname=None, atomId=None, 903 reloadIdx=True): 904 """Wrapper to create a G2VarObj. Takes either a string representaiton ("p:h:name:a") 905 or individual names of phase, histogram, varname, and atomId. 906 907 Automatically converts string phase, hist, or atom names into the ID required 908 by G2VarObj.""" 909 if reloadIdx: 910 self.index_ids() 911 912 # If string representation, short circuit 913 if hist is None and varname is None and atomId is None: 914 if isinstance(phase, str) and ':' in phase: 915 return G2obj.G2VarObj(phase) 916 917 # Get phase index 918 phaseObj = None 919 if isinstance(phase, G2Phase): 920 phaseObj = phase 921 phase = G2obj.PhaseRanIdLookup[phase.ranId] 922 elif phase in self['Phases']: 923 phaseObj = self.phase(phase) 924 phaseRanId = phaseObj.ranId 925 phase = G2obj.PhaseRanIdLookup[phaseRanId] 926 927 # Get histogram index 928 if isinstance(hist, G2PwdrData): 929 hist = G2obj.HistRanIdLookup[hist.ranId] 930 elif hist in self.data: 931 histRanId = self.histogram(hist).ranId 932 hist = G2obj.HistRanIdLookup[histRanId] 933 934 # Get atom index (if any) 935 if isinstance(atomId, G2AtomRecord): 936 atomId = G2obj.AtomRanIdLookup[phase][atomId.ranId] 937 elif phaseObj: 938 atomObj = phaseObj.atom(atomId) 939 if atomObj: 940 atomRanId = atomObj.ranId 941 atomId = G2obj.AtomRanIdLookup[phase][atomRanId] 942 943 return G2obj.G2VarObj(phase, hist, varname, atomId) 944 945 946 class G2AtomRecord(G2ObjectWrapper): 947 """Wrapper for an atom record 948 Author: Jackson O'Donnell jacksonhodonnell@gmail.com 949 """ 950 def __init__(self, data, indices): 951 self.data = data 952 self.cx, self.ct, self.cs, self.cia = indices 953 954 @property 955 def label(self): 956 return self.data[self.ct-1] 957 958 @property 959 def type(self): 960 return self.data[self.ct] 961 962 @property 963 def refinement_flags(self): 964 return self.data[self.ct+1] 965 966 @refinement_flags.setter 967 def set_refinement(self, other): 968 for c in other: 969 if c not in ' FXU': 970 raise ValueError("Invalid atom refinement: ", other) 971 self.data[self.ct+1] = unicode(other) 972 973 @property 974 def coordinates(self): 975 return tuple(self.data[self.cx:self.cx+3]) 976 977 @property 978 def ranId(self): 979 return self.data[self.cia+8] 980 981 @property 982 def adp_flag(self): 983 # Either 'I' or 'A' 984 return self.data[self.cia] 985 986 @property 987 def uiso(self): 988 if self.adp_flag == 'I': 989 return self.data[self.cia+1] 990 else: 991 return self.data[self.cia+2:self.cia+8] 992 993 994 class G2PwdrData(G2ObjectWrapper): 995 """Wraps a Poweder Data Histogram. 996 Author: Jackson O'Donnell jacksonhodonnell@gmail.com 997 """ 998 @staticmethod 999 def is_valid_refinement_key(key): 1000 valid_keys = ['Limits', 'Sample Parameters', 'Background', 1001 'Instrument Parameters'] 1002 return key in valid_keys 1003 1004 @property 1005 def name(self): 1006 return self['data'][-1] 1007 1008 @property 1009 def ranId(self): 1010 return self['data'][0]['ranId'] 1011 1012 def fit_fixed_points(self): 1013 """Attempts to apply a background fit to the fixed points currently specified.""" 1014 1015 def SetInstParms(Inst): 1016 dataType = Inst['Type'][0] 1017 insVary = [] 1018 insNames = [] 1019 insVals = [] 1020 for parm in Inst: 1021 insNames.append(parm) 1022 insVals.append(Inst[parm][1]) 1023 if parm in ['U','V','W','X','Y','SH/L','I(L2)/I(L1)','alpha', 1024 'beta-0','beta-1','beta-q','sig-0','sig-1','sig-2','sig-q',] and Inst[parm][2]: 1025 Inst[parm][2] = False 1026 instDict = dict(zip(insNames, insVals)) 1027 instDict['X'] = max(instDict['X'], 0.01) 1028 instDict['Y'] = max(instDict['Y'], 0.01) 1029 if 'SH/L' in instDict: 1030 instDict['SH/L'] = max(instDict['SH/L'], 0.002) 1031 return dataType, instDict, insVary 1032 1033 bgrnd = self['Background'] 1034 1035 # Need our fixed points in order 1036 bgrnd[1]['FixedPoints'].sort(key=lambda pair: pair[0]) 1037 X = [x for x, y in bgrnd[1]['FixedPoints']] 1038 Y = [y for x, y in bgrnd[1]['FixedPoints']] 1039 1040 # Some simple lookups 1041 limits = self['Limits'] 1042 inst, inst2 = self['Instrument Parameters'] 1043 pwddata = self['data'][1] 1044 1045 # Construct the data for background fitting 1046 xBeg = np.searchsorted(pwddata[0], limits[0]) 1047 xFin = np.searchsorted(pwddata[0], limits[1]) 1048 xdata = pwddata[0][xBeg:xFin] 1049 ydata = si.interp1d(X,Y)(ma.getdata(xdata)) 1050 1051 W = [1]*len(xdata) 1052 Z = [0]*len(xdata) 1053 1054 dataType, insDict, insVary = SetInstParms(inst) 1055 bakType, bakDict, bakVary = G2pwd.SetBackgroundParms(bgrnd) 1056 1057 # Do the fit 1058 # TODO get controls from root 1059 data = np.array([xdata, ydata, W, Z, Z, Z]) 1060 G2pwd.DoPeakFit('LSQ', [], bgrnd, limits, inst, inst2, data, 1061 preVaryList=bakVary, controls={}) 1062 1063 # Post-fit 1064 parmDict = {} 1065 bakType, bakDict, bakVary = G2pwd.SetBackgroundParms(bgrnd) 1066 parmDict.update(bakDict) 1067 parmDict.update(insDict) 1068 pwddata[3][xBeg:xFin] *= 0 1069 pwddata[5][xBeg:xFin] *= 0 1070 pwddata[4][xBeg:xFin] = G2pwd.getBackground('', parmDict, bakType, dataType, xdata)[0] 1071 1072 # TODO adjust pwddata? GSASIIpwdGUI.py:1041 1073 1074 def y_calc(self): 1075 return self['data'][1][3] 1076 1077 def set_refinement(self, key, value): 1078 """Sets the refinement parameter 'key' to the specification 'value'""" 1079 if key == 'Limits': 1080 old_limits = self.data['Limits'][1] 1081 new_limits = value 1082 if isinstance(new_limits, dict): 1083 if 'low' in new_limits: 1084 old_limits[0] = new_limits['low'] 1085 if 'high' in new_limits: 1086 old_limits[1] = new_limits['high'] 1087 else: 1088 old_limits[0], old_limits[1] = new_limits 1089 elif key == 'Sample Parameters': 1090 sample = self.data['Sample Parameters'] 1091 for sparam in value: 1092 sample[sparam][1] = True 1093 elif key == 'Background': 1094 bkg, peaks = self.data['Background'] 1095 1096 # If True or False, just set the refine parameter 1097 if value in (True, False): 1098 bkg[1] = value 1099 return 1100 1101 if 'type' in value: 1102 bkg[0] = value['type'] 1103 if 'refine' in value: 1104 bkg[1] = value['refine'] 1105 if 'no. coeffs' in value: 1106 cur_coeffs = bkg[2] 1107 n_coeffs = value['no. coeffs'] 1108 if n_coeffs > cur_coeffs: 1109 for x in range(n_coeffs - cur_coeffs): 1110 bkg.append(0.0) 1111 else: 1112 for _ in range(cur_coeffs - n_coeffs): 1113 bkg.pop() 1114 bkg[2] = n_coeffs 1115 if 'coeffs' in value: 1116 bkg[3:] = value['coeffs'] 1117 if 'FixedPoints' in value: 1118 peaks['FixedPoints'] = value 1119 if value.get('fit fixed points', False): 1120 self.fit_fixed_points() 1121 1122 elif key == 'Instrument Parameters': 1123 instrument, secondary = self.data['Instrument Parameters'] 1124 for iparam in value: 1125 try: 1126 instrument[iparam][2] = True 1127 except IndexError: 1128 raise ValueError("Invalid key:", iparam) 1129 else: 1130 raise ValueError("Unknown key:", key) 1131 1132 def clear_refinement(self, key, value): 1133 """Clears the refinement parameter 'key' and its associated value.""" 1134 if key == 'Limits': 1135 old_limits, cur_limits = self.data['Limits'] 1136 cur_limits[0], cur_limits[1] = old_limits 1137 elif key == 'Sample Parameters': 1138 sample = self.data['Sample Parameters'] 1139 for sparam in value: 1140 sample[sparam][1] = False 1141 elif key == 'Background': 1142 bkg, peaks = self.data['Background'] 1143 1144 # If True or False, just set the refine parameter 1145 if value in (True, False): 1146 bkg[1] = False 1147 return 1148 1149 bkg[1] = False 1150 if 'FixedPoints' in value: 1151 if 'FixedPoints' in peaks: 1152 del peaks['FixedPoints'] 1153 elif key == 'Instrument Parameters': 1154 instrument, secondary = self.data['Instrument Parameters'] 1155 for iparam in value: 1156 instrument[iparam][2] = False 1157 else: 1158 raise ValueError("Unknown key:", key) 1159 1160 1161 class G2Phase(G2ObjectWrapper): 1162 """A wrapper object around a given phase. 1163 Author: Jackson O'Donnell jacksonhodonnell@gmail.com 1164 """ 1165 @staticmethod 1166 def is_valid_refinement_key(key): 1167 valid_keys = ["Cell", "Atoms", "LeBail"] 1168 return key in valid_keys 1169 1170 def atom(self, atomlabel): 1171 """Returns the atom specified by atomlabel, or None if it does not 1172 exist.""" 1173 # Consult GSASIIobj.py for the meaning of this 1174 cx, ct, cs, cia = self.data['General']['AtomPtrs'] 1175 ptrs = [cx, ct, cs, cia] 1176 atoms = self.data['Atoms'] 1177 for atom in atoms: 1178 if atom[ct-1] == atomlabel: 1179 return G2AtomRecord(atom, ptrs) 1180 1181 def atoms(self): 1182 """Returns a list of atoms present in the phase.""" 1183 ptrs = self.data['General']['AtomPtrs'] 1184 output = [] 1185 atoms = self.data['Atoms'] 1186 for atom in atoms: 1187 output.append(G2AtomRecord(atom, ptrs)) 1188 return output 1189 1190 @property 1191 def ranId(self): 1192 return self.data['ranId'] 1193 1194 def cell_dict(self): 1195 cell = self['General']['Cell'] 1196 return {'a': cell[1], 'b': cell[2], 'c': cell[3], 1197 'alpha': cell[4], 'beta': cell[5], 'gamma': cell[6], 1198 'vol': cell[6]} 1199 1200 def set_refinement(self, key, value): 1201 if key == "Cell": 1202 self.data['General']['Cell'][0] = True 1203 elif key == "Atoms": 1204 cx, ct, cs, cia = self.data['General']['AtomPtrs'] 1205 1206 for atomlabel, atomrefinement in value.items(): 1207 atom = self.atom(atomlabel) 1208 atom.refinement_flags = atomrefinement 1209 elif key == "LeBail": 1210 hists = self.data['Histograms'] 1211 for hname, hoptions in hists.items(): 1212 if 'LeBail' not in hoptions: 1213 hoptions['newLeBail'] = True 1214 hoptions['LeBail'] = bool(value) 1215 else: 1216 raise ValueError("Unknown key:", key) 1217 1218 def clear_refinement(self, key, value): 1219 if key == "Cell": 1220 self.data['General']['Cell'][0] = False 1221 elif key == "Atoms": 1222 cx, ct, cs, cia = self.data['General']['AtomPtrs'] 1223 1224 for atomlabel in value: 1225 atom = self.atom(atomlabel) 1226 # Set refinement to none 1227 atom.refinement_flags = ' ' 1228 elif key == "LeBail": 1229 hists = self.data['Histograms'] 1230 for hname, hoptions in hists.items(): 1231 if 'LeBail' not in hoptions: 1232 hoptions['newLeBail'] = True 1233 hoptions['LeBail'] = False 1234 else: 1235 raise ValueError("Unknown key:", key) 142 1236 143 1237 def main(): 144 'Needs a doc string' 1238 '''TODO: the command-line options need some thought 1239 ''' 145 1240 arg = sys.argv 146 print arg1241 print(arg) 147 1242 if len(arg) > 1: 148 1243 GPXfile = arg[1] 149 1244 if not ospath.exists(GPXfile): 150 print 'ERROR - ',GPXfile," doesn't exist!"1245 print(u'ERROR - '+GPXfile+u" doesn't exist!") 151 1246 exit() 152 1247 Project,nameList = LoadDictFromProjFile(GPXfile) 153 1248 SaveDictToProjFile(Project,nameList,'testout.gpx') 154 1249 else: 155 print 'ERROR - missing filename'1250 print('ERROR - missing filename') 156 1251 exit() 157 print "Done"1252 print("Done") 158 1253 159 1254 if __name__ == '__main__': 1255 PwdrDataReaders = G2fil.LoadImportRoutines("pwd", "Powder_Data") 1256 PhaseReaders = G2fil.LoadImportRoutines("phase", "Phase") 160 1257 main() 1258 1259 # from gpx_manipulatons.py 1260 # try: 1261 # filename, authorname = sys.argv[1:3] 1262 # proj, names = make_empty_project(authorname, filename) 1263 # SaveDictToProjFile(proj, names, os.path.abspath(filename)) 1264 # except ValueError: 1265 # print("Usage: {} <filename> <author>".format(sys.argv[0])) 1266 # sys.exit(-1) 1267 1268 1269 # from refinements.py 1270 # USAGE = """USAGE: {} datafile instparams phasefile projectname refinements 1271 1272 # datafile: Input powder data 1273 # intparams: Corresponding instrument parameter file 1274 # phasefile: Phase to refine against data 1275 # projectname: Project file to be created, should end in .gpx 1276 # refinements: JSON file of refinements to be executed 1277 # """ 1278 # try: 1279 # datafile, instprm, phasefile, projectname, refinements = sys.argv[1:] 1280 # except ValueError: 1281 # print(USAGE.format(sys.argv[0])) 1282 # sys.exit(-1) 1283 1284 # try: 1285 # with open(refinements) as f: 1286 # refinements = json.load(f) 1287 # except IOError: 1288 # print("No such refinements file: {}".format(refinements)) 1289 1290 # print("Creating project file \"{}\"...".format(projectname)) 1291 # proj = G2Project(filename=projectname) 1292 # # Add the histogram 1293 # hist = proj.add_powder_histogram(datafile, instprm) 1294 # # Add the phase, and associate it with the histogram 1295 # proj.add_phase(phasefile, histograms=[hist.name]) 1296 1297 # proj.do_refinements(refinements['refinements']) 1298 # proj.save() 1299 1300 1301 # from gpx_dumper 1302 # import IPython.lib.pretty as pretty 1303 # proj, nameList = LoadDictFromProjFile(sys.argv[1]) 1304 # print("names:", nameList) 1305 # for key, val in proj.items(): 1306 # print(key, ":", sep='') 1307 # pretty.pprint(val) 1308
Note: See TracChangeset
for help on using the changeset viewer.