# -*- coding: utf-8 -*- #GSASIIdataGUI - Main GUI routines ########### SVN repository information ################### # $Date: 2017-07-14 14:16:05 +0000 (Fri, 14 Jul 2017) $ # $Author: vondreele $ # $Revision: 2933 $ # $URL: branch/2frame/GSASIIdataGUI.py $ # $Id: GSASIIdataGUI.py 2933 2017-07-14 14:16:05Z vondreele $ ########### SVN repository information ################### ''' *GSASIIdataGUI: Main GSAS-II GUI* ------------------------------------ Module that defines GUI routines and classes for the main GUI Frame (window) and the main routines that define the GSAS-II tree panel and much of the data editing panel. ''' import time import math import random as ran import copy import sys import os import glob import imp import inspect import numpy as np import numpy.ma as ma import matplotlib as mpl import OpenGL as ogl import scipy as sp import scipy.optimize as so import wx import wx.grid as wg #import wx.wizard as wz #import wx.aui import wx.lib.scrolledpanel as wxscroll import GSASIIpath GSASIIpath.SetVersionNumber("$Revision: 2933 $") import GSASIImath as G2mth import GSASIIIO as G2IO import GSASIIstrIO as G2stIO import GSASIIlattice as G2lat import GSASIIplot as G2plt import GSASIIpwdGUI as G2pdG import GSASIIimgGUI as G2imG import GSASIIphsGUI as G2phG import GSASIIspc as G2spc import GSASIImapvars as G2mv import GSASIIconstrGUI as G2cnstG import GSASIIrestrGUI as G2restG import GSASIIobj as G2obj import GSASIIexprGUI as G2exG import GSASIIlog as log import GSASIIctrlGUI as G2G import GSASIIElem as G2elem import GSASIIpwd as G2pwd import GSASIIstrMain as G2stMn # trig functions in degrees sind = lambda x: np.sin(x*np.pi/180.) tand = lambda x: np.tan(x*np.pi/180.) cosd = lambda x: np.cos(x*np.pi/180.) # Define short names for convenience WACV = wx.ALIGN_CENTER_VERTICAL VERY_LIGHT_GREY = wx.Colour(240,240,240) DULL_YELLOW = (230,230,190) # define Ids for wx menu items commonTrans = {'abc':np.eye(3),'a-cb':np.array([[1.,0.,0.],[0.,0.,-1.],[0.,1.,0.]]), 'ba-c':np.array([[0.,1.,0.],[1.,0.,0.],[0.,0.,-1.]]),'-cba':np.array([[0.,0.,-1.],[0.,1.,0.],[1.,0.,0.]]), 'bca':np.array([[0.,1.,0.],[0.,0.,1.],[1.,0.,0.]]),'cab':np.array([[0.,0.,1.],[1.,0.,0.],[0.,1.,0.]]), 'R->H':np.array([[1.,-1.,0.],[0.,1.,-1.],[1.,1.,1.]]),'H->R':np.array([[2./3,1./3,1./3],[-1./3,1./3,1./3],[-1./3,-2./3,1./3]]), 'P->A':np.array([[-1.,0.,0.],[0.,-1.,1.],[0.,1.,1.]]),'R->O':np.array([[-1.,0.,0.],[0.,-1.,0.],[0.,0.,1.]]), 'P->B':np.array([[-1.,0.,1.],[0.,-1.,0.],[1.,0.,1.]]),'B->P':np.array([[-.5,0.,.5],[0.,-1.,0.],[.5,0.,.5]]), 'P->C':np.array([[1.,1.,0.],[1.,-1.,0.],[0.,0.,-1.]]),'C->P':np.array([[.5,.5,0.],[.5,-.5,0.],[0.,0.,-1.]]), 'P->F':np.array([[-1.,1.,1.],[1.,-1.,1.],[1.,1.,-1.]]),'F->P':np.array([[0.,.5,.5],[.5,0.,.5],[.5,.5,0.]]), 'P->I':np.array([[0.,1.,1.],[1.,0.,1.],[1.,1.,0.]]),'I->P':np.array([[-.5,.5,.5],[.5,-.5,.5],[.5,.5,-.5]]), 'A->P':np.array([[-1.,0.,0.],[0.,-.5,.5],[0.,.5,.5]]),'O->R':np.array([[-1.,0.,0.],[0.,-1.,0.],[0.,0.,1.]]), 'abc*':np.eye(3), } commonNames = ['abc','bca','cab','a-cb','ba-c','-cba','P->A','A->P','P->B','B->P','P->C','C->P', 'P->I','I->P','P->F','F->P','H->R','R->H','R->O','O->R','abc*','setting 1->2'] #don't put any new ones after the setting one! def SetDefaultDData(dType,histoName,NShkl=0,NDij=0): if dType in ['SXC','SNC']: return {'Histogram':histoName,'Show':False,'Scale':[1.0,True], 'Babinet':{'BabA':[0.0,False],'BabU':[0.0,False]}, 'Extinction':['Lorentzian','None', {'Tbar':0.1,'Cos2TM':0.955, 'Eg':[1.e-10,False],'Es':[1.e-10,False],'Ep':[1.e-10,False]}], 'Flack':[0.0,False]} elif dType == 'SNT': return {'Histogram':histoName,'Show':False,'Scale':[1.0,True], 'Babinet':{'BabA':[0.0,False],'BabU':[0.0,False]}, 'Extinction':['Lorentzian','None', { 'Eg':[1.e-10,False],'Es':[1.e-10,False],'Ep':[1.e-10,False]}]} elif 'P' in dType: return {'Histogram':histoName,'Show':False,'Scale':[1.0,False], 'Pref.Ori.':['MD',1.0,False,[0,0,1],0,{},[],0.1], 'Size':['isotropic',[1.,1.,1.],[False,False,False],[0,0,1], [1.,1.,1.,0.,0.,0.],6*[False,]], 'Mustrain':['isotropic',[1000.0,1000.0,1.0],[False,False,False],[0,0,1], NShkl*[0.01,],NShkl*[False,]], 'HStrain':[NDij*[0.0,],NDij*[False,]], 'Extinction':[0.0,False],'Babinet':{'BabA':[0.0,False],'BabU':[0.0,False]}} def GetDisplay(pos): '''Gets display number (0=main display) for window position (pos). If pos outside all displays returns None ''' displays = np.array([list(wx.Display(i).GetGeometry()) for i in range(wx.Display.GetCount())]) for ip,display in enumerate(displays): display[2:3] += display[0:1] if (display[0] < pos[0] < display[2]) and (display[1] < pos[1] < display[3]): return ip return None ################################################################################ #### class definitions used for main GUI ################################################################################ class MergeDialog(wx.Dialog): ''' HKL transformation & merge dialog :param wx.Frame parent: reference to parent frame (or None) :param data: HKLF data ''' def __init__(self,parent,data): wx.Dialog.__init__(self,parent,wx.ID_ANY,'Setup HKLF merge', pos=wx.DefaultPosition,style=wx.DEFAULT_DIALOG_STYLE) self.panel = wx.Panel(self) #just a dummy - gets destroyed in Draw! self.data = data self.Super = data[1]['Super'] if self.Super: self.Trans = np.eye(4) else: self.Trans = np.eye(3) self.Cent = 'noncentrosymmetric' self.Laue = '1' self.Class = 'triclinic' self.Common = 'abc' self.Draw() def Draw(self): def OnCent(event): Obj = event.GetEventObject() self.Cent = Obj.GetValue() self.Laue = '' wx.CallAfter(self.Draw) def OnLaue(event): Obj = event.GetEventObject() self.Laue = Obj.GetValue() wx.CallAfter(self.Draw) def OnClass(event): Obj = event.GetEventObject() self.Class = Obj.GetValue() self.Laue = '' wx.CallAfter(self.Draw) def OnCommon(event): Obj = event.GetEventObject() self.Common = Obj.GetValue() self.Trans = commonTrans[self.Common] wx.CallAfter(self.Draw) self.panel.Destroy() self.panel = wx.Panel(self) mainSizer = wx.BoxSizer(wx.VERTICAL) MatSizer = wx.BoxSizer(wx.HORIZONTAL) transSizer = wx.BoxSizer(wx.VERTICAL) transSizer.Add(wx.StaticText(self.panel,label=" HKL Transformation matrix: M*H = H'")) if self.Super: Trmat = wx.FlexGridSizer(4,4,0,0) else: commonSizer = wx.BoxSizer(wx.HORIZONTAL) commonSizer.Add(wx.StaticText(self.panel,label=' Common transformations: '),0,WACV) common = wx.ComboBox(self.panel,value=self.Common,choices=commonNames[:-2], #not the last two! style=wx.CB_READONLY|wx.CB_DROPDOWN) common.Bind(wx.EVT_COMBOBOX,OnCommon) commonSizer.Add(common,0,WACV) transSizer.Add(commonSizer) Trmat = wx.FlexGridSizer(3,3,0,0) for iy,line in enumerate(self.Trans): for ix,val in enumerate(line): item = G2G.ValidatedTxtCtrl(self.panel,self.Trans[iy],ix,nDig=(10,3),size=(65,25)) Trmat.Add(item) transSizer.Add(Trmat) MatSizer.Add((10,0),0) MatSizer.Add(transSizer) mainSizer.Add(MatSizer) laueClass = ['triclinic','monoclinic','orthorhombic','trigonal(H)','tetragonal','hexagonal','cubic'] centroLaue = {'triclinic':['-1',],'monoclinic':['2/m','1 1 2/m','2/m 1 1',], 'orthorhombic':['m m m',],'trigonal(H)':['-3','-3 m 1','-3 1 m',], \ 'tetragonal':['4/m','4/m m m',],'hexagonal':['6/m','6/m m m',],'cubic':['m 3','m 3 m']} noncentroLaue = {'triclinic':['1',],'monoclinic':['2','2 1 1','1 1 2','m','m 1 1','1 1 m',], 'orthorhombic':['2 2 2','m m 2','m 2 m','2 m m',], 'trigonal(H)':['3','3 1 2','3 2 1','3 m 1','3 1 m',], 'tetragonal':['4','-4','4 2 2','4 m m','-4 2 m','-4 m 2',], \ 'hexagonal':['6','-6','6 2 2','6 m m','-6 m 2','-6 2 m',],'cubic':['2 3','4 3 2','-4 3 m']} centChoice = ['noncentrosymmetric','centrosymmetric'] mainSizer.Add(wx.StaticText(self.panel,label=' Select Laue class for new lattice:'),0,WACV) Class = wx.ComboBox(self.panel,value=self.Class,choices=laueClass, style=wx.CB_READONLY|wx.CB_DROPDOWN) Class.Bind(wx.EVT_COMBOBOX,OnClass) mainSizer.Add(Class,0,WACV) mainSizer.Add(wx.StaticText(self.panel,label=' Target Laue symmetry:'),0,WACV) Cent = wx.ComboBox(self.panel,value=self.Cent,choices=centChoice, style=wx.CB_READONLY|wx.CB_DROPDOWN) Cent.Bind(wx.EVT_COMBOBOX,OnCent) mergeSizer = wx.BoxSizer(wx.HORIZONTAL) mergeSizer.Add(Cent,0,WACV) mergeSizer.Add((10,0),0) Choice = centroLaue[self.Class] if 'non' in self.Cent: Choice = noncentroLaue[self.Class] Laue = wx.ComboBox(self.panel,value=self.Laue,choices=Choice, style=wx.CB_READONLY|wx.CB_DROPDOWN) Laue.Bind(wx.EVT_COMBOBOX,OnLaue) mergeSizer.Add(Laue,0,WACV) mainSizer.Add(mergeSizer) OkBtn = wx.Button(self.panel,-1,"Ok") OkBtn.Bind(wx.EVT_BUTTON, self.OnOk) cancelBtn = wx.Button(self.panel,-1,"Cancel") cancelBtn.Bind(wx.EVT_BUTTON, self.OnCancel) btnSizer = wx.BoxSizer(wx.HORIZONTAL) btnSizer.Add((20,20),1) if self.Laue: btnSizer.Add(OkBtn) btnSizer.Add((20,20),1) btnSizer.Add(cancelBtn) btnSizer.Add((20,20),1) mainSizer.Add(btnSizer,0,wx.EXPAND|wx.BOTTOM|wx.TOP, 10) self.panel.SetSizer(mainSizer) self.panel.Fit() self.Fit() def GetSelection(self): return self.Trans,self.Cent,self.Laue def OnOk(self,event): parent = self.GetParent() parent.Raise() self.EndModal(wx.ID_OK) def OnCancel(self,event): parent = self.GetParent() parent.Raise() self.EndModal(wx.ID_CANCEL) def GUIpatches(): 'Misc fixes that only needs to be done when running a GUI' try: # patch for LANG environment var problem on occasional OSX machines import locale locale.getdefaultlocale() except ValueError: print('Fixing location (see https://github.com/matplotlib/matplotlib/issues/5420.)') os.environ['LC_ALL'] = 'en_US.UTF-8' locale.getdefaultlocale() try: import OpenGL OpenGL # avoids unused package error except ImportError: print('*******************************************************') print('PyOpenGL is missing from your python installation') print(' - we will try to install it') print('*******************************************************') def install_with_easyinstall(package): try: print "trying a system-wide PyOpenGl install" easy_install.main(['-f',os.path.split(__file__)[0],package]) return except: pass try: print "trying a user level PyOpenGl install" easy_install.main(['-f',os.path.split(__file__)[0],'--user',package]) return except: print "Install of '+package+' failed. Please report this information:" import traceback print traceback.format_exc() sys.exit() from setuptools.command import easy_install install_with_easyinstall('PyOpenGl') print('*******************************************************') print('OpenGL has been installed. Restarting GSAS-II') print('*******************************************************') loc = os.path.dirname(__file__) import subprocess subprocess.Popen([sys.executable,os.path.join(loc,'GSASII.py')]) sys.exit() # PATCH: for Mavericks (OS X 10.9.x), wx produces an annoying warning about LucidaGrandeUI. # In case stderr has been suppressed there, redirect python error output to stdout. Nobody # else should care much about this. sys.stderr = sys.stdout def ShowVersions(): '''Show the versions all of required Python packages, etc. ''' import numpy as np import scipy as sp import wx import matplotlib as mpl import OpenGL as ogl import GSASIIpath # print versions print "Python module versions loaded:" print " Python: ",sys.version.split()[0] print " wx: ",wx.__version__ print " matplotlib: ",mpl.__version__ print " numpy: ",np.__version__ print " scipy: ",sp.__version__ print " OpenGL: ",ogl.__version__ # TODO: not sure this prints the right message with pillow try: from PIL import Image try: from PIL import PILLOW_VERSION version = PILLOW_VERSION except: version = Image.VERSION print " PIL.Image: ",version except ImportError: try: import Image print "Image (PIL):",Image.VERSION except ImportError: print "Image module not present; Note that PIL (Python Imaging Library) or pillow is needed for some image operations" import platform print " Platform: ",sys.platform,platform.architecture()[0],platform.machine() try: import mkl print " Max threads:",mkl.get_max_threads() except: pass #print "wxPython description",wx.PlatformInfo print "This is GSAS-II revision "+str(GSASIIpath.GetVersionNumber())+'\n' ############################################################################### # Main application ############################################################################### def GSASIImain(): '''Start up the GSAS-II application''' ShowVersions() GUIpatches() #GSASIIpath.InvokeDebugOpts() #application = GSASIImain() # don't redirect output, someday we # may want to do this if we can application = GSASIIGUI(0) if GSASIIpath.GetConfigValue('wxInspector'): import wx.lib.inspection as wxeye wxeye.InspectionTool().Show() #application.main.OnRefine(None) try: application.SetAppDisplayName('GSAS-II') except: pass #application.GetTopWindow().dataWindow.SendSizeEvent() #application.GetTopWindow().treePanel.SendSizeEvent() #application.GetTopWindow().SendSizeEvent() application.GetTopWindow().Show(True) application.MainLoop() class GSASIIGUI(wx.App): '''Defines a wxApp for GSAS-II Creates a wx frame (self.main) which contains the display of the data tree. ''' def OnInit(self): '''Called automatically when the app is created.''' import platform if '2.7' not in sys.version[:5]: dlg = wx.MessageDialog(None, 'GSAS-II requires Python 2.7.x\n Yours is '+sys.version.split()[0], 'Python version error', wx.OK) try: dlg.ShowModal() finally: dlg.Destroy() sys.exit() self.main = GSASII(None) self.SetTopWindow(self.main) # save the current package versions self.main.PackageVersions = [] self.main.PackageVersions.append(['Python',sys.version.split()[0]]) for p in (wx,mpl,np,sp,ogl): self.main.PackageVersions.append([p.__name__,p.__version__]) # TODO: not sure how this works with pillow try: from PIL import Image try: from PIL import PILLOW_VERSION self.main.PackageVersions.append([Image.__name__,PILLOW_VERSION]) except: self.main.PackageVersions.append([Image.__name__,Image.VERSION]) except ImportError: try: import Image self.main.PackageVersions.append([Image.__name__,Image.VERSION]) except ImportError: pass self.main.PackageVersions.append(['Platform',sys.platform+' '+platform.architecture()[0]+' '+platform.machine()]) return True # def MacOpenFile(self, filename): # '''Called on Mac every time a file is dropped on the app when it is running, # treat this like a File/Open project menu action. # Should be ignored on other platforms # ''' # # PATCH: Canopy 1.4 script main seems dropped on app; ignore .py files # print 'MacOpen',filename # if os.path.splitext(filename)[1] == '.py': return # # end PATCH # self.main.OnFileOpen(None,filename) # removed because this gets triggered when a file is on the command line in canopy 1.4 -- not likely used anyway ################################################################################ # Create main frame (window) for GUI ################################################################################ class GSASII(wx.Frame): '''Define the main GSAS-II frame and its associated menu items ''' def MenuBinding(self,event): '''Called when a menu is clicked upon; looks up the binding in table ''' log.InvokeMenuCommand(event.GetId(),self,event) def Bind(self,eventtype,handler,*args,**kwargs): '''Override the Bind function so that we can wrap calls that will be logged. N.B. This is a bit kludgy. Menu bindings with an id are wrapped and menu bindings with an object and no id are not. ''' if eventtype == wx.EVT_MENU and 'id' in kwargs: menulabels = log.SaveMenuCommand(kwargs['id'],self,handler) if menulabels: wx.Frame.Bind(self,eventtype,self.MenuBinding,*args,**kwargs) return wx.Frame.Bind(self,eventtype,handler,*args,**kwargs) def _Add_FileMenuItems(self, parent): item = parent.Append( help='Open a GSAS-II project file (*.gpx)', id=wx.ID_ANY, kind=wx.ITEM_NORMAL,text='&Open project...') self.Bind(wx.EVT_MENU, self.OnFileOpen, id=item.GetId()) item = parent.Append( help='Save project under current name', id=wx.ID_ANY, kind=wx.ITEM_NORMAL,text='&Save project') self.Bind(wx.EVT_MENU, self.OnFileSave, id=item.GetId()) item = parent.Append( help='Save current project to new file', id=wx.ID_ANY, kind=wx.ITEM_NORMAL,text='Save project as...') self.Bind(wx.EVT_MENU, self.OnFileSaveas, id=item.GetId()) item = parent.Append( help='Create empty new project, saving current is optional', id=wx.ID_ANY, kind=wx.ITEM_NORMAL,text='&New project') self.Bind(wx.EVT_MENU, self.OnFileClose, id=item.GetId()) item = parent.Append(wx.ID_PREFERENCES, text = "&Preferences") self.Bind(wx.EVT_MENU, self.OnPreferences, item) if GSASIIpath.GetConfigValue('debug'): def OnIPython(event): GSASIIpath.IPyBreak() item = parent.Append(wx.ID_ANY, text = "IPython Console") self.Bind(wx.EVT_MENU, OnIPython, item) item = parent.Append( help='Exit from GSAS-II', id=wx.ID_ANY, kind=wx.ITEM_NORMAL,text='&Exit') self.Bind(wx.EVT_MENU, self.ExitMain, id=item.GetId()) def _Add_DataMenuItems(self,parent): # item = parent.Append( # help='',id=wx.ID_ANY, # kind=wx.ITEM_NORMAL, # text='Read image data...') # self.Bind(wx.EVT_MENU, self.OnImageRead, id=item.GetId()) item = parent.Append( help='',id=wx.ID_ANY, kind=wx.ITEM_NORMAL, text='Read Powder Pattern Peaks...') self.Bind(wx.EVT_MENU, self.OnReadPowderPeaks, id=item.GetId()) item = parent.Append( help='',id=wx.ID_ANY, kind=wx.ITEM_NORMAL, text='Sum powder data') self.Bind(wx.EVT_MENU, self.OnPwdrSum, id=item.GetId()) item = parent.Append( help='',id=wx.ID_ANY, kind=wx.ITEM_NORMAL, text='Sum image data') self.Bind(wx.EVT_MENU, self.OnImageSum, id=item.GetId()) item = parent.Append( help='',id=wx.ID_ANY, kind=wx.ITEM_NORMAL, text='Add new phase') self.Bind(wx.EVT_MENU, self.OnAddPhase, id=item.GetId()) item = parent.Append( help='',id=wx.ID_ANY, kind=wx.ITEM_NORMAL, text='Delete phase') self.Bind(wx.EVT_MENU, self.OnDeletePhase, id=item.GetId()) item = parent.Append( help='Rename the selected data tree item (PWDR, HKLF or IMG)',id=wx.ID_ANY, kind=wx.ITEM_NORMAL, text='Rename tree item') self.Bind(wx.EVT_MENU, self.OnRenameData, id=item.GetId()) item = parent.Append( help='Delete selected data items from data tree',id=wx.ID_ANY, kind=wx.ITEM_NORMAL, text='Delete tree items') self.Bind(wx.EVT_MENU, self.OnDataDelete, id=item.GetId()) expandmenu = wx.Menu() item = parent.AppendMenu( wx.ID_ANY, 'Expand tree items', expandmenu, help='Expand items of type in GSAS-II data tree') for s in 'all','IMG','PWDR','PDF','HKLF','SASD','REFD': if s == 'all': help = 'Expand all items in GSAS-II data tree' else: help = 'Expand '+s+' type items in GSAS-II data tree' item = expandmenu.Append(wx.ID_ANY,kind=wx.ITEM_NORMAL,text=s,help=help) self.Bind(wx.EVT_MENU,self.ExpandAll,id=item.GetId()) movemenu = wx.Menu() item = parent.AppendMenu( wx.ID_ANY, 'Move tree items', movemenu, help='Move items of type items to end of GSAS-II data tree') for s in 'IMG','PWDR','PDF','HKLF','SASD','REFD','Phase': help = 'Move '+s+' type items to end of GSAS-II data tree' item = movemenu.Append(wx.ID_ANY,kind=wx.ITEM_NORMAL,text=s,help=help) self.Bind(wx.EVT_MENU,self.MoveTreeItems,id=item.GetId()) def _Add_CalculateMenuItems(self,parent): item = parent.Append(help='Create PDF tree entries for selected powder patterns', id=wx.ID_ANY, kind=wx.ITEM_NORMAL,text='Setup PDFs') self.MakePDF.append(item) self.Bind(wx.EVT_MENU, self.OnMakePDFs, id=item.GetId()) item = parent.Append(help='View least squares parameters', id=wx.ID_ANY, kind=wx.ITEM_NORMAL,text='&View LS parms') self.Bind(wx.EVT_MENU, self.OnShowLSParms, id=item.GetId()) item = parent.Append(help='', id=wx.ID_ANY, kind=wx.ITEM_NORMAL, text='&Refine') if len(self.Refine): # extend state for new menus to match main (on mac) state = self.Refine[0].IsEnabled() else: state = False item.Enable(state) self.Refine.append(item) self.Bind(wx.EVT_MENU, self.OnRefine, id=item.GetId()) item = parent.Append(help='', id=wx.ID_ANY, kind=wx.ITEM_NORMAL, text='Sequential refine') self.Bind(wx.EVT_MENU, self.OnSeqRefine, id=item.GetId()) if len(self.SeqRefine): # extend state for new menus to match main (on mac) state = self.SeqRefine[0].IsEnabled() else: state = False item.Enable(state) self.SeqRefine.append(item) # save menu obj for use in self.EnableSeqRefineMenu # if GSASIIpath.GetConfigValue('debug'): # allow exceptions for debugging # item = parent.Append(help='', id=wx.ID_ANY, kind=wx.ITEM_NORMAL, # text='tree test') # self.Bind(wx.EVT_MENU, self.TreeTest, id=item.GetId()) def _init_Imports(self): '''import all the G2phase*.py & G2sfact*.py & G2pwd*.py files that are found in the path ''' self.ImportPhaseReaderlist = [] self._init_Import_routines('phase',self.ImportPhaseReaderlist,'Phase') self.ImportSfactReaderlist = [] self._init_Import_routines('sfact',self.ImportSfactReaderlist,'Struct_Factor') self.ImportPowderReaderlist = [] self._init_Import_routines('pwd',self.ImportPowderReaderlist,'Powder_Data') self.ImportSmallAngleReaderlist = [] self._init_Import_routines('sad',self.ImportSmallAngleReaderlist,'SmallAngle_Data') self.ImportReflectometryReaderlist = [] self._init_Import_routines('rfd',self.ImportReflectometryReaderlist,'Reflectometry_Data') self.ImportPDFReaderlist = [] self._init_Import_routines('pdf',self.ImportPDFReaderlist,'PDF_Data') self.ImportImageReaderlist = [] self._init_Import_routines('img',self.ImportImageReaderlist,'Images') self.ImportMenuId = {} def _init_Import_routines(self,prefix,readerlist,errprefix): '''import all the import readers matching the prefix ''' #path2GSAS2 = os.path.dirname(os.path.realpath(__file__)) # location of this file #pathlist = sys.path[:] #if path2GSAS2 not in pathlist: pathlist.append(path2GSAS2) #path2GSAS2 = os.path.join( # os.path.dirname(os.path.realpath(__file__)), # location of this file # 'imports') pathlist = sys.path[:] #if path2GSAS2 not in pathlist: pathlist.append(path2GSAS2) if '.' not in pathlist: pathlist.append('.') # insert the directory where G2 is started filelist = [] for path in pathlist: for filename in glob.iglob(os.path.join( path, "G2"+prefix+"*.py")): filelist.append(filename) #print 'debug: found',filename filelist = sorted(list(set(filelist))) # remove duplicates for filename in filelist: path,rootname = os.path.split(filename) pkg = os.path.splitext(rootname)[0] try: fp = None fp, fppath,desc = imp.find_module(pkg,[path,]) pkg = imp.load_module(pkg,fp,fppath,desc) for clss in inspect.getmembers(pkg): # find classes defined in package if clss[0].startswith('_'): continue if inspect.isclass(clss[1]): # check if we have the required methods for m in 'Reader','ExtensionValidator','ContentsValidator': if not hasattr(clss[1],m): break if not callable(getattr(clss[1],m)): break else: reader = clss[1]() # create an import instance if reader.UseReader: readerlist.append(reader) except AttributeError: print 'Import_'+errprefix+': Attribute Error '+ filename #except ImportError: # print 'Import_'+errprefix+': Error importing file '+ filename except Exception,errmsg: print('\nImport_'+errprefix+': Error importing file '+ filename) print(u'Error message: {}\n'.format(errmsg)) if fp: fp.close() def EnableSeqRefineMenu(self): '''Enable or disable the sequential refinement menu items based on the contents of the Controls 'Seq Data' item (if present) ''' controls = self.GPXtree.GetItemPyData(GetGPXtreeItemId(self,self.root, 'Controls')) if controls.get('Seq Data'): for i in self.SeqRefine: i.Enable(True) else: for i in self.SeqRefine: i.Enable(False) def PreviewFile(self,filename,fp): 'confirm we have the right file' rdmsg = 'File '+ filename +' begins:\n\n' try: rdmsg += fp.read(80) rdmsg += '\n\nDo you want to read this file?' except UnicodeDecodeError: rdmsg = None if rdmsg is None or not all([ord(c) < 128 and ord(c) != 0 for c in rdmsg]): # show only if ASCII rdmsg = 'File '+ filename +' is a binary file. Do you want to read this file?' # it would be better to use something that # would resize better, but this will do for now dlg = wx.MessageDialog( self, rdmsg, 'Is this the file you want?', wx.YES_NO | wx.ICON_QUESTION, ) dlg.SetSize((700,300)) # does not resize on Mac result = wx.ID_NO try: result = dlg.ShowModal() finally: dlg.Destroy() if result == wx.ID_NO: return True return False def OnImportGeneric(self,reader,readerlist,label,multiple=False, usedRanIdList=[],Preview=True,load2Tree=False): '''Used for all imports, including Phases, datasets, images... Called from :meth:`GSASII.OnImportPhase`, :meth:`GSASII.OnImportImage`, :meth:`GSASII.OnImportSfact`, :meth:`GSASII.OnImportPowder`, :meth:`GSASII.OnImportSmallAngle` and :meth:'GSASII.OnImportReflectometry` Uses reader_objects subclassed from :class:`GSASIIobj.ImportPhase`, :class:`GSASIIobj.ImportStructFactor`, :class:`GSASIIobj.ImportPowderData`, :class:`GSASIIobj.ImportSmallAngleData` :class:`GSASIIobj.ImportReflectometryData` or :class:`GSASIIobj.ImportImage`. If a specific reader is specified, only that method will be called, but if no reader is specified, every one that is potentially compatible (by file extension) will be tried on the file(s) selected in the Open File dialog. :param reader_object reader: This will be a reference to a particular object to be used to read a file or None, if every appropriate reader should be used. :param list readerlist: a list of reader objects appropriate for the current read attempt. At present, this will be either self.ImportPhaseReaderlist, self.ImportSfactReaderlist self.ImportPowderReaderlist or self.ImportImageReaderlist (defined in _init_Imports from the files found in the path), but in theory this list could be tailored. Used only when reader is None. :param str label: string to place on the open file dialog: Open `label` input file :param bool multiple: True if multiple files can be selected in the file dialog. False is default. At present True is used only for reading of powder data. :param list usedRanIdList: an optional list of random Ids that have been used and should not be reused :param bool Preview: indicates if a preview of the file should be shown. Default is True, but set to False for image files which are all binary. :param bool load2Tree: indicates if the file should be loaded into the data tree immediately (used for images only). True only when called from :meth:`OnImportImage`; causes return value to change to a list of True values rather than reader objects. :returns: a list of reader objects (rd_list) that were able to read the specified file(s). This list may be empty. ''' self.lastimport = '' self.zipfile = None singlereader = True if reader is None: singlereader = False multiple = False #print "use all formats" choices = "any file (*.*)|*.*" choices += "|zip archive (.zip)|*.zip" extdict = {} # compile a list of allowed extensions for rd in readerlist: fmt = rd.formatName for extn in rd.extensionlist: if not extdict.get(extn): extdict[extn] = [] extdict[extn] += [fmt,] for extn in sorted(extdict.keys(),cmp=lambda x,y: cmp(x.lower(), y.lower())): fmt = '' for f in extdict[extn]: if fmt != "": fmt += ', ' fmt += f choices += "|" + fmt + " file (*" + extn + ")|*" + extn else: readerlist = [reader,] # compile a list of allowed extensions choices = reader.formatName + " file (" w = "" for extn in reader.extensionlist: if w != "": w += ";" w += "*" + extn choices += w + ")|" + w choices += "|zip archive (.zip)|*.zip" if not reader.strictExtension: choices += "|any file (*.*)|*.*" # get the file(s) if multiple: mode = wx.OPEN|wx.MULTIPLE else: mode = wx.OPEN filelist = G2G.GetImportFile(self,message="Choose "+label+" input file", defaultFile="",wildcard=choices,style=mode) rd_list = [] filelist1 = [] for filename in filelist: # is this a zip file? if os.path.splitext(filename)[1].lower() == '.zip': extractedfiles = G2IO.ExtractFileFromZip( filename,parent=self, multipleselect=True) if extractedfiles is None: continue # error or Cancel if extractedfiles != filename: self.zipfile = filename # save zip name filelist1 += extractedfiles continue filelist1.append(filename) filelist = filelist1 Start = True #1st time read - clear selections below for filename in filelist: # is this a zip file? if os.path.splitext(filename)[1].lower() == '.zip': extractedfile = G2IO.ExtractFileFromZip(filename,parent=self) if extractedfile is None: continue # error or Cancel if extractedfile != filename: filename,self.zipfile = extractedfile,filename # now use the file that was created # determine which formats are compatible with this file primaryReaders = [] secondaryReaders = [] for rd in readerlist: flag = rd.ExtensionValidator(filename) if flag is None: secondaryReaders.append(rd) elif flag: primaryReaders.append(rd) if len(secondaryReaders) + len(primaryReaders) == 0 and reader: self.ErrorDialog('Not supported','The selected reader cannot read file '+filename) return [] elif len(secondaryReaders) + len(primaryReaders) == 0: self.ErrorDialog('No Format','No matching format for file '+filename) return [] fp = None msg = '' fp = open(filename,'Ur') if len(filelist) == 1 and Preview: if self.PreviewFile(filename,fp): return [] self.lastimport = filename # this is probably not what I want to do -- it saves only the # last name in a series. See rd.readfilename for a better name. # try the file first with Readers that specify the # file's extension and later with ones that merely allow it errorReport = '' for rd in primaryReaders+secondaryReaders: if Start: #clear old bank selections to allow new ones to be selected by user rd.selections = [] rd.dnames = [] rd.ReInitialize() # purge anything from a previous read fp.seek(0) # rewind rd.errors = "" # clear out any old errors if not rd.ContentsValidator(fp): # rejected on cursory check errorReport += "\n "+rd.formatName + ' validator error' if rd.errors: errorReport += ': '+rd.errors continue if len(rd.selections)>1 and Start: dlg = G2G.G2MultiChoiceDialog(self,'Dataset Selector','Select data to read from the list below',rd.dnames) if dlg.ShowModal() == wx.ID_OK: rd.selections = dlg.GetSelections() Start = False dlg.Destroy() repeat = True rdbuffer = {} # create temporary storage for file reader block = 0 fp.seek(0) # rewind while repeat: # loop if the reader asks for another pass on the file block += 1 repeat = False rd.objname = os.path.basename(filename) flag = False if GSASIIpath.GetConfigValue('debug'): # allow exceptions for debugging flag = rd.Reader(filename,fp,self,buffer=rdbuffer,blocknum=block, usedRanIdList=usedRanIdList,) else: try: flag = rd.Reader(filename,fp,self,buffer=rdbuffer, blocknum=block,usedRanIdList=usedRanIdList,) except rd.ImportException as detail: rd.errors += "\n Read exception: "+str(detail) except Exception as detail: import traceback rd.errors += "\n Unhandled read exception: "+str(detail) rd.errors += "\n Traceback info:\n"+str(traceback.format_exc()) if flag: # this read succeeded if rd.SciPy: #was default read by scipy; needs 1 time fixes G2IO.EditImageParms(self,rd.Data,rd.Comments,rd.Image,filename) rd.SciPy = False rd.readfilename = filename if load2Tree: #images only if rd.repeatcount == 1 and not rd.repeat: # skip image number if only one in set rd.Data['ImageTag'] = None else: rd.Data['ImageTag'] = rd.repeatcount rd.Data['formatName'] = rd.formatName if rd.sumfile: rd.readfilename = rd.sumfile G2IO.LoadImage2Tree(rd.readfilename,self,rd.Comments,rd.Data,rd.Npix,rd.Image) rd_list.append(True) # save a stub the result before it is written over del rd.Image else: rd_list.append(copy.deepcopy(rd)) # save the result before it is written over if rd.repeat: repeat = True continue errorReport += '\n'+rd.formatName + ' read error' if rd.errors: errorReport += ': '+rd.errors if rd_list: # read succeeded, was there a warning or any errors? if rd.warnings: self.ErrorDialog('Read Warning','The '+ rd.formatName+ ' reader reported a warning message:\n\n'+rd.warnings) break # success in reading, try no further else: if singlereader: print('The '+ rd.formatName+' reader was not able to read file '+filename+msg) try: print('\n\nError message(s):\n\t'+errorReport) except: pass self.ErrorDialog('Read Error','The '+ rd.formatName+ ' reader was not able to read file '+filename+msg) else: print('No reader was able to read file '+filename+msg) try: print('\n\nError message(s):\n\t'+errorReport) except: pass self.ErrorDialog('Read Error','No reader was able to read file '+filename+msg) if fp: fp.close() return rd_list def _Add_ImportMenu_Phase(self,parent): '''configure the Import Phase menus accord to the readers found in _init_Imports ''' submenu = wx.Menu() item = parent.AppendMenu(wx.ID_ANY, 'Phase', submenu, help='Import phase data') for reader in self.ImportPhaseReaderlist: item = submenu.Append(wx.ID_ANY,help=reader.longFormatName, kind=wx.ITEM_NORMAL,text='from '+reader.formatName+' file') self.ImportMenuId[item.GetId()] = reader self.Bind(wx.EVT_MENU, self.OnImportPhase, id=item.GetId()) item = submenu.Append(wx.ID_ANY,help='Import phase data, use file to try to determine format', kind=wx.ITEM_NORMAL,text='guess format from file') self.Bind(wx.EVT_MENU, self.OnImportPhase, id=item.GetId()) def OnImportPhase(self,event): '''Called in response to an Import/Phase/... menu item to read phase information. dict self.ImportMenuId is used to look up the specific reader item associated with the menu item, which will be None for the last menu item, which is the "guess" option where all appropriate formats will be tried. ''' # look up which format was requested reqrdr = self.ImportMenuId.get(event.GetId()) # make a list of phase names, ranId's and the histograms used in those phases phaseRIdList,usedHistograms = self.GetPhaseInfofromTree() phaseNameList = usedHistograms.keys() # phase names in use usedHKLFhists = [] # used single-crystal histograms for p in usedHistograms: for h in usedHistograms[p]: if h.startswith('HKLF ') and h not in usedHKLFhists: usedHKLFhists.append(h) rdlist = self.OnImportGeneric(reqrdr,self.ImportPhaseReaderlist, 'phase',usedRanIdList=phaseRIdList) if len(rdlist) == 0: return # for now rdlist is only expected to have one element # but below will allow multiple phases to be imported # if ever the import routines ever implement multiple phase reads. self.CheckNotebook() newPhaseList = [] for rd in rdlist: PhaseName = '' dlg = wx.TextEntryDialog(self, 'Enter the name for the new phase', 'Edit phase name', rd.Phase['General']['Name'],style=wx.OK) while PhaseName == '': dlg.CenterOnParent() if dlg.ShowModal() == wx.ID_OK: PhaseName = dlg.GetValue().strip() else: dlg.Destroy() return dlg.Destroy() # make new phase names unique rd.Phase['General']['Name'] = G2obj.MakeUniqueLabel(PhaseName,phaseNameList) PhaseName = rd.Phase['General']['Name'][:] newPhaseList.append(PhaseName) print(u'Read phase {} from file {}'.format(PhaseName,self.lastimport)) if not GetGPXtreeItemId(self,self.root,'Phases'): sub = self.GPXtree.AppendItem(parent=self.root,text='Phases') else: sub = GetGPXtreeItemId(self,self.root,'Phases') psub = self.GPXtree.AppendItem(parent=sub,text=PhaseName) self.GPXtree.SetItemPyData(psub,rd.Phase) self.GPXtree.Expand(self.root) # make sure phases are seen self.GPXtree.Expand(sub) self.GPXtree.Expand(psub) wx.CallAfter(SelectDataTreeItem,self,psub) #bring up new phase General tab if rd.Constraints: sub = GetGPXtreeItemId(self,self.root,'Constraints') # was created in CheckNotebook if needed Constraints = self.GPXtree.GetItemPyData(sub) # TODO: make sure that NEWVAR names are unique here? for i in rd.Constraints: if type(i) is dict: #for j in i: print j,' --> ',i[j] if '_Explain' not in Constraints: Constraints['_Explain'] = {} Constraints['_Explain'].update(i) continue Constraints['Phase'].append(i) if not newPhaseList: return # somehow, no new phases # get a list of existing histograms PWDRlist = [] HKLFlist = [] if self.GPXtree.GetCount(): item, cookie = self.GPXtree.GetFirstChild(self.root) while item: name = self.GPXtree.GetItemText(item) if name.startswith('PWDR ') and name not in PWDRlist: PWDRlist.append(name) if name.startswith('HKLF ') and name not in HKLFlist: HKLFlist.append(name) item, cookie = self.GPXtree.GetNextChild(self.root, cookie) TextList = PWDRlist + HKLFlist if not TextList: return #no histograms header = 'Select histogram(s) to add to new phase(s):' for phaseName in newPhaseList: header += '\n '+phaseName notOK = True while notOK: result = G2G.ItemSelector(TextList,self,header,header='Add histogram(s)',multiple=True) if not result: return # check that selected single crystal histograms are not already in use! used = [TextList[i] for i in result if TextList[i] in usedHKLFhists] #for i in result: # if TextList[i] in usedHKLFhists: used.append(TextList[i]) if used: msg = 'The following single crystal histogram(s) are already in use' for i in used: msg += '\n '+str(i) msg += '\nAre you sure you want to add them to this phase? ' msg += 'Associating a single crystal dataset to >1 histogram is usually an error, ' msg += 'so No is suggested here.' if self.ErrorDialog('Likely error',msg,self,wtype=wx.YES_NO) == wx.ID_YES: notOK = False else: notOK = False # connect new phases to histograms sub = GetGPXtreeItemId(self,self.root,'Phases') if not sub: raise Exception('ERROR -- why are there no phases here?') wx.BeginBusyCursor() item, cookie = self.GPXtree.GetFirstChild(sub) while item: # loop over (new) phases phaseName = self.GPXtree.GetItemText(item) data = self.GPXtree.GetItemPyData(item) item, cookie = self.GPXtree.GetNextChild(sub, cookie) if phaseName not in newPhaseList: continue generalData = data['General'] SGData = generalData['SGData'] Super = generalData.get('Super',0) SuperVec = [] if Super: SuperVec = np.array(generalData['SuperVec'][0]) UseList = data['Histograms'] NShkl = len(G2spc.MustrainNames(SGData)) NDij = len(G2spc.HStrainNames(SGData)) for i in result: histoName = TextList[i] if histoName in HKLFlist: #redo UpdateHKLFdata(histoName) here: Id = GetGPXtreeItemId(self,self.root,histoName) refDict,reflData = self.GPXtree.GetItemPyData(Id) G,g = G2lat.cell2Gmat(generalData['Cell'][1:7]) Super = reflData.get('Super',0) for iref,ref in enumerate(reflData['RefList']): hkl = ref[:3] if Super: H = list(hkl+SuperVec*ref[3]) else: H = hkl ref[4+Super] = np.sqrt(1./G2lat.calc_rDsq2(H,G)) iabsnt = G2spc.GenHKLf(H,SGData)[0] if iabsnt: #flag space gp. absences if Super: if not ref[2+Super]: ref[3+Super] = 0 else: ref[3+Super] = 1 #twin id else: ref[3] = 0 UseList[histoName] = SetDefaultDData(reflData['Type'],histoName) elif histoName in PWDRlist: Id = GetGPXtreeItemId(self,self.root,histoName) refList = self.GPXtree.GetItemPyData( GetGPXtreeItemId(self,Id,'Reflection Lists')) refList[generalData['Name']] = {} UseList[histoName] = SetDefaultDData('PWDR',histoName,NShkl=NShkl,NDij=NDij) else: raise Exception('Unexpected histogram '+histoName) wx.EndBusyCursor() self.EnableRefineCommand() return # success def _Add_ImportMenu_Image(self,parent): '''configure the Import Image menus accord to the readers found in _init_Imports ''' submenu = wx.Menu() item = parent.AppendMenu(wx.ID_ANY, 'Image', submenu, help='Import image file') for reader in self.ImportImageReaderlist: item = submenu.Append(wx.ID_ANY,help=reader.longFormatName, kind=wx.ITEM_NORMAL,text='from '+reader.formatName+' file') self.ImportMenuId[item.GetId()] = reader self.Bind(wx.EVT_MENU, self.OnImportImage, id=item.GetId()) item = submenu.Append(wx.ID_ANY,help='Import image data, use file to try to determine format', kind=wx.ITEM_NORMAL,text='guess format from file') self.Bind(wx.EVT_MENU, self.OnImportImage, id=item.GetId()) def OnImportImage(self,event): '''Called in response to an Import/Image/... menu item to read an image from a file. Like all the other imports, dict self.ImportMenuId is used to look up the specific reader item associated with the menu item, which will be None for the last menu item, which is the "guess" option where all appropriate formats will be tried. A reader object is filled each time an image is read. ''' self.CheckNotebook() # look up which format was requested reqrdr = self.ImportMenuId.get(event.GetId()) rdlist = self.OnImportGeneric(reqrdr,self.ImportImageReaderlist, 'image',multiple=True,Preview=False,load2Tree=True) if rdlist: self.GPXtree.SelectItem(GetGPXtreeItemId(self,self.Image,'Image Controls')) #show last image to have beeen read def _Add_ImportMenu_Sfact(self,parent): '''configure the Import Structure Factor menus accord to the readers found in _init_Imports ''' submenu = wx.Menu() item = parent.AppendMenu(wx.ID_ANY, 'Structure Factor', submenu, help='Import Structure Factor data') for reader in self.ImportSfactReaderlist: item = submenu.Append(wx.ID_ANY,help=reader.longFormatName, kind=wx.ITEM_NORMAL,text='from '+reader.formatName+' file') self.ImportMenuId[item.GetId()] = reader self.Bind(wx.EVT_MENU, self.OnImportSfact, id=item.GetId()) item = submenu.Append(wx.ID_ANY, help='Import Structure Factor, use file to try to determine format', kind=wx.ITEM_NORMAL, text='guess format from file') self.Bind(wx.EVT_MENU, self.OnImportSfact, id=item.GetId()) def OnImportSfact(self,event): '''Called in response to an Import/Structure Factor/... menu item to read single crystal datasets. dict self.ImportMenuId is used to look up the specific reader item associated with the menu item, which will be None for the last menu item, which is the "guess" option where all appropriate formats will be tried. ''' # get a list of existing histograms HKLFlist = [] if self.GPXtree.GetCount(): item, cookie = self.GPXtree.GetFirstChild(self.root) while item: name = self.GPXtree.GetItemText(item) if name.startswith('HKLF ') and name not in HKLFlist: HKLFlist.append(name) item, cookie = self.GPXtree.GetNextChild(self.root, cookie) # look up which format was requested reqrdr = self.ImportMenuId.get(event.GetId()) rdlist = self.OnImportGeneric(reqrdr,self.ImportSfactReaderlist, 'Structure Factor',multiple=True) if len(rdlist) == 0: return self.CheckNotebook() newHistList = [] for rd in rdlist: HistName = rd.objname if len(rdlist) <= 2: dlg = wx.TextEntryDialog( # allow editing of Structure Factor name self, 'Enter the name for the new Structure Factor', 'Edit Structure Factor name', HistName, style=wx.OK) dlg.CenterOnParent() if dlg.ShowModal() == wx.ID_OK: HistName = dlg.GetValue() dlg.Destroy() HistName = 'HKLF '+G2obj.StripUnicode(HistName,'_') # make new histogram names unique if len(rd.Banks): for Bank in rd.Banks: valuesdict = {'wtFactor':1.0,'Dummy':False,'ranId':ran.randint(0,sys.maxint),} HistName = G2obj.MakeUniqueLabel(HistName,HKLFlist) print 'Read structure factor table '+HistName+' from file '+self.lastimport Id = self.GPXtree.AppendItem(parent=self.root,text=HistName) if not Bank['RefDict'].get('FF'): Bank['RefDict']['FF'] = {} self.GPXtree.SetItemPyData(Id,[valuesdict,Bank['RefDict']]) Sub = self.GPXtree.AppendItem(Id,text='Instrument Parameters') self.GPXtree.SetItemPyData(Sub,copy.copy(rd.Parameters)) self.GPXtree.SetItemPyData( self.GPXtree.AppendItem(Id,text='Reflection List'),{}) #dummy entry for GUI use newHistList.append(HistName) else: valuesdict = {'wtFactor':1.0,'Dummy':False,'ranId':ran.randint(0,sys.maxint),} HistName = G2obj.MakeUniqueLabel(HistName,HKLFlist) print 'Read structure factor table '+HistName+' from file '+self.lastimport if not rd.RefDict.get('FF'): rd.RefDict['FF'] = {} Id = self.GPXtree.AppendItem(parent=self.root,text=HistName) self.GPXtree.SetItemPyData(Id,[valuesdict,rd.RefDict]) Sub = self.GPXtree.AppendItem(Id,text='Instrument Parameters') self.GPXtree.SetItemPyData(Sub,rd.Parameters) self.GPXtree.SetItemPyData( self.GPXtree.AppendItem(Id,text='Reflection List'),{}) #dummy entry for GUI use newHistList.append(HistName) self.GPXtree.SelectItem(Id) self.GPXtree.Expand(Id) self.Sngl = True if not newHistList: return # somehow, no new histograms # make a list of phase names phaseRIdList,usedHistograms = self.GetPhaseInfofromTree() phaseNameList = usedHistograms.keys() # phase names in use if not phaseNameList: return # no phases yet, nothing to do header = 'Select phase(s) to add the new\nsingle crystal dataset(s) to:' for Name in newHistList: header += '\n '+str(Name) result = G2G.ItemSelector(phaseNameList,self,header,header='Add to phase(s)',multiple=True) if not result: return # connect new phases to histograms sub = GetGPXtreeItemId(self,self.root,'Phases') if not sub: raise Exception('ERROR -- why are there no phases here?') wx.BeginBusyCursor() item, cookie = self.GPXtree.GetFirstChild(sub) iph = -1 while item: # loop over (new) phases iph += 1 data = self.GPXtree.GetItemPyData(item) item, cookie = self.GPXtree.GetNextChild(sub, cookie) if iph not in result: continue generalData = data['General'] SGData = generalData['SGData'] Super = generalData.get('Super',0) SuperVec = [] if Super: SuperVec = np.array(generalData['SuperVec'][0]) UseList = data['Histograms'] for histoName in newHistList: #redo UpdateHKLFdata(histoName) here: Id = GetGPXtreeItemId(self,self.root,histoName) refDict,reflData = self.GPXtree.GetItemPyData(Id) UseList[histoName] = SetDefaultDData(reflData['Type'],histoName) G,g = G2lat.cell2Gmat(generalData['Cell'][1:7]) if 'TwMax' in reflData: #nonmerohedral twins present UseList[histoName]['Twins'] = [] for iT in range(reflData['TwMax'][0]+1): if iT in reflData['TwMax'][1]: UseList[histoName]['Twins'].append([False,0.0]) else: UseList[histoName]['Twins'].append([np.array([[1,0,0],[0,1,0],[0,0,1]]),[1.0,False,reflData['TwMax'][0]]]) else: #no nonmerohedral twins UseList[histoName]['Twins'] = [[np.array([[1,0,0],[0,1,0],[0,0,1]]),[1.0,False,0]],] for iref,ref in enumerate(reflData['RefList']): hkl = ref[:3] if Super: H = list(hkl+SuperVec*ref[3]) else: H = hkl ref[4+Super] = np.sqrt(1./G2lat.calc_rDsq2(H,G)) iabsnt,mul,Uniq,phi = G2spc.GenHKLf(H,SGData) if iabsnt: #flag space gp. absences if Super: if not ref[2+Super]: ref[3+Super] = 0 else: ref[3+Super] = 1 #twin id? else: ref[3] = 0 wx.EndBusyCursor() self.EnableRefineCommand() return # success def _Add_ImportMenu_powder(self,parent): '''configure the Powder Data menus accord to the readers found in _init_Imports ''' submenu = wx.Menu() item = parent.AppendMenu(wx.ID_ANY, 'Powder Data', submenu, help='Import Powder data') for reader in self.ImportPowderReaderlist: item = submenu.Append(wx.ID_ANY,help=reader.longFormatName, kind=wx.ITEM_NORMAL,text='from '+reader.formatName+' file') self.ImportMenuId[item.GetId()] = reader self.Bind(wx.EVT_MENU, self.OnImportPowder, id=item.GetId()) item = submenu.Append(wx.ID_ANY, help='Import powder data, use file to try to determine format', kind=wx.ITEM_NORMAL,text='guess format from file') self.Bind(wx.EVT_MENU, self.OnImportPowder, id=item.GetId()) submenu.AppendSeparator() item = submenu.Append(wx.ID_ANY, help='Create a powder data set entry that will be simulated', kind=wx.ITEM_NORMAL,text='Simulate a dataset') self.Bind(wx.EVT_MENU, self.OnDummyPowder, id=item.GetId()) def OpenPowderInstprm(self,instfile): '''Read a GSAS-II (new) instrument parameter file :param str instfile: name of instrument parameter file ''' File = open(instfile,'r') lines = File.readlines() File.close() return lines def ReadPowderInstprm(self,instLines,bank,databanks,rd): '''Read lines from a GSAS-II (new) instrument parameter file similar to G2pwdGUI.OnLoad If instprm file has multiple banks each with header #Bank n: ..., this finds matching bank no. to load - problem with nonmatches? :param list instLines: strings from GSAS-II parameter file; can be concatenated with ';' :param int bank: bank number to check when instprm file has '#BANK n:...' strings when bank = n then use parameters; otherwise skip that set. Ignored if BANK n: not present. NB: this kind of instprm file made by a Save all profile command in Instrument Parameters :return dict: Inst instrument parameter dict if OK, or str: Error message if failed ''' if 'GSAS-II' not in instLines[0]: # not a valid file return 'Not a valid GSAS-II instprm file' newItems = [] newVals = [] Found = False il = 0 if bank is None: # no bank was specified in the input file, is more than one present in file? banklist = set([]) for S in instLines: if S[0] == '#' and 'Bank' in S: banklist.add(int(S.split(':')[0].split()[1])) if len(banklist) > 1: # yes, the user must make a selection choices = [str(i) for i in banklist] bank = int(G2G.ItemSelector(choices,self.G2frame,multiple=False)) else: bank = 1 rd.powderentry[2] = bank while il < len(instLines): S = instLines[il] if S[0] == '#': if Found: break if 'Bank' in S: if bank == int(S.split(':')[0].split()[1]): il += 1 S = instLines[il] else: il += 1 S = instLines[il] while il < len(instLines) and '#Bank' not in S: il += 1 if il == len(instLines): return 'Bank %d not found in instprm file'%(bank) S = instLines[il] continue else: #a non #Bank file il += 1 S = instLines[il] Found = True if '"""' in S: delim = '"""' elif "'''" in S: delim = "'''" else: S = S.replace(' ','') SS = S.strip().split(';') for s in SS: [item,val] = s.split(':',1) newItems.append(item) try: newVals.append(float(val)) except ValueError: newVals.append(val) il += 1 continue # read multiline values, delimited by ''' or """ item,val = S.strip().split(':',1) val = val.replace(delim,'').rstrip() val += '\n' while True: il += 1 if il >= len(instLines): break S = instLines[il] if delim in S: val += S.replace(delim,'').rstrip() val += '\n' break else: val += S.rstrip() val += '\n' newItems.append(item) newVals.append(val) il += 1 return [G2IO.makeInstDict(newItems,newVals,len(newVals)*[False,]),{}] def ReadPowderIparm(self,instfile,bank,databanks,rd): '''Read a GSAS (old) instrument parameter file :param str instfile: name of instrument parameter file :param int bank: the bank number read in the raw data file :param int databanks: the number of banks in the raw data file. If the number of banks in the data and instrument parameter files agree, then the sets of banks are assumed to match up and bank is used to select the instrument parameter file. If not and not TOF, the user is asked to make a selection. :param obj rd: the raw data (histogram) data object. This sets rd.instbank. ''' if not os.path.exists(instfile): # no such file return {} fp = 0 try: fp = open(instfile,'Ur') Iparm = {} for S in fp: if '#' in S[0]: continue Iparm[S[:12]] = S[12:-1] except IOError: print(u'Error reading file: {}'.format(instfile)) if fp: fp.close() ibanks = int(Iparm.get('INS BANK ','1').strip()) if ibanks == 1: # there is only one bank here, return it rd.instbank = 1 rd.powderentry[2] = 1 return Iparm if 'PNT' in Iparm['INS HTYPE ']: #allow mismatch between banks in data iparm file for TOF rd.instbank = bank elif ibanks != databanks or bank is None: choices = [] for i in range(1,1+ibanks): choices.append('Bank '+str(i)) bank = 1 + G2IO.BlockSelector( choices, self, title='Select an instrument parameter bank for '+ os.path.split(rd.powderentry[0])[1]+' BANK '+str(bank)+ '\nOr use Cancel to select from the default parameter sets', header='Block Selector') if bank is None: return {} # pull out requested bank # bank from the data, and change the bank to 1 IparmS = {} for key in Iparm: if 'INS' in key[:3]: #skip around rubbish lines in some old iparm files if key[4:6] == " ": IparmS[key] = Iparm[key] elif int(key[4:6].strip()) == bank: IparmS[key[:4]+' 1'+key[6:]] = Iparm[key] rd.instbank = bank return IparmS def GetPowderIparm(self,rd, prevIparm, lastIparmfile, lastdatafile): '''Open and read an instrument parameter file for a data file Returns the list of parameters used in the data tree :param obj rd: the raw data (histogram) data object. :param str prevIparm: not used :param str lastIparmfile: Name of last instrument parameter file that was read, or a empty string. :param str lastdatafile: Name of last data file that was read. :returns: a list of two dicts, the first containing instrument parameters and the second used for TOF lookup tables for profile coeff. ''' def SetPowderInstParms(Iparm, rd): '''extracts values from instrument parameters in rd.instdict or in array Iparm. Create and return the contents of the instrument parameter tree entry. ''' Irads = {0:' ',1:'CrKa',2:'FeKa',3:'CuKa',4:'MoKa',5:'AgKa',6:'TiKa',7:'CoKa'} DataType = Iparm['INS HTYPE '].strip()[:3] # take 1st 3 chars # override inst values with values read from data file Bank = rd.powderentry[2] #should be used in multibank iparm files if rd.instdict.get('type'): DataType = rd.instdict.get('type') data = [DataType,] instname = Iparm.get('INS 1INAME ') irad = int(Iparm.get('INS 1 IRAD ','0')) if instname: rd.Sample['InstrName'] = instname.strip() if 'C' in DataType: wave1 = None wave2 = 0.0 if rd.instdict.get('wave'): wl = rd.instdict.get('wave') wave1 = wl[0] if len(wl) > 1: wave2 = wl[1] s = Iparm['INS 1 ICONS'] if not wave1: wave1 = G2IO.sfloat(s[:10]) wave2 = G2IO.sfloat(s[10:20]) v = (wave1,wave2, G2IO.sfloat(s[20:30])/100.,G2IO.sfloat(s[55:65]),G2IO.sfloat(s[40:50])) #get lam1, lam2, zero, pola & ratio if not v[1]: names = ['Type','Lam','Zero','Polariz.','U','V','W','X','Y','SH/L','Azimuth'] v = (v[0],v[2],v[4]) codes = [0,0,0,0] rd.Sample.update({'Type':'Debye-Scherrer','Absorption':[0.,False],'DisplaceX':[0.,False],'DisplaceY':[0.,False]}) else: names = ['Type','Lam1','Lam2','Zero','I(L2)/I(L1)','Polariz.','U','V','W','X','Y','SH/L','Azimuth'] codes = [0,0,0,0,0,0] rd.Sample.update({'Type':'Bragg-Brentano','Shift':[0.,False],'Transparency':[0.,False], 'SurfRoughA':[0.,False],'SurfRoughB':[0.,False]}) data.extend(v) if 'INS 1PRCF ' in Iparm: v1 = Iparm['INS 1PRCF '].split() v = Iparm['INS 1PRCF 1'].split() data.extend([float(v[0]),float(v[1]),float(v[2])]) #get GU, GV & GW - always here azm = float(Iparm.get('INS 1DETAZM','0.0')) v = Iparm['INS 1PRCF 2'].split() if v1[0] == 3: data.extend([float(v[0]),float(v[1]),float(v[2])+float(v[3],azm)]) #get LX, LY, S+H/L & azimuth else: data.extend([0.0,0.0,0.002,azm]) #OK defaults if fxn #3 not 1st in iprm file else: v1 = Iparm['INS 1PRCF1 '].split() v = Iparm['INS 1PRCF11'].split() data.extend([float(v[0]),float(v[1]),float(v[2])]) #get GU, GV & GW - always here azm = float(Iparm.get('INS 1DETAZM','0.0')) v = Iparm['INS 1PRCF12'].split() if v1[0] == 3: data.extend([float(v[0]),float(v[1]),float(v[2])+float(v[3],azm)]) #get LX, LY, S+H/L & azimuth else: data.extend([0.0,0.0,0.002,azm]) #OK defaults if fxn #3 not 1st in iprm file codes.extend([0,0,0,0,0,0,0]) Iparm1 = G2IO.makeInstDict(names,data,codes) Iparm1['Source'] = [Irads[irad],Irads[irad]] Iparm1['Bank'] = [Bank,Bank,0] return [Iparm1,{}] elif 'T' in DataType: names = ['Type','fltPath','2-theta','difC','difA', 'difB','Zero','alpha','beta-0','beta-1', 'beta-q','sig-0','sig-1','sig-2','sig-q', 'X','Y','Azimuth',] codes = [0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,] azm = 0. if 'INS 1DETAZM' in Iparm: azm = float(Iparm['INS 1DETAZM']) rd.Sample['Azimuth'] = azm fltPath0 = 20. #arbitrary if 'INS FPATH1' in Iparm: s = Iparm['INS FPATH1'].split() fltPath0 = G2IO.sfloat(s[0]) if 'INS 1BNKPAR' not in Iparm: #bank missing from Iparm file return [] s = Iparm['INS 1BNKPAR'].split() fltPath1 = G2IO.sfloat(s[0]) data.extend([fltPath0+fltPath1,]) #Flight path source-sample-detector data.extend([G2IO.sfloat(s[1]),]) #2-theta for bank s = Iparm['INS 1 ICONS'].split() data.extend([G2IO.sfloat(s[0]),G2IO.sfloat(s[1]),0.0,G2IO.sfloat(s[2])]) #difC,difA,difB,Zero if 'INS 1PRCF ' in Iparm: s = Iparm['INS 1PRCF '].split() pfType = int(s[0]) s = Iparm['INS 1PRCF 1'].split() if abs(pfType) == 1: data.extend([G2IO.sfloat(s[1]),G2IO.sfloat(s[2]),G2IO.sfloat(s[3])]) #alpha, beta-0, beta-1 s = Iparm['INS 1PRCF 2'].split() 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, Y elif abs(pfType) in [3,4,5]: data.extend([G2IO.sfloat(s[0]),G2IO.sfloat(s[1]),G2IO.sfloat(s[2])]) #alpha, beta-0, beta-1 if abs(pfType) == 4: 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, Y else: s = Iparm['INS 1PRCF 2'].split() 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, Y elif abs(pfType) == 2: data.extend([G2IO.sfloat(s[1]),0.0,1./G2IO.sfloat(s[3])]) #alpha, beta-0, beta-1 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, Y else: s = Iparm['INS 1PRCF1 '].split() pfType = int(s[0]) s = Iparm['INS 1PRCF11'].split() if abs(pfType) == 1: data.extend([G2IO.sfloat(s[1]),G2IO.sfloat(s[2]),G2IO.sfloat(s[3])]) #alpha, beta-0, beta-1 s = Iparm['INS 1PRCF12'].split() 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, Y elif abs(pfType) in [3,4,5]: data.extend([G2IO.sfloat(s[0]),G2IO.sfloat(s[1]),G2IO.sfloat(s[2])]) #alpha, beta-0, beta-1 if abs(pfType) == 4: 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, Y else: s = Iparm['INS 1PRCF12'].split() 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, Y Inst1 = G2IO.makeInstDict(names,data,codes) Inst1['Bank'] = [Bank,Bank,0] Inst2 = {} if pfType < 0: Ipab = 'INS 1PAB'+str(-pfType) Npab = int(Iparm[Ipab+' '].strip()) Inst2['Pdabc'] = [] for i in range(Npab): k = Ipab+str(i+1).rjust(2) s = Iparm[k].split() Inst2['Pdabc'].append([float(t) for t in s]) Inst2['Pdabc'] = np.array(Inst2['Pdabc']) Inst2['Pdabc'].T[3] += Inst2['Pdabc'].T[0]*Inst1['difC'][0] #turn 3rd col into TOF if 'INS 1I ITYP' in Iparm: s = Iparm['INS 1I ITYP'].split() Ityp = int(s[0]) Tminmax = [float(s[1])*1000.,float(s[2])*1000.] Itypes = ['Exponential','Maxwell/Exponential','','Maxwell/Chebyschev',''] if Ityp in [1,2,4]: Inst2['Itype'] = Itypes[Ityp-1] Inst2['Tminmax'] = Tminmax Icoeff = [] Iesd = [] Icovar = [] for i in range(3): s = Iparm['INS 1ICOFF'+str(i+1)].split() Icoeff += [float(S) for S in s] s = Iparm['INS 1IECOF'+str(i+1)].split() Iesd += [float(S) for S in s] NT = 10 for i in range(8): s = Iparm['INS 1IECOR'+str(i+1)] if i == 7: NT = 8 Icovar += [float(s[6*j:6*j+6]) for j in range(NT)] Inst2['Icoeff'] = Icoeff Inst2['Iesd'] = Iesd Inst2['Icovar'] = Icovar return [Inst1,Inst2] def GetDefaultParms(self,rd): '''Solicits from user a default set of parameters & returns Inst parm dict param: self: refers to the GSASII main class param: rd: importer data structure returns: dict: Instrument parameter dictionary ''' sind = lambda x: math.sin(x*math.pi/180.) tand = lambda x: math.tan(x*math.pi/180.) import defaultIparms as dI while True: # loop until we get a choice choices = [] head = 'Select from default instrument parameters for '+rd.idstring for l in dI.defaultIparm_lbl: choices.append('Defaults for '+l) res = G2IO.BlockSelector(choices,ParentFrame=self,title=head, header='Select default inst parms',useCancel=True) if res is None: return None rd.instfile = '' if 'lab data' in choices[res]: rd.Sample.update({'Type':'Bragg-Brentano','Shift':[0.,False],'Transparency':[0.,False], 'SurfRoughA':[0.,False],'SurfRoughB':[0.,False]}) else: rd.Sample.update({'Type':'Debye-Scherrer','Absorption':[0.,False],'DisplaceX':[0.,False], 'DisplaceY':[0.,False]}) if 'Generic' in choices[res]: dlg = G2G.MultiFloatDialog(self,title='Generic TOF detector bank', prompts=['Total FP','2-theta',],values=[25.0,150.,], limits=[[6.,200.],[5.,175.],],formats=['%6.2f','%6.1f',]) if dlg.ShowModal() == wx.ID_OK: #strictly empirical approx. FP,tth = dlg.GetValues() difC = 505.632*FP*sind(tth/2.) sig1 = 50.+2.5e-6*(difC/tand(tth/2.))**2 bet1 = .00226+7.76e+11/difC**4 rd.instmsg = 'default: '+dI.defaultIparm_lbl[res] Inst = self.ReadPowderInstprm(dI.defaultIparms[res],bank,numbanks,rd) Inst[0]['difC'] = [difC,difC,0] Inst[0]['sig-1'] = [sig1,sig1,0] Inst[0]['beta-1'] = [bet1,bet1,0] return Inst #this is [Inst1,Inst2] a pair of dicts dlg.Destroy() else: rd.instmsg = 'default: '+dI.defaultIparm_lbl[res] return self.ReadPowderInstprm(dI.defaultIparms[res],bank,numbanks,rd) #this is [Inst1,Inst2] a pair of dicts # stuff we might need from the reader filename = rd.powderentry[0] bank = rd.powderentry[2] numbanks = rd.numbanks #1st priority: is there an instrument parameter file matching the current file # with extension .instprm, .prm, .inst, or .ins? If so read it basename = os.path.splitext(filename)[0] for ext in '.prm','.inst','.ins','.instprm': if self.zipfile: instfile = G2IO.ExtractFileFromZip(self.zipfile, selection=os.path.split(basename + ext)[1],parent=self) if instfile == None: continue else: instfile = basename + ext if not os.path.exists(instfile): continue if 'instprm' in instfile: Lines = self.OpenPowderInstprm(instfile) instParmList = self.ReadPowderInstprm(Lines,bank,numbanks,rd) #this is [Inst1,Inst2] a pair of dicts if 'list' in str(type(instParmList)): rd.instfile = instfile rd.instmsg = 'GSAS-II file '+instfile return instParmList else: #print 'debug: open/read failed',instfile pass # fail silently else: Iparm = self.ReadPowderIparm(instfile,bank,numbanks,rd) if Iparm: #print 'debug: success' rd.instfile = instfile rd.instmsg = instfile + ' bank ' + str(rd.instbank) return SetPowderInstParms(Iparm,rd) else: #print 'debug: open/read failed',instfile pass # fail silently #2nd priority: is there an instrument parameter file defined for the current data set? # or if this is a read on a set of set of files, use the last one again #if rd.instparm as found in data file header or (lastdatafile == filename and lastIparmfile): if rd.instparm or lastIparmfile: if rd.instparm: instfile = os.path.join(os.path.split(filename)[0],rd.instparm) else: # for multiple reads of one data file, reuse the inst parm file instfile = lastIparmfile # if self.zipfile: # instfile = G2IO.ExtractFileFromZip(self.zipfile, # selection=os.path.split(instfile)[1],parent=self) if instfile != None and os.path.exists(instfile): #print 'debug: try read',instfile if 'instprm' in instfile: #GSAS-II file must have .instprm as extension Lines = self.OpenPowderInstprm(instfile) if Lines is not None: instParmList = self.ReadPowderInstprm(Lines,bank,numbanks,rd) #this is [Inst1,Inst2] a pair of dicts else: #old GSAS style iparm file - could be named anything! Iparm = self.ReadPowderIparm(instfile,bank,numbanks,rd) if Iparm: #print 'debug: success' rd.instfile = instfile rd.instmsg = instfile + ' bank ' + str(rd.instbank) instParmList = SetPowderInstParms(Iparm,rd) #this is [Inst1,Inst2] a pair of dicts if 'list' in str(type(instParmList)): #record stuff & return stuff rd.instfile = instfile rd.instmsg = 'GSAS-II file '+instfile return instParmList else: #bad iparms - try default rd.instmsg = instParmList #an error message return GetDefaultParms(self,rd) else: self.ErrorDialog('Open Error',u'Error opening instrument parameter file ' \ +'{} requested by file '.format(instfile,filename)) #Finally - ask user for Instrument parametrs file - seems it can't be in a zip file while True: # loop until we get a file that works or we get a cancel instfile = '' pth = G2G.GetImportPath(self) if not pth: pth = '.' dlg = wx.FileDialog(self, 'Choose inst. param file for "'+rd.idstring+'" (or Cancel for default)', pth, '', 'GSAS iparm file (*.prm,*.inst,*.ins)|*.prm;*.inst;*.ins|' 'GSAS-II iparm file (*.instprm)|*.instprm|' 'All files (*.*)|*.*', wx.OPEN) if os.path.exists(lastIparmfile): dlg.SetFilename(lastIparmfile) if dlg.ShowModal() == wx.ID_OK: instfile = dlg.GetPath() dlg.Destroy() if not instfile: return GetDefaultParms(self,rd) #on Cancel/break if 'instprm' in instfile: Lines = self.OpenPowderInstprm(instfile) if Lines is not None: instParmList = self.ReadPowderInstprm(Lines,bank,numbanks,rd) #this is [Inst1,Inst2] a pair of dicts if 'list' in str(type(instParmList)): rd.instfile = instfile rd.instmsg = 'GSAS-II file '+instfile return instParmList else: rd.instmsg = instParmList #an error message return GetDefaultParms(self,rd) else: Iparm = self.ReadPowderIparm(instfile,bank,numbanks,rd) if Iparm: #print 'debug: success with',instfile rd.instfile = instfile rd.instmsg = instfile + ' bank ' + str(rd.instbank) return SetPowderInstParms(Iparm,rd) else: self.ErrorDialog('Read Error', u'Error opening/reading file {}'.format(instfile)) def EnableRefineCommand(self): haveData = False # check for phases connected to histograms sub = GetGPXtreeItemId(self,self.root,'Phases') if not sub: return item, cookie = self.GPXtree.GetFirstChild(sub) while item: # loop over phases data = self.GPXtree.GetItemPyData(item) item, cookie = self.GPXtree.GetNextChild(sub, cookie) UseList = data['Histograms'] if UseList: haveData = True if haveData: self.dataWindow.DataMenu.Enable(G2G.wxID_DATADELETE,True) for item in self.Refine: item.Enable(True) else: self.dataWindow.DataMenu.Enable(G2G.wxID_DATADELETE,False) for item in self.Refine: item.Enable(False) def OnImportPowder(self,event): '''Called in response to an Import/Powder Data/... menu item to read a powder diffraction data set. dict self.ImportMenuId is used to look up the specific reader item associated with the menu item, which will be None for the last menu item, which is the "guess" option where all appropriate formats will be tried. Also reads an instrument parameter file for each dataset. ''' # get a list of existing histograms PWDRlist = [] if self.GPXtree.GetCount(): item, cookie = self.GPXtree.GetFirstChild(self.root) while item: name = self.GPXtree.GetItemText(item) if name.startswith('PWDR ') and name not in PWDRlist: PWDRlist.append(name) item, cookie = self.GPXtree.GetNextChild(self.root, cookie) # look up which format was requested reqrdr = self.ImportMenuId.get(event.GetId()) rdlist = self.OnImportGeneric( reqrdr,self.ImportPowderReaderlist,'Powder Data',multiple=True) if len(rdlist) == 0: return self.CheckNotebook() Iparm = None lastIparmfile = '' lastdatafile = '' newHistList = [] # lastVals = [] self.EnablePlot = False Iparms = {} for rd in rdlist: if 'Instrument Parameters' in rd.pwdparms: Iparm1,Iparm2 = rd.pwdparms['Instrument Parameters'] elif Iparms and not lastIparmfile: Iparm1,Iparm2 = Iparms else: # get instrument parameters for each dataset, unless already set # if lastIparmfile: # is this histogram like previous? # if lastVals != (rd.powderdata[0].min(),rd.powderdata[0].max(),len(rd.powderdata[0])): # lastIparmfile = '' Iparms = self.GetPowderIparm(rd, Iparm, lastIparmfile, lastdatafile) if not Iparms: #may have bailed out Id = 0 continue Iparm1,Iparm2 = Iparms if rd.repeat_instparm: lastIparmfile = rd.instfile else: Iparms = {} # lastVals = (rd.powderdata[0].min(),rd.powderdata[0].max(),len(rd.powderdata[0])) # override any keys in read instrument parameters with ones set in import for key in Iparm1: if key in rd.instdict: Iparm1[key] = rd.instdict[key] lastdatafile = rd.powderentry[0] HistName = 'PWDR '+G2obj.StripUnicode(rd.idstring,'_') # make new histogram names unique if HistName in PWDRlist: dlg = wx.MessageDialog(self,'Skip %s?'%(HistName),'Duplicate data name',wx.YES_NO) try: if dlg.ShowModal() == wx.ID_YES: Id = 0 continue finally: dlg.Destroy() HistName = G2obj.MakeUniqueLabel(HistName,PWDRlist) print('Read powder data '+HistName+ ' from file '+rd.readfilename + ' (format: '+ rd.formatName + '). Inst parameters from '+rd.instmsg) # data are read, now store them in the tree Id = self.GPXtree.AppendItem(parent=self.root,text=HistName) if 'T' in Iparm1['Type'][0]: if not rd.clockWd and rd.GSAS: rd.powderdata[0] *= 100. #put back the CW centideg correction cw = np.diff(rd.powderdata[0]) rd.powderdata[0] = rd.powderdata[0][:-1]+cw/2. if rd.GSAS: #NB: old GSAS wanted intensities*CW even if normalized! npts = min(len(rd.powderdata[0]),len(rd.powderdata[1]),len(cw)) rd.powderdata[1] = rd.powderdata[1][:npts]/cw[:npts] rd.powderdata[2] = rd.powderdata[2][:npts]*cw[:npts]**2 #1/var=w at this point else: #NB: from topas/fullprof type files rd.powderdata[1] = rd.powderdata[1][:-1] rd.powderdata[2] = rd.powderdata[2][:-1] if 'Itype' in Iparm2: Ibeg = np.searchsorted(rd.powderdata[0],Iparm2['Tminmax'][0]) Ifin = np.searchsorted(rd.powderdata[0],Iparm2['Tminmax'][1]) rd.powderdata[0] = rd.powderdata[0][Ibeg:Ifin] YI,WYI = G2pwd.calcIncident(Iparm2,rd.powderdata[0]) rd.powderdata[1] = rd.powderdata[1][Ibeg:Ifin]/YI var = 1./rd.powderdata[2][Ibeg:Ifin] var += WYI*rd.powderdata[1]**2 var /= YI**2 rd.powderdata[2] = 1./var rd.powderdata[3] = np.zeros_like(rd.powderdata[0]) rd.powderdata[4] = np.zeros_like(rd.powderdata[0]) rd.powderdata[5] = np.zeros_like(rd.powderdata[0]) Ymin = np.min(rd.powderdata[1]) Ymax = np.max(rd.powderdata[1]) valuesdict = { 'wtFactor':1.0, 'Dummy':False, 'ranId':ran.randint(0,sys.maxint), 'Offset':[0.0,0.0],'delOffset':0.02*Ymax,'refOffset':-.1*Ymax,'refDelt':0.1*Ymax, 'qPlot':False,'dPlot':False,'sqrtPlot':False,'Yminmax':[Ymin,Ymax] } # apply user-supplied corrections to powder data if 'CorrectionCode' in Iparm1: print('Applying corrections from instprm file') corr = Iparm1['CorrectionCode'][0] try: exec(corr) print('done') except Exception as err: print(u'error: {}'.format(err)) print('with commands -------------------') print(corr) print('---------------------------------') finally: del Iparm1['CorrectionCode'] rd.Sample['ranId'] = valuesdict['ranId'] # this should be removed someday self.GPXtree.SetItemPyData(Id,[valuesdict,rd.powderdata]) self.GPXtree.SetItemPyData( self.GPXtree.AppendItem(Id,text='Comments'), rd.comments) Tmin = min(rd.powderdata[0]) Tmax = max(rd.powderdata[0]) Tmin1 = Tmin if 'NT' in Iparm1['Type'][0] and G2lat.Pos2dsp(Iparm1,Tmin) < 0.4: Tmin1 = G2lat.Dsp2pos(Iparm1,0.4) self.GPXtree.SetItemPyData( self.GPXtree.AppendItem(Id,text='Limits'), rd.pwdparms.get('Limits',[(Tmin,Tmax),[Tmin1,Tmax]]) ) self.PatternId = GetGPXtreeItemId(self,Id,'Limits') self.GPXtree.SetItemPyData( self.GPXtree.AppendItem(Id,text='Background'), rd.pwdparms.get('Background', [['chebyschev',True,3,1.0,0.0,0.0],{'nDebye':0,'debyeTerms':[],'nPeaks':0,'peaksList':[]}]) ) self.GPXtree.SetItemPyData( self.GPXtree.AppendItem(Id,text='Instrument Parameters'), [Iparm1,Iparm2]) self.GPXtree.SetItemPyData( self.GPXtree.AppendItem(Id,text='Sample Parameters'), rd.Sample) self.GPXtree.SetItemPyData( self.GPXtree.AppendItem(Id,text='Peak List') ,{'peaks':[],'sigDict':{}}) self.GPXtree.SetItemPyData( self.GPXtree.AppendItem(Id,text='Index Peak List'), [[],[]]) self.GPXtree.SetItemPyData( self.GPXtree.AppendItem(Id,text='Unit Cells List'), []) self.GPXtree.SetItemPyData( self.GPXtree.AppendItem(Id,text='Reflection Lists'), {}) # if any Control values have been set, move them into tree Controls = self.GPXtree.GetItemPyData(GetGPXtreeItemId(self,self.root, 'Controls')) Controls.update(rd.Controls) newHistList.append(HistName) rd.repeat_instparm = False #clear the iparm reuse flag else: self.EnablePlot = True if Id: self.GPXtree.Expand(Id) self.GPXtree.SelectItem(Id) if not newHistList: return # somehow, no new histograms # make a list of phase names phaseRIdList,usedHistograms = self.GetPhaseInfofromTree() phaseNameList = usedHistograms.keys() # phase names in use if not phaseNameList: return # no phases yet, nothing to do header = 'Select phase(s) to link\nto the newly-read data:' for Name in newHistList: header += '\n '+str(Name) result = G2G.ItemSelector(phaseNameList,self,header,header='Add to phase(s)',multiple=True) if not result: return # connect new phases to histograms sub = GetGPXtreeItemId(self,self.root,'Phases') if not sub: raise Exception('ERROR -- why are there no phases here?') item, cookie = self.GPXtree.GetFirstChild(sub) iph = -1 while item: # loop over (new) phases iph += 1 data = self.GPXtree.GetItemPyData(item) item, cookie = self.GPXtree.GetNextChild(sub, cookie) if iph not in result: continue generalData = data['General'] SGData = generalData['SGData'] UseList = data['Histograms'] NShkl = len(G2spc.MustrainNames(SGData)) NDij = len(G2spc.HStrainNames(SGData)) for histoName in newHistList: UseList[histoName] = SetDefaultDData('PWDR',histoName,NShkl=NShkl,NDij=NDij) Id = GetGPXtreeItemId(self,self.root,histoName) refList = self.GPXtree.GetItemPyData( GetGPXtreeItemId(self,Id,'Reflection Lists')) refList[generalData['Name']] = [] self.EnableRefineCommand() return # success def OnDummyPowder(self,event): '''Called in response to Import/Powder Data/Simulate menu item to create a Dummy powder diffraction data set. Reads an instrument parameter file and then gets input from the user ''' # get a list of existing histograms PWDRlist = [] if self.GPXtree.GetCount(): item, cookie = self.GPXtree.GetFirstChild(self.root) while item: name = self.GPXtree.GetItemText(item) if name.startswith('PWDR ') and name not in PWDRlist: PWDRlist.append(name) item, cookie = self.GPXtree.GetNextChild(self.root, cookie) # Initialize a base class reader rd = G2obj.ImportPowderData( extensionlist=tuple(), strictExtension=False, formatName = 'Simulate dataset', longFormatName = 'Compute a simulated pattern') rd.powderentry[0] = '' # no filename # #self.powderentry[1] = pos # bank offset (N/A here) rd.powderentry[2] = 1 # only one bank rd.comments.append('This is a dummy dataset for powder pattern simulation') self.CheckNotebook() Iparm = None lastdatafile = '' self.zipfile = None # get instrument parameters for it Iparm1,Iparm2 = self.GetPowderIparm(rd, Iparm, '', lastdatafile) if 'T' in Iparm1['Type'][0]: print('TOF simulation not supported yet') return False else: # need to get name, 2theta start, end, step rd.idstring = ' CW' if 'X' in Iparm1['Type'][0]: rd.idstring = 'CW x-ray simulation' else: rd.idstring = 'CW neutron simulation' # base initial range on wavelength wave = Iparm1.get('Lam') if wave: wave = wave[0] else: wave = Iparm1.get('Lam1') if wave: wave = wave[0] N = 0 while (N < 3): # insist on a dataset with a few points names = ('dataset name', 'start angle', 'end angle', 'step size') if not wave or wave < 1.0: inp = [rd.idstring, 10.,40.,0.005] # see names for what's what else: inp = [rd.idstring, 10.,80.,0.01] # see names for what's what dlg = G2G.ScrolledMultiEditor( self,[inp] * len(inp),range(len(inp)),names, header='Enter simulation name and range', minvals=(None,0.001,0.001,0.0001), maxvals=(None,180.,180.,.1), sizevals=((225,-1),) ) dlg.CenterOnParent() if dlg.ShowModal() == wx.ID_OK: if inp[1] > inp[2]: end,start,step = inp[1:] else: start,end,step = inp[1:] step = abs(step) else: return False N = int((end-start)/step)+1 x = np.linspace(start,end,N,True) N = len(x) rd.powderdata = [ np.array(x), # x-axis values np.zeros_like(x), # powder pattern intensities np.ones_like(x), # 1/sig(intensity)^2 values (weights) np.zeros_like(x), # calc. intensities (zero) np.zeros_like(x), # calc. background (zero) np.zeros_like(x), # obs-calc profiles ] Tmin = rd.powderdata[0][0] Tmax = rd.powderdata[0][-1] # data are read, now store them in the tree HistName = inp[0] HistName = 'PWDR '+HistName HistName = G2obj.MakeUniqueLabel(HistName,PWDRlist) # make new histogram names unique Id = self.GPXtree.AppendItem(parent=self.root,text=HistName) Ymin = np.min(rd.powderdata[1]) Ymax = np.max(rd.powderdata[1]) valuesdict = { 'wtFactor':1.0, 'Dummy':True, 'ranId':ran.randint(0,sys.maxint), 'Offset':[0.0,0.0],'delOffset':0.02*Ymax,'refOffset':-.1*Ymax,'refDelt':0.1*Ymax, 'qPlot':False,'dPlot':False,'sqrtPlot':False,'Yminmax':[Ymin,Ymax] } self.GPXtree.SetItemPyData(Id,[valuesdict,rd.powderdata]) self.GPXtree.SetItemPyData( self.GPXtree.AppendItem(Id,text='Comments'), rd.comments) self.GPXtree.SetItemPyData( self.GPXtree.AppendItem(Id,text='Limits'), [(Tmin,Tmax),[Tmin,Tmax]]) self.PatternId = GetGPXtreeItemId(self,Id,'Limits') self.GPXtree.SetItemPyData( self.GPXtree.AppendItem(Id,text='Background'), [['chebyschev',True,3,1.0,0.0,0.0], {'nDebye':0,'debyeTerms':[],'nPeaks':0,'peaksList':[]}]) self.GPXtree.SetItemPyData( self.GPXtree.AppendItem(Id,text='Instrument Parameters'), [Iparm1,Iparm2]) self.GPXtree.SetItemPyData( self.GPXtree.AppendItem(Id,text='Sample Parameters'), rd.Sample) self.GPXtree.SetItemPyData( self.GPXtree.AppendItem(Id,text='Peak List') ,{'peaks':[],'sigDict':{}}) self.GPXtree.SetItemPyData( self.GPXtree.AppendItem(Id,text='Index Peak List'), [[],[]]) self.GPXtree.SetItemPyData( self.GPXtree.AppendItem(Id,text='Unit Cells List'), []) self.GPXtree.SetItemPyData( self.GPXtree.AppendItem(Id,text='Reflection Lists'), {}) self.GPXtree.Expand(Id) self.GPXtree.SelectItem(Id) print(u'Added simulation powder data {}'.format(HistName)+ ' with parameters from {}'.format(rd.instmsg)) # make a list of phase names phaseRIdList,usedHistograms = self.GetPhaseInfofromTree() phaseNameList = usedHistograms.keys() # phase names in use if not phaseNameList: return # no phases yet, nothing to do header = 'Select phase(s) to add the new\npowder simulation (dummy) dataset to:' result = G2G.ItemSelector(phaseNameList,self,header,header='Add to phase(s)',multiple=True) if not result: return # connect new phases to histograms sub = GetGPXtreeItemId(self,self.root,'Phases') if not sub: raise Exception('ERROR -- why are there no phases here?') item, cookie = self.GPXtree.GetFirstChild(sub) iph = -1 while item: # loop over (new) phases iph += 1 data = self.GPXtree.GetItemPyData(item) item, cookie = self.GPXtree.GetNextChild(sub, cookie) if iph not in result: continue generalData = data['General'] SGData = generalData['SGData'] UseList = data['Histograms'] NShkl = len(G2spc.MustrainNames(SGData)) NDij = len(G2spc.HStrainNames(SGData)) UseList[HistName] = SetDefaultDData('PWDR',HistName,NShkl=NShkl,NDij=NDij) Id = GetGPXtreeItemId(self,self.root,HistName) refList = self.GPXtree.GetItemPyData( GetGPXtreeItemId(self,Id,'Reflection Lists')) refList[generalData['Name']] = [] self.EnableRefineCommand() return # success def OnPreferences(self,event): 'Edit the GSAS-II configuration variables' dlg = G2G.SelectConfigSetting(self) dlg.ShowModal() == wx.ID_OK dlg.Destroy() def _Add_ImportMenu_smallangle(self,parent): '''configure the Small Angle Data menus accord to the readers found in _init_Imports ''' submenu = wx.Menu() item = parent.AppendMenu(wx.ID_ANY, 'Small Angle Data', submenu, help='Import small angle data') for reader in self.ImportSmallAngleReaderlist: item = submenu.Append(wx.ID_ANY,help=reader.longFormatName, kind=wx.ITEM_NORMAL,text='from '+reader.formatName+' file') self.ImportMenuId[item.GetId()] = reader self.Bind(wx.EVT_MENU, self.OnImportSmallAngle, id=item.GetId()) # item = submenu.Append(wx.ID_ANY, # help='Import small angle data, use file to try to determine format', # kind=wx.ITEM_NORMAL,text='guess format from file') # self.Bind(wx.EVT_MENU, self.OnImportSmallAngle, id=item.GetId()) def OnImportSmallAngle(self,event): '''Called in response to an Import/Small Angle Data/... menu item to read a small angle diffraction data set. dict self.ImportMenuId is used to look up the specific reader item associated with the menu item, which will be None for the last menu item, which is the "guess" option where all appropriate formats will be tried. ''' def GetSASDIparm(reader): parm = reader.instdict Iparm = {'Type':[parm['type'],parm['type'],0],'Lam':[parm['wave'], parm['wave'],0],'Azimuth':[0.,0.,0]} return Iparm,{} # get a list of existing histograms SASDlist = [] if self.GPXtree.GetCount(): item, cookie = self.GPXtree.GetFirstChild(self.root) while item: name = self.GPXtree.GetItemText(item) if name.startswith('SASD ') and name not in SASDlist: SASDlist.append(name) item, cookie = self.GPXtree.GetNextChild(self.root, cookie) # look up which format was requested reqrdr = self.ImportMenuId.get(event.GetId()) rdlist = self.OnImportGeneric( reqrdr,self.ImportSmallAngleReaderlist,'Small Angle Data',multiple=True) if len(rdlist) == 0: return self.CheckNotebook() newHistList = [] self.EnablePlot = False for rd in rdlist: HistName = rd.idstring HistName = 'SASD '+HistName # make new histogram names unique HistName = G2obj.MakeUniqueLabel(HistName,SASDlist) print 'Read small angle data '+HistName+ \ ' from file '+self.lastimport # data are read, now store them in the tree Id = self.GPXtree.AppendItem(parent=self.root,text=HistName) Iparm1,Iparm2 = GetSASDIparm(rd) # if 'T' in Iparm1['Type'][0]: # if not rd.clockWd and rd.GSAS: # rd.powderdata[0] *= 100. #put back the CW centideg correction # cw = np.diff(rd.powderdata[0]) # rd.powderdata[0] = rd.powderdata[0][:-1]+cw/2. # rd.powderdata[1] = rd.powderdata[1][:-1]/cw # rd.powderdata[2] = rd.powderdata[2][:-1]*cw**2 #1/var=w at this point # if 'Itype' in Iparm2: # Ibeg = np.searchsorted(rd.powderdata[0],Iparm2['Tminmax'][0]) # Ifin = np.searchsorted(rd.powderdata[0],Iparm2['Tminmax'][1]) # rd.powderdata[0] = rd.powderdata[0][Ibeg:Ifin] # YI,WYI = G2pwd.calcIncident(Iparm2,rd.powderdata[0]) # rd.powderdata[1] = rd.powderdata[1][Ibeg:Ifin]/YI # var = 1./rd.powderdata[2][Ibeg:Ifin] # var += WYI*rd.powderdata[1]**2 # var /= YI**2 # rd.powderdata[2] = 1./var # rd.powderdata[3] = np.zeros_like(rd.powderdata[0]) # rd.powderdata[4] = np.zeros_like(rd.powderdata[0]) # rd.powderdata[5] = np.zeros_like(rd.powderdata[0]) Tmin = min(rd.smallangledata[0]) Tmax = max(rd.smallangledata[0]) valuesdict = { 'wtFactor':1.0, 'Dummy':False, 'ranId':ran.randint(0,sys.maxint), 'Offset':[0.0,0.0], } rd.Sample['ranId'] = valuesdict['ranId'] # this should be removed someday self.GPXtree.SetItemPyData(Id,[valuesdict,rd.smallangledata]) self.GPXtree.SetItemPyData( self.GPXtree.AppendItem(Id,text='Comments'), rd.comments) self.GPXtree.SetItemPyData( self.GPXtree.AppendItem(Id,text='Limits'), [(Tmin,Tmax),[Tmin,Tmax]]) self.PatternId = GetGPXtreeItemId(self,Id,'Limits') self.GPXtree.SetItemPyData( self.GPXtree.AppendItem(Id,text='Instrument Parameters'), [Iparm1,Iparm2]) self.GPXtree.SetItemPyData( self.GPXtree.AppendItem(Id,text='Substances'),G2pdG.SetDefaultSubstances()) self.GPXtree.SetItemPyData( self.GPXtree.AppendItem(Id,text='Sample Parameters'), rd.Sample) self.GPXtree.SetItemPyData( self.GPXtree.AppendItem(Id,text='Models'),G2pdG.SetDefaultSASDModel()) newHistList.append(HistName) else: self.EnablePlot = True self.GPXtree.Expand(Id) self.GPXtree.SelectItem(Id) if not newHistList: return # somehow, no new histograms return # success def _Add_ImportMenu_reflectometry(self,parent): '''configure the reflectometry Data menus accord to the readers found in _init_Imports ''' submenu = wx.Menu() item = parent.AppendMenu(wx.ID_ANY, 'Reflectometry Data', submenu, help='Import reflectometry data') for reader in self.ImportReflectometryReaderlist: item = submenu.Append(wx.ID_ANY,help=reader.longFormatName, kind=wx.ITEM_NORMAL,text='from '+reader.formatName+' file') self.ImportMenuId[item.GetId()] = reader self.Bind(wx.EVT_MENU, self.OnImportReflectometry, id=item.GetId()) # item = submenu.Append(wx.ID_ANY, # help='Import reflectometry data, use file to try to determine format', # kind=wx.ITEM_NORMAL,text='guess format from file') # self.Bind(wx.EVT_MENU, self.OnImportReflectometry, id=item.GetId()) def OnImportReflectometry(self,event): '''Called in response to an Import/Reflectometry Data/... menu item to read a reflectometry data set. dict self.ImportMenuId is used to look up the specific reader item associated with the menu item, which will be None for the last menu item, which is the "guess" option where all appropriate formats will be tried. ''' def GetREFDIparm(reader): parm = reader.instdict Iparm = {'Type':[parm['type'],parm['type'],0],'Lam':[parm['wave'], parm['wave'],0],'Azimuth':[0.,0.,0]} return Iparm,{} # get a list of existing histograms REFDlist = [] if self.GPXtree.GetCount(): item, cookie = self.GPXtree.GetFirstChild(self.root) while item: name = self.GPXtree.GetItemText(item) if name.startswith('REFD ') and name not in REFDlist: REFDlist.append(name) item, cookie = self.GPXtree.GetNextChild(self.root, cookie) # look up which format was requested reqrdr = self.ImportMenuId.get(event.GetId()) rdlist = self.OnImportGeneric( reqrdr,self.ImportReflectometryReaderlist,'Reflectometry Data',multiple=True) if len(rdlist) == 0: return self.CheckNotebook() newHistList = [] self.EnablePlot = False for rd in rdlist: HistName = rd.idstring HistName = 'REFD '+HistName # make new histogram names unique HistName = G2obj.MakeUniqueLabel(HistName,REFDlist) print 'Read reflectometry data '+HistName+ \ ' from file '+self.lastimport # data are read, now store them in the tree Id = self.GPXtree.AppendItem(parent=self.root,text=HistName) Iparm1,Iparm2 = GetREFDIparm(rd) # if 'T' in Iparm1['Type'][0]: # if not rd.clockWd and rd.GSAS: # rd.powderdata[0] *= 100. #put back the CW centideg correction # cw = np.diff(rd.powderdata[0]) # rd.powderdata[0] = rd.powderdata[0][:-1]+cw/2. # rd.powderdata[1] = rd.powderdata[1][:-1]/cw # rd.powderdata[2] = rd.powderdata[2][:-1]*cw**2 #1/var=w at this point # if 'Itype' in Iparm2: # Ibeg = np.searchsorted(rd.powderdata[0],Iparm2['Tminmax'][0]) # Ifin = np.searchsorted(rd.powderdata[0],Iparm2['Tminmax'][1]) # rd.powderdata[0] = rd.powderdata[0][Ibeg:Ifin] # YI,WYI = G2pwd.calcIncident(Iparm2,rd.powderdata[0]) # rd.powderdata[1] = rd.powderdata[1][Ibeg:Ifin]/YI # var = 1./rd.powderdata[2][Ibeg:Ifin] # var += WYI*rd.powderdata[1]**2 # var /= YI**2 # rd.powderdata[2] = 1./var # rd.powderdata[3] = np.zeros_like(rd.powderdata[0]) # rd.powderdata[4] = np.zeros_like(rd.powderdata[0]) # rd.powderdata[5] = np.zeros_like(rd.powderdata[0]) Tmin = min(rd.reflectometrydata[0]) Tmax = max(rd.reflectometrydata[0]) ifDQ = np.any(rd.reflectometrydata[5]) valuesdict = { 'wtFactor':1.0, 'Dummy':False, 'ranId':ran.randint(0,sys.maxint), 'Offset':[0.0,0.0], 'ifDQ':ifDQ } rd.Sample['ranId'] = valuesdict['ranId'] # this should be removed someday self.GPXtree.SetItemPyData(Id,[valuesdict,rd.reflectometrydata]) self.GPXtree.SetItemPyData( self.GPXtree.AppendItem(Id,text='Comments'), rd.comments) self.GPXtree.SetItemPyData( self.GPXtree.AppendItem(Id,text='Limits'), [(Tmin,Tmax),[Tmin,Tmax]]) self.PatternId = GetGPXtreeItemId(self,Id,'Limits') self.GPXtree.SetItemPyData( self.GPXtree.AppendItem(Id,text='Instrument Parameters'), [Iparm1,Iparm2]) self.GPXtree.SetItemPyData( self.GPXtree.AppendItem(Id,text='Substances'),G2pdG.SetDefaultSubstances()) self.GPXtree.SetItemPyData( self.GPXtree.AppendItem(Id,text='Sample Parameters'), rd.Sample) self.GPXtree.SetItemPyData( self.GPXtree.AppendItem(Id,text='Models'),G2pdG.SetDefaultREFDModel()) newHistList.append(HistName) else: self.EnablePlot = True self.GPXtree.Expand(Id) self.GPXtree.SelectItem(Id) if not newHistList: return # somehow, no new histograms return # success def _Add_ImportMenu_PDF(self,parent): '''configure the PDF Data menus accord to the readers found in _init_Imports ''' submenu = wx.Menu() item = parent.AppendMenu(wx.ID_ANY, 'PDF G(R) Data', submenu, help='Import PDF G(R) data') for reader in self.ImportPDFReaderlist: item = submenu.Append(wx.ID_ANY,help=reader.longFormatName, kind=wx.ITEM_NORMAL,text='from '+reader.formatName+' file') self.ImportMenuId[item.GetId()] = reader self.Bind(wx.EVT_MENU, self.OnImportPDF, id=item.GetId()) # item = submenu.Append(wx.ID_ANY, # help='Import reflectometry data, use file to try to determine format', # kind=wx.ITEM_NORMAL,text='guess format from file') # self.Bind(wx.EVT_MENU, self.OnImportReflectometry, id=item.GetId()) def OnImportPDF(self,event): '''Called in response to an Import/PDF G(R) Data/... menu item to read a PDF G(R) data set. dict self.ImportMenuId is used to look up the specific reader item associated with the menu item, which will be None for the last menu item, which is the "guess" option where all appropriate formats will be tried. ''' # get a list of existing histograms PDFlist = [] if self.GPXtree.GetCount(): item, cookie = self.GPXtree.GetFirstChild(self.root) while item: name = self.GPXtree.GetItemText(item) if name.startswith('PDF ') and name not in PDFlist: PDFlist.append(name) item, cookie = self.GPXtree.GetNextChild(self.root, cookie) # look up which format was requested reqrdr = self.ImportMenuId.get(event.GetId()) rdlist = self.OnImportGeneric( reqrdr,self.ImportPDFReaderlist,'PDF G(R) Data',multiple=True) if len(rdlist) == 0: return self.CheckNotebook() newHistList = [] self.EnablePlot = False for rd in rdlist: HistName = rd.idstring HistName = 'PDF '+HistName # make new histogram names unique HistName = G2obj.MakeUniqueLabel(HistName,PDFlist) print 'Read PDF G(R) data '+HistName+ \ ' from file '+self.lastimport # data are read, now store them in the tree Id = self.GPXtree.AppendItem(self.root,text=HistName) Ymin = np.min(rd.pdfdata[1]) Ymax = np.max(rd.pdfdata[1]) valuesdict = { 'wtFactor':1.0,'Dummy':False,'ranId':ran.randint(0,sys.maxint), 'Offset':[0.0,0.0],'delOffset':0.02*Ymax, 'qPlot':False,'dPlot':False,'sqrtPlot':False,'Yminmax':[Ymin,Ymax] } self.GPXtree.SetItemPyData( self.GPXtree.AppendItem(Id,text='PDF Controls'), {'G(R)':[valuesdict,rd.pdfdata,HistName],'diffGRname':'','diffMult':1.0}) self.GPXtree.SetItemPyData(self.GPXtree.AppendItem(Id,text='PDF Peaks'), {'Limits':[1.,5.],'Background':[2,[0.,-0.2*np.pi],False],'Peaks':[]}) else: self.EnablePlot = True self.GPXtree.Expand(Id) self.GPXtree.SelectItem(Id) if not newHistList: return # somehow, no new histograms return # success ############################################################################### #Command logging ############################################################################### def OnMacroRecordStatus(self,event,setvalue=None): '''Called when the record macro menu item is used which toggles the value. Alternately a value to be set can be provided. Note that this routine is made more complex because on the Mac there are lots of menu items (listed in self.MacroStatusList) and this loops over all of them. ''' nextvalue = log.ShowLogStatus() != True if setvalue is not None: nextvalue = setvalue if nextvalue: log.LogOn() set2 = True else: log.LogOff() set2 = False for menuitem in self.MacroStatusList: menuitem.Check(set2) def _init_Macro(self): '''Define the items in the macro menu. ''' menu = self.MacroMenu item = menu.Append( help='Start or stop recording of menu actions, etc.', id=wx.ID_ANY, kind=wx.ITEM_CHECK,text='Record actions') self.MacroStatusList.append(item) item.Check(log.ShowLogStatus()) self.Bind(wx.EVT_MENU, self.OnMacroRecordStatus, item) # this may only be of value for development work item = menu.Append( help='Show logged commands', id=wx.ID_ANY, kind=wx.ITEM_NORMAL,text='Show log') def OnShowLog(event): print 70*'=' print 'List of logged actions' for i,line in enumerate(log.G2logList): if line: print i,line print 70*'=' self.Bind(wx.EVT_MENU, OnShowLog, item) item = menu.Append( help='Clear logged commands', id=wx.ID_ANY, kind=wx.ITEM_NORMAL,text='Clear log') def OnClearLog(event): log.G2logList=[None] self.Bind(wx.EVT_MENU, OnClearLog, item) item = menu.Append( help='Save logged commands to file', id=wx.ID_ANY, kind=wx.ITEM_NORMAL,text='Save log') def OnSaveLog(event): import cPickle defnam = os.path.splitext( os.path.split(self.GSASprojectfile)[1] )[0]+'.gcmd' dlg = wx.FileDialog(self, 'Choose an file to save past actions', '.', defnam, 'GSAS-II cmd output (*.gcmd)|*.gcmd', wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT) dlg.CenterOnParent() try: if dlg.ShowModal() == wx.ID_OK: filename = dlg.GetPath() # make sure extension is correct filename = os.path.splitext(filename)[0]+'.gcmd' else: filename = None finally: dlg.Destroy() if filename: fp = open(filename,'wb') fp.write(str(len(log.G2logList)-1)+'\n') for item in log.G2logList: if item: cPickle.dump(item,fp) fp.close() self.Bind(wx.EVT_MENU, OnSaveLog, item) item = menu.Append( help='Load logged commands from file', id=wx.ID_ANY, kind=wx.ITEM_NORMAL,text='Load log') def OnLoadLog(event): # this appends. Perhaps we should ask to clear? import cPickle defnam = os.path.splitext( os.path.split(self.GSASprojectfile)[1] )[0]+'.gcmd' dlg = wx.FileDialog(self, 'Choose an file to read saved actions', '.', defnam, 'GSAS-II cmd output (*.gcmd)|*.gcmd', wx.OPEN) dlg.CenterOnParent() try: if dlg.ShowModal() == wx.ID_OK: filename = dlg.GetPath() # make sure extension is correct filename = os.path.splitext(filename)[0]+'.gcmd' else: filename = None finally: dlg.Destroy() if filename and os.path.exists(filename): fp = open(filename,'rb') lines = fp.readline() for i in range(int(lines)): log.G2logList.append(cPickle.load(fp)) fp.close() self.Bind(wx.EVT_MENU, OnLoadLog, item) item = menu.Append( help='Replay saved commands', id=wx.ID_ANY, kind=wx.ITEM_NORMAL,text='Replay log') self.Bind(wx.EVT_MENU, log.ReplayLog, item) def _init_Exports(self,menu): '''Find exporter routines and add them into menus ''' # set up the top-level menus projectmenu = wx.Menu() item = menu.AppendMenu( wx.ID_ANY, 'Entire project as', projectmenu, help='Export entire project') phasemenu = wx.Menu() item = menu.AppendMenu( wx.ID_ANY, 'Phase as', phasemenu, help='Export phase or sometimes phases') powdermenu = wx.Menu() item = menu.AppendMenu( wx.ID_ANY, 'Powder data as', powdermenu, help='Export powder diffraction histogram(s)') singlemenu = wx.Menu() item = menu.AppendMenu( wx.ID_ANY, 'Single crystal data as', singlemenu, help='Export single crystal histogram(s)') imagemenu = wx.Menu() item = menu.AppendMenu( wx.ID_ANY, 'Image data as', imagemenu, help='Export powder image(s) data') mapmenu = wx.Menu() item = menu.AppendMenu( wx.ID_ANY, 'Maps as', mapmenu, help='Export density map(s)') # pdfmenu = wx.Menu() # item = menu.AppendMenu( # wx.ID_ANY, 'PDFs as', # pdfmenu, help='Export pair distribution function(s)') # find all the exporter files if not self.exporterlist: # this only needs to be done once pathlist = sys.path filelist = [] for path in pathlist: for filename in glob.iglob(os.path.join(path,"G2export*.py")): filelist.append(filename) filelist = sorted(list(set(filelist))) # remove duplicates # go through the routines and import them, saving objects that # have export routines (method Exporter) for filename in filelist: path,rootname = os.path.split(filename) pkg = os.path.splitext(rootname)[0] # try: fp = None fp, fppath,desc = imp.find_module(pkg,[path,]) pkg = imp.load_module(pkg,fp,fppath,desc) for clss in inspect.getmembers(pkg): # find classes defined in package if clss[0].startswith('_'): continue if inspect.isclass(clss[1]): # check if we have the required methods for m in 'Exporter','loadParmDict': if not hasattr(clss[1],m): break if not callable(getattr(clss[1],m)): break else: exporter = clss[1](self) # create an export instance self.exporterlist.append(exporter) # except AttributeError: # print 'Import_'+errprefix+': Attribute Error'+str(filename) # pass # except ImportError: # print 'Import_'+errprefix+': Error importing file'+str(filename) # pass if fp: fp.close() # Add submenu item(s) for each Exporter by its self-declared type (can be more than one) for obj in self.exporterlist: #print 'exporter',obj for typ in obj.exporttype: if typ == "project": submenu = projectmenu elif typ == "phase": submenu = phasemenu elif typ == "powder": submenu = powdermenu elif typ == "single": submenu = singlemenu elif typ == "image": submenu = imagemenu elif typ == "map": submenu = mapmenu # elif typ == "pdf": # submenu = pdfmenu else: print("Error, unknown type in "+str(obj)) break item = submenu.Append( wx.ID_ANY, help=obj.longFormatName, kind=wx.ITEM_NORMAL, text=obj.formatName) self.Bind(wx.EVT_MENU, obj.Exporter, id=item.GetId()) self.ExportLookup[item.GetId()] = typ # lookup table for submenu item item = imagemenu.Append(wx.ID_ANY, help='Export image controls and masks for multiple images', kind=wx.ITEM_NORMAL, text='Multiple image controls and masks') self.Bind(wx.EVT_MENU, self.OnSaveMultipleImg, id=item.GetId()) #code to debug an Exporter. hard-code the routine below, to allow a reload before use # def DebugExport(event): # print 'start reload' # reload(G2IO) # import G2export_pwdr as dev # reload(dev) # dev.ExportPowderFXYE(self).Exporter(event) # item = menu.Append( # wx.ID_ANY,kind=wx.ITEM_NORMAL, # help="debug exporter",text="test Export FXYE") # self.Bind(wx.EVT_MENU, DebugExport, id=item.GetId()) # # #self.ExportLookup[item.GetId()] = 'image' # self.ExportLookup[item.GetId()] = 'powder' ############################################################################### # Exporters ############################################################################### def _Add_ExportMenuItems(self,parent): # item = parent.Append( # help='Select PWDR item to enable',id=wx.ID_ANY, # kind=wx.ITEM_NORMAL, # text='Export Powder Patterns...') # self.ExportPattern.append(item) # item.Enable(False) # self.Bind(wx.EVT_MENU, self.OnExportPatterns, id=item.GetId()) item = parent.Append( help='',id=wx.ID_ANY, kind=wx.ITEM_NORMAL, text='Export All Peak Lists...') self.ExportPeakList.append(item) item.Enable(True) self.Bind(wx.EVT_MENU, self.OnExportPeakList, id=item.GetId()) item = parent.Append( help='',id=wx.ID_ANY, kind=wx.ITEM_NORMAL, text='Export HKLs...') self.ExportHKL.append(item) self.Bind(wx.EVT_MENU, self.OnExportHKL, id=item.GetId()) item = parent.Append( help='Select PDF item to enable', id=wx.ID_ANY, kind=wx.ITEM_NORMAL, text='Export PDF...') self.ExportPDF.append(item) item.Enable(False) self.Bind(wx.EVT_MENU, self.OnExportPDF, id=item.GetId()) def FillMainMenu(self,menubar,addhelp=True): '''Define contents of the main GSAS-II menu for the (main) data tree window. For the mac, this is also called for the data item windows as well so that the main menu items are data menu as well. ''' File = wx.Menu(title='') menubar.Append(menu=File, title='&File') self._Add_FileMenuItems(File) Data = wx.Menu(title='') menubar.Append(menu=Data, title='Data') self._Add_DataMenuItems(Data) Calculate = wx.Menu(title='') menubar.Append(menu=Calculate, title='&Calculate') self._Add_CalculateMenuItems(Calculate) Import = wx.Menu(title='') menubar.Append(menu=Import, title='Import') self._Add_ImportMenu_Image(Import) self._Add_ImportMenu_Phase(Import) self._Add_ImportMenu_powder(Import) self._Add_ImportMenu_Sfact(Import) self._Add_ImportMenu_smallangle(Import) self._Add_ImportMenu_reflectometry(Import) self._Add_ImportMenu_PDF(Import) #====================================================================== # Code to help develop/debug an importer, much is hard-coded below # but module is reloaded before each use, allowing faster testing # def DebugImport(event): # print 'start reload' # import G2phase_ISO as dev # reload(dev) # rd = dev.ISODISTORTPhaseReader() # self.ImportMenuId[event.GetId()] = rd # self.OnImportPhase(event) # or ---------------------------------------------------------------------- #self.OnImportGeneric(rd,[],'test of ISODISTORTPhaseReader') # special debug code # or ---------------------------------------------------------------------- # filename = '/Users/toby/projects/branton/subgroup_cif.txt' # fp = open(filename,'Ur') # if not rd.ContentsValidator(fp): # print 'not validated' # # make a list of used phase ranId's # phaseRIdList = [] # sub = GetGPXtreeItemId(self,self.root,'Phases') # if sub: # item, cookie = self.GPXtree.GetFirstChild(sub) # while item: # phaseName = self.GPXtree.GetItemText(item) # ranId = self.GPXtree.GetItemPyData(item).get('ranId') # if ranId: phaseRIdList.append(ranId) # item, cookie = self.GPXtree.GetNextChild(sub, cookie) # if rd.Reader(filename,fp,usedRanIdList=phaseRIdList): # print 'read OK' # item = Import.Append( # wx.ID_ANY,kind=wx.ITEM_NORMAL, # help="debug importer",text="test importer") # self.Bind(wx.EVT_MENU, DebugImport, id=item.GetId()) #====================================================================== self.ExportMenu = wx.Menu(title='') menubar.Append(menu=self.ExportMenu, title='Export') self._init_Exports(self.ExportMenu) self._Add_ExportMenuItems(self.ExportMenu) if GSASIIpath.GetConfigValue('Enable_logging'): self.MacroMenu = wx.Menu(title='') menubar.Append(menu=self.MacroMenu, title='Macro') self._init_Macro() if addhelp: HelpMenu=G2G.MyHelp(self,includeTree=True, morehelpitems=[('&Tutorials','Tutorials'),]) menubar.Append(menu=HelpMenu,title='&Help') def _init_ctrls(self, parent): wx.Frame.__init__(self, name='GSASII', parent=parent, size=wx.Size(700, 450),style=wx.DEFAULT_FRAME_STYLE, title='GSAS-II main window') self._init_Imports() #initialize Menu item objects (these contain lists of menu items that are enabled or disabled) self.MakePDF = [] self.Refine = [] self.SeqRefine = [] # pointer(s) to Sequential Refinement menu objects #self.ExportPattern = [] self.ExportPeakList = [] self.ExportHKL = [] self.ExportPDF = [] self.ExportPhase = [] self.ExportCIF = [] # self.MacroStatusList = [] # logging self.Status = self.CreateStatusBar() self.Status.SetFieldsCount(2) # Bob: note different ways to display the SplitterWindow. I like the 3d effect on the Mac # as it makes the splitter bar a bit easier to "grab" -- this might need to be platform selected. #self.mainPanel = wx.SplitterWindow(self, wx.ID_ANY, style=wx.SP_BORDER|wx.SP_LIVE_UPDATE) #self.mainPanel = wx.SplitterWindow(self, wx.ID_ANY, style=wx.SP_BORDER|wx.SP_LIVE_UPDATE|wx.SP_3DSASH) self.mainPanel = wx.SplitterWindow(self, wx.ID_ANY, style=wx.SP_LIVE_UPDATE|wx.SP_3D) self.mainPanel.SetMinimumPaneSize(100) self.treePanel = wx.Panel(self.mainPanel, wx.ID_ANY, style = wx.TAB_TRAVERSAL|wx.SUNKEN_BORDER) self.dataWindow = G2DataWindow(self.mainPanel) dataSizer = wx.BoxSizer(wx.VERTICAL) self.dataWindow.SetSizer(dataSizer) self.mainPanel.SplitVertically(self.treePanel, self.dataWindow, 200) self.Status.SetStatusWidths([200,-1]) # make these match? G2G.wxID_GPXTREE = wx.NewId() treeSizer = wx.BoxSizer(wx.VERTICAL) self.treePanel.SetSizer(treeSizer) self.GPXtree = G2G.G2TreeCtrl(id=G2G.wxID_GPXTREE, parent=self.treePanel, size=self.treePanel.GetClientSize(),style=wx.TR_DEFAULT_STYLE ) treeSizer.Add(self.GPXtree,1,wx.EXPAND|wx.ALL,0) self.GPXtree.Bind(wx.EVT_TREE_SEL_CHANGED,self.OnDataTreeSelChanged) self.GPXtree.Bind(wx.EVT_TREE_ITEM_RIGHT_CLICK,self.OnDataTreeSelChanged) self.GPXtree.Bind(wx.EVT_TREE_ITEM_COLLAPSED, self.OnGPXtreeItemCollapsed, id=G2G.wxID_GPXTREE) self.GPXtree.Bind(wx.EVT_TREE_ITEM_EXPANDED, self.OnGPXtreeItemExpanded, id=G2G.wxID_GPXTREE) self.GPXtree.Bind(wx.EVT_TREE_DELETE_ITEM, self.OnGPXtreeItemDelete, id=G2G.wxID_GPXTREE) self.GPXtree.Bind(wx.EVT_TREE_KEY_DOWN, self.OnGPXtreeKeyDown, id=G2G.wxID_GPXTREE) self.GPXtree.Bind(wx.EVT_TREE_BEGIN_RDRAG, self.OnGPXtreeBeginRDrag, id=G2G.wxID_GPXTREE) self.GPXtree.Bind(wx.EVT_TREE_END_DRAG, self.OnGPXtreeEndDrag, id=G2G.wxID_GPXTREE) self.root = self.GPXtree.root self.dataWindow.SetupScrolling() self.plotFrame = wx.Frame(None,-1,'GSASII Plots',size=wx.Size(700,600), \ style=wx.DEFAULT_FRAME_STYLE ^ wx.CLOSE_BOX) self.G2plotNB = G2plt.G2PlotNoteBook(self.plotFrame,G2frame=self) self.plotFrame.Show() try: main_pos = eval(GSASIIpath.GetConfigValue('Main_Pos')) self.SetPosition(main_pos) if GetDisplay(main_pos) is None: self.Center() except: if GSASIIpath.GetConfigValue('Main_Pos'): print('Value for config Main_Pos {} is invalid'.format(GSASIIpath.GetConfigValue('Main_Pos'))) self.Center() try: plot_pos = eval(GSASIIpath.GetConfigValue('Plot_Pos')) self.plotFrame.SetPosition(plot_pos) if GetDisplay(plot_pos) is None: self.plotFrame.Center() except: if GSASIIpath.GetConfigValue('Plot_Pos'): print('Value for config Plot_Pos {} is invalid'.format(GSASIIpath.GetConfigValue('Plot_Pos'))) self.plotFrame.Center() def __init__(self, parent): self.ExportLookup = {} self.exporterlist = [] self._init_ctrls(parent) self.Image = wx.Image( os.path.join(GSASIIpath.path2GSAS2,'gsas2.ico'), wx.BITMAP_TYPE_ICO) if "wxMSW" in wx.PlatformInfo: img = self.Image.Scale(16, 16).ConvertToBitmap() elif "wxGTK" in wx.PlatformInfo: img = self.Image.Scale(22, 22).ConvertToBitmap() else: img = self.Image.ConvertToBitmap() self.SetIcon(wx.IconFromBitmap(img)) self.Bind(wx.EVT_CLOSE, self.ExitMain) # various defaults self.oldFocus = None self.GSASprojectfile = '' self.undofile = '' self.TreeItemDelete = False self.plotStyle = {'qPlot':False,'dPlot':False,'sqrtPlot':False,'sqPlot':False} self.Weight = False self.IfPlot = False self.DDShowAll = False self.atmSel = '' self.PatternId = 0 self.PickId = 0 self.PickIdText = None self.PeakTable = [] self.LimitsTable = [] self.ifX20 = True #use M20 /= (1+X20) in powder indexing, etc. self.HKL = [] self.Lines = [] self.itemPicked = None self.Interpolate = 'nearest' self.ContourColor = GSASIIpath.GetConfigValue('Contour_color','Paired') self.VcovColor = 'RdYlGn' self.RamaColor = 'Blues' self.Projection = 'equal area' self.logPlot = False self.plusPlot = True self.ErrorBars = False self.Contour = False self.Legend = False self.SinglePlot = True self.Waterfall = False self.selections= None self.PDFselections = None self.SubBack = False self.seqReverse = False self.seqLines = True #draw lines between points self.plotView = 0 self.Image = 0 self.oldImagefile = '' # the name of the last image file read self.oldImageTag = None # the name of the tag for multi-image files self.PauseIntegration = False self.ImageZ = [] self.Integrate = 0 self.imageDefault = {} self.IntgOutList = [] # list of integration tree item Ids created in G2IO.SaveIntegration self.AutointPWDRnames = [] # list of autoint created PWDR tree item names (to be deleted on a reset) self.autoIntFrame = None self.IntegratedList = [] # list of already integrated IMG tree items self.Sngl = False self.ifGetRing = False self.MaskKey = '' #trigger for making image masks self.MskDelete = False #trigger for mask delete self.StrainKey = '' #ditto for new strain d-zeros self.EnablePlot = True self.hist = '' # selected histogram in Phase/Data tab self.dirname = os.path.abspath(os.path.expanduser('~')) #start in the users home directory by default; may be meaningless self.TutorialImportDir = None # location to read tutorial files, set when a tutorial is viewed self.LastImportDir = None # last-used directory where an import was done self.LastGPXdir = None # directory where a GPX file was last read self.LastExportDir = None # the last directory used for exports, if any. self.dataDisplay = None self.dataDisplayPhaseText = '' self.lastTreeSetting = [] self.ExpandingAll = False self.SeqTblHideList = [] arg = sys.argv if len(arg) > 1 and arg[1]: self.GSASprojectfile = os.path.splitext(arg[1])[0]+'.gpx' self.dirname = os.path.abspath(os.path.dirname(arg[1])) if self.dirname: os.chdir(self.dirname) try: self.StartProject() #open the file if possible return except Exception: print 'Error opening or reading file',arg[1] import traceback print traceback.format_exc() if GSASIIpath.GetConfigValue('Starting_directory'): try: pth = GSASIIpath.GetConfigValue('Starting_directory') pth = os.path.expanduser(pth) os.chdir(pth) self.LastGPXdir = pth except: print('Ignoring Config Starting_directory value: '+ GSASIIpath.GetConfigValue('Starting_directory')) def GetTreeItemsList(self,item): return self.GPXtree._getTreeItemsList(item) # def OnSize(self,event): # 'Called to make GPXtree fill mainPanel' # print 'OnSize' # event.Skip() # w,h = self.GetClientSizeTuple() # self.dataWindow.SetupScrolling() # self.mainPanel.SetSize(wx.Size(w,h)) # self.GPXtree.SetSize(wx.Size(w,h)) # self.dataWindow.SetSize(self.dataPanel.GetClientSize()) def SetDataSize(self): '''this routine is a placeholder until all G2frame.SetDataSize calls are replaced by G2frame.dataWindow.SetDataSize ''' # TOTO: diagnostic patch print 'G2frame.SetDataSize called rather than dataWindow.SetDataSize' G2obj.HowDidIgetHere(True) self.dataWindow.SetDataSize() def OnDataTreeSelChanged(self, event): '''Called when a data tree item is selected''' if self.TreeItemDelete: self.TreeItemDelete = False else: if self.ExpandingAll: if GSASIIpath.GetConfigValue('debug'): print('Skipping Tree selection due to ExpandAll') return pltNum = self.G2plotNB.nb.GetSelection() if pltNum >= 0: #to avoid the startup with no plot! self.G2plotNB.nb.GetPage(pltNum) item = event.GetItem() wx.CallAfter(SelectDataTreeItem,self,item,self.oldFocus) #if self.oldFocus: # now done via last parameter on SelectDataTreeItem # wx.CallAfter(self.oldFocus.SetFocus) def OnGPXtreeItemCollapsed(self, event): 'Called when a tree item is collapsed - all children will be collapsed' self.GPXtree.CollapseAllChildren(event.GetItem()) def OnGPXtreeItemExpanded(self, event): 'Called when a tree item is expanded' #self.OnDataTreeSelChanged(event) # removed -- why select & show a tree item when expanding it? BHT event.Skip() def OnGPXtreeItemDelete(self, event): 'Called when a tree item is deleted -- not sure what this does' self.TreeItemDelete = True def OnGPXtreeItemActivated(self, event): 'Called when a tree item is activated' event.Skip() def OnGPXtreeBeginRDrag(self,event): event.Allow() self.BeginDragId = event.GetItem() self.ParentId = self.GPXtree.GetItemParent(self.BeginDragId) DragText = self.GPXtree.GetItemText(self.BeginDragId) self.DragData = [[DragText,self.GPXtree.GetItemPyData(self.BeginDragId)],] item, cookie = self.GPXtree.GetFirstChild(self.BeginDragId) while item: #G2 data tree has no sub children under a child of a tree item name = self.GPXtree.GetItemText(item) self.DragData.append([name,self.GPXtree.GetItemPyData(item)]) item, cookie = self.GPXtree.GetNextChild(self.BeginDragId, cookie) def OnGPXtreeEndDrag(self,event): event.Allow() self.EndDragId = event.GetItem() try: NewParent = self.GPXtree.GetItemParent(self.EndDragId) except: self.EndDragId = self.GPXtree.GetLastChild(self.root) NewParent = self.root if self.ParentId != NewParent: self.ErrorDialog('Drag not allowed','Wrong parent for item dragged') else: Name,Item = self.DragData[0] NewId = self.GPXtree.InsertItem(self.ParentId,self.EndDragId,Name,data=None) self.GPXtree.SetItemPyData(NewId,Item) for name,item in self.DragData[1:]: #loop over children Id = self.GPXtree.AppendItem(parent=NewId,text=name) self.GPXtree.SetItemPyData(Id,item) self.GPXtree.Delete(self.BeginDragId) SelectDataTreeItem(self,NewId) def OnGPXtreeKeyDown(self,event): #doesn't exactly work right with Shift key down 'Allows stepping through the tree with the up/down arrow keys' self.oldFocus = wx.Window.FindFocus() keyevt = event.GetKeyEvent() key = event.GetKeyCode() item = self.GPXtree.GetSelection() if type(item) is int: return # is this the toplevel in tree? name = self.GPXtree.GetItemText(item) parent = self.GPXtree.GetItemParent(item) if key == wx.WXK_UP: if keyevt.GetModifiers() == wx.MOD_SHIFT and parent != self.root: if type(parent) is int: return # is this the toplevel in tree? prev = self.GPXtree.GetPrevSibling(parent) NewId = GetGPXtreeItemId(self,prev,name) if NewId: self.GPXtree.Collapse(parent) self.GPXtree.Expand(prev) self.oldFocus = wx.Window.FindFocus() wx.CallAfter(self.GPXtree.SelectItem,NewId) else: wx.CallAfter(self.GPXtree.SelectItem,item) elif sys.platform == "win32": self.GPXtree.GetPrevSibling(item) self.GPXtree.SelectItem(item) else: item = self.GPXtree.GetPrevSibling(item) if item.IsOk(): self.GPXtree.SelectItem(item) elif key == wx.WXK_DOWN: if keyevt.GetModifiers() == wx.MOD_SHIFT and parent != self.root: next = self.GPXtree.GetNextSibling(parent) NewId = GetGPXtreeItemId(self,next,name) if NewId: self.GPXtree.Collapse(parent) self.GPXtree.Expand(next) self.oldFocus = wx.Window.FindFocus() wx.CallAfter(self.GPXtree.SelectItem,NewId) else: wx.CallAfter(self.GPXtree.SelectItem,item) elif sys.platform == "win32": self.GPXtree.GetNextSibling(item) self.GPXtree.SelectItem(item) else: item = self.GPXtree.GetNextSibling(item) if item.IsOk(): self.GPXtree.SelectItem(item) def SetTitle(self,text,location=0): '''Override the standard method with a call that puts text into either the top box on the tree or the label on the frame. :param str text: text to be displayed :param int location: if 0 (default) labels go into the the Frame; if 1, labels go into the G2frame.treeTitle control, which is above the data Tree. ''' if location == 1: # self.treeTitle.SetLabel(text) pass elif not location: wx.Frame.SetTitle(self,text) else: print(u'unexpected SetTitle option: '+str(location)+", "+ text) def SetLabel(self,text,location=0): 'implement unfortunate synonym. with luck no longer used' self.SetTitle(text,location=0) def OnReadPowderPeaks(self,event): 'Bound to menu Data/Read Powder Peaks' self.CheckNotebook() pth = G2G.GetImportPath(self) if not pth: pth = '.' dlg = wx.FileDialog(self, 'Choose file with peak list', pth, '', 'peak files (*.txt)|*.txt|All files (*.*)|*.*',wx.OPEN) try: if dlg.ShowModal() == wx.ID_OK: self.HKL = [] self.powderfile = dlg.GetPath() comments,peaks,limits,wave = G2IO.GetPowderPeaks(self.powderfile) Id = self.GPXtree.AppendItem(parent=self.root,text='PKS '+os.path.basename(self.powderfile)) data = ['PKS',wave,0.0] names = ['Type','Lam','Zero'] codes = [0,0,0] inst = [G2IO.makeInstDict(names,data,codes),{}] self.GPXtree.SetItemPyData(self.GPXtree.AppendItem(Id,text='Instrument Parameters'),inst) self.GPXtree.SetItemPyData(self.GPXtree.AppendItem(Id,text='Comments'),comments) self.GPXtree.SetItemPyData(self.GPXtree.AppendItem(Id,text='Limits'),[tuple(limits),limits]) self.GPXtree.SetItemPyData(self.GPXtree.AppendItem(Id,text='Index Peak List'),[peaks,[]]) self.GPXtree.SetItemPyData(self.GPXtree.AppendItem(Id,text='Unit Cells List'),[]) self.GPXtree.Expand(Id) self.GPXtree.SelectItem(Id) os.chdir(dlg.GetDirectory()) # to get Mac/Linux to change directory! finally: dlg.Destroy() def CheckNotebook(self): '''Make sure the data tree has the minimally expected controls. ''' if not GetGPXtreeItemId(self,self.root,'Notebook'): sub = self.GPXtree.AppendItem(parent=self.root,text='Notebook') self.GPXtree.SetItemPyData(sub,['']) if not GetGPXtreeItemId(self,self.root,'Controls'): sub = self.GPXtree.AppendItem(parent=self.root,text='Controls') self.GPXtree.SetItemPyData(sub,copy.copy(G2obj.DefaultControls)) if not GetGPXtreeItemId(self,self.root,'Covariance'): sub = self.GPXtree.AppendItem(parent=self.root,text='Covariance') self.GPXtree.SetItemPyData(sub,{}) if not GetGPXtreeItemId(self,self.root,'Constraints'): sub = self.GPXtree.AppendItem(parent=self.root,text='Constraints') self.GPXtree.SetItemPyData(sub,{'Hist':[],'HAP':[],'Phase':[]}) if not GetGPXtreeItemId(self,self.root,'Restraints'): sub = self.GPXtree.AppendItem(parent=self.root,text='Restraints') self.GPXtree.SetItemPyData(sub,{}) if not GetGPXtreeItemId(self,self.root,'Rigid bodies'): sub = self.GPXtree.AppendItem(parent=self.root,text='Rigid bodies') self.GPXtree.SetItemPyData(sub,{'Vector':{'AtInfo':{}}, 'Residue':{'AtInfo':{}},'RBIds':{'Vector':[],'Residue':[]}}) class CopyDialog(wx.Dialog): '''Creates a dialog for copying control settings between data tree items''' def __init__(self,parent,title,text,data): wx.Dialog.__init__(self,parent,-1,title, pos=wx.DefaultPosition,style=wx.DEFAULT_DIALOG_STYLE) self.data = data panel = wx.Panel(self) mainSizer = wx.BoxSizer(wx.VERTICAL) topLabl = wx.StaticText(panel,-1,text) mainSizer.Add((10,10),1) mainSizer.Add(topLabl,0,wx.ALIGN_CENTER_VERTICAL|wx.LEFT,10) mainSizer.Add((10,10),1) ncols = len(data)/40+1 dataGridSizer = wx.FlexGridSizer(cols=ncols,hgap=2,vgap=2) for id,item in enumerate(self.data): ckbox = wx.CheckBox(panel,id,item[1]) ckbox.Bind(wx.EVT_CHECKBOX,self.OnCopyChange) dataGridSizer.Add(ckbox,0,wx.LEFT,10) mainSizer.Add(dataGridSizer,0,wx.EXPAND) OkBtn = wx.Button(panel,-1,"Ok") OkBtn.Bind(wx.EVT_BUTTON, self.OnOk) cancelBtn = wx.Button(panel,-1,"Cancel") cancelBtn.Bind(wx.EVT_BUTTON, self.OnCancel) btnSizer = wx.BoxSizer(wx.HORIZONTAL) btnSizer.Add((20,20),1) btnSizer.Add(OkBtn) btnSizer.Add((20,20),1) btnSizer.Add(cancelBtn) btnSizer.Add((20,20),1) mainSizer.Add(btnSizer,0,wx.EXPAND|wx.BOTTOM|wx.TOP, 10) panel.SetSizer(mainSizer) panel.Fit() self.Fit() def OnCopyChange(self,event): id = event.GetId() self.data[id][0] = self.FindWindowById(id).GetValue() def OnOk(self,event): parent = self.GetParent() parent.Raise() self.EndModal(wx.ID_OK) def OnCancel(self,event): parent = self.GetParent() parent.Raise() self.EndModal(wx.ID_CANCEL) def GetData(self): return self.data class SumDialog(wx.Dialog): '''Allows user to supply scale factor(s) when summing data - TODO: CAN WE PREVIEW RESULT HERE?''' def __init__(self,parent,title,text,dataType,data,dataList): wx.Dialog.__init__(self,parent,-1,title,size=(400,250), pos=wx.DefaultPosition,style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER) self.plotFrame = wx.Frame(self,-1,'Sum Plots',size=wx.Size(700,600), \ style=wx.DEFAULT_FRAME_STYLE ^ wx.CLOSE_BOX) self.G2plotNB = G2plt.G2PlotNoteBook(self.plotFrame,G2frame=self) self.data = data self.dataList = dataList self.dataType = dataType size = (450,350) panel = wxscroll.ScrolledPanel(self, wx.ID_ANY,size=size, style = wx.TAB_TRAVERSAL|wx.SUNKEN_BORDER) mainSizer = wx.BoxSizer(wx.VERTICAL) topLabl = wx.StaticText(panel,-1,text) mainSizer.Add((10,10),1) mainSizer.Add(topLabl,0,wx.ALIGN_CENTER_VERTICAL|wx.LEFT,10) mainSizer.Add((10,10),1) self.dataGridSizer = wx.FlexGridSizer(cols=2,hgap=2,vgap=2) for id,item in enumerate(self.data[:-1]): name = wx.TextCtrl(panel,-1,item[1],size=wx.Size(300,20)) name.SetEditable(False) # azmthOff = G2G.ValidatedTxtCtrl(G2frame.dataDisplay,data,'azmthOff',nDig=(10,2),typeHint=float,OnLeave=OnAzmthOff) scale = wx.TextCtrl(panel,id,'%.3f'%(item[0]),style=wx.TE_PROCESS_ENTER) scale.Bind(wx.EVT_TEXT_ENTER,self.OnScaleChange) scale.Bind(wx.EVT_KILL_FOCUS,self.OnScaleChange) self.dataGridSizer.Add(scale,0,wx.LEFT,10) self.dataGridSizer.Add(name,0,wx.RIGHT,10) if self.dataType: self.dataGridSizer.Add(wx.StaticText(panel,-1,'Sum result name: '+self.dataType),0, \ wx.LEFT|wx.TOP|wx.ALIGN_CENTER_VERTICAL,10) self.name = wx.TextCtrl(panel,-1,self.data[-1],size=wx.Size(300,20),style=wx.TE_PROCESS_ENTER) self.name.Bind(wx.EVT_TEXT_ENTER,self.OnNameChange) self.name.Bind(wx.EVT_KILL_FOCUS,self.OnNameChange) self.dataGridSizer.Add(self.name,0,wx.RIGHT|wx.TOP,10) self.dataGridSizer.Add(wx.StaticText(panel,label='All scales value: '),0, \ wx.LEFT|wx.TOP|wx.ALIGN_CENTER_VERTICAL,10) # azmthOff = G2G.ValidatedTxtCtrl(G2frame.dataDisplay,data,'azmthOff',nDig=(10,2),typeHint=float,OnLeave=OnAzmthOff) allScale = wx.TextCtrl(panel,value='',style=wx.TE_PROCESS_ENTER) allScale.Bind(wx.EVT_TEXT_ENTER,self.OnAllScale) allScale.Bind(wx.EVT_KILL_FOCUS,self.OnAllScale) self.dataGridSizer.Add(allScale,0,WACV) mainSizer.Add(self.dataGridSizer,0,wx.EXPAND) OkBtn = wx.Button(panel,-1,"Ok") OkBtn.Bind(wx.EVT_BUTTON, self.OnOk) cancelBtn = wx.Button(panel,-1,"Cancel") cancelBtn.Bind(wx.EVT_BUTTON, self.OnCancel) btnSizer = wx.FlexGridSizer(0,3,10,20) if self.dataType =='PWDR': TestBtn = wx.Button(panel,-1,"Test") TestBtn.Bind(wx.EVT_BUTTON, self.OnTest) btnSizer.Add(TestBtn) btnSizer.Add(OkBtn) btnSizer.Add(cancelBtn) panel.SetSizer(mainSizer) panel.SetAutoLayout(1) panel.SetupScrolling() mainSizer.Add((10,10),1) mainSizer.Add(btnSizer,0,wx.CENTER) panel.SetSizer(mainSizer) panel.Fit() self.Fit() def OnScaleChange(self,event): event.Skip() id = event.GetId() value = self.FindWindowById(id).GetValue() try: self.data[id][0] = float(value) self.FindWindowById(id).SetValue('%.3f'%(self.data[id][0])) except ValueError: if value and '-' not in value[0]: print 'bad input - numbers only' self.FindWindowById(id).SetValue('0.000') def OnAllScale(self,event): event.Skip() id = event.GetId() try: scale = float(self.FindWindowById(id).GetValue()) self.FindWindowById(id).SetValue('%.3f'%(scale)) entries = self.dataGridSizer.GetChildren() for i,item in enumerate(self.data[:-1]): item[0] = scale entries[2*i].GetWindow().SetValue('%.3f'%(scale)) except ValueError: print 'bad input - numbers only' self.FindWindowById(id).SetValue('') def OnNameChange(self,event): event.Skip() self.data[-1] = self.name.GetValue() def OnTest(self,event): lenX = 0 Xminmax = [0,0] XY = [] Xsum = [] Ysum = [] Vsum = [] result = self.data for i,item in enumerate(result[:-1]): scale,name = item data = self.dataList[i] if scale: x,y,w,yc,yb,yd = data #numpy arrays! XY.append([x,scale*y]) v = 1./w if lenX: if lenX != len(x): self.ErrorDialog('Data length error','Data to be summed must have same number of points'+ \ '\nExpected:'+str(lenX)+ \ '\nFound: '+str(len(x))+'\nfor '+name) self.OnCancel(event) else: lenX = len(x) if Xminmax[1]: if Xminmax != [x[0],x[-1]]: self.ErrorDialog('Data range error','Data to be summed must span same range'+ \ '\nExpected:'+str(Xminmax[0])+' '+str(Xminmax[1])+ \ '\nFound: '+str(x[0])+' '+str(x[-1])+'\nfor '+name) self.OnCancel(event) else: for j,yi in enumerate(y): Ysum[j] += scale*yi Vsum[j] += abs(scale)*v[j] else: Xminmax = [x[0],x[-1]] Xsum = x Ysum = scale*y Vsum = abs(scale*v) Wsum = 1./np.array(Vsum) YCsum = np.zeros(lenX) YBsum = np.zeros(lenX) YDsum = np.zeros(lenX) XY.append([Xsum,Ysum]) self.result = [Xsum,Ysum,Wsum,YCsum,YBsum,YDsum] # N.B. PlotXY expects the first arg to point to G2frame. In this case, we # create a duplicate (temporary) Plot notebook window that is a child of the # modal SumDialog dialog (self). This nicely gets deleted when the dialog is destroyed, # but the plot window is not fully functional, at least on the Mac. G2plt.PlotXY(self,XY,lines=True,Title='Sum:'+self.data[-1],labelY='Intensity',) self.plotFrame.Show() def OnOk(self,event): if self.dataType == 'PWDR': self.OnTest(event) parent = self.GetParent() parent.Raise() self.EndModal(wx.ID_OK) def OnCancel(self,event): parent = self.GetParent() parent.Raise() self.EndModal(wx.ID_CANCEL) def GetData(self): if self.dataType == 'PWDR': return self.data,self.result else: return self.data def OnPwdrSum(self,event): 'Sum together powder data(?)' TextList = [] DataList = [] Names = [] Inst = None Comments = ['Sum equals: \n'] if self.GPXtree.GetCount(): item, cookie = self.GPXtree.GetFirstChild(self.root) while item: name = self.GPXtree.GetItemText(item) Names.append(name) if 'PWDR' in name: TextList.append([0.0,name]) DataList.append(self.GPXtree.GetItemPyData(item)[1]) # (x,y,w,yc,yb,yd) if not Inst: Inst = self.GPXtree.GetItemPyData(GetGPXtreeItemId(self,item, 'Instrument Parameters')) item, cookie = self.GPXtree.GetNextChild(self.root, cookie) if len(TextList) < 2: self.ErrorDialog('Not enough data to sum','There must be more than one "PWDR" pattern') return TextList.append('default_sum_name') dlg = self.SumDialog(self,'Sum data','Enter scale for each pattern in summation','PWDR',TextList,DataList) try: if dlg.ShowModal() == wx.ID_OK: result,sumData = dlg.GetData() Xsum,Ysum,Wsum,YCsum,YBsum,YDsum = sumData Xminmax = [Xsum[0],Xsum[-1]] outname = 'PWDR '+result[-1] Id = 0 if outname in Names: dlg2 = wx.MessageDialog(self,'Overwrite data?','Duplicate data name',wx.OK|wx.CANCEL) try: if dlg2.ShowModal() == wx.ID_OK: Id = GetGPXtreeItemId(self,self.root,name) self.GPXtree.Delete(Id) finally: dlg2.Destroy() Id = self.GPXtree.AppendItem(parent=self.root,text=outname) if Id: Sample = G2obj.SetDefaultSample() Ymin = np.min(Ysum) Ymax = np.max(Ysum) valuesdict = { 'wtFactor':1.0, 'Dummy':False, 'ranId':ran.randint(0,sys.maxint), 'Offset':[0.0,0.0],'delOffset':0.02*Ymax,'refOffset':-.1*Ymax,'refDelt':0.1*Ymax, 'qPlot':False,'dPlot':False,'sqrtPlot':False,'Yminmax':[Ymin,Ymax] } self.GPXtree.SetItemPyData(Id,[valuesdict,[np.array(Xsum),np.array(Ysum),np.array(Wsum), np.array(YCsum),np.array(YBsum),np.array(YDsum)]]) self.GPXtree.SetItemPyData(self.GPXtree.AppendItem(Id,text='Comments'),Comments) self.GPXtree.SetItemPyData(self.GPXtree.AppendItem(Id,text='Limits'),[tuple(Xminmax),Xminmax]) self.GPXtree.SetItemPyData(self.GPXtree.AppendItem(Id,text='Background'),[['chebyschev',True,3,1.0,0.0,0.0], {'nDebye':0,'debyeTerms':[],'nPeaks':0,'peaksList':[]}]) self.GPXtree.SetItemPyData(self.GPXtree.AppendItem(Id,text='Instrument Parameters'),Inst) self.GPXtree.SetItemPyData(self.GPXtree.AppendItem(Id,text='Sample Parameters'),Sample) self.GPXtree.SetItemPyData(self.GPXtree.AppendItem(Id,text='Peak List'),{'peaks':[],'sigDict':{}}) self.GPXtree.SetItemPyData(self.GPXtree.AppendItem(Id,text='Index Peak List'),[[],[]]) self.GPXtree.SetItemPyData(self.GPXtree.AppendItem(Id,text='Unit Cells List'),[]) self.GPXtree.SetItemPyData(self.GPXtree.AppendItem(Id,text='Reflection Lists'),{}) self.GPXtree.SelectItem(Id) self.GPXtree.Expand(Id) finally: dlg.Destroy() def OnImageSum(self,event): 'Sum together image data' TextList = [] DataList = [] IdList = [] Names = [] Comments = ['Sum equals: \n'] if self.GPXtree.GetCount(): item, cookie = self.GPXtree.GetFirstChild(self.root) while item: name = self.GPXtree.GetItemText(item) Names.append(name) if 'IMG' in name: TextList.append([0.0,name]) DataList.append(self.GPXtree.GetImageLoc(item)) #Size,Image,Tag IdList.append(item) Data = self.GPXtree.GetItemPyData(GetGPXtreeItemId(self,item,'Image Controls')) item, cookie = self.GPXtree.GetNextChild(self.root, cookie) if len(TextList) < 2: self.ErrorDialog('Not enough data to sum','There must be more than one "IMG" pattern') return TextList.append('default_sum_name') dlg = self.SumDialog(self,'Sum data','Enter scale for each image in summation','IMG',TextList,DataList) try: if dlg.ShowModal() == wx.ID_OK: imSize = 0 result = dlg.GetData() First = True Found = False for i,item in enumerate(result[:-1]): scale,name = item if scale: Found = True Comments.append("%10.3f %s" % (scale,' * '+name)) Npix,imagefile,imagetag = DataList[i] imagefile = G2IO.GetCheckImageFile(self,IdList[i])[1] image = G2IO.GetImageData(self,imagefile,imageOnly=True,ImageTag=imagetag) if First: newImage = np.zeros_like(image) First = False if imSize: if imSize != Npix: self.ErrorDialog('Image size error','Images to be summed must be same size'+ \ '\nExpected:'+str(imSize)+ \ '\nFound: '+str(Npix)+'\nfor '+name) return newImage = newImage+scale*image else: imSize = Npix newImage = newImage+scale*image del(image) if not Found: self.ErrorDialog('Image sum error','No nonzero image multipliers found') return newImage = np.array(newImage,dtype=np.int32) outname = 'IMG '+result[-1] Id = 0 if outname in Names: dlg2 = wx.MessageDialog(self,'Overwrite data?','Duplicate data name',wx.OK|wx.CANCEL) try: if dlg2.ShowModal() == wx.ID_OK: Id = GetGPXtreeItemId(self,self.root,name) finally: dlg2.Destroy() else: Id = self.GPXtree.AppendItem(parent=self.root,text=outname) if Id: pth = G2G.GetExportPath(self) dlg = wx.FileDialog(self, 'Choose sum image filename', pth,outname.split('IMG ')[1], 'G2img files (*.G2img)|*.G2img', wx.SAVE|wx.FD_OVERWRITE_PROMPT) if dlg.ShowModal() == wx.ID_OK: newimagefile = dlg.GetPath() newimagefile = G2IO.FileDlgFixExt(dlg,newimagefile) G2IO.PutG2Image(newimagefile,Comments,Data,Npix,newImage) Imax = np.amax(newImage) Imin = np.amin(newImage) newImage = [] self.GPXtree.SetItemPyData(Id,[imSize,newimagefile]) self.GPXtree.SetItemPyData(self.GPXtree.AppendItem(Id,text='Comments'),Comments) del(newImage) if self.imageDefault: Data = copy.copy(self.imageDefault) Data['formatName'] = 'GSAS-II image' Data['showLines'] = True Data['ring'] = [] Data['rings'] = [] Data['cutoff'] = 10 Data['pixLimit'] = 20 Data['ellipses'] = [] Data['calibrant'] = '' Data['range'] = [(Imin,Imax),[Imin,Imax]] self.GPXtree.SetItemPyData(self.GPXtree.AppendItem(Id,text='Image Controls'),Data) Masks = {'Points':[],'Rings':[],'Arcs':[],'Polygons':[],'Frames':[],'Thresholds':[(Imin,Imax),[Imin,Imax]]} self.GPXtree.SetItemPyData(self.GPXtree.AppendItem(Id,text='Masks'),Masks) self.GPXtree.SetItemPyData(self.GPXtree.AppendItem(Id,text='Stress/Strain'), {'Type':'True','d-zero':[],'Sample phi':0.0,'Sample z':0.0,'Sample load':0.0}) self.GPXtree.SelectItem(Id) self.GPXtree.Expand(Id) self.PickId = GetGPXtreeItemId(self,self.root,outname) self.Image = self.PickId finally: dlg.Destroy() def OnAddPhase(self,event): 'Add a new, empty phase to the tree. Called by Data/Add Phase menu' if not GetGPXtreeItemId(self,self.root,'Phases'): sub = self.GPXtree.AppendItem(parent=self.root,text='Phases') else: sub = GetGPXtreeItemId(self,self.root,'Phases') PhaseName = '' dlg = wx.TextEntryDialog(None,'Enter a name for this phase','Phase Name Entry','New phase', style=wx.OK) if dlg.ShowModal() == wx.ID_OK: PhaseName = dlg.GetValue() dlg.Destroy() sub = self.GPXtree.AppendItem(parent=sub,text=PhaseName) E,SGData = G2spc.SpcGroup('P 1') self.GPXtree.SetItemPyData(sub,G2obj.SetNewPhase(Name=PhaseName,SGData=SGData)) SelectDataTreeItem(self,sub) #bring up new phase General tab def OnDeletePhase(self,event): 'Delete a phase from the tree. Called by Data/Delete Phase menu' #Hmm, also need to delete this phase from Reflection Lists for each PWDR histogram if self.dataWindow: self.dataWindow.ClearData() TextList = [] DelList = [] DelItemList = [] if GetGPXtreeItemId(self,self.root,'Phases'): sub = GetGPXtreeItemId(self,self.root,'Phases') else: return if sub: item, cookie = self.GPXtree.GetFirstChild(sub) while item: TextList.append(self.GPXtree.GetItemText(item)) item, cookie = self.GPXtree.GetNextChild(sub, cookie) dlg = wx.MultiChoiceDialog(self, 'Which phase to delete?', 'Delete phase', TextList, wx.CHOICEDLG_STYLE) try: if dlg.ShowModal() == wx.ID_OK: result = dlg.GetSelections() for i in result: DelList.append([i,TextList[i]]) item, cookie = self.GPXtree.GetFirstChild(sub) i = 0 while item: if [i,self.GPXtree.GetItemText(item)] in DelList: DelItemList.append(item) item, cookie = self.GPXtree.GetNextChild(sub, cookie) i += 1 for item in DelItemList: name = self.GPXtree.GetItemText(item) self.GPXtree.Delete(item) self.G2plotNB.Delete(name) item, cookie = self.GPXtree.GetFirstChild(self.root) while item: name = self.GPXtree.GetItemText(item) if 'PWDR' in name: Id = GetGPXtreeItemId(self,item, 'Reflection Lists') refList = self.GPXtree.GetItemPyData(Id) if len(refList): for i,item in DelList: if item in refList: del(refList[item]) # self.GPXtree.SetItemPyData(Id,refList) elif 'HKLF' in name: data = self.GPXtree.GetItemPyData(item) data[0] = {} # self.GPXtree.SetItemPyData(item,data) item, cookie = self.GPXtree.GetNextChild(self.root, cookie) finally: dlg.Destroy() def OnRenameData(self,event): 'Renames an existing phase. Called by Data/Rename Phase menu' name = self.GPXtree.GetItemText(self.PickId) if 'PWDR' in name or 'HKLF' in name or 'IMG' in name: if 'Bank' in name: names = name.split('Bank') names[1] = ' Bank'+names[1] elif 'Azm' in name: names = name.split('Azm') names[1] = ' Azm'+names[1] else: names = [name,''] dataType = names[0][:names[0].index(' ')+1] #includes the ' ' dlg = wx.TextEntryDialog(self,'Data name: '+name,'Change data name', defaultValue=names[0][names[0].index(' ')+1:]) try: if dlg.ShowModal() == wx.ID_OK: name = dataType+dlg.GetValue()+names[1] self.GPXtree.SetItemText(self.PickId,name) finally: dlg.Destroy() def GetFileList(self,fileType,skip=None): #potentially useful? 'Appears unused. Note routine of same name in GSASIIpwdGUI' fileList = [] Source = '' id, cookie = self.GPXtree.GetFirstChild(self.root) while id: name = self.GPXtree.GetItemText(id) if fileType in name: if id == skip: Source = name else: fileList.append([False,name,id]) id, cookie = self.GPXtree.GetNextChild(self.root, cookie) if skip: return fileList,Source else: return fileList def OnDataDelete(self, event): '''Delete one or more histograms from data tree. Called by the Data/DeleteData menu ''' TextList = [] DelList = [] DelItemList = [] nItems = {'PWDR':0,'SASD':0,'REFD':0,'IMG':0,'HKLF':0,'PDF':0} PDFnames = [] if self.GPXtree.GetCount(): item, cookie = self.GPXtree.GetFirstChild(self.root) while item: name = self.GPXtree.GetItemText(item) if name not in ['Notebook','Controls','Covariance','Constraints', 'Restraints','Phases','Rigid bodies'] and 'Sequential' not in name: if 'PWDR' in name[:4]: nItems['PWDR'] += 1 if 'SASD' in name[:4]: nItems['SASD'] += 1 if 'REFD' in name[:4]: nItems['REFD'] += 1 if 'IMG' in name[:3]: nItems['IMG'] += 1 if 'HKLF' in name[:4]: nItems['HKLF'] += 1 if 'PDF' in name[:3]: PDFnames.append(name) nItems['PDF'] += 1 TextList.append(name) item, cookie = self.GPXtree.GetNextChild(self.root, cookie) for pdfName in PDFnames: try: TextList.remove('PWDR'+pdfName[4:]) except ValueError: print 'PWDR'+pdfName[4:]+' for '+pdfName+' not found' dlg = G2G.G2MultiChoiceDialog(self, 'Which data to delete?', 'Delete data', TextList, wx.CHOICEDLG_STYLE) try: if dlg.ShowModal() == wx.ID_OK: result = dlg.GetSelections() for i in result: DelList.append(TextList[i]) item, cookie = self.GPXtree.GetFirstChild(self.root) while item: itemName = self.GPXtree.GetItemText(item) if itemName in DelList: if 'PWDR' in itemName[:4]: nItems['PWDR'] -= 1 elif 'SASD' in itemName[:4]: nItems['SASD'] -= 1 elif 'REFD' in itemName[:4]: nItems['REFD'] -= 1 elif 'IMG' in itemName[:3]: nItems['IMG'] -= 1 elif 'HKLF' in itemName[:4]: nItems['HKLF'] -= 1 elif 'PDF' in itemName[:3]: nItems['PDF'] -= 1 DelItemList.append(item) item, cookie = self.GPXtree.GetNextChild(self.root, cookie) for item in DelItemList: self.GPXtree.Delete(item) self.PickId = 0 self.PickIdText = None self.PatternId = 0 if nItems['PWDR']: wx.CallAfter(G2plt.PlotPatterns,self,True) else: self.G2plotNB.Delete('Powder Patterns') if not nItems['IMG']: self.G2plotNB.Delete('2D Powder Image') if not nItems['HKLF']: self.G2plotNB.Delete('Structure Factors') if '3D Structure Factors' in self.G2plotNB.plotList: self.G2plotNB.Delete('3D Structure Factors') finally: dlg.Destroy() def OnFileOpen(self, event, filename=None): '''Gets a GSAS-II .gpx project file in response to the File/Open Project menu button ''' def SaveOld(): if self.dataWindow: self.dataWindow.ClearData() dlg = wx.MessageDialog( self, 'Do you want to overwrite the current project? '+ 'Any unsaved changes in current project will be lost. Press OK to continue.', 'Overwrite?', wx.OK | wx.CANCEL) try: result = dlg.ShowModal() if result == wx.ID_OK: dlg.Destroy() self.GPXtree.DeleteChildren(self.root) self.GSASprojectfile = '' self.HKL = [] if self.G2plotNB.plotList: self.G2plotNB.clear() finally: pass return result def GetGPX(): if self.LastGPXdir: pth = self.LastGPXdir else: pth = '.' dlg = wx.FileDialog(self, 'Choose GSAS-II project file', pth, wildcard='GSAS-II project file (*.gpx)|*.gpx',style=wx.OPEN) try: if dlg.ShowModal() != wx.ID_OK: return self.GSASprojectfile = dlg.GetPath() self.GSASprojectfile = G2IO.FileDlgFixExt(dlg,self.GSASprojectfile) self.dirname = dlg.GetDirectory() finally: dlg.Destroy() self.EnablePlot = False result = wx.ID_OK if self.GPXtree.GetChildrenCount(self.root,False): result = SaveOld() if result != wx.ID_OK: return if not filename: GetGPX() else: self.GSASprojectfile = os.path.splitext(filename)[0]+'.gpx' self.dirname = os.path.split(filename)[0] try: self.StartProject() #open the file if possible except: print '\nError opening file ',filename import traceback print traceback.format_exc() def StartProject(self): '''Opens a GSAS-II project file & selects the 1st available data set to display (PWDR, HKLF, REFD or SASD) ''' Id = 0 phaseId = None G2IO.ProjFileOpen(self) self.GPXtree.SetItemText(self.root,'Project: '+self.GSASprojectfile) self.GPXtree.Expand(self.root) self.HKL = [] item, cookie = self.GPXtree.GetFirstChild(self.root) while item and not Id: name = self.GPXtree.GetItemText(item) if name[:4] in ['PWDR','HKLF','IMG ','PDF ','SASD','REFD']: Id = item elif name == "Phases": phaseId = item elif name == 'Controls': data = self.GPXtree.GetItemPyData(item) if data: for item in self.Refine: item.Enable(True) self.EnableSeqRefineMenu() item, cookie = self.GPXtree.GetNextChild(self.root, cookie) if phaseId: # show all phases self.GPXtree.Expand(phaseId) if Id: self.EnablePlot = True self.GPXtree.SelectItem(Id) self.GPXtree.Expand(Id) elif phaseId: self.GPXtree.SelectItem(phaseId) self.CheckNotebook() if self.dirname: os.chdir(self.dirname) # to get Mac/Linux to change directory! pth = os.path.split(os.path.abspath(self.GSASprojectfile))[0] if GSASIIpath.GetConfigValue('Save_paths'): G2G.SaveGPXdirectory(pth) self.LastGPXdir = pth def OnFileClose(self, event): '''Clears the data tree in response to the File/New Project menu button. User is given option to save the project. ''' dlg = wx.MessageDialog(self, 'Save current project?', ' ', wx.YES | wx.NO | wx.CANCEL) try: result = dlg.ShowModal() if result == wx.ID_OK: self.OnFileSaveMenu(event) if result != wx.ID_CANCEL: self.GSASprojectfile = '' self.GPXtree.SetItemText(self.root,'Project: ') self.GPXtree.DeleteChildren(self.root) if self.HKL: self.HKL = [] if self.G2plotNB.plotList: self.G2plotNB.clear() finally: dlg.Destroy() def OnFileSave(self, event): '''Save the current project in response to the File/Save Project menu button ''' if self.GSASprojectfile: self.GPXtree.SetItemText(self.root,'Project: '+self.GSASprojectfile) self.CheckNotebook() G2IO.ProjFileSave(self) else: self.OnFileSaveas(event) def OnFileSaveas(self, event): '''Save the current project in response to the File/Save as menu button ''' if GSASIIpath.GetConfigValue('Starting_directory'): pth = GSASIIpath.GetConfigValue('Starting_directory') pth = os.path.expanduser(pth) elif self.LastGPXdir: pth = self.LastGPXdir else: pth = '.' dlg = wx.FileDialog(self, 'Choose GSAS-II project file name', pth, '', 'GSAS-II project file (*.gpx)|*.gpx',wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT) try: if dlg.ShowModal() == wx.ID_OK: self.GSASprojectfile = dlg.GetPath() self.GSASprojectfile = G2IO.FileDlgFixExt(dlg,self.GSASprojectfile) self.GPXtree.SetItemText(self.root,'Project: '+self.GSASprojectfile) #self.SetTitle("GSAS-II data tree: "+os.path.split(self.GSASprojectfile)[1]) self.SetTitle("GSAS-II project: "+os.path.split(self.GSASprojectfile)[1],1) self.CheckNotebook() G2IO.ProjFileSave(self) os.chdir(dlg.GetDirectory()) # to get Mac/Linux to change directory! finally: dlg.Destroy() def ExpandAll(self,event): '''Expand all tree items or those of a single type ''' txt = self.GetMenuBar().GetLabel(event.Id) if txt == 'all': self.ExpandingAll = True try: self.GPXtree.ExpandAll() finally: self.ExpandingAll = False else: self.ExpandingAll = True try: item, cookie = self.GPXtree.GetFirstChild(self.root) while item: name = self.GPXtree.GetItemText(item) if name.startswith(txt+' '): self.GPXtree.Expand(item) item, cookie = self.GPXtree.GetNextChild(self.root, cookie) finally: self.ExpandingAll = False def MoveTreeItems(self,event): '''Move tree items of a single type to the end of the tree ''' txt = self.GetMenuBar().GetLabel(event.Id) # make a list of items to copy copyList = [] item, cookie = self.GPXtree.GetFirstChild(self.root) while item: if self.GPXtree.GetItemText(item).startswith(txt+' '): copyList.append(item) item, cookie = self.GPXtree.GetNextChild(self.root, cookie) self.ExpandingAll = True try: for item in copyList: name = self.GPXtree.GetItemText(item) newId = self.GPXtree.AppendItem(self.root,name) self.GPXtree.SetItemPyData(newId,self.GPXtree.GetItemPyData(item)) chld, chldcookie = self.GPXtree.GetFirstChild(item) while chld: chname = self.GPXtree.GetItemText(chld) newCh = self.GPXtree.AppendItem(newId,chname) self.GPXtree.SetItemPyData(newCh,self.GPXtree.GetItemPyData(chld)) chld, chldcookie = self.GPXtree.GetNextChild(item, chldcookie) self.GPXtree.Delete(item) finally: self.ExpandingAll = False SelectDataTreeItem(self,self.root) def ExitMain(self, event): '''Called if the main window is closed''' FramePos = {'Main_Pos':tuple(self.GetPosition()),'Plot_Pos':tuple(self.plotFrame.GetPosition())} GSASIIpath.SetConfigValue(FramePos) print FramePos config = G2G.GetConfigValsDocs() G2G.SaveConfigVars(config) if self.G2plotNB: self.G2plotNB.Destroy() if self.undofile: os.remove(self.undofile) sys.exit() # def OnFileExit(self, event): # '''Called in response to the File/Quit menu button''' # if self.G2plotNB: # self.G2plotNB.Destroy() # self.Close() # def OnExportPeakList(self,event): nptand = lambda x: np.tan(x*math.pi/180.) pth = G2G.GetExportPath(self) dlg = wx.FileDialog(self, 'Choose output peak list file name', pth, '', '(*.*)|*.*',wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT) try: if dlg.ShowModal() == wx.ID_OK: self.peaklistfile = dlg.GetPath() self.peaklistfile = G2IO.FileDlgFixExt(dlg,self.peaklistfile) file = open(self.peaklistfile,'w') item, cookie = self.GPXtree.GetFirstChild(self.root) while item: name = self.GPXtree.GetItemText(item) if 'PWDR' in name: item2, cookie2 = self.GPXtree.GetFirstChild(item) wave = 0.0 while item2: name2 = self.GPXtree.GetItemText(item2) if name2 == 'Instrument Parameters': Inst = self.GPXtree.GetItemPyData(item2)[0] Type = Inst['Type'][0] if 'T' not in Type: wave = G2mth.getWave(Inst) elif name2 == 'Peak List': pkdata = self.GPXtree.GetItemPyData(item2) peaks = pkdata['peaks'] sigDict = pkdata['sigDict'] item2, cookie2 = self.GPXtree.GetNextChild(item, cookie2) file.write("#%s \n" % (name+' Peak List')) if wave: file.write('#wavelength = %10.6f\n'%(wave)) if 'T' in Type: file.write('#%9s %10s %10s %12s %10s %10s %10s %10s %10s\n'%('pos','dsp','esd','int','alp','bet','sig','gam','FWHM')) else: file.write('#%9s %10s %10s %12s %10s %10s %10s\n'%('pos','dsp','esd','int','sig','gam','FWHM')) for ip,peak in enumerate(peaks): dsp = G2lat.Pos2dsp(Inst,peak[0]) if 'T' in Type: #TOF - more cols esds = {'pos':0.,'int':0.,'alp':0.,'bet':0.,'sig':0.,'gam':0.} for name in esds.keys(): esds[name] = sigDict.get('%s%d'%(name,ip),0.) sig = np.sqrt(peak[8]) gam = peak[10] esddsp = G2lat.Pos2dsp(Inst,esds['pos']) FWHM = G2pwd.getgamFW(gam,sig) #to get delta-TOF from Gam(peak) file.write("%10.2f %10.5f %10.5f %12.2f %10.3f %10.3f %10.3f %10.3f %10.3f\n" % \ (peak[0],dsp,esddsp,peak[2],np.sqrt(max(0.0001,peak[4])),peak[6],peak[8],peak[10],FWHM)) else: #CW #get esds from sigDict for each peak & put in output - esds for sig & gam from UVWXY? esds = {'pos':0.,'int':0.,'sig':0.,'gam':0.} for name in esds.keys(): esds[name] = sigDict.get('%s%d'%(name,ip),0.) sig = np.sqrt(peak[4]) #var -> sig gam = peak[6] esddsp = 0.5*esds['pos']*dsp/nptand(peak[0]/2.) FWHM = G2pwd.getgamFW(gam,sig) #to get delta-2-theta in deg. from Gam(peak) file.write("%10.4f %10.5f %10.5f %12.2f %10.5f %10.5f %10.5f \n" % \ (peak[0],dsp,esddsp,peak[2],np.sqrt(max(0.0001,peak[4]))/100.,peak[6]/100.,FWHM/100.)) #convert to deg item, cookie = self.GPXtree.GetNextChild(self.root, cookie) file.close() finally: dlg.Destroy() def OnExportHKL(self,event): pth = G2G.GetExportPath(self) dlg = wx.FileDialog(self, 'Choose output reflection list file name', pth, '', '(*.*)|*.*',wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT) try: if dlg.ShowModal() == wx.ID_OK: self.peaklistfile = dlg.GetPath() self.peaklistfile = G2IO.FileDlgFixExt(dlg,self.peaklistfile) file = open(self.peaklistfile,'w') item, cookie = self.GPXtree.GetFirstChild(self.root) while item: name = self.GPXtree.GetItemText(item) if 'PWDR' in name: item2, cookie2 = self.GPXtree.GetFirstChild(item) while item2: name2 = self.GPXtree.GetItemText(item2) if name2 == 'Reflection Lists': data = self.GPXtree.GetItemPyData(item2) phases = data.keys() for phase in phases: peaks = data[phase] I100 = peaks['RefList'].T[8]*np.array([refl[11] for refl in peaks['RefList']]) Imax = np.max(I100) if Imax: I100 *= 100.0/Imax file.write("%s %s %s \n" % (name,phase,' Reflection List')) if 'T' in peaks.get('Type','PXC'): file.write('%s \n'%(' h k l m d-space TOF wid Fo**2 Fc**2 Icorr Prfo Trans ExtP I100')) else: file.write('%s \n'%(' h k l m d-space 2-theta wid Fo**2 Fc**2 Icorr Prfo Trans ExtP I100')) for ipk,peak in enumerate(peaks['RefList']): if 'T' in peaks.get('Type','PXC'): sig = np.sqrt(peak[6]) gam = peak[7] FWHM = G2pwd.getgamFW(gam,sig) file.write(" %3d %3d %3d %3d%10.5f%10.2f%10.5f%10.3f%10.3f%10.3f%10.3f%10.3f%10.3f%10.3f\n" % \ (int(peak[0]),int(peak[1]),int(peak[2]),int(peak[3]),peak[4],peak[5],FWHM,peak[8], peak[9],peak[11],peak[12],peak[13],peak[14],I100[ipk])) else: sig = np.sqrt(peak[6]) gam = peak[7] FWHM = G2pwd.getgamFW(gam,sig) file.write(" %3d %3d %3d %3d%10.5f%10.5f%10.5f%10.3f%10.3f%10.3f%10.3f%10.3f%10.3f%10.3f\n" % \ (int(peak[0]),int(peak[1]),int(peak[2]),int(peak[3]),peak[4],peak[5],FWHM/100., peak[8],peak[9],peak[11],peak[12],peak[13],peak[14],I100[ipk])) item2, cookie2 = self.GPXtree.GetNextChild(item, cookie2) item, cookie = self.GPXtree.GetNextChild(self.root, cookie) file.close() finally: dlg.Destroy() def OnExportPDF(self,event): #need S(Q) and G(R) to be saved here - probably best from selection? names = G2pdG.GetFileList(self,'PDF') exports = [] if names: od = {'label_1':'Export I(Q)','value_1':False,'label_2':'Export S(Q)','value_2':False, 'label_3':'Export F(Q)','value_3':False,'label_4':'Export G(R)','value_4':True, 'label_5':'Make G(R) for pdfGUI','value_5':False} dlg = G2G.G2MultiChoiceDialog(self,'Select','PDF patterns to export',names,extraOpts=od) if dlg.ShowModal() == wx.ID_OK: sel = dlg.GetSelections() for x in sel: exports.append(names[x]) dlg.Destroy() if exports: PDFsaves = [od['value_1'],od['value_2'],od['value_3'],od['value_4'],od['value_5']] G2IO.PDFSave(self,exports,PDFsaves) def OnMakePDFs(self,event): '''Sets up PDF data structure filled with defaults; if found chemical formula is inserted so a default PDF can be made. ''' sind = lambda x: math.sin(x*math.pi/180.) tth2q = lambda t,w:4.0*math.pi*sind(t/2.0)/w tof2q = lambda t,C:2.0*math.pi*C/t TextList = [] ElLists = [] Qlimits = [] Names = [] if self.GPXtree.GetCount(): id, cookie = self.GPXtree.GetFirstChild(self.root) while id: name = self.GPXtree.GetItemText(id) Names.append(name) if 'PWDR' in name: TextList.append(name) Data = self.GPXtree.GetItemPyData(id)[1] pwdrMin = np.min(Data[1]) Comments = self.GPXtree.GetItemPyData(GetGPXtreeItemId(self,id,'Comments')) Parms = self.GPXtree.GetItemPyData(GetGPXtreeItemId(self,id,'Instrument Parameters'))[0] fullLimits = self.GPXtree.GetItemPyData(GetGPXtreeItemId(self,id,'Limits'))[0] if 'C' in Parms['Type'][0]: wave = G2mth.getWave(Parms) qMax = tth2q(fullLimits[1],wave) else: #'T'of qMax = tof2q(fullLimits[0],Parms['difC'][1]) Qlimits.append([0.9*qMax,qMax]) ElList = {} sumnum = 1. for item in Comments: #grab chemical formula from Comments if 'formula' in item[:15].lower(): formula = item.split('=')[1].split() try: elems = formula[::2] nums = formula[1::2] Formula = zip(elems,nums) sumnum = 0. for [elem,num] in Formula: ElData = G2elem.GetElInfo(elem,Parms) ElData['FormulaNo'] = float(num) sumnum += float(num) ElList[elem] = ElData except ValueError: ElData = G2elem.GetElInfo(formula[0],Parms) ElData['FormulaNo'] = 1.0 ElList[elem] = ElData ElLists.append(ElList) id, cookie = self.GPXtree.GetNextChild(self.root, cookie) if len(TextList) < 1: self.ErrorDialog('Nothing to make PDFs for','There must be at least one "PWDR" pattern') return dlg = G2G.G2MultiChoiceDialog(self,'Make PDF controls','Make PDF controls for:',TextList, wx.CHOICEDLG_STYLE) try: if dlg.ShowModal() == wx.ID_OK: for i in dlg.GetSelections(): PDFnames = GetGPXtreeDataNames(self,['PDF ',]) G2obj.CreatePDFitems(self,TextList[i],ElLists[i],Qlimits[i],sumnum,pwdrMin,PDFnames) for item in self.ExportPDF: item.Enable(True) finally: dlg.Destroy() def GetPWDRdatafromTree(self,PWDRname): ''' Returns powder data from GSASII tree :param str PWDRname: a powder histogram name as obtained from :meth:`GSASIIstruct.GetHistogramNames` :returns: PWDRdata = powder data dictionary with Powder data arrays, Limits, Instrument Parameters, Sample Parameters ''' PWDRdata = {} try: PWDRdata.update(self.GPXtree.GetItemPyData(PWDRname)[0]) #wtFactor + ? except ValueError: PWDRdata['wtFactor'] = 1.0 PWDRdata['Data'] = self.GPXtree.GetItemPyData(PWDRname)[1] #powder data arrays PWDRdata['Limits'] = self.GPXtree.GetItemPyData(GetGPXtreeItemId(self,PWDRname,'Limits')) PWDRdata['Background'] = self.GPXtree.GetItemPyData(GetGPXtreeItemId(self,PWDRname,'Background')) PWDRdata['Instrument Parameters'] = self.GPXtree.GetItemPyData(GetGPXtreeItemId(self,PWDRname,'Instrument Parameters')) PWDRdata['Sample Parameters'] = self.GPXtree.GetItemPyData(GetGPXtreeItemId(self,PWDRname,'Sample Parameters')) PWDRdata['Reflection Lists'] = self.GPXtree.GetItemPyData(GetGPXtreeItemId(self,PWDRname,'Reflection Lists')) if 'ranId' not in PWDRdata: # patch, add a random Id PWDRdata['ranId'] = ran.randint(0,sys.maxint) if 'ranId' not in PWDRdata['Sample Parameters']: # I hope this becomes obsolete at some point PWDRdata['Sample Parameters']['ranId'] = PWDRdata['ranId'] return PWDRdata def GetHKLFdatafromTree(self,HKLFname): ''' Returns single crystal data from GSASII tree :param str HKLFname: a single crystal histogram name as obtained from :meth:`GSASIIstruct.GetHistogramNames` :returns: HKLFdata = single crystal data list of reflections ''' HKLFdata = {} HKLFdata.update(self.GPXtree.GetItemPyData(HKLFname)[0]) #wtFactor + ? # try: # HKLFdata.update(self.GPXtree.GetItemPyData(HKLFname)[0]) #wtFactor + ? # except ValueError: # HKLFdata['wtFactor'] = 1.0 HKLFdata['Data'] = self.GPXtree.GetItemPyData(HKLFname)[1] HKLFdata['Instrument Parameters'] = self.GPXtree.GetItemPyData(GetGPXtreeItemId(self,HKLFname,'Instrument Parameters')) return HKLFdata def GetPhaseData(self): '''Returns a dict with defined phases. Note routine :func:`GSASIIstrIO.GetPhaseData` also exists to get same info from GPX file. ''' phaseData = {} if GetGPXtreeItemId(self,self.root,'Phases'): sub = GetGPXtreeItemId(self,self.root,'Phases') else: print 'no phases found in GetPhaseData' sub = None if sub: item, cookie = self.GPXtree.GetFirstChild(sub) while item: phaseName = self.GPXtree.GetItemText(item) phaseData[phaseName] = self.GPXtree.GetItemPyData(item) if 'ranId' not in phaseData[phaseName]: phaseData[phaseName]['ranId'] = ran.randint(0,sys.maxint) item, cookie = self.GPXtree.GetNextChild(sub, cookie) return phaseData def GetPhaseInfofromTree(self): '''Get the phase names and their rId values, also the histograms used in each phase. :returns: (phaseRIdList, usedHistograms) where * phaseRIdList is a list of random Id values for each phase * usedHistograms is a dict where the keys are the phase names and the values for each key are a list of the histogram names used in each phase. ''' phaseRIdList = [] usedHistograms = {} sub = GetGPXtreeItemId(self,self.root,'Phases') if sub: item, cookie = self.GPXtree.GetFirstChild(sub) while item: phaseName = self.GPXtree.GetItemText(item) ranId = self.GPXtree.GetItemPyData(item).get('ranId') if ranId: phaseRIdList.append(ranId) data = self.GPXtree.GetItemPyData(item) UseList = data['Histograms'] usedHistograms[phaseName] = UseList.keys() item, cookie = self.GPXtree.GetNextChild(sub, cookie) return phaseRIdList,usedHistograms def GetPhaseNames(self): '''Returns a list of defined phases. Note routine :func:`GSASIIstrIO.GetPhaseNames` also exists to get same info from GPX file. ''' phaseNames = [] if GetGPXtreeItemId(self,self.root,'Phases'): sub = GetGPXtreeItemId(self,self.root,'Phases') else: print 'no phases found in GetPhaseNames' sub = None if sub: item, cookie = self.GPXtree.GetFirstChild(sub) while item: phase = self.GPXtree.GetItemText(item) phaseNames.append(phase) item, cookie = self.GPXtree.GetNextChild(sub, cookie) return phaseNames def GetHistogramNames(self,hType): """ Returns a list of histogram names found in the GSASII data tree Note routine :func:`GSASIIstrIO.GetHistogramNames` also exists to get same info from GPX file. :param str hType: list of histogram types :return: list of histogram names """ HistogramNames = [] if self.GPXtree.GetCount(): item, cookie = self.GPXtree.GetFirstChild(self.root) while item: name = self.GPXtree.GetItemText(item) if name[:4] in hType: HistogramNames.append(name) item, cookie = self.GPXtree.GetNextChild(self.root, cookie) return HistogramNames def GetUsedHistogramsAndPhasesfromTree(self): ''' Returns all histograms that are found in any phase and any phase that uses a histogram. This also assigns numbers to used phases and histograms by the order they appear in the file. Note routine :func:`GSASIIstrIO.GetUsedHistogramsAndPhasesfromTree` also exists to get same info from GPX file. :returns: (Histograms,Phases) * Histograms = dictionary of histograms as {name:data,...} * Phases = dictionary of phases that use histograms ''' Histograms = {} Phases = {} phaseNames = self.GetPhaseNames() phaseData = self.GetPhaseData() histoList = self.GetHistogramNames(['PWDR','HKLF']) for phase in phaseData: Phase = phaseData[phase] pId = phaseNames.index(phase) Phase['pId'] = pId if Phase['Histograms']: if phase not in Phases: Phases[phase] = Phase for hist in Phase['Histograms']: if 'Use' not in Phase['Histograms'][hist]: #patch: add Use flag as True Phase['Histograms'][hist]['Use'] = True if hist not in Histograms and Phase['Histograms'][hist]['Use']: item = GetGPXtreeItemId(self,self.root,hist) if item: if 'PWDR' in hist[:4]: Histograms[hist] = self.GetPWDRdatafromTree(item) elif 'HKLF' in hist[:4]: Histograms[hist] = self.GetHKLFdatafromTree(item) hId = histoList.index(hist) Histograms[hist]['hId'] = hId else: # would happen if a referenced histogram were renamed or deleted print('For phase "'+phase+ '" unresolved reference to histogram "'+hist+'"') #G2obj.IndexAllIds(Histograms=Histograms,Phases=Phases) G2obj.IndexAllIds(Histograms=Histograms,Phases=phaseData) return Histograms,Phases def MakeLSParmDict(self): '''Load all parameters used for computation from the tree into a dict of paired values [value, refine flag]. Note that this is different than the parmDict used in the refinement, which only has values. Note that similar things are done in :meth:`GSASIIIO.ExportBaseclass.loadParmDict` (from the tree) and :func:`GSASIIstrMain.Refine` and :func:`GSASIIstrMain.SeqRefine` (from a GPX file). :returns: (parmDict,varyList) where: * parmDict is a dict with values and refinement flags for each parameter and * varyList is a list of variables (refined parameters). ''' parmDict = {} Histograms,Phases = self.GetUsedHistogramsAndPhasesfromTree() for phase in Phases: if 'pId' not in Phases[phase]: self.ErrorDialog('View parameter error','You must run least squares at least once') raise Exception,'No pId for phase '+phase rigidbodyDict = self.GPXtree.GetItemPyData( GetGPXtreeItemId(self,self.root,'Rigid bodies')) rbVary,rbDict = G2stIO.GetRigidBodyModels(rigidbodyDict,Print=False) rbIds = rigidbodyDict.get('RBIds',{'Vector':[],'Residue':[]}) Natoms,atomIndx,phaseVary,phaseDict,pawleyLookup,FFtable,BLtable,MFtable,maxSSwave = G2stIO.GetPhaseData(Phases,RestraintDict=None,rbIds=rbIds,Print=False) hapVary,hapDict,controlDict = G2stIO.GetHistogramPhaseData(Phases,Histograms,Print=False) histVary,histDict,controlDict = G2stIO.GetHistogramData(Histograms,Print=False) varyList = rbVary+phaseVary+hapVary+histVary parmDict.update(rbDict) parmDict.update(phaseDict) parmDict.update(hapDict) parmDict.update(histDict) for parm in parmDict: if parm.split(':')[-1] in ['Azimuth','Gonio. radius','Lam1','Lam2', 'Omega','Chi','Phi','nDebye','nPeaks']: parmDict[parm] = [parmDict[parm],'-'] elif parm.split(':')[-2] in ['Ax','Ay','Az','SHmodel','SHord']: parmDict[parm] = [parmDict[parm],'-'] elif parm in varyList: parmDict[parm] = [parmDict[parm],'T'] else: parmDict[parm] = [parmDict[parm],'F'] # for i in parmDict: print i,'\t',parmDict[i] # fl = open('parmDict.dat','wb') # import cPickle # cPickle.dump(parmDict,fl,1) # fl.close() return parmDict,varyList def OnShowLSParms(self,event): '''Displays a window showing all parameters in the refinement. Called from the Calculate/View LS Parms menu. ''' try: parmDict,varyList = self.MakeLSParmDict() except: print('Error retrieving parameters') return parmValDict = {} for i in parmDict: parmValDict[i] = parmDict[i][0] reqVaryList = tuple(varyList) # save requested variables try: # process constraints sub = GetGPXtreeItemId(self,self.root,'Constraints') Constraints = self.GPXtree.GetItemPyData(sub) constList = [] for item in Constraints: if item.startswith('_'): continue constList += Constraints[item] G2mv.InitVars() constrDict,fixedList,ignored = G2stIO.ProcessConstraints(constList) groups,parmlist = G2mv.GroupConstraints(constrDict) G2mv.GenerateConstraints(groups,parmlist,varyList,constrDict,fixedList,parmValDict) G2mv.Map2Dict(parmValDict,varyList) except: pass dlg = G2G.ShowLSParms(self,'Least Squares Parameters',parmValDict,varyList,reqVaryList) dlg.ShowModal() dlg.Destroy() def OnRefine(self,event): '''Perform a refinement. Called from the Calculate/Refine menu. ''' Id = GetGPXtreeItemId(self,self.root,'Sequential results') if Id: dlg = wx.MessageDialog( self, 'Your last refinement was sequential. Continue with "Refine", removing previous sequential results?', 'Remove sequential results?',wx.OK|wx.CANCEL) if dlg.ShowModal() == wx.ID_OK: self.GPXtree.Delete(Id) dlg.Destroy() else: dlg.Destroy() return self.OnFileSave(event) # check that constraints are OK here errmsg, warnmsg = G2stIO.ReadCheckConstraints(self.GSASprojectfile) if errmsg: self.ErrorDialog('Refinement error',errmsg) return if warnmsg: print('Conflict between refinment flag settings and constraints:\n'+ warnmsg+'\nRefinement not possible') self.ErrorDialog('Refinement Flag Error', 'Conflict between refinement flag settings and constraints:\n'+ warnmsg+'\nRefinement not possible') return dlg = wx.ProgressDialog('Residual','All data Rw =',101.0, style = wx.PD_ELAPSED_TIME|wx.PD_AUTO_HIDE|wx.PD_CAN_ABORT, parent=self) Size = dlg.GetSize() if 50 < Size[0] < 500: # sanity check on size, since this fails w/Win & wx3.0 dlg.SetSize((int(Size[0]*1.2),Size[1])) # increase size a bit along x dlg.CenterOnParent() Rw = 100.00 self.SaveTreeSetting() self.GPXtree.SaveExposedItems() try: OK,Msg = G2stMn.Refine(self.GSASprojectfile,dlg) #Msg is Rvals dict if Ok=True finally: dlg.Update(101.) # forces the Auto_Hide; needed after move w/Win & wx3.0 dlg.Destroy() wx.Yield() if OK: Rw = Msg['Rwp'] lamMax = Msg.get('lamMax',0.001) lst = os.path.splitext(os.path.abspath(self.GSASprojectfile))[0] text = u'Detailed results are in '+lst+'.lst\n\nLoad new result?' if lamMax >= 10.: text += '\nWARNING: Steepest descents dominates;'+ \ ' minimum may not have been reached\nor result may be false minimum.'+ \ ' You should reconsider your parameter suite' dlg2 = wx.MessageDialog(self,text,'Refinement results, Rw =%.3f'%(Rw),wx.OK|wx.CANCEL) try: if dlg2.ShowModal() == wx.ID_OK: self.GPXtree.DeleteChildren(self.root) self.HKL = [] G2IO.ProjFileOpen(self,False) self.GPXtree.RestoreExposedItems() self.ResetPlots() finally: dlg2.Destroy() else: self.ErrorDialog('Refinement error',Msg) def SaveTreeSetting(self): 'Save the last tree setting' oldId = self.GPXtree.GetSelection() #retain current selection oldPath = self.GetTreeItemsList(oldId) self.lastTreeSetting = oldPath # note that for reasons unclear, it does not seem necessary to reload the Atoms tab #parentName = '' #tabId = None # parentId = self.GPXtree.GetItemParent(oldId) # if parentId: # parentName = self.GPXtree.GetItemText(parentId) #find the current data tree name # if 'Phases' in parentName: # tabId = self.dataDisplay.GetSelection() #self.lastTreeSetting = oldPath,tabId #GSASIIpath.IPyBreak() def TestResetPlot(self,event): '''Debug code to test cleaning up plots after a refinement''' #for i in range(self.G2plotNB.nb.GetPageCount()): # [self.G2plotNB.nb.GetPageText(i) # save current tree item and (if needed) atoms tab self.SaveTreeSetting() self.ResetPlots() def ResetPlots(self): '''This reloads the current tree item, often drawing a plot. It refreshes any plots that have registered a refresh routine (see G2plotNB.RegisterRedrawRoutine) and deletes all plots that have not been refreshed and require one (see G2plotNB.SetNoDelete). ''' lastRaisedPlotTab = self.G2plotNB.lastRaisedPlotTab # save the last page saved #print 'lastRaisedPlotTab=',lastRaisedPlotTab self.G2plotNB.lastRaisedPlotTab = None # mark displayed plots as invalid for lbl,frame in zip(self.G2plotNB.plotList,self.G2plotNB.panelList): frame.plotInvalid = True # reload current tree item, triggering the routine to redraw the data window and possibly a plot #oldPath,tabId = self.lastTreeSetting oldPath = self.lastTreeSetting Id = self.root for txt in oldPath: Id = GetGPXtreeItemId(self, Id, txt) self.PickIdText = None #force reload of page if Id: self.PickId = Id self.GPXtree.SelectItem(Id) # update other self-updating plots # for lbl,frame in zip(self.G2plotNB.plotList,self.G2plotNB.panelList): # if frame.plotInvalid and frame.replotFunction: # frame.replotFunction(*frame.replotArgs,**frame.replotKWargs) # delete any remaining plots that are still invalid and need a refresh for lbl,frame in zip(self.G2plotNB.plotList,self.G2plotNB.panelList): if frame.plotInvalid and frame.plotRequiresRedraw: self.G2plotNB.Delete(lbl) # put the previously last-raised tab on top, if present. If not, use the one corresponding to # the last tree item to be selected wx.CallAfter(self.G2plotNB.RaiseLastPage,lastRaisedPlotTab,self.G2plotNB.lastRaisedPlotTab) def OnSeqRefine(self,event): '''Perform a sequential refinement. Called from the Calculate/Sequential refine menu. ''' Id = GetGPXtreeItemId(self,self.root,'Sequential results') if not Id: Id = self.GPXtree.AppendItem(self.root,text='Sequential results') self.GPXtree.SetItemPyData(Id,{}) self.G2plotNB.Delete('Sequential refinement') #clear away probably invalid plot Controls = self.GPXtree.GetItemPyData(GetGPXtreeItemId(self,self.root, 'Controls')) if not Controls.get('Seq Data'): print('Error: a sequential refinement has not been set up') return Controls['ShowCell'] = True self.OnFileSave(event) # check that constraints are OK here errmsg, warnmsg = G2stIO.ReadCheckConstraints(self.GSASprojectfile) if errmsg: self.ErrorDialog('Refinement error',errmsg) return if warnmsg: print('Conflict between refinment flag settings and constraints:\n'+ warnmsg+'\nRefinement not possible') self.ErrorDialog('Refinement Flag Error', 'Conflict between refinment flag settings and constraints:\n'+ warnmsg+'\nRefinement not possible') return self.GPXtree.SaveExposedItems() dlg = wx.ProgressDialog('Residual for histogram 0','Powder profile Rwp =',101.0, style = wx.PD_ELAPSED_TIME|wx.PD_AUTO_HIDE|wx.PD_CAN_ABORT, parent=self) Size = dlg.GetSize() if 50 < Size[0] < 500: # sanity check on size, since this fails w/Win & wx3.0 dlg.SetSize((int(Size[0]*1.2),Size[1])) # increase size a bit along x dlg.CenterOnParent() try: OK,Msg = G2stMn.SeqRefine(self.GSASprojectfile,dlg,G2plt.SequentialPlotPattern,self) #Msg is Rvals dict if Ok=True finally: dlg.Update(101.) # forces the Auto_Hide; needed after move w/Win & wx3.0 dlg.Destroy() wx.Yield() if OK: dlg = wx.MessageDialog(self,'Load new result?','Refinement results',wx.OK|wx.CANCEL) try: if dlg.ShowModal() == wx.ID_OK: self.PickIdText = None #force reload of PickId contents self.GPXtree.DeleteChildren(self.root) if len(self.HKL): self.HKL = [] if self.G2plotNB.plotList: self.G2plotNB.clear() G2IO.ProjFileOpen(self,False) self.GPXtree.RestoreExposedItems() self.ResetPlots() Id = GetGPXtreeItemId(self,self.root,'Sequential results') self.GPXtree.SelectItem(Id) finally: dlg.Destroy() self.SeqTblHideList = [] else: self.ErrorDialog('Sequential refinement error',Msg) def ErrorDialog(self,title,message,parent=None, wtype=wx.OK): 'Display an error message' result = None if parent is None: dlg = wx.MessageDialog(self, message, title, wtype) else: dlg = wx.MessageDialog(parent, message, title, wtype) dlg.CenterOnParent() # not working on Mac try: result = dlg.ShowModal() finally: dlg.Destroy() return result def OnSaveMultipleImg(self,event): '''Select and save multiple image parameter and mask files ''' G2IO.SaveMultipleImg(self) ################################################################################ # Data window side of main GUI ################################################################################ class G2DataWindow(wxscroll.ScrolledPanel): '''Create the data item window entries in menus used in that window. The menu entries are created for all data item windows, but in the Mac the menu is accessed from all windows. This means that a different menu is posted depending on which data item is posted. On the Mac, all the menus contain the data tree menu items, but additional menus are added specific to the data item. Note that while the menus are created here, the binding for the menus is done later in various GSASII*GUI modules, where the functions to be called are defined. Use of the dataWindow scrolled panel ==================================== dataWindow has a “master” vertical BoxSizer: find it with G2frame.dataWindow.GetSizer() and always use it. A call to dataWindow.SetSizer() should not be needed. When placing a widget in the sizer that has its own scrolling (e.g. G2G.GSNoteBook, anything else?) that one widget should be placed in the sizer as G2frame.dataWindow.GetSizer().Add(G2frame.,1,wx.ALL|wx.EXPAND) [is wx.ALL superfluous here?] so that it consumes the full size of the panel and so that the NoteBook widget does the scrolling. For other uses, one will likely place a bunch of widgets and (other [sub-]sizers) into the master sizer. In this case, DO NOT use wx.EXPAND, as this will result in the widget resizing/repositioning as the window resizes. Possible exceptions might be for widgets going into a fixed-size panel that is inside the dataWindow (probably not being done). A call to Sizer.Fit(dataWindow) will do bad things, though a call to SubSizer.Fit(dataWindow.subpanel) could make sense. Initial GUI draws to dataWindow will go through GSASIIdataGUI.SelectDataTreeItem(), which is called after any changes to data tree selection. SelectDataTreeItem places items in dataWindow or calls that do that. Before it calls those routines, it calls G2frame.dataWindow.ClearData() which deletes the contents of the master sizer. After the contents are posted a call is made to G2frame.dataWindow.SetDataSize() which repaints the window. For routines [such as GSASII.UpdatePeakGrid()] that are called repeatedly to update the entire contents of dataWindow themselves, it is important to add calls to G2frame.dataWindow.ClearData() and G2frame.dataWindow.SetDataSize() at the beginning and end respectively to clear and refresh. This is not needed for GSNoteBook repaints, which seem to be working mostly automatically. If there is a problem, a call like wx.CallAfter(G2frame.phaseDisplay.SendSizeEvent) might be needed. There are some calls to G2frame.dataWindow.SendSizeEvent() that may be doing the same thing. ''' # TODO: debug code ###################################################################### def Bind(self,eventtype,handler,*args,**kwargs): # PATCH: debug code: catch when a menu is bind'ed to # the dataWindow as this should not be done in the 2 frame version. if eventtype == wx.wx.EVT_MENU: print 'wx.EVT_MENU Bind to dataWindow' G2obj.HowDidIgetHere(True) wx.Frame.Bind(self.GetTopLevelParent(),eventtype,handler,*args,**kwargs) else: wxscroll.ScrolledPanel.Bind(self,eventtype,handler,*args,**kwargs) def DestroyChildren(self): print 'Fix this: dataWindow.DestroyChildren called' G2obj.HowDidIgetHere() def SetTitle(self,*args): print('Warning: attempt to label dataWindow') G2obj.HowDidIgetHere(True) self.G2frame.SetTitle(*args) def SetLabel(self,*args): print('Warning: attempt to label dataWindow') G2obj.HowDidIgetHere(True) self.G2frame.SetTitle(*args) # end TODO: remove this later ############################################################ def __init__(self,parent): wxscroll.ScrolledPanel.__init__(self,parent,wx.ID_ANY,size=parent.GetSize()) self.parent = parent self._initMenus() self.currentGrids = [] self.helpKey = '' # defines help entry for current item selected in data tree def ClearData(self): '''Initializes the contents of the dataWindow panel ''' #self.SetBackgroundColour(wx.WHITE) self.SetBackgroundColour(VERY_LIGHT_GREY) # BHT: I prefer a gray background. Makes TextCtrls stand out, but # a bit lighter than the splitter bar Sizer = self.GetSizer() if Sizer: Sizer.Clear(True) else: print 'No sizer in dataWindow' if GSASIIpath.GetConfigValue('debug'): raise Exception def SetDataSize(self): '''Sizes the contents of the dataWindow panel ''' Sizer = self.GetSizer() if GSASIIpath.GetConfigValue('debug') and not Sizer: print 'No sizer in dataWindow' raise Exception self.Layout() self.SendSizeEvent() def PrefillDataMenu(self,menu,empty=False): '''Create the "standard" part of data frame menus & add the dataWindow menu headings This menu duplicates the tree menu, but adds an extra help command for the current data item and a separator. ''' self.datamenu = menu self.GetTopLevelParent().FillMainMenu(menu,addhelp=False) # add the data tree menu items to the main menu if not empty: menu.Append(wx.Menu(title=''),title='|') # add a separator def PostfillDataMenu(self,empty=False): '''Add the help menu to the menus associated with data tree items. ''' menu = self.datamenu G2frame = self.GetTopLevelParent() if not empty: menu.Append(wx.Menu(title=''),title='|') # add another separator HelpMenu=G2G.MyHelp(G2frame,includeTree=True, morehelpitems=[('&Tutorials','Tutorials'),]) menu.Append(menu=HelpMenu,title='&Help') def _initMenus(self): 'define all GSAS-II data window menus' # G2G.Define_wxId('wxID_MCRON', 'wxID_MCRLIST', 'wxID_MCRSAVE', 'wxID_MCRPLAY',) # Main menu G2frame = self.GetTopLevelParent() G2frame.GSASIIMenu = wx.MenuBar() G2frame.dataMenuBars = [G2frame.GSASIIMenu] # list of all menus (added to in PrefillDataMenu) G2frame.FillMainMenu(G2frame.GSASIIMenu) G2frame.SetMenuBar(G2frame.GSASIIMenu) # Controls self.ControlsMenu = wx.MenuBar() self.PrefillDataMenu(self.ControlsMenu,empty=True) self.PostfillDataMenu(empty=True) # Notebook self.DataNotebookMenu = wx.MenuBar() self.PrefillDataMenu(self.DataNotebookMenu,empty=True) self.PostfillDataMenu(empty=True) # Comments self.DataCommentsMenu = wx.MenuBar() self.PrefillDataMenu(self.DataCommentsMenu,empty=True) self.PostfillDataMenu(empty=True) # Constraints G2G.Define_wxId('wxID_CONSTRAINTADD', 'wxID_EQUIVADD', 'wxID_HOLDADD', 'wxID_FUNCTADD', 'wxID_ADDRIDING', 'wxID_CONSPHASE', 'wxID_CONSHIST', 'wxID_CONSHAP', 'wxID_CONSGLOBAL', 'wxID_EQUIVALANCEATOMS',) self.ConstraintMenu = wx.MenuBar() self.PrefillDataMenu(self.ConstraintMenu) self.ConstraintTab = wx.Menu(title='') self.ConstraintMenu.Append(menu=self.ConstraintTab, title='Select tab') for id,txt in ( (G2G.wxID_CONSPHASE,'Phase'), (G2G.wxID_CONSHAP,'Histogram/Phase'), (G2G.wxID_CONSHIST,'Histogram'), (G2G.wxID_CONSGLOBAL,'Global')): self.ConstraintTab.Append(id=id, kind=wx.ITEM_NORMAL,text=txt, help='Select '+txt+' constraint editing tab') self.ConstraintEdit = wx.Menu(title='') self.ConstraintMenu.Append(menu=self.ConstraintEdit, title='Edit Constr.') # renamed from Edit due to Mac adding extra items to menu self.ConstraintEdit.Append(id=G2G.wxID_HOLDADD, kind=wx.ITEM_NORMAL,text='Add hold', help='Prevent refinement of parameter values') self.ConstraintEdit.Append(id=G2G.wxID_EQUIVADD, kind=wx.ITEM_NORMAL,text='Add equivalence', help='Force parameter values to be equivalent') self.ConstraintEdit.Append(id=G2G.wxID_CONSTRAINTADD, kind=wx.ITEM_NORMAL,text='Add constraint equation', help='Add a constraint equation to apply to parameter values') self.ConstraintEdit.Append(id=G2G.wxID_FUNCTADD, kind=wx.ITEM_NORMAL,text='Add New Var', help='Create a variable composed of existing parameters') self.ConstraintEdit.Append(id=G2G.wxID_EQUIVALANCEATOMS, kind=wx.ITEM_NORMAL,text='Make atoms equivalent', help='Force atom parameter values to be equivalent') self.ConstraintEdit.Enable(G2G.wxID_EQUIVALANCEATOMS,False) # self.ConstraintEdit.Append(id=G2G.wxID_ADDRIDING, kind=wx.ITEM_NORMAL,text='Add H riding constraints', # help='Add H atom riding constraints between atom parameter values') # self.ConstraintEdit.Enable(G2G.wxID_ADDRIDING,False) self.PostfillDataMenu() # Rigid bodies G2G.Define_wxId('wxID_RIGIDBODYADD', 'wxID_DRAWDEFINERB', 'wxID_RIGIDBODYIMPORT', 'wxID_RESIDUETORSSEQ', 'wxID_VECTORBODYADD') self.RigidBodyMenu = wx.MenuBar() self.PrefillDataMenu(self.RigidBodyMenu) self.ResidueRBMenu = wx.Menu(title='') self.ResidueRBMenu.Append(id=G2G.wxID_RIGIDBODYIMPORT, kind=wx.ITEM_NORMAL,text='Import XYZ', help='Import rigid body XYZ from file') self.ResidueRBMenu.Append(id=G2G.wxID_RESIDUETORSSEQ, kind=wx.ITEM_NORMAL,text='Define sequence', help='Define torsion sequence') self.ResidueRBMenu.Append(id=G2G.wxID_RIGIDBODYADD, kind=wx.ITEM_NORMAL,text='Import residues', help='Import residue rigid bodies from macro file') self.RigidBodyMenu.Append(menu=self.ResidueRBMenu, title='Edit Body') self.PostfillDataMenu() self.VectorBodyMenu = wx.MenuBar() self.PrefillDataMenu(self.VectorBodyMenu) self.VectorRBEdit = wx.Menu(title='') self.VectorRBEdit.Append(id=G2G.wxID_VECTORBODYADD, kind=wx.ITEM_NORMAL,text='Add rigid body', help='Add vector rigid body') self.VectorBodyMenu.Append(menu=self.VectorRBEdit, title='Edit Vector Body') self.PostfillDataMenu() # Restraints G2G.Define_wxId('wxID_RESTRAINTADD', 'wxID_RESTSELPHASE', 'wxID_RESTDELETE', 'wxID_RESRCHANGEVAL', 'wxID_RESTCHANGEESD', 'wxID_AARESTRAINTADD', 'wxID_AARESTRAINTPLOT',) self.RestraintTab = wx.Menu(title='') self.RestraintEdit = wx.Menu(title='') self.RestraintEdit.Append(id=G2G.wxID_RESTSELPHASE, kind=wx.ITEM_NORMAL,text='Select phase', help='Select phase') self.RestraintEdit.Append(id=G2G.wxID_RESTRAINTADD, kind=wx.ITEM_NORMAL,text='Add restraints', help='Add restraints') self.RestraintEdit.Enable(G2G.wxID_RESTRAINTADD,True) #gets disabled if macromolecule phase self.RestraintEdit.Append(id=G2G.wxID_AARESTRAINTADD, kind=wx.ITEM_NORMAL,text='Add residue restraints', help='Add residue based restraints for macromolecules from macro file') self.RestraintEdit.Enable(G2G.wxID_AARESTRAINTADD,False) #gets enabled if macromolecule phase self.RestraintEdit.Append(id=G2G.wxID_AARESTRAINTPLOT, kind=wx.ITEM_NORMAL,text='Plot residue restraints', help='Plot selected residue based restraints for macromolecules from macro file') self.RestraintEdit.Enable(G2G.wxID_AARESTRAINTPLOT,False) #gets enabled if macromolecule phase self.RestraintEdit.Append(id=G2G.wxID_RESRCHANGEVAL, kind=wx.ITEM_NORMAL,text='Change value', help='Change observed value') self.RestraintEdit.Append(id=G2G.wxID_RESTCHANGEESD, kind=wx.ITEM_NORMAL,text='Change esd', help='Change esd in observed value') self.RestraintEdit.Append(id=G2G.wxID_RESTDELETE, kind=wx.ITEM_NORMAL,text='Delete restraints', help='Delete selected restraints') self.RestraintMenu = wx.MenuBar() self.PrefillDataMenu(self.RestraintMenu) self.RestraintMenu.Append(menu=self.RestraintTab, title='Select tab') self.RestraintMenu.Append(menu=self.RestraintEdit, title='Edit Restr.') self.PostfillDataMenu() # Sequential results G2G.Define_wxId('wxID_RENAMESEQSEL', 'wxID_SAVESEQSEL', 'wxID_SAVESEQCSV', 'wxID_SAVESEQSELCSV', 'wxID_PLOTSEQSEL', 'wxID_ORGSEQSEL', 'wxID_ADDSEQVAR', 'wxID_DELSEQVAR', 'wxID_EDITSEQVAR', 'wxID_COPYPARFIT', 'wxID_AVESEQSEL','wxID_SELECTUSE', 'wxID_ADDPARFIT', 'wxID_DELPARFIT', 'wxID_EDITPARFIT', 'wxID_DOPARFIT', 'wxID_ADDSEQDIST', 'wxID_ADDSEQANGLE', 'wxID_ORGSEQINC',) self.SequentialMenu = wx.MenuBar() self.PrefillDataMenu(self.SequentialMenu) self.SequentialFile = wx.Menu(title='') self.SequentialMenu.Append(menu=self.SequentialFile, title='Columns') self.SequentialFile.Append(id=G2G.wxID_SELECTUSE, kind=wx.ITEM_NORMAL,text='Select used', help='Select rows to be used in plots/equation fitting') self.SequentialFile.Append(id=G2G.wxID_RENAMESEQSEL, kind=wx.ITEM_NORMAL,text='Rename selected', help='Rename selected sequential refinement columns') self.SequentialFile.Append(id=G2G.wxID_SAVESEQSEL, kind=wx.ITEM_NORMAL,text='Save selected as text', help='Save selected sequential refinement results as a text file') self.SequentialFile.Append(id=G2G.wxID_SAVESEQCSV, kind=wx.ITEM_NORMAL,text='Save all as CSV', help='Save all sequential refinement results as a CSV spreadsheet file') self.SequentialFile.Append(id=G2G.wxID_SAVESEQSELCSV, kind=wx.ITEM_NORMAL,text='Save selected as CSV', help='Save selected sequential refinement results as a CSV spreadsheet file') self.SequentialFile.Append(id=G2G.wxID_PLOTSEQSEL, kind=wx.ITEM_NORMAL,text='Plot selected', help='Plot selected sequential refinement results') self.SequentialFile.Append(id=G2G.wxID_AVESEQSEL, kind=wx.ITEM_NORMAL,text='Compute average', help='Compute average for selected parameter') # self.SequentialFile.Append(id=G2G.wxID_ORGSEQSEL, kind=wx.ITEM_NORMAL,text='Reorganize', # help='Reorganize variables where variables change') self.SequentialFile.Append(id=G2G.wxID_ORGSEQINC, kind=wx.ITEM_NORMAL,text='Hide columns...', help='Select columns to remove from displayed table') self.SequentialPvars = wx.Menu(title='') self.SequentialMenu.Append(menu=self.SequentialPvars, title='Pseudo Vars') self.SequentialPvars.Append( id=G2G.wxID_ADDSEQVAR, kind=wx.ITEM_NORMAL,text='Add Formula', help='Add a new custom pseudo-variable') self.SequentialPvars.Append( id=G2G.wxID_ADDSEQDIST, kind=wx.ITEM_NORMAL,text='Add Distance', help='Add a new bond distance pseudo-variable') self.SequentialPvars.Append( id=G2G.wxID_ADDSEQANGLE, kind=wx.ITEM_NORMAL,text='Add Angle', help='Add a new bond angle pseudo-variable') self.SequentialPvars.Append( id=G2G.wxID_DELSEQVAR, kind=wx.ITEM_NORMAL,text='Delete', help='Delete an existing pseudo-variable') self.SequentialPvars.Append( id=G2G.wxID_EDITSEQVAR, kind=wx.ITEM_NORMAL,text='Edit', help='Edit an existing pseudo-variable') self.SequentialPfit = wx.Menu(title='') self.SequentialMenu.Append(menu=self.SequentialPfit, title='Parametric Fit') self.SequentialPfit.Append( id=G2G.wxID_ADDPARFIT, kind=wx.ITEM_NORMAL,text='Add equation', help='Add a new equation to minimize') self.SequentialPfit.Append( id=G2G.wxID_COPYPARFIT, kind=wx.ITEM_NORMAL,text='Copy equation', help='Copy an equation to minimize - edit it next') self.SequentialPfit.Append( id=G2G.wxID_DELPARFIT, kind=wx.ITEM_NORMAL,text='Delete equation', help='Delete an equation for parametric minimization') self.SequentialPfit.Append( id=G2G.wxID_EDITPARFIT, kind=wx.ITEM_NORMAL,text='Edit equation', help='Edit an existing parametric minimization equation') self.SequentialPfit.Append( id=G2G.wxID_DOPARFIT, kind=wx.ITEM_NORMAL,text='Fit to equation(s)', help='Perform a parametric minimization') # fill sequential Export menu # for an exporter to be used for sequential exports, it must have a Writer method and # that Writer method must offer a mode argument. self.SeqExportLookup = {} self.SequentialEx = wx.Menu(title='') self.SequentialMenu.Append(menu=self.SequentialEx, title='Seq Export') import inspect for lbl,txt in (('Phase','Export selected phase(s)'), ('Project','Export entire sequential fit'), ('Powder','Export selected powder histogram(s)') ): objlist = [] for obj in self.parent.GetTopLevelParent().exporterlist: if lbl.lower() in obj.exporttype: try: obj.Writer except AttributeError: continue if 'mode' in inspect.getargspec(obj.Writer)[0]: objlist.append(obj) if objlist: submenu = wx.Menu() item = self.SequentialEx.AppendMenu(wx.ID_ANY, lbl+' as',submenu, help=txt) for obj in objlist: item = submenu.Append(wx.ID_ANY,help=obj.longFormatName, kind=wx.ITEM_NORMAL,text=obj.formatName) self.SeqExportLookup[item.GetId()] = (obj,lbl) # lookup table for submenu item self.PostfillDataMenu() # PWDR & SASD G2G.Define_wxId('wxID_PWDANALYSIS','wxID_PWDCOPY','wxID_PLOTCTRLCOPY','wxID_MERGEHKL', 'wxID_PWDHKLPLOT', 'wxID_PWD3DHKLPLOT','wxID_3DALLHKLPLOT',) self.PWDRMenu = wx.MenuBar() self.PrefillDataMenu(self.PWDRMenu) self.ErrorAnal = wx.Menu(title='') self.PWDRMenu.Append(menu=self.ErrorAnal,title='Commands') self.ErrorAnal.Append(id=G2G.wxID_PWDANALYSIS,kind=wx.ITEM_NORMAL,text='Error Analysis', help='Error analysis on powder pattern') self.ErrorAnal.Append(id=G2G.wxID_PWDCOPY,kind=wx.ITEM_NORMAL,text='Copy params', help='Copy of PWDR parameters') self.ErrorAnal.Append(id=G2G.wxID_PLOTCTRLCOPY,kind=wx.ITEM_NORMAL,text='Copy plot controls', help='Copy of PWDR plot controls') self.moveDiffCurve = self.ErrorAnal.Append(id=wx.ID_ANY,kind=wx.ITEM_NORMAL,text='Move diff. curve', help='Click on position where difference curve is placed') self.moveTickLoc = self.ErrorAnal.Append(id=wx.ID_ANY,kind=wx.ITEM_NORMAL,text='Move ticks', help='Move mouse to where tick marks should be positioned') self.moveTickSpc = self.ErrorAnal.Append(id=wx.ID_ANY,kind=wx.ITEM_NORMAL,text='Set tick space', help='Click to set spacing between phase tick marks') self.PostfillDataMenu() # HKLF - wxIDs defined in PWDR & SASD above self.HKLFMenu = wx.MenuBar() self.PrefillDataMenu(self.HKLFMenu) self.ErrorAnal = wx.Menu(title='') self.HKLFMenu.Append(menu=self.ErrorAnal,title='Commands') self.ErrorAnal.Append(id=G2G.wxID_PWDANALYSIS,kind=wx.ITEM_NORMAL,text='Error Analysis', help='Error analysis on single crystal data') self.ErrorAnal.Append(id=G2G.wxID_MERGEHKL,kind=wx.ITEM_NORMAL,text='Merge HKLs', help='Transform & merge HKLF data to new histogram') self.ErrorAnal.Append(id=G2G.wxID_PWD3DHKLPLOT,kind=wx.ITEM_NORMAL,text='Plot 3D HKLs', help='Plot HKLs from single crystal data in 3D') self.ErrorAnal.Append(id=G2G.wxID_3DALLHKLPLOT,kind=wx.ITEM_NORMAL,text='Plot all 3D HKLs', help='Plot HKLs from all single crystal data in 3D') self.ErrorAnal.Append(id=G2G.wxID_PWDCOPY,kind=wx.ITEM_NORMAL,text='Copy params', help='Copy of HKLF parameters') self.PostfillDataMenu() # PWDR / Limits G2G.Define_wxId('wxID_LIMITCOPY', 'wxID_ADDEXCLREGION',) self.LimitMenu = wx.MenuBar() self.PrefillDataMenu(self.LimitMenu) self.LimitEdit = wx.Menu(title='') self.LimitMenu.Append(menu=self.LimitEdit, title='Edit Limits') self.LimitEdit.Append(id=G2G.wxID_LIMITCOPY, kind=wx.ITEM_NORMAL,text='Copy', help='Copy limits to other histograms') self.LimitEdit.Append(id=G2G.wxID_ADDEXCLREGION, kind=wx.ITEM_NORMAL,text='Add exclude', help='Add excluded region - select a point on plot; drag to adjust') self.PostfillDataMenu() # PDR / Background G2G.Define_wxId('wxID_BACKCOPY', 'wxID_BACKFLAGCOPY','wxID_MAKEBACKRDF', 'wxID_RESCALEALL','wxID_BACKPEAKSMOVE',) self.BackMenu = wx.MenuBar() self.PrefillDataMenu(self.BackMenu) self.BackEdit = wx.Menu(title='') self.BackMenu.Append(menu=self.BackEdit, title='File') self.BackEdit.Append(id=G2G.wxID_BACKCOPY, kind=wx.ITEM_NORMAL,text='Copy', help='Copy background parameters to other histograms') self.BackEdit.Append(id=G2G.wxID_BACKFLAGCOPY, kind=wx.ITEM_NORMAL,text='Copy flags', help='Copy background refinement flags to other histograms') self.BackEdit.Append(id=G2G.wxID_BACKPEAKSMOVE, kind=wx.ITEM_NORMAL,text='Move peaks', help='Move background peaks to Peak List') self.BackEdit.Append(id=G2G.wxID_MAKEBACKRDF, kind=wx.ITEM_NORMAL,text='Plot RDF', help='Plot radial distribution from differences') self.BackFixed = wx.Menu(title='') # fixed background point menu self.BackMenu.Append(menu=self.BackFixed, title='Fixed Points') self.wxID_BackPts = {} self.wxID_BackPts['Add'] = wx.NewId() # N.B. not using wxID_ global as for other menu items self.BackFixed.Append(id=self.wxID_BackPts['Add'], kind=wx.ITEM_RADIO,text='Add', help='Add fixed background points with mouse clicks') self.wxID_BackPts['Move'] = wx.NewId() item = self.BackFixed.Append(id=self.wxID_BackPts['Move'], kind=wx.ITEM_RADIO,text='Move', help='Move selected fixed background points with mouse drags') item.Check(True) self.wxID_BackPts['Del'] = wx.NewId() self.BackFixed.Append(id=self.wxID_BackPts['Del'], kind=wx.ITEM_RADIO,text='Delete', help='Delete fixed background points with mouse clicks') self.wxID_BackPts['Clear'] = wx.NewId() self.BackFixed.Append(id=self.wxID_BackPts['Clear'], kind=wx.ITEM_NORMAL,text='Clear', help='Clear fixed background points') self.wxID_BackPts['Fit'] = wx.NewId() self.BackFixed.Append(id=self.wxID_BackPts['Fit'], kind=wx.ITEM_NORMAL,text='Fit background', help='Fit background function to fixed background points') self.PostfillDataMenu() # PDR / Instrument Parameters G2G.Define_wxId('wxID_INSTPRMRESET','wxID_INSTCOPY','wxID_INSTFLAGCOPY','wxID_INSTLOAD', 'wxID_INSTSAVE', 'wxID_INST1VAL', 'wxID_INSTCALIB', 'wxID_INSTSAVEALL',) self.InstMenu = wx.MenuBar() self.PrefillDataMenu(self.InstMenu) self.InstEdit = wx.Menu(title='') self.InstMenu.Append(menu=self.InstEdit, title='Operations') self.InstEdit.Append(help='Calibrate from indexed peaks', id=G2G.wxID_INSTCALIB, kind=wx.ITEM_NORMAL,text='Calibrate') self.InstEdit.Append(help='Reset instrument profile parameters to default', id=G2G.wxID_INSTPRMRESET, kind=wx.ITEM_NORMAL,text='Reset profile') self.InstEdit.Append(help='Load instrument profile parameters from file', id=G2G.wxID_INSTLOAD, kind=wx.ITEM_NORMAL,text='Load profile...') self.InstEdit.Append(help='Save instrument profile parameters to file', id=G2G.wxID_INSTSAVE, kind=wx.ITEM_NORMAL,text='Save profile...') self.InstEdit.Append(help='Save all instrument profile parameters to one file', id=G2G.wxID_INSTSAVEALL, kind=wx.ITEM_NORMAL,text='Save all profile...') self.InstEdit.Append(help='Copy instrument profile parameters to other histograms', id=G2G.wxID_INSTCOPY, kind=wx.ITEM_NORMAL,text='Copy') self.InstEdit.Append(id=G2G.wxID_INSTFLAGCOPY, kind=wx.ITEM_NORMAL,text='Copy flags', help='Copy instrument parameter refinement flags to other histograms') self.InstEdit.Append(id=G2G.wxID_INST1VAL, kind=wx.ITEM_NORMAL,text='Set one value', help='Set one instrument parameter value across multiple histograms') self.PostfillDataMenu() # PDR / Sample Parameters G2G.Define_wxId('wxID_SAMPLECOPY', 'wxID_SAMPLECOPYSOME', 'wxID_SAMPLEFLAGCOPY','wxID_SAMPLESAVE', 'wxID_SAMPLELOAD', 'wxID_SETSCALE', 'wxID_SAMPLE1VAL', 'wxID_ALLSAMPLELOAD',) self.SampleMenu = wx.MenuBar() self.PrefillDataMenu(self.SampleMenu) self.SampleEdit = wx.Menu(title='') self.SampleMenu.Append(menu=self.SampleEdit, title='Command') self.SetScale = self.SampleEdit.Append(id=G2G.wxID_SETSCALE, kind=wx.ITEM_NORMAL,text='Set scale', help='Set scale by matching to another histogram') self.SampleEdit.Append(id=G2G.wxID_SAMPLELOAD, kind=wx.ITEM_NORMAL,text='Load', help='Load sample parameters from file') self.SampleEdit.Append(id=G2G.wxID_SAMPLESAVE, kind=wx.ITEM_NORMAL,text='Save', help='Save sample parameters to file') self.SampleEdit.Append(id=G2G.wxID_SAMPLECOPY, kind=wx.ITEM_NORMAL,text='Copy', help='Copy refinable and most other sample parameters to other histograms') self.SampleEdit.Append(id=G2G.wxID_SAMPLECOPYSOME, kind=wx.ITEM_NORMAL,text='Copy selected...', help='Copy selected sample parameters to other histograms') self.SampleEdit.Append(id=G2G.wxID_SAMPLEFLAGCOPY, kind=wx.ITEM_NORMAL,text='Copy flags', help='Copy sample parameter refinement flags to other histograms') self.SampleEdit.Append(id=G2G.wxID_SAMPLE1VAL, kind=wx.ITEM_NORMAL,text='Set one value', help='Set one sample parameter value across multiple histograms') self.SampleEdit.Append(id=G2G.wxID_ALLSAMPLELOAD, kind=wx.ITEM_NORMAL,text='Load all', help='Load sample parmameters over multiple histograms') self.SampleEdit.Append(id=G2G.wxID_RESCALEALL, kind=wx.ITEM_NORMAL,text='Rescale all', help='Rescale all data with selected range') self.PostfillDataMenu() self.SetScale.Enable(False) # PDR / Peak List G2G.Define_wxId('wxID_UNDO', 'wxID_LSQPEAKFIT', 'wxID_LSQONECYCLE', 'wxID_RESETSIGGAM', 'wxID_CLEARPEAKS', 'wxID_AUTOSEARCH','wxID_PEAKSCOPY', 'wxID_SEQPEAKFIT',) self.PeakMenu = wx.MenuBar() self.PrefillDataMenu(self.PeakMenu) self.PeakEdit = wx.Menu(title='') self.PeakMenu.Append(menu=self.PeakEdit, title='Peak Fitting') self.peaksSel = self.PeakEdit.Append(wx.ID_ANY,help='Set refinement flags for selected peaks', kind=wx.ITEM_NORMAL,text='Set sel. ref flags...') self.peaksAll = self.PeakEdit.Append(wx.ID_ANY,help='Set refinement flags for all peaks', kind=wx.ITEM_NORMAL,text='Set all ref flags...') self.AutoSearch = self.PeakEdit.Append(help='Automatic peak search', id=G2G.wxID_AUTOSEARCH, kind=wx.ITEM_NORMAL,text='Auto search') self.UnDo = self.PeakEdit.Append(help='Undo last least squares refinement', id=G2G.wxID_UNDO, kind=wx.ITEM_NORMAL,text='UnDo') self.PeakFit = self.PeakEdit.Append(id=G2G.wxID_LSQPEAKFIT, kind=wx.ITEM_NORMAL,text='Peakfit', help='Peak fitting' ) self.PFOneCycle = self.PeakEdit.Append(id=G2G.wxID_LSQONECYCLE, kind=wx.ITEM_NORMAL,text='Peakfit one cycle', help='One cycle of Peak fitting' ) self.PeakEdit.Append(id=G2G.wxID_RESETSIGGAM, kind=wx.ITEM_NORMAL, text='Reset sig and gam',help='Reset sigma and gamma to global fit' ) self.PeakCopy = self.PeakEdit.Append(help='Copy peaks to other histograms', id=G2G.wxID_PEAKSCOPY, kind=wx.ITEM_NORMAL,text='Peak copy') self.SeqPeakFit = self.PeakEdit.Append(id=G2G.wxID_SEQPEAKFIT, kind=wx.ITEM_NORMAL,text='Seq PeakFit', help='Sequential Peak fitting for all histograms' ) self.PeakEdit.Append(id=G2G.wxID_CLEARPEAKS, kind=wx.ITEM_NORMAL,text='Clear peaks', help='Clear the peak list' ) self.movePeak = self.PeakEdit.Append(id=wx.ID_ANY,kind=wx.ITEM_NORMAL,text='Move selected peak', help='Select a peak in the table, then use this to move it with the mouse.') self.PostfillDataMenu() self.UnDo.Enable(False) self.PeakFit.Enable(False) self.PFOneCycle.Enable(False) self.AutoSearch.Enable(True) # PDR / Index Peak List G2G.Define_wxId('wxID_INDXRELOAD',) self.IndPeaksMenu = wx.MenuBar() self.PrefillDataMenu(self.IndPeaksMenu) self.IndPeaksEdit = wx.Menu(title='') self.IndPeaksMenu.Append(menu=self.IndPeaksEdit,title='Operations') self.IndPeaksEdit.Append(help='Load/Reload index peaks from peak list',id=G2G.wxID_INDXRELOAD, kind=wx.ITEM_NORMAL,text='Load/Reload') self.PostfillDataMenu() # PDR / Unit Cells List G2G.Define_wxId('wxID_INDEXPEAKS', 'wxID_REFINECELL', 'wxID_COPYCELL', 'wxID_MAKENEWPHASE', 'wxID_EXPORTCELLS',) self.IndexMenu = wx.MenuBar() self.PrefillDataMenu(self.IndexMenu) self.IndexEdit = wx.Menu(title='') self.IndexMenu.Append(menu=self.IndexEdit, title='Cell Index/Refine') self.IndexPeaks = self.IndexEdit.Append(help='', id=G2G.wxID_INDEXPEAKS, kind=wx.ITEM_NORMAL, text='Index Cell') self.CopyCell = self.IndexEdit.Append( id=G2G.wxID_COPYCELL, kind=wx.ITEM_NORMAL,text='Copy Cell', help='Copy selected unit cell from indexing to cell refinement fields') self.RefineCell = self.IndexEdit.Append( id=G2G.wxID_REFINECELL, kind=wx.ITEM_NORMAL, text='Refine Cell',help='Refine unit cell parameters from indexed peaks') self.MakeNewPhase = self.IndexEdit.Append( id=G2G.wxID_MAKENEWPHASE, kind=wx.ITEM_NORMAL, text='Make new phase',help='Make new phase from selected unit cell') self.ExportCells = self.IndexEdit.Append( id=G2G.wxID_EXPORTCELLS, kind=wx.ITEM_NORMAL, text='Export cell list',help='Export cell list to csv file') self.PostfillDataMenu() self.IndexPeaks.Enable(False) self.CopyCell.Enable(False) self.RefineCell.Enable(False) self.MakeNewPhase.Enable(False) # PDR / Reflection Lists G2G.Define_wxId('wxID_SELECTPHASE', ) #some wxIDs defined above in PWDR & SASD self.ReflMenu = wx.MenuBar() self.PrefillDataMenu(self.ReflMenu) self.ReflEdit = wx.Menu(title='') self.ReflMenu.Append(menu=self.ReflEdit, title='Reflection List') self.SelectPhase = self.ReflEdit.Append(help='Select phase for reflection list',id=G2G.wxID_SELECTPHASE, kind=wx.ITEM_NORMAL,text='Select phase') self.ReflEdit.Append(id=G2G.wxID_PWDHKLPLOT,kind=wx.ITEM_NORMAL,text='Plot HKLs', help='Plot HKLs from powder pattern') self.ReflEdit.Append(id=G2G.wxID_PWD3DHKLPLOT,kind=wx.ITEM_NORMAL,text='Plot 3D HKLs', help='Plot HKLs from powder pattern in 3D') self.PostfillDataMenu() # SASD / Instrument Parameters G2G.Define_wxId('wxID_SASDINSTCOPY',) self.SASDInstMenu = wx.MenuBar() self.PrefillDataMenu(self.SASDInstMenu) self.SASDInstEdit = wx.Menu(title='') self.SASDInstMenu.Append(menu=self.SASDInstEdit, title='Operations') self.SASDInstEdit.Append(help='Copy instrument profile parameters to other histograms', id=G2G.wxID_SASDINSTCOPY, kind=wx.ITEM_NORMAL,text='Copy') self.PostfillDataMenu() #SASD & REFL/ Substance editor G2G.Define_wxId('wxID_LOADSUBSTANCE','wxID_RELOADSUBSTANCES','wxID_ADDSUBSTANCE','wxID_COPYSUBSTANCE', 'wxID_DELETESUBSTANCE','wxID_ELEMENTADD', 'wxID_ELEMENTDELETE',) self.SubstanceMenu = wx.MenuBar() self.PrefillDataMenu(self.SubstanceMenu) self.SubstanceEdit = wx.Menu(title='') self.SubstanceMenu.Append(menu=self.SubstanceEdit, title='Edit substance') self.SubstanceEdit.Append(id=G2G.wxID_LOADSUBSTANCE, kind=wx.ITEM_NORMAL,text='Load substance', help='Load substance from file') self.SubstanceEdit.Append(id=G2G.wxID_RELOADSUBSTANCES, kind=wx.ITEM_NORMAL,text='Reload substances', help='Reload all substances from file') self.SubstanceEdit.Append(id=G2G.wxID_ADDSUBSTANCE, kind=wx.ITEM_NORMAL,text='Add substance', help='Add new substance to list') self.SubstanceEdit.Append(id=G2G.wxID_COPYSUBSTANCE, kind=wx.ITEM_NORMAL,text='Copy substances', help='Copy substances') self.SubstanceEdit.Append(id=G2G.wxID_DELETESUBSTANCE, kind=wx.ITEM_NORMAL,text='Delete substance', help='Delete substance from list') self.SubstanceEdit.Append(id=G2G.wxID_ELEMENTADD, kind=wx.ITEM_NORMAL,text='Add elements', help='Add elements to substance') self.SubstanceEdit.Append(id=G2G.wxID_ELEMENTDELETE, kind=wx.ITEM_NORMAL,text='Delete elements', help='Delete elements from substance') self.PostfillDataMenu() # SASD/ Models G2G.Define_wxId('wxID_MODELCOPY', 'wxID_MODELFIT', 'wxID_MODELADD','wxID_MODELUNDO', 'wxID_MODELFITALL', 'wxID_MODELCOPYFLAGS','wxID_MODELPLOT',) self.ModelMenu = wx.MenuBar() self.PrefillDataMenu(self.ModelMenu) self.ModelEdit = wx.Menu(title='') self.ModelMenu.Append(menu=self.ModelEdit, title='Models') self.ModelEdit.Append(id=G2G.wxID_MODELADD,kind=wx.ITEM_NORMAL,text='Add', help='Add new term to model') self.ModelEdit.Append(id=G2G.wxID_MODELFIT, kind=wx.ITEM_NORMAL,text='Fit', help='Fit model parameters to data') self.SasdUndo = self.ModelEdit.Append(id=G2G.wxID_MODELUNDO, kind=wx.ITEM_NORMAL,text='Undo', help='Undo model fit') self.SasdUndo.Enable(False) self.ModelEdit.Append(id=G2G.wxID_MODELFITALL, kind=wx.ITEM_NORMAL,text='Sequential fit', help='Sequential fit of model parameters to all SASD data') self.ModelEdit.Append(id=G2G.wxID_MODELCOPY, kind=wx.ITEM_NORMAL,text='Copy', help='Copy model parameters to other histograms') self.ModelEdit.Append(id=G2G.wxID_MODELCOPYFLAGS, kind=wx.ITEM_NORMAL,text='Copy flags', help='Copy model refinement flags to other histograms') self.PostfillDataMenu() # REFD/ Models - wxIDs as for SASD/Models self.REFDModelMenu = wx.MenuBar() self.PrefillDataMenu(self.REFDModelMenu) self.REFDModelEdit = wx.Menu(title='') self.REFDModelMenu.Append(menu=self.REFDModelEdit, title='Models') self.REFDModelEdit.Append(id=G2G.wxID_MODELFIT, kind=wx.ITEM_NORMAL,text='Fit', help='Fit model parameters to data') self.REFDUndo = self.REFDModelEdit.Append(id=G2G.wxID_MODELUNDO, kind=wx.ITEM_NORMAL,text='Undo', help='Undo model fit') self.REFDUndo.Enable(False) self.REFDModelEdit.Append(id=G2G.wxID_MODELFITALL, kind=wx.ITEM_NORMAL,text='Sequential fit', help='Sequential fit of model parameters to all REFD data') self.REFDModelEdit.Append(id=G2G.wxID_MODELCOPY, kind=wx.ITEM_NORMAL,text='Copy', help='Copy model parameters to other histograms') self.REFDModelEdit.Append(id=G2G.wxID_MODELPLOT, kind=wx.ITEM_NORMAL,text='Plot', help='Plot model SDL for selected histograms') self.PostfillDataMenu() # IMG / Image Controls G2G.Define_wxId('wxID_IMCALIBRATE', 'wxID_IMRECALIBRATE', 'wxID_IMINTEGRATE', 'wxID_IMCLEARCALIB', 'wxID_IMRECALIBALL', 'wxID_IMCOPYCONTROLS', 'wxID_INTEGRATEALL', 'wxID_IMSAVECONTROLS', 'wxID_IMLOADCONTROLS', 'wxID_IMAUTOINTEG', 'wxID_IMCOPYSELECTED', 'wxID_SAVESELECTEDCONTROLS', 'wxID_IMXFERCONTROLS', 'wxID_IMRESETDIST',) self.ImageMenu = wx.MenuBar() self.PrefillDataMenu(self.ImageMenu) self.ImageEdit = wx.Menu(title='') self.ImageMenu.Append(menu=self.ImageEdit, title='Calibration') self.ImageEdit.Append(help='Calibrate detector by fitting to calibrant lines', id=G2G.wxID_IMCALIBRATE, kind=wx.ITEM_NORMAL,text='Calibrate') self.ImageEdit.Append(help='Recalibrate detector by fitting to calibrant lines', id=G2G.wxID_IMRECALIBRATE, kind=wx.ITEM_NORMAL,text='Recalibrate') self.ImageEdit.Append(help='Recalibrate all images by fitting to calibrant lines', id=G2G.wxID_IMRECALIBALL, kind=wx.ITEM_NORMAL,text='Recalibrate all') self.ImageEdit.Append(help='Clear calibration data points and rings', id=G2G.wxID_IMCLEARCALIB, kind=wx.ITEM_NORMAL,text='Clear calibration') ImageIntegrate = wx.Menu(title='') self.ImageMenu.Append(menu=ImageIntegrate, title='Integration') ImageIntegrate.Append(help='Integrate selected image',id=G2G.wxID_IMINTEGRATE, kind=wx.ITEM_NORMAL,text='Integrate') ImageIntegrate.Append(help='Integrate all images selected from list',id=G2G.wxID_INTEGRATEALL, kind=wx.ITEM_NORMAL,text='Integrate all') ImageIntegrate.Append(help='Open Auto-integration window to integrate a series of images', id=G2G.wxID_IMAUTOINTEG, kind=wx.ITEM_NORMAL,text='Auto Integrate') ImageParams = wx.Menu(title='') self.ImageMenu.Append(menu=ImageParams, title='Parms') ImageParams.Append(help='Copy image controls to other images', id=G2G.wxID_IMCOPYCONTROLS, kind=wx.ITEM_NORMAL,text='Copy Controls') ImageParams.Append(help='Copy selected image controls to other images', id=G2G.wxID_IMCOPYSELECTED, kind=wx.ITEM_NORMAL,text='Copy Selected') ImageParams.Append(help='Save image controls to file', id=G2G.wxID_IMSAVECONTROLS, kind=wx.ITEM_NORMAL,text='Save Controls') ImageParams.Append(help='Save controls from selected images to file', id=G2G.wxID_SAVESELECTEDCONTROLS, kind=wx.ITEM_NORMAL,text='Save Multiple Controls') ImageParams.Append(help='Load image controls from file', id=G2G.wxID_IMLOADCONTROLS, kind=wx.ITEM_NORMAL,text='Load Controls') ImageParams.Append(help='Transfer integration range for other detector distances', id=G2G.wxID_IMXFERCONTROLS, kind=wx.ITEM_NORMAL,text='Xfer angles') ImageParams.Append(help='Reset all detector dist to set dist', id=G2G.wxID_IMRESETDIST, kind=wx.ITEM_NORMAL,text='Reset dist') self.PostfillDataMenu() # IMG / Masks G2G.Define_wxId('wxID_MASKCOPY', 'wxID_MASKSAVE', 'wxID_MASKLOAD', 'wxID_NEWMASKSPOT', 'wxID_NEWMASKARC', 'wxID_NEWMASKRING', 'wxID_NEWMASKFRAME', 'wxID_NEWMASKPOLY', 'wxID_MASKLOADNOT', 'wxID_FINDSPOTS', 'wxID_DELETESPOTS',) self.MaskMenu = wx.MenuBar() self.PrefillDataMenu(self.MaskMenu) self.MaskEdit = wx.Menu(title='') self.MaskMenu.Append(menu=self.MaskEdit, title='Operations') submenu = wx.Menu() self.MaskEdit.AppendMenu(wx.ID_ANY,'Create new', submenu,help='') self.MaskEdit.Append(help='Copy mask to other images', id=G2G.wxID_MASKCOPY, kind=wx.ITEM_NORMAL,text='Copy mask') self.MaskEdit.Append(help='Save mask to file', id=G2G.wxID_MASKSAVE, kind=wx.ITEM_NORMAL,text='Save mask') self.MaskEdit.Append(help='Load mask from file; ignoring threshold', id=G2G.wxID_MASKLOADNOT, kind=wx.ITEM_NORMAL,text='Load mask') self.MaskEdit.Append(help='Load mask from file keeping the threshold value', id=G2G.wxID_MASKLOAD, kind=wx.ITEM_NORMAL,text='Load mask w/threshold') self.MaskEdit.Append(help='Auto search for spot masks; NB: will clear old spot masks', id=G2G.wxID_FINDSPOTS, kind=wx.ITEM_NORMAL,text='Auto spot masks') self.MaskEdit.Append(help='Delete all spot masks', id=G2G.wxID_DELETESPOTS, kind=wx.ITEM_NORMAL,text='Delete spot masks') submenu.Append(help='Create an arc mask with mouse input', id=G2G.wxID_NEWMASKARC, kind=wx.ITEM_NORMAL,text='Arc mask') submenu.Append(help='Create a frame mask with mouse input', id=G2G.wxID_NEWMASKFRAME, kind=wx.ITEM_NORMAL,text='Frame mask') submenu.Append(help='Create a polygon mask with mouse input', id=G2G.wxID_NEWMASKPOLY, kind=wx.ITEM_NORMAL,text='Polygon mask') submenu.Append(help='Create a ring mask with mouse input', id=G2G.wxID_NEWMASKRING, kind=wx.ITEM_NORMAL,text='Ring mask') submenu.Append(help='Create spot masks with mouse input', id=G2G.wxID_NEWMASKSPOT, kind=wx.ITEM_NORMAL,text='Spot mask') self.PostfillDataMenu() # IMG / Stress/Strain G2G.Define_wxId('wxID_STRSTACOPY', 'wxID_STRSTAFIT', 'wxID_STRSTASAVE', 'wxID_STRSTALOAD', 'wxID_STRSTSAMPLE', 'wxID_APPENDDZERO', 'wxID_STRSTAALLFIT', 'wxID_UPDATEDZERO', 'wxID_STRSTAPLOT', 'wxID_STRRINGSAVE',) self.StrStaMenu = wx.MenuBar() self.PrefillDataMenu(self.StrStaMenu) self.StrStaEdit = wx.Menu(title='') self.StrStaMenu.Append(menu=self.StrStaEdit, title='Operations') self.StrStaEdit.Append(help='Append d-zero for one ring', id=G2G.wxID_APPENDDZERO, kind=wx.ITEM_NORMAL,text='Append d-zero') self.StrStaEdit.Append(help='Fit stress/strain data', id=G2G.wxID_STRSTAFIT, kind=wx.ITEM_NORMAL,text='Fit stress/strain') self.StrStaEdit.Append(help='Plot intensity distribution', id=G2G.wxID_STRSTAPLOT, kind=wx.ITEM_NORMAL,text='Plot intensity distribution') self.StrStaEdit.Append(help='Save intensity distribution', id=G2G.wxID_STRRINGSAVE, kind=wx.ITEM_NORMAL,text='Save intensity distribution') self.StrStaEdit.Append(help='Update d-zero from ave d-zero', id=G2G.wxID_UPDATEDZERO, kind=wx.ITEM_NORMAL,text='Update d-zero') self.StrStaEdit.Append(help='Fit stress/strain data for all images', id=G2G.wxID_STRSTAALLFIT, kind=wx.ITEM_NORMAL,text='All image fit') self.StrStaEdit.Append(help='Copy stress/strain data to other images', id=G2G.wxID_STRSTACOPY, kind=wx.ITEM_NORMAL,text='Copy stress/strain') self.StrStaEdit.Append(help='Save stress/strain data to file', id=G2G.wxID_STRSTASAVE, kind=wx.ITEM_NORMAL,text='Save stress/strain') self.StrStaEdit.Append(help='Load stress/strain data from file', id=G2G.wxID_STRSTALOAD, kind=wx.ITEM_NORMAL,text='Load stress/strain') self.StrStaEdit.Append(help='Load sample data from file', id=G2G.wxID_STRSTSAMPLE, kind=wx.ITEM_NORMAL,text='Load sample data') self.PostfillDataMenu() # PDF / PDF Controls G2G.Define_wxId('wxID_PDFCOPYCONTROLS', 'wxID_PDFSAVECONTROLS', 'wxID_PDFLOADCONTROLS', 'wxID_PDFCOMPUTE', 'wxID_PDFCOMPUTEALL', 'wxID_PDFADDELEMENT', 'wxID_PDFDELELEMENT',) self.PDFMenu = wx.MenuBar() self.PrefillDataMenu(self.PDFMenu) self.PDFEdit = wx.Menu(title='') self.PDFMenu.Append(menu=self.PDFEdit, title='PDF Controls') self.PDFEdit.Append(help='Add one or more elements to sample composition',id=G2G.wxID_PDFADDELEMENT, kind=wx.ITEM_NORMAL, text='Add elements') self.PDFEdit.Append(help='Delete element from sample composition',id=G2G.wxID_PDFDELELEMENT, kind=wx.ITEM_NORMAL, text='Delete element') self.PDFEdit.Append(help='Copy PDF controls', id=G2G.wxID_PDFCOPYCONTROLS, kind=wx.ITEM_NORMAL, text='Copy controls') self.PDFEdit.Append(help='Load PDF controls from file',id=G2G.wxID_PDFLOADCONTROLS, kind=wx.ITEM_NORMAL, text='Load Controls') self.PDFEdit.Append(help='Save PDF controls to file', id=G2G.wxID_PDFSAVECONTROLS, kind=wx.ITEM_NORMAL, text='Save controls') self.PDFEdit.Append(help='Compute PDF', id=G2G.wxID_PDFCOMPUTE, kind=wx.ITEM_NORMAL, text='Compute PDF') self.PDFEdit.Append(help='Compute all PDFs with or w/o optimization', id=G2G.wxID_PDFCOMPUTEALL, kind=wx.ITEM_NORMAL, text='Compute all PDFs') self.PostfillDataMenu() # PDF / PDF Peaks G2G.Define_wxId('wxID_PDFPKSFIT','wxID_PDFPKSFITALL', 'wxID_PDFCOPYPEAKS', 'wxID_CLEARPDFPEAKS',) self.PDFPksMenu = wx.MenuBar() self.PrefillDataMenu(self.PDFPksMenu) self.PDFPksEdit = wx.Menu(title='') self.PDFPksMenu.Append(menu=self.PDFPksEdit, title='PDF Peaks') self.PDFPksEdit.Append(help='Fit PDF peaks', id=G2G.wxID_PDFPKSFIT, kind=wx.ITEM_NORMAL, text='PDF peak fit') self.PDFPksEdit.Append(help='Sequential Peak fitting for all PDFs', id=G2G.wxID_PDFPKSFITALL, kind=wx.ITEM_NORMAL, text='Seq PDF peak fit') self.PDFPksEdit.Append(help='Copy PDF peaks', id=G2G.wxID_PDFCOPYPEAKS, kind=wx.ITEM_NORMAL, text='Copy peaks') self.PDFPksEdit.Append(help='Clear PDF peaks', id=G2G.wxID_CLEARPDFPEAKS, kind=wx.ITEM_NORMAL, text='Clear peaks') self.PostfillDataMenu() # Phase / General tab G2G.Define_wxId('wxID_FOURCALC', 'wxID_FOURSEARCH', 'wxID_FOURCLEAR','wxID_CHARGEFLIP', 'wxID_MULTIMCSA','wxID_SINGLEMCSA', 'wxID_4DCHARGEFLIP', 'wxID_TRANSFORMSTRUCTURE',) self.DataGeneral = wx.MenuBar() self.PrefillDataMenu(self.DataGeneral) self.DataGeneral.Append(menu=wx.Menu(title=''),title='Select tab') self.GeneralCalc = wx.Menu(title='') self.DataGeneral.Append(menu=self.GeneralCalc,title='Compute') self.GeneralCalc.Append(help='Compute Fourier map',id=G2G.wxID_FOURCALC, kind=wx.ITEM_NORMAL, text='Fourier map') self.GeneralCalc.Append(help='Search Fourier map',id=G2G.wxID_FOURSEARCH, kind=wx.ITEM_NORMAL, text='Search map') self.GeneralCalc.Append(help='Run charge flipping',id=G2G.wxID_CHARGEFLIP, kind=wx.ITEM_NORMAL, text='Charge flipping') self.GeneralCalc.Append(help='Run 4D charge flipping',id=G2G.wxID_4DCHARGEFLIP, kind=wx.ITEM_NORMAL, text='4D Charge flipping') self.GeneralCalc.Enable(G2G.wxID_4DCHARGEFLIP,False) self.GeneralCalc.Append(help='Clear map',id=G2G.wxID_FOURCLEAR, kind=wx.ITEM_NORMAL, text='Clear map') self.GeneralCalc.Append(help='Run Monte Carlo - Simulated Annealing',id=G2G.wxID_SINGLEMCSA, kind=wx.ITEM_NORMAL, text='MC/SA') self.GeneralCalc.Append(help='Run Monte Carlo - Simulated Annealing on multiprocessors',id=G2G.wxID_MULTIMCSA, kind=wx.ITEM_NORMAL, text='Multi MC/SA') #currently not useful self.GeneralCalc.Append(help='Transform crystal structure',id=G2G.wxID_TRANSFORMSTRUCTURE, kind=wx.ITEM_NORMAL, text='Transform') self.PostfillDataMenu() # Phase / Data tab G2G.Define_wxId('wxID_DATACOPY', 'wxID_DATACOPYFLAGS', 'wxID_DATASELCOPY', 'wxID_DATAUSE', 'wxID_PWDRADD', 'wxID_HKLFADD','wxID_DATADELETE', ) self.DataMenu = wx.MenuBar() self.PrefillDataMenu(self.DataMenu) self.DataMenu.Append(menu=wx.Menu(title=''),title='Select tab') self.DataEdit = wx.Menu(title='') self.DataMenu.Append(menu=self.DataEdit, title='Edit Phase') self.DataEdit.Append(id=G2G.wxID_DATACOPY, kind=wx.ITEM_NORMAL,text='Copy data', help='Copy phase data to other histograms') self.DataEdit.Append(id=G2G.wxID_DATACOPYFLAGS, kind=wx.ITEM_NORMAL,text='Copy flags', help='Copy phase data flags to other histograms') self.DataEdit.Append(id=G2G.wxID_DATASELCOPY, kind=wx.ITEM_NORMAL,text='Copy selected data', help='Copy selected phase data to other histograms') self.DataEdit.Append(id=G2G.wxID_DATAUSE, kind=wx.ITEM_NORMAL,text='Select used data', help='Select all histograms to use') self.DataEdit.Append(id=G2G.wxID_PWDRADD, kind=wx.ITEM_NORMAL,text='Add powder histograms', help='Select new powder histograms to be used for this phase') self.DataEdit.Append(id=G2G.wxID_HKLFADD, kind=wx.ITEM_NORMAL,text='Add single crystal histograms', help='Select new single crystal histograms to be used for this phase') self.DataEdit.Append(id=G2G.wxID_DATADELETE, kind=wx.ITEM_NORMAL,text='Remove histograms', help='Remove histograms from use for this phase') self.PostfillDataMenu() # Phase / Atoms tab G2G.Define_wxId('wxID_ATOMSEDITADD', 'wxID_ATOMSEDITINSERT', 'wxID_ATOMSEDITDELETE', 'wxID_ATOMSMODIFY', 'wxID_ATOMSTRANSFORM', 'wxID_ATOMSVIEWADD', 'wxID_ATOMVIEWINSERT', 'wxID_RELOADDRAWATOMS', 'wxID_ATOMSDISAGL', 'wxID_ATOMMOVE', 'wxID_MAKEMOLECULE', 'wxID_ATOMSPDISAGL', 'wxID_ISODISP', 'wxID_ADDHATOM', 'wxID_UPDATEHATOM', 'wxID_ATOMSROTATE', 'wxID_ATOMSDENSITY', 'wxID_VALIDPROTEIN', 'wxID_ATOMSSETALL', 'wxID_ATOMSSETSEL',) self.AtomsMenu = wx.MenuBar() self.PrefillDataMenu(self.AtomsMenu) self.AtomsMenu.Append(menu=wx.Menu(title=''),title='Select tab') self.AtomEdit = wx.Menu(title='') self.AtomCompute = wx.Menu(title='') self.AtomsMenu.Append(menu=self.AtomEdit, title='Edit Atoms') self.AtomsMenu.Append(menu=self.AtomCompute, title='Compute') submenu = wx.Menu() self.AtomEdit.AppendMenu(wx.ID_ANY, 'On selected atoms...', submenu, help='Set/Act on selected atoms') submenu.Append(G2G.wxID_ATOMSSETSEL,help='Set refinement flags for selected atoms', kind=wx.ITEM_NORMAL,text='Refine selected') submenu.Append(id=G2G.wxID_ATOMSMODIFY, kind=wx.ITEM_NORMAL,text='Modify parameters', help='Modify parameters values for all selected atoms') submenu.Append(id=G2G.wxID_ATOMSEDITINSERT, kind=wx.ITEM_NORMAL,text='Insert atom', help='Inserts an H atom before all selected atoms') submenu.Append(id=G2G.wxID_ADDHATOM, kind=wx.ITEM_NORMAL,text='Calc H atoms', help='Insert H atoms in expected bonding positions for selected atoms') submenu.Append(id=G2G.wxID_ATOMSEDITDELETE, kind=wx.ITEM_NORMAL,text='Delete atom', help='Delete selected atoms') submenu.Append(id=G2G.wxID_ATOMSTRANSFORM, kind=wx.ITEM_NORMAL,text='Transform atoms', help='Symmetry transform selected atoms') # self.AtomEdit.Append(id=G2G.wxID_ATOMSROTATE, kind=wx.ITEM_NORMAL,text='Rotate atoms', # help='Select atoms to rotate first') submenu.Append(G2G.wxID_ATOMSSETALL,help='Set refinement flags for all atoms', kind=wx.ITEM_NORMAL,text='Select All') self.AtomEdit.Append(id=G2G.wxID_ATOMSEDITADD, kind=wx.ITEM_NORMAL,text='Append atom', help='Appended as an H atom') self.AtomEdit.Append(id=G2G.wxID_ATOMSVIEWADD, kind=wx.ITEM_NORMAL,text='Append view point', help='Appended as an H atom') self.AtomEdit.Append(id=G2G.wxID_ATOMVIEWINSERT, kind=wx.ITEM_NORMAL,text='Insert view point', help='Select atom row to insert before; inserted as an H atom') self.AtomEdit.Append(id=G2G.wxID_UPDATEHATOM, kind=wx.ITEM_NORMAL,text='Update H atoms', help='Update H atoms in standard positions') self.AtomEdit.Append(id=G2G.wxID_ATOMMOVE, kind=wx.ITEM_NORMAL,text='Move selected atom to view point', help='Select a single atom to be moved to view point in plot') self.AtomEdit.Append(id=G2G.wxID_MAKEMOLECULE, kind=wx.ITEM_NORMAL,text='Assemble molecule', help='Select a single atom to assemble as a molecule from scattered atom positions') self.AtomEdit.Append(id=G2G.wxID_RELOADDRAWATOMS, kind=wx.ITEM_NORMAL,text='Reload draw atoms', help='Reload atom drawing list') submenu = wx.Menu() self.AtomEdit.AppendMenu(wx.ID_ANY, 'Reimport atoms', submenu, help='Reimport atoms from file; sequence must match') # setup a cascade menu for the formats that have been defined self.ReImportMenuId = {} # points to readers for each menu entry for reader in self.parent.GetTopLevelParent().ImportPhaseReaderlist: item = submenu.Append(wx.ID_ANY,help=reader.longFormatName, kind=wx.ITEM_NORMAL,text='reimport coordinates from '+reader.formatName+' file') self.ReImportMenuId[item.GetId()] = reader item = submenu.Append(wx.ID_ANY,help='Reimport coordinates, try to determine format from file', kind=wx.ITEM_NORMAL,text='guess format from file') self.ReImportMenuId[item.GetId()] = None # try all readers self.AtomCompute.Append(id=G2G.wxID_ATOMSDISAGL, kind=wx.ITEM_NORMAL,text='Show Distances && Angles', help='Compute distances & angles for selected atoms') self.AtomCompute.Append(id=G2G.wxID_ATOMSPDISAGL, kind=wx.ITEM_NORMAL,text='Save Distances && Angles', help='Compute distances & angles for selected atoms') self.AtomCompute.Append(id=G2G.wxID_ATOMSDENSITY, kind=wx.ITEM_NORMAL, text='Density',help='Compute density for current phase') self.AtomCompute.Append(id=G2G.wxID_VALIDPROTEIN, kind=wx.ITEM_NORMAL, text='Protein quality',help='Protein quality analysis') self.AtomCompute.ISOcalc = self.AtomCompute.Append(id=G2G.wxID_ISODISP, kind=wx.ITEM_NORMAL, text='ISODISTORT mode values',help='Compute values of ISODISTORT modes from atom parameters') self.PostfillDataMenu() # Phase / Imcommensurate "waves" tab G2G.Define_wxId('wxID_WAVEVARY',) self.WavesData = wx.MenuBar() self.PrefillDataMenu(self.WavesData) self.WavesData.Append(menu=wx.Menu(title=''),title='Select tab') self.WavesDataEdit = wx.Menu(title='') self.WavesData.Append(menu=self.WavesDataEdit, title='Edit Wave') self.WavesDataEdit.Append(id=G2G.wxID_WAVEVARY, kind=wx.ITEM_NORMAL,text='Global wave vary', help='Global setting of wave vary flags') self.PostfillDataMenu() # Phase / Layer tab G2G.Define_wxId('wxID_LOADDIFFAX', 'wxID_LAYERSIMULATE', 'wxID_SEQUENCESIMULATE', 'wxID_LAYERSFIT', 'wxID_COPYPHASE',) self.LayerData = wx.MenuBar() self.PrefillDataMenu(self.LayerData) self.LayerData.Append(menu=wx.Menu(title=''),title='Select tab') self.LayerDataEdit = wx.Menu(title='') self.LayerData.Append(menu=self.LayerDataEdit, title='Operations') self.LayerDataEdit.Append(id=G2G.wxID_LOADDIFFAX, kind=wx.ITEM_NORMAL,text='Load from DIFFaX file', help='Load layer info from DIFFaX file') self.LayerDataEdit.Append(id=G2G.wxID_COPYPHASE, kind=wx.ITEM_NORMAL,text='Copy phase cell', help='Copy phase cell from another project') self.LayerDataEdit.Append(id=G2G.wxID_LAYERSIMULATE, kind=wx.ITEM_NORMAL,text='Simulate pattern', help='Simulate diffraction pattern from layer stacking') self.LayerDataEdit.Append(id=G2G.wxID_LAYERSFIT, kind=wx.ITEM_NORMAL,text='Fit pattern', help='Fit diffraction pattern with layer stacking model') self.LayerDataEdit.Append(id=G2G.wxID_SEQUENCESIMULATE, kind=wx.ITEM_NORMAL,text='Sequence simulations', help='Sequence simulation changing one parameter') self.PostfillDataMenu() # Phase / Draw Options tab self.DataDrawOptions = wx.MenuBar() self.PrefillDataMenu(self.DataDrawOptions) self.DataDrawOptions.Append(menu=wx.Menu(title=''),title='Select tab') self.PostfillDataMenu() # Phase / Draw Atoms tab G2G.Define_wxId('wxID_DRAWATOMSTYLE', 'wxID_DRAWATOMLABEL', 'wxID_DRAWATOMCOLOR', 'wxID_DRAWATOMRESETCOLOR', 'wxID_DRAWVIEWPOINT', 'wxID_DRAWTRANSFORM', 'wxID_DRAWDELETE', 'wxID_DRAWFILLCELL', 'wxID_DRAWADDEQUIV', 'wxID_DRAWFILLCOORD', 'wxID_DRAWDISAGLTOR', 'wxID_DRAWPLANE', 'wxID_DRAWDISTVP', 'wxID_DRAWADDSPHERE', 'wxID_DRWAEDITRADII',) G2G.Define_wxId('wxID_DRAWRESTRBOND', 'wxID_DRAWRESTRANGLE', 'wxID_DRAWRESTRPLANE', 'wxID_DRAWRESTRCHIRAL',) self.DrawAtomsMenu = wx.MenuBar() self.PrefillDataMenu(self.DrawAtomsMenu) self.DrawAtomsMenu.Append(menu=wx.Menu(title=''),title='Select tab') self.DrawAtomEdit = wx.Menu(title='') self.DrawAtomCompute = wx.Menu(title='') self.DrawAtomRestraint = wx.Menu(title='') self.DrawAtomRigidBody = wx.Menu(title='') self.DrawAtomsMenu.Append(menu=self.DrawAtomEdit, title='Edit Figure') self.DrawAtomsMenu.Append(menu=self.DrawAtomCompute,title='Compute') self.DrawAtomsMenu.Append(menu=self.DrawAtomRestraint, title='Restraints') self.DrawAtomsMenu.Append(menu=self.DrawAtomRigidBody, title='Rigid body') self.DrawAtomEdit.Append(id=G2G.wxID_DRAWATOMSTYLE, kind=wx.ITEM_NORMAL,text='Atom style', help='Select atoms first') self.DrawAtomEdit.Append(id=G2G.wxID_DRAWATOMLABEL, kind=wx.ITEM_NORMAL,text='Atom label', help='Select atoms first') self.DrawAtomEdit.Append(id=G2G.wxID_DRAWATOMCOLOR, kind=wx.ITEM_NORMAL,text='Atom color', help='Select atoms first') self.DrawAtomEdit.Append(id=G2G.wxID_DRAWATOMRESETCOLOR, kind=wx.ITEM_NORMAL,text='Reset atom colors', help='Resets all atom colors to defaults') self.DrawAtomEdit.Append(id=G2G.wxID_DRWAEDITRADII, kind=wx.ITEM_NORMAL,text='Edit atom radii', help='Edit drawing atom radii') self.DrawAtomEdit.Append(id=G2G.wxID_DRAWVIEWPOINT, kind=wx.ITEM_NORMAL,text='View point', help='View point is 1st atom selected') self.DrawAtomEdit.Append(id=G2G.wxID_DRAWADDEQUIV, kind=wx.ITEM_NORMAL,text='Add atoms', help='Add symmetry & cell equivalents to drawing set from selected atoms') self.DrawAtomEdit.Append(id=G2G.wxID_DRAWADDSPHERE, kind=wx.ITEM_NORMAL,text='Add sphere of atoms', help='Add atoms within sphere of enclosure') self.DrawAtomEdit.Append(id=G2G.wxID_DRAWTRANSFORM, kind=wx.ITEM_NORMAL,text='Transform draw atoms', help='Transform selected atoms by symmetry & cell translations') self.DrawAtomEdit.Append(id=G2G.wxID_DRAWFILLCOORD, kind=wx.ITEM_NORMAL,text='Fill CN-sphere', help='Fill coordination sphere for selected atoms') self.DrawAtomEdit.Append(id=G2G.wxID_DRAWFILLCELL, kind=wx.ITEM_NORMAL,text='Fill unit cell', help='Fill unit cell with selected atoms') self.DrawAtomEdit.Append(id=G2G.wxID_DRAWDELETE, kind=wx.ITEM_NORMAL,text='Delete atoms', help='Delete atoms from drawing set') self.DrawAtomCompute.Append(id=G2G.wxID_DRAWDISTVP, kind=wx.ITEM_NORMAL,text='View pt. dist.', help='Compute distance of selected atoms from view point') self.DrawAtomCompute.Append(id=G2G.wxID_DRAWDISAGLTOR, kind=wx.ITEM_NORMAL,text='Dist. Ang. Tors.', help='Compute distance, angle or torsion for 2-4 selected atoms') self.DrawAtomCompute.Append(id=G2G.wxID_DRAWPLANE, kind=wx.ITEM_NORMAL,text='Best plane', help='Compute best plane for 4+ selected atoms') self.DrawAtomRestraint.Append(id=G2G.wxID_DRAWRESTRBOND, kind=wx.ITEM_NORMAL,text='Add bond restraint', help='Add bond restraint for selected atoms (2)') self.DrawAtomRestraint.Append(id=G2G.wxID_DRAWRESTRANGLE, kind=wx.ITEM_NORMAL,text='Add angle restraint', help='Add angle restraint for selected atoms (3: one end 1st)') self.DrawAtomRestraint.Append(id=G2G.wxID_DRAWRESTRPLANE, kind=wx.ITEM_NORMAL,text='Add plane restraint', help='Add plane restraint for selected atoms (4+)') self.DrawAtomRestraint.Append(id=G2G.wxID_DRAWRESTRCHIRAL, kind=wx.ITEM_NORMAL,text='Add chiral restraint', help='Add chiral restraint for selected atoms (4: center atom 1st)') self.DrawAtomRigidBody.Append(id=G2G.wxID_DRAWDEFINERB, kind=wx.ITEM_NORMAL,text='Define rigid body', help='Define rigid body with selected atoms') self.PostfillDataMenu() # Phase / MCSA tab G2G.Define_wxId('wxID_ADDMCSAATOM', 'wxID_ADDMCSARB', 'wxID_CLEARMCSARB', 'wxID_MOVEMCSA', 'wxID_MCSACLEARRESULTS',) self.MCSAMenu = wx.MenuBar() self.PrefillDataMenu(self.MCSAMenu) self.MCSAMenu.Append(menu=wx.Menu(title=''),title='Select tab') self.MCSAEdit = wx.Menu(title='') self.MCSAMenu.Append(menu=self.MCSAEdit, title='MC/SA') self.MCSAEdit.Append(id=G2G.wxID_ADDMCSAATOM, kind=wx.ITEM_NORMAL,text='Add atom', help='Add single atom to MC/SA model') self.MCSAEdit.Append(id=G2G.wxID_ADDMCSARB, kind=wx.ITEM_NORMAL,text='Add rigid body', help='Add rigid body to MC/SA model' ) self.MCSAEdit.Append(id=G2G.wxID_CLEARMCSARB, kind=wx.ITEM_NORMAL,text='Clear rigid bodies', help='Clear all atoms & rigid bodies from MC/SA model' ) self.MCSAEdit.Append(id=G2G.wxID_MOVEMCSA, kind=wx.ITEM_NORMAL,text='Move MC/SA solution', help='Move MC/SA solution to atom list' ) self.MCSAEdit.Append(id=G2G.wxID_MCSACLEARRESULTS, kind=wx.ITEM_NORMAL,text='Clear results', help='Clear table of MC/SA results' ) self.PostfillDataMenu() # Phase / Texture tab G2G.Define_wxId('wxID_CLEARTEXTURE', 'wxID_REFINETEXTURE',) self.TextureMenu = wx.MenuBar() self.PrefillDataMenu(self.TextureMenu) self.TextureMenu.Append(menu=wx.Menu(title=''),title='Select tab') self.TextureEdit = wx.Menu(title='') self.TextureMenu.Append(menu=self.TextureEdit, title='Texture') self.TextureEdit.Append(id=G2G.wxID_REFINETEXTURE, kind=wx.ITEM_NORMAL,text='Refine texture', help='Refine the texture coefficients from sequential results') # self.TextureEdit.Append(id=G2G.wxID_CLEARTEXTURE, kind=wx.ITEM_NORMAL,text='Clear texture', # help='Clear the texture coefficients' ) self.PostfillDataMenu() # Phase / Pawley tab G2G.Define_wxId('wxID_PAWLEYLOAD', 'wxID_PAWLEYESTIMATE', 'wxID_PAWLEYUPDATE', 'wxID_PAWLEYSELALL', 'wxID_PAWLEYSELNONE','wxID_PAWLEYSELTOGGLE', 'wxID_PAWLEYSET',) self.PawleyMenu = wx.MenuBar() self.PrefillDataMenu(self.PawleyMenu) self.PawleyMenu.Append(menu=wx.Menu(title=''),title='Select tab') self.PawleyEdit = wx.Menu(title='') self.PawleyMenu.Append(menu=self.PawleyEdit,title='Operations') self.PawleyEdit.Append(id=G2G.wxID_PAWLEYSET, kind=wx.ITEM_NORMAL,text='Pawley settings', help='Change Pawley refinement settings') self.PawleyEdit.Append(id=G2G.wxID_PAWLEYLOAD, kind=wx.ITEM_NORMAL,text='Pawley create', help='Initialize Pawley reflection list') self.PawleyEdit.Append(id=G2G.wxID_PAWLEYESTIMATE, kind=wx.ITEM_NORMAL,text='Pawley estimate', help='Estimate initial Pawley intensities') self.PawleyEdit.Append(id=G2G.wxID_PAWLEYUPDATE, kind=wx.ITEM_NORMAL,text='Pawley update', help='Update negative Pawley intensities with -0.5*Fobs and turn off refinement') self.PawleyEdit.Append(id=G2G.wxID_PAWLEYSELALL, kind=wx.ITEM_NORMAL,text='Select all', help='Select all reflections to be refined') self.PawleyEdit.Append(id=G2G.wxID_PAWLEYSELNONE, kind=wx.ITEM_NORMAL,text='Select none', help='Set flag for all reflections for no refinement') self.PawleyEdit.Append(id=G2G.wxID_PAWLEYSELTOGGLE, kind=wx.ITEM_NORMAL,text='Toggle Selection', help='Toggle Selection flag for all reflections to opposite setting') self.PostfillDataMenu() # Phase / Map peaks tab G2G.Define_wxId('wxID_PEAKSMOVE', 'wxID_PEAKSCLEAR','wxID_PEAKSUNIQUE', 'wxID_PEAKSDELETE', 'wxID_PEAKSDA','wxID_PEAKSDISTVP', 'wxID_PEAKSVIEWPT', 'wxID_FINDEQVPEAKS', 'wxID_SHOWBONDS',) self.MapPeaksMenu = wx.MenuBar() self.PrefillDataMenu(self.MapPeaksMenu) self.MapPeaksMenu.Append(menu=wx.Menu(title=''),title='Select tab') self.MapPeaksEdit = wx.Menu(title='') self.MapPeaksMenu.Append(menu=self.MapPeaksEdit, title='Map peaks') self.MapPeaksEdit.Append(id=G2G.wxID_PEAKSMOVE, kind=wx.ITEM_NORMAL,text='Move peaks', help='Move selected peaks to atom list') self.MapPeaksEdit.Append(id=G2G.wxID_PEAKSVIEWPT, kind=wx.ITEM_NORMAL,text='View point', help='View point is 1st peak selected') self.MapPeaksEdit.Append(id=G2G.wxID_PEAKSDISTVP, kind=wx.ITEM_NORMAL,text='View pt. dist.', help='Compute distance of selected peaks from view point') self.MapPeaksEdit.Append(id=G2G.wxID_SHOWBONDS, kind=wx.ITEM_NORMAL,text='Hide bonds', help='Hide or show bonds between peak positions') self.MapPeaksEdit.Append(id=G2G.wxID_PEAKSDA, kind=wx.ITEM_NORMAL,text='Calc dist/ang', help='Calculate distance or angle for selection') self.MapPeaksEdit.Append(id=G2G.wxID_FINDEQVPEAKS, kind=wx.ITEM_NORMAL,text='Equivalent peaks', help='Find equivalent peaks') self.MapPeaksEdit.Append(id=G2G.wxID_PEAKSUNIQUE, kind=wx.ITEM_NORMAL,text='Unique peaks', help='Select unique set') self.MapPeaksEdit.Append(id=G2G.wxID_PEAKSDELETE, kind=wx.ITEM_NORMAL,text='Delete peaks', help='Delete selected peaks') self.MapPeaksEdit.Append(id=G2G.wxID_PEAKSCLEAR, kind=wx.ITEM_NORMAL,text='Clear peaks', help='Clear the map peak list') self.PostfillDataMenu() # Phase / Rigid bodies tab G2G.Define_wxId( 'wxID_ASSIGNATMS2RB','wxID_GLOBALRESREFINE','wxID_RBREMOVEALL','wxID_AUTOFINDRESRB', 'wxID_COPYRBPARMS','wxID_GLOBALTHERM',) self.RigidBodiesMenu = wx.MenuBar() self.PrefillDataMenu(self.RigidBodiesMenu) self.RigidBodiesMenu.Append(menu=wx.Menu(title=''),title='Select tab') self.RigidBodiesEdit = wx.Menu(title='') self.RigidBodiesMenu.Append(menu=self.RigidBodiesEdit, title='Edit Body') self.RigidBodiesEdit.Append(id=G2G.wxID_ASSIGNATMS2RB, kind=wx.ITEM_NORMAL,text='Assign atoms to rigid body', help='Select & position rigid body in structure of existing atoms') self.RigidBodiesEdit.Append(id=G2G.wxID_AUTOFINDRESRB, kind=wx.ITEM_NORMAL,text='Auto find residues', help='Auto find of residue RBs in macromolecule') self.RigidBodiesEdit.Append(id=G2G.wxID_COPYRBPARMS, kind=wx.ITEM_NORMAL,text='Copy rigid body parms', help='Copy rigid body location & TLS parameters') self.RigidBodiesEdit.Append(id=G2G.wxID_GLOBALTHERM, kind=wx.ITEM_NORMAL,text='Global thermal motion', help='Global setting of residue thermal motion models') self.RigidBodiesEdit.Append(id=G2G.wxID_GLOBALRESREFINE, kind=wx.ITEM_NORMAL,text='Global residue refine', help='Global setting of residue RB refinement flags') self.RigidBodiesEdit.Append(id=G2G.wxID_RBREMOVEALL, kind=wx.ITEM_NORMAL,text='Remove all rigid bodies', help='Remove all rigid body assignment for atoms') self.PostfillDataMenu() # end of GSAS-II menu definitions #TODO - remove # def _init_ctrls(self, parent,name=None,size=None,pos=None): # wx.Frame.__init__( # self,parent=parent, # #style=wx.DEFAULT_FRAME_STYLE ^ wx.CLOSE_BOX | wx.FRAME_FLOAT_ON_PARENT , # style=wx.DEFAULT_FRAME_STYLE ^ wx.CLOSE_BOX, # size=size,pos=pos,title='GSAS-II data display') # self._init_menus() # if name: # self.SetLabel(name) # self.Show() # # def __init__(self,parent,frame,data=None,name=None, size=None,pos=None): # self.G2frame = frame # self._init_ctrls(parent,name,size,pos) # self.data = data # clientSize = wx.ClientDisplayRect() # Size = self.GetSize() # xPos = clientSize[2]-Size[0] # self.SetPosition(wx.Point(xPos,clientSize[1]+250)) # self.AtomGrid = [] # self.selectedRow = 0 # self.lastSize = Size # self.manualPhaseSize = None # self.userReSize = False # wx.Frame.Bind(self,wx.EVT_SIZE,self.OnReSize) # # def OnReSize(self,event): # '''Keep track of size changes for Phase windows # ''' # id = self.G2frame.GPXtree.GetSelection() # try: # parent = self.G2frame.GPXtree.GetItemParent(id) # except: #avoid bad tree item on start via gpx file selection # parent = 0 # if self.userReSize and parent and self.G2frame.GPXtree.GetItemText(parent) == "Phases": # newSize = event.EventObject.GetSize() # if newSize[1] < 200: return #avois spurious small window after Refine # if self.lastSize == newSize: ## if GSASIIpath.GetConfigValue('debug'): ## print 'no save size=',self.lastSize # return # self.manualPhaseSize = newSize # self.lastSize = event.EventObject.GetSize() ## if GSASIIpath.GetConfigValue('debug'): ## print 'Saving Phase size=',self.manualPhaseSize # #HowDidIgetHere() # event.Skip() # # def SendSizeEvent(self): # '''Prevent SendSizeEvent from overriding the saved size # ''' # self.userReSize = False # wx.Frame.SendSizeEvent(self) # self.userReSize = True # # def Clear(self): # self.ClearBackground() # self.DestroyChildren() ################################################################################ ##### Notebook Tree Item editor ################################################################################ def UpdateNotebook(G2frame,data): '''Called when the data tree notebook entry is selected. Allows for editing of the text in that tree entry ''' def OnNoteBook(event): event.Skip() data = text.GetValue().split('\n') G2frame.GPXtree.SetItemPyData(GetGPXtreeItemId(G2frame,G2frame.root,'Notebook'),data) if 'nt' not in os.name: text.AppendText('\n') #G2frame.SetLabel(G2frame.GetLabel().split('||')[0]+' || '+'Notebook') G2frame.SetTitle('Notebook') text = wx.TextCtrl(G2frame.dataWindow,wx.ID_ANY, style=wx.TE_MULTILINE|wx.TE_PROCESS_ENTER | wx.TE_DONTWRAP) text.Bind(wx.EVT_TEXT_ENTER,OnNoteBook) text.Bind(wx.EVT_KILL_FOCUS,OnNoteBook) for line in data: text.AppendText(line+"\n") text.AppendText('Notebook entry @ '+time.ctime()+"\n") G2frame.dataWindow.GetSizer().Add(wx.StaticText(G2frame.dataWindow,-1,' Add notes on project here: '),0,WACV) G2frame.dataWindow.GetSizer().Add(text,1,wx.ALL|wx.EXPAND) ################################################################################ ##### Comments ################################################################################ def UpdateComments(G2frame,data): #G2frame.SetLabel(G2frame.GetLabel().split('||')[0]+' || '+'Comments') G2frame.SetTitle('Comments') lines = "" for line in data: lines += line.rstrip()+'\n' text = wx.StaticText(G2frame.dataWindow,wx.ID_ANY,lines) G2frame.dataWindow.GetSizer().Add(text,1,wx.ALL|wx.EXPAND) ################################################################################ ##### Controls Tree Item editor ################################################################################ def UpdateControls(G2frame,data): '''Edit overall GSAS-II controls in main Controls data tree entry ''' #patch if 'deriv type' not in data: data = {} data['deriv type'] = 'analytic Hessian' data['min dM/M'] = 0.001 data['shift factor'] = 1. data['max cyc'] = 3 data['F**2'] = False if 'SVDtol' not in data: data['SVDtol'] = 1.e-6 if 'shift factor' not in data: data['shift factor'] = 1. if 'max cyc' not in data: data['max cyc'] = 3 if 'F**2' not in data: data['F**2'] = False if 'Author' not in data: data['Author'] = 'no name' if 'FreePrm1' not in data: data['FreePrm1'] = 'Sample humidity (%)' if 'FreePrm2' not in data: data['FreePrm2'] = 'Sample voltage (V)' if 'FreePrm3' not in data: data['FreePrm3'] = 'Applied load (MN)' if 'Copy2Next' not in data: data['Copy2Next'] = False if 'Reverse Seq' not in data: data['Reverse Seq'] = False if 'UsrReject' not in data: data['UsrReject'] = {'minF/sig':0,'MinExt':0.01,'MaxDF/F':20.,'MaxD':500.,'MinD':0.05} if 'HatomFix' not in data: data['HatomFix'] = False if 'Marquardt' not in data: data['Marquardt'] = -3 #end patch def SeqSizer(): def OnSelectData(event): choices = GetGPXtreeDataNames(G2frame,['PWDR','HKLF',]) sel = [] try: if 'Seq Data' in data: # for item in data['Seq Data']: # sel.append(choices.index(item)) sel = [choices.index(item) for item in data['Seq Data']] except ValueError: #data changed somehow - start fresh sel = [] dlg = G2G.G2MultiChoiceDialog(G2frame, 'Sequential refinement', 'Select dataset to include',choices) dlg.SetSelections(sel) names = [] if dlg.ShowModal() == wx.ID_OK: for sel in dlg.GetSelections(): names.append(choices[sel]) data['Seq Data'] = names G2frame.EnableSeqRefineMenu() dlg.Destroy() wx.CallAfter(UpdateControls,G2frame,data) def OnReverse(event): data['Reverse Seq'] = reverseSel.GetValue() def OnCopySel(event): data['Copy2Next'] = copySel.GetValue() seqSizer = wx.BoxSizer(wx.VERTICAL) dataSizer = wx.BoxSizer(wx.HORIZONTAL) dataSizer.Add(wx.StaticText(G2frame.dataWindow,label=' Sequential Refinement: '),0,WACV) selSeqData = wx.Button(G2frame.dataWindow,-1,label=' Select data') selSeqData.Bind(wx.EVT_BUTTON,OnSelectData) dataSizer.Add(selSeqData,0,WACV) SeqData = data.get('Seq Data',[]) if not SeqData: lbl = ' (no data selected)' else: lbl = ' ('+str(len(SeqData))+' dataset(s) selected)' dataSizer.Add(wx.StaticText(G2frame.dataWindow,label=lbl),0,WACV) seqSizer.Add(dataSizer,0) if SeqData: selSizer = wx.BoxSizer(wx.HORIZONTAL) reverseSel = wx.CheckBox(G2frame.dataWindow,-1,label=' Reverse order?') reverseSel.Bind(wx.EVT_CHECKBOX,OnReverse) reverseSel.SetValue(data['Reverse Seq']) selSizer.Add(reverseSel,0,WACV) copySel = wx.CheckBox(G2frame.dataWindow,-1,label=' Copy results to next histogram?') copySel.Bind(wx.EVT_CHECKBOX,OnCopySel) copySel.SetValue(data['Copy2Next']) selSizer.Add(copySel,0,WACV) seqSizer.Add(selSizer,0) return seqSizer def LSSizer(): def OnDerivType(event): data['deriv type'] = derivSel.GetValue() derivSel.SetValue(data['deriv type']) wx.CallAfter(UpdateControls,G2frame,data) def OnMaxCycles(event): data['max cyc'] = int(maxCyc.GetValue()) maxCyc.SetValue(str(data['max cyc'])) def OnMarqLam(event): data['Marquardt'] = int(marqLam.GetValue()) marqLam.SetValue(str(data['Marquardt'])) def OnFactor(event): event.Skip() try: value = min(max(float(Factr.GetValue()),0.00001),100.) except ValueError: value = 1.0 data['shift factor'] = value Factr.SetValue('%.5f'%(value)) def OnFsqRef(event): data['F**2'] = fsqRef.GetValue() LSSizer = wx.FlexGridSizer(cols=4,vgap=5,hgap=5) LSSizer.Add(wx.StaticText(G2frame.dataWindow,label=' Refinement derivatives: '),0,WACV) Choice=['analytic Jacobian','numeric','analytic Hessian','Hessian SVD'] #TODO +'SVD refine' - what flags will it need? derivSel = wx.ComboBox(parent=G2frame.dataWindow,value=data['deriv type'],choices=Choice, style=wx.CB_READONLY|wx.CB_DROPDOWN) derivSel.SetValue(data['deriv type']) derivSel.Bind(wx.EVT_COMBOBOX, OnDerivType) LSSizer.Add(derivSel,0,WACV) LSSizer.Add(wx.StaticText(G2frame.dataWindow,label=' Min delta-M/M: '),0,WACV) LSSizer.Add(G2G.ValidatedTxtCtrl(G2frame.dataWindow,data,'min dM/M',nDig=(10,2,'g'),min=1.e-9,max=1.),0,WACV) if 'Hessian' in data['deriv type']: LSSizer.Add(wx.StaticText(G2frame.dataWindow,label=' Max cycles: '),0,WACV) Choice = ['0','1','2','3','5','10','15','20'] maxCyc = wx.ComboBox(parent=G2frame.dataWindow,value=str(data['max cyc']),choices=Choice, style=wx.CB_READONLY|wx.CB_DROPDOWN) maxCyc.Bind(wx.EVT_COMBOBOX, OnMaxCycles) LSSizer.Add(maxCyc,0,WACV) if 'SVD' not in data['deriv type']: LSSizer.Add(wx.StaticText(G2frame.dataWindow,label=' Initial lambda = 10**'),0,WACV) MarqChoice = ['-3','-2','-1','0','1','2','3','4'] marqLam = wx.ComboBox(parent=G2frame.dataWindow,value=str(data['Marquardt']),choices=MarqChoice, style=wx.CB_READONLY|wx.CB_DROPDOWN) marqLam.Bind(wx.EVT_COMBOBOX,OnMarqLam) LSSizer.Add(marqLam,0,WACV) LSSizer.Add(wx.StaticText(G2frame.dataWindow,label=' SVD zero tolerance:'),0,WACV) LSSizer.Add(G2G.ValidatedTxtCtrl(G2frame.dataWindow,data,'SVDtol',nDig=(10,1,'g'),min=1.e-9,max=.01),0,WACV) else: #TODO what for SVD refine? LSSizer.Add(wx.StaticText(G2frame.dataWindow,label=' Initial shift factor: '),0,WACV) Factr = G2G.ValidatedTxtCtrl(G2frame.dataWindow,data,'shift factor',nDig=(10,5),min=1.e-5,max=100.) LSSizer.Add(Factr,0,WACV) if G2frame.Sngl: userReject = data['UsrReject'] usrRej = {'minF/sig':[' Min obs/sig (0-5): ',[0,5], ],'MinExt':[' Min extinct. (0-.9): ',[0,.9],], 'MaxDF/F':[' Max delt-F/sig (3-1000): ',[3.,1000.],],'MaxD':[' Max d-spacing (3-500): ',[3,500],], 'MinD':[' Min d-spacing (0.1-2.0): ',[0.1,2.0],]} fsqRef = wx.CheckBox(G2frame.dataWindow,-1,label='Refine HKLF as F^2? ') fsqRef.SetValue(data['F**2']) fsqRef.Bind(wx.EVT_CHECKBOX,OnFsqRef) LSSizer.Add(fsqRef,0,WACV) LSSizer.Add((1,0),) for item in usrRej: LSSizer.Add(wx.StaticText(G2frame.dataWindow,-1,label=usrRej[item][0]),0,WACV) usrrej = G2G.ValidatedTxtCtrl(G2frame.dataWindow,userReject,item,nDig=(10,2), min=usrRej[item][1][0],max=usrRej[item][1][1]) LSSizer.Add(usrrej,0,WACV) return LSSizer def AuthSizer(): def OnAuthor(event): event.Skip() data['Author'] = auth.GetValue() Author = data['Author'] authSizer = wx.BoxSizer(wx.HORIZONTAL) authSizer.Add(wx.StaticText(G2frame.dataWindow,label=' CIF Author (last, first):'),0,WACV) auth = wx.TextCtrl(G2frame.dataWindow,-1,value=Author,style=wx.TE_PROCESS_ENTER) auth.Bind(wx.EVT_TEXT_ENTER,OnAuthor) auth.Bind(wx.EVT_KILL_FOCUS,OnAuthor) authSizer.Add(auth,0,WACV) return authSizer if 'SVD' in data['deriv type']: G2frame.GetStatusBar().SetStatusText('Hessian SVD not recommended for initial refinements; use analytic Hessian or Jacobian',1) else: G2frame.GetStatusBar().SetStatusText('',1) G2frame.dataWindow.ClearData() G2frame.dataWindow.SetupScrolling() #G2frame.SetLabel(G2frame.GetLabel().split('||')[0]+' || '+'Controls') G2frame.SetTitle('Controls') SetDataMenuBar(G2frame,G2frame.dataWindow.ControlsMenu) mainSizer = wx.BoxSizer(wx.VERTICAL) mainSizer.Add((5,5),0) mainSizer.Add(wx.StaticText(G2frame.dataWindow,label=' Refinement Controls:'),0,WACV) mainSizer.Add(LSSizer()) mainSizer.Add((5,5),0) mainSizer.Add(SeqSizer()) mainSizer.Add((5,5),0) mainSizer.Add(AuthSizer()) mainSizer.Add((5,5),0) mainSizer.Layout() mainSizer.FitInside(G2frame.dataWindow) G2frame.dataWindow.SetSizer(mainSizer) G2frame.dataWindow.SetAutoLayout(1) G2frame.SetDataSize() ################################################################################ ##### Display of Sequential Results ################################################################################ def UpdateSeqResults(G2frame,data,prevSize=None): """ Called when the Sequential Results data tree entry is selected to show results from a sequential refinement. :param wx.Frame G2frame: main GSAS-II data tree windows :param dict data: a dictionary containing the following items: * 'histNames' - list of histogram names in order as processed by Sequential Refinement * 'varyList' - list of variables - identical over all refinements in sequence note that this is the original list of variables, prior to processing constraints. * 'variableLabels' -- a dict of labels to be applied to each parameter (this is created as an empty dict if not present in data). * keyed by histName - dictionaries for all data sets processed, which contains: * 'variables'- result[0] from leastsq call * 'varyList' - list of variables passed to leastsq call (not same as above) * 'sig' - esds for variables * 'covMatrix' - covariance matrix from individual refinement * 'title' - histogram name; same as dict item name * 'newAtomDict' - new atom parameters after shifts applied * 'newCellDict' - refined cell parameters after shifts to A0-A5 from Dij terms applied' """ def GetSampleParms(): '''Make a dictionary of the sample parameters that are not the same over the refinement series. Controls here is local ''' if 'IMG' in histNames[0]: sampleParmDict = {'Sample load':[],} else: sampleParmDict = {'Temperature':[],'Pressure':[],'Time':[], 'FreePrm1':[],'FreePrm2':[],'FreePrm3':[],'Omega':[], 'Chi':[],'Phi':[],'Azimuth':[],} Controls = G2frame.GPXtree.GetItemPyData( GetGPXtreeItemId(G2frame,G2frame.root, 'Controls')) sampleParm = {} for name in histNames: if 'IMG' in name: if name not in data: continue for item in sampleParmDict: sampleParmDict[item].append(data[name]['parmDict'].get(item,0)) else: if 'PDF' in name: name = 'PWDR' + name[4:] Id = GetGPXtreeItemId(G2frame,G2frame.root,name) if Id: sampleData = G2frame.GPXtree.GetItemPyData(GetGPXtreeItemId(G2frame,Id,'Sample Parameters')) for item in sampleParmDict: sampleParmDict[item].append(sampleData.get(item,0)) for item in sampleParmDict: if sampleParmDict[item]: frstValue = sampleParmDict[item][0] if np.any(np.array(sampleParmDict[item])-frstValue): if item.startswith('FreePrm'): sampleParm[Controls[item]] = sampleParmDict[item] else: sampleParm[item] = sampleParmDict[item] return sampleParm def GetColumnInfo(col): '''returns column label, lists of values and errors (or None) for each column in the table for plotting. The column label is reformatted from Unicode to MatPlotLib encoding ''' colName = G2frame.SeqTable.GetColLabelValue(col) plotName = variableLabels.get(colName,colName) plotName = plotSpCharFix(plotName) return plotName,G2frame.colList[col],G2frame.colSigs[col] def PlotSelectedColRow(calltyp=''): '''Called to plot a selected column or row. This is called after the event is processed so that the column or row gets selected. Single click on row: plots histogram Double click on row: plots V-C matrix Single or double click on column: plots values in column ''' cols = G2frame.dataDisplay.GetSelectedCols() rows = G2frame.dataDisplay.GetSelectedRows() if cols: G2plt.PlotSelectedSequence(G2frame,cols,GetColumnInfo,SelectXaxis) elif rows and calltyp == 'single': name = histNames[rows[0]] #only does 1st one selected if not name.startswith('PWDR'): return pickId = G2frame.PickId G2frame.PickId = G2frame.PatternId = GetGPXtreeItemId(G2frame, G2frame.root, name) G2plt.PlotPatterns(G2frame,newPlot=True,plotType='PWDR') G2frame.PickId = pickId elif rows: name = histNames[rows[0]] #only does 1st one selected G2plt.PlotCovariance(G2frame,data[name]) else: G2frame.ErrorDialog( 'Select row or columns', 'Nothing selected in table. Click on column or row label(s) to plot. N.B. Grid selection can be a bit funky.' ) def PlotSSelect(event): 'Called by a single click on a row or column label. ' event.Skip() wx.CallAfter(PlotSelectedColRow,'single') def PlotSelect(event): 'Called by a double-click on a row or column label' event.Skip() wx.CallAfter(PlotSelectedColRow,'double') def OnPlotSelSeq(event): 'plot the selected columns or row from menu command' cols = sorted(G2frame.dataDisplay.GetSelectedCols()) # ignore selection order rows = G2frame.dataDisplay.GetSelectedRows() if cols: G2plt.PlotSelectedSequence(G2frame,cols,GetColumnInfo,SelectXaxis) elif rows: name = histNames[rows[0]] #only does 1st one selected G2plt.PlotCovariance(G2frame,data[name]) else: G2frame.ErrorDialog('Select columns', 'No columns or rows selected in table. Click on row or column labels to select fields for plotting.') def OnAveSelSeq(event): 'average the selected columns from menu command' cols = sorted(G2frame.dataDisplay.GetSelectedCols()) # ignore selection order useCol = -np.array(G2frame.SeqTable.GetColValues(0),dtype=bool) if cols: for col in cols: items = GetColumnInfo(col)[1] noneMask = np.array([item is None for item in items]) info = ma.array(items,mask=useCol+noneMask) ave = ma.mean(ma.compressed(info)) sig = ma.std(ma.compressed(info)) print ' Average for '+G2frame.SeqTable.GetColLabelValue(col)+': '+'%.6g'%(ave)+' +/- '+'%.6g'%(sig) else: G2frame.ErrorDialog('Select columns', 'No columns selected in table. Click on column labels to select fields for averaging.') def OnSelectUse(event): dlg = G2G.G2MultiChoiceDialog(G2frame, 'Select rows to use','Select rows',histNames) sellist = [i for i,item in enumerate(G2frame.colList[0]) if item] dlg.SetSelections(sellist) if dlg.ShowModal() == wx.ID_OK: sellist = dlg.GetSelections() for row in range(G2frame.SeqTable.GetNumberRows()): G2frame.SeqTable.SetValue(row,0,False) G2frame.colList[0][row] = False for row in sellist: G2frame.SeqTable.SetValue(row,0,True) G2frame.colList[0][row] = True G2frame.dataDisplay.ForceRefresh() dlg.Destroy() def OnRenameSelSeq(event): cols = sorted(G2frame.dataDisplay.GetSelectedCols()) # ignore selection order colNames = [G2frame.SeqTable.GetColLabelValue(c) for c in cols] newNames = colNames[:] for i,name in enumerate(colNames): if name in variableLabels: newNames[i] = variableLabels[name] if not cols: G2frame.ErrorDialog('Select columns', 'No columns selected in table. Click on column labels to select fields for rename.') return dlg = G2G.MultiStringDialog(G2frame.dataDisplay,'Set column names',colNames,newNames) if dlg.Show(): newNames = dlg.GetValues() variableLabels.update(dict(zip(colNames,newNames))) data['variableLabels'] = variableLabels dlg.Destroy() UpdateSeqResults(G2frame,data,G2frame.dataDisplay.GetSize()) # redisplay variables G2plt.PlotSelectedSequence(G2frame,cols,GetColumnInfo,SelectXaxis) # def OnReOrgSelSeq(event): # 'Reorder the columns -- probably not fully implemented' # G2G.GetItemOrder(G2frame,VaryListChanges,vallookup,posdict) # UpdateSeqResults(G2frame,data,G2frame.dataDisplay.GetSize()) # redisplay variables def OnSaveSelSeqCSV(event): 'export the selected columns to a .csv file from menu command' OnSaveSelSeq(event,csv=True) def OnSaveSeqCSV(event): 'export all columns to a .csv file from menu command' OnSaveSelSeq(event,csv=True,allcols=True) def OnSaveSelSeq(event,csv=False,allcols=False): 'export the selected columns to a .txt or .csv file from menu command' def WriteCSV(): def WriteList(headerItems): line = '' for lbl in headerItems: if line: line += ',' line += '"'+lbl+'"' return line head = ['name'] for col in cols: item = G2frame.SeqTable.GetColLabelValue(col) # get rid of labels that have Unicode characters if not all([ord(c) < 128 and ord(c) != 0 for c in item]): item = '?' if col in havesig: head += [item,'esd-'+item] else: head += [item] SeqFile.write(WriteList(head)+'\n') for row,name in enumerate(saveNames): line = '"'+saveNames[row]+'"' for col in cols: if col in havesig: line += ','+str(saveData[col][row])+','+str(saveSigs[col][row]) else: line += ','+str(saveData[col][row]) SeqFile.write(line+'\n') def WriteSeq(): lenName = len(saveNames[0]) line = ' %s '%('name'.center(lenName)) for col in cols: item = G2frame.SeqTable.GetColLabelValue(col) if col in havesig: line += ' %12s %12s '%(item.center(12),'esd'.center(12)) else: line += ' %12s '%(item.center(12)) SeqFile.write(line+'\n') for row,name in enumerate(saveNames): line = " '%s' "%(saveNames[row]) for col in cols: if col in havesig: line += ' %12.6f %12.6f '%(saveData[col][row],saveSigs[col][row]) else: line += ' %12.6f '%saveData[col][row] SeqFile.write(line+'\n') # start of OnSaveSelSeq code if allcols: cols = range(G2frame.SeqTable.GetNumberCols()) else: cols = sorted(G2frame.dataDisplay.GetSelectedCols()) # ignore selection order nrows = G2frame.SeqTable.GetNumberRows() if not cols: G2frame.ErrorDialog('Select columns', 'No columns selected in table. Click on column labels to select fields for output.') return saveNames = [G2frame.SeqTable.GetRowLabelValue(r) for r in range(nrows)] saveData = {} saveSigs = {} havesig = [] for col in cols: name,vals,sigs = GetColumnInfo(col) saveData[col] = vals if sigs: havesig.append(col) saveSigs[col] = sigs if csv: wild = 'CSV output file (*.csv)|*.csv' else: wild = 'Text output file (*.txt)|*.txt' pth = G2G.GetExportPath(G2frame) dlg = wx.FileDialog( G2frame, 'Choose text output file for your selection', pth, '', wild,wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT) try: if dlg.ShowModal() == wx.ID_OK: SeqTextFile = dlg.GetPath() SeqTextFile = G2IO.FileDlgFixExt(dlg,SeqTextFile) SeqFile = open(SeqTextFile,'w') if csv: WriteCSV() else: WriteSeq() SeqFile.close() finally: dlg.Destroy() def striphist(var,insChar=''): 'strip a histogram number from a var name' sv = var.split(':') if len(sv) <= 1: return var if sv[1]: sv[1] = insChar return ':'.join(sv) def plotSpCharFix(lbl): 'Change selected unicode characters to their matplotlib equivalent' for u,p in [ (u'\u03B1',r'$\alpha$'), (u'\u03B2',r'$\beta$'), (u'\u03B3',r'$\gamma$'), (u'\u0394\u03C7',r'$\Delta\chi$'), ]: lbl = lbl.replace(u,p) return lbl def SelectXaxis(): 'returns a selected column number (or None) as the X-axis selection' ncols = G2frame.SeqTable.GetNumberCols() colNames = [G2frame.SeqTable.GetColLabelValue(r) for r in range(ncols)] dlg = G2G.G2SingleChoiceDialog( G2frame.dataDisplay, 'Select x-axis parameter for plot or Cancel for sequence number', 'Select X-axis', colNames) try: if dlg.ShowModal() == wx.ID_OK: col = dlg.GetSelection() else: col = None finally: dlg.Destroy() return col def EnablePseudoVarMenus(): 'Enables or disables the PseudoVar menu items that require existing defs' if data['SeqPseudoVars']: val = True else: val = False G2frame.dataWindow.SequentialPvars.Enable(G2G.wxID_DELSEQVAR,val) G2frame.dataWindow.SequentialPvars.Enable(G2G.wxID_EDITSEQVAR,val) def DelPseudoVar(event): 'Ask the user to select a pseudo var expression to delete' choices = data['SeqPseudoVars'].keys() selected = G2G.ItemSelector( choices,G2frame, multiple=True, title='Select expressions to remove', header='Delete expression') if selected is None: return for item in selected: del data['SeqPseudoVars'][choices[item]] if selected: UpdateSeqResults(G2frame,data,G2frame.dataDisplay.GetSize()) # redisplay variables def EditPseudoVar(event): 'Edit an existing pseudo var expression' choices = data['SeqPseudoVars'].keys() if len(choices) == 1: selected = 0 else: selected = G2G.ItemSelector( choices,G2frame, multiple=False, title='Select an expression to edit', header='Edit expression') if selected is not None: dlg = G2exG.ExpressionDialog( G2frame.dataDisplay,PSvarDict, data['SeqPseudoVars'][choices[selected]], header="Edit the PseudoVar expression", VarLabel="PseudoVar #"+str(selected+1), fit=False) newobj = dlg.Show(True) if newobj: calcobj = G2obj.ExpressionCalcObj(newobj) del data['SeqPseudoVars'][choices[selected]] data['SeqPseudoVars'][calcobj.eObj.expression] = newobj UpdateSeqResults(G2frame,data,G2frame.dataDisplay.GetSize()) # redisplay variables def AddNewPseudoVar(event): 'Create a new pseudo var expression' dlg = G2exG.ExpressionDialog(G2frame.dataDisplay,PSvarDict, header='Enter an expression for a PseudoVar here', VarLabel = "New PseudoVar",fit=False) obj = dlg.Show(True) dlg.Destroy() if obj: calcobj = G2obj.ExpressionCalcObj(obj) data['SeqPseudoVars'][calcobj.eObj.expression] = obj UpdateSeqResults(G2frame,data,G2frame.dataDisplay.GetSize()) # redisplay variables def AddNewDistPseudoVar(event): obj = None dlg = G2exG.BondDialog( G2frame.dataDisplay,Phases,PSvarDict, header='Select a Bond here', VarLabel = "New Bond") if dlg.ShowModal() == wx.ID_OK: pName,Oatom,Tatom = dlg.GetSelection() if Tatom: Phase = Phases[pName] General = Phase['General'] cx,ct = General['AtomPtrs'][:2] pId = Phase['pId'] SGData = General['SGData'] sB = Tatom.find('(')+1 symNo = 0 if sB: sF = Tatom.find(')') symNo = int(Tatom[sB:sF]) cellNo = [0,0,0] cB = Tatom.find('[') if cB>0: cF = Tatom.find(']')+1 cellNo = eval(Tatom[cB:cF]) Atoms = Phase['Atoms'] aNames = [atom[ct-1] for atom in Atoms] oId = aNames.index(Oatom) tId = aNames.index(Tatom.split(' +')[0]) # create an expression object obj = G2obj.ExpressionObj() obj.expression = 'Dist(%s,\n%s)'%(Oatom,Tatom.split(' d=')[0].replace(' ','')) obj.distance_dict = {'pId':pId,'SGData':SGData,'symNo':symNo,'cellNo':cellNo} obj.distance_atoms = [oId,tId] else: dlg.Destroy() return dlg.Destroy() if obj: data['SeqPseudoVars'][obj.expression] = obj UpdateSeqResults(G2frame,data,G2frame.dataDisplay.GetSize()) # redisplay variables def AddNewAnglePseudoVar(event): obj = None dlg = G2exG.AngleDialog( G2frame.dataDisplay,Phases,PSvarDict, header='Enter an Angle here', VarLabel = "New Angle") if dlg.ShowModal() == wx.ID_OK: pName,Oatom,Tatoms = dlg.GetSelection() if Tatoms: Phase = Phases[pName] General = Phase['General'] cx,ct = General['AtomPtrs'][:2] pId = Phase['pId'] SGData = General['SGData'] Atoms = Phase['Atoms'] aNames = [atom[ct-1] for atom in Atoms] tIds = [] symNos = [] cellNos = [] oId = aNames.index(Oatom) Tatoms = Tatoms.split(';') for Tatom in Tatoms: sB = Tatom.find('(')+1 symNo = 0 if sB: sF = Tatom.find(')') symNo = int(Tatom[sB:sF]) symNos.append(symNo) cellNo = [0,0,0] cB = Tatom.find('[') if cB>0: cF = Tatom.find(']')+1 cellNo = eval(Tatom[cB:cF]) cellNos.append(cellNo) tIds.append(aNames.index(Tatom.split('+')[0])) # create an expression object obj = G2obj.ExpressionObj() obj.expression = 'Angle(%s,%s,\n%s)'%(Tatoms[0],Oatom,Tatoms[1]) obj.angle_dict = {'pId':pId,'SGData':SGData,'symNo':symNos,'cellNo':cellNos} obj.angle_atoms = [oId,tIds] else: dlg.Destroy() return dlg.Destroy() if obj: data['SeqPseudoVars'][obj.expression] = obj UpdateSeqResults(G2frame,data,G2frame.dataDisplay.GetSize()) # redisplay variables def UpdateParmDict(parmDict): '''generate the atom positions and the direct & reciprocal cell values, because they might be needed to evaluate the pseudovar ''' Ddict = dict(zip(['D11','D22','D33','D12','D13','D23'], ['A'+str(i) for i in range(6)]) ) delList = [] phaselist = [] for item in parmDict: if ':' not in item: continue key = item.split(':') if len(key) < 3: continue # remove the dA[xyz] terms, they would only bring confusion if key[0] and key[0] not in phaselist: phaselist.append(key[0]) if key[2].startswith('dA'): delList.append(item) # compute and update the corrected reciprocal cell terms using the Dij values elif key[2] in Ddict: akey = key[0]+'::'+Ddict[key[2]] parmDict[akey] -= parmDict[item] delList.append(item) for item in delList: del parmDict[item] for i in phaselist: pId = int(i) # apply cell symmetry A,zeros = G2stIO.cellFill(str(pId)+'::',SGdata[pId],parmDict,zeroDict[pId]) # convert to direct cell & add the unique terms to the dictionary for i,val in enumerate(G2lat.A2cell(A)): if i in uniqCellIndx[pId]: lbl = str(pId)+'::'+cellUlbl[i] parmDict[lbl] = val lbl = str(pId)+'::'+'Vol' parmDict[lbl] = G2lat.calc_V(A) return parmDict def EvalPSvarDeriv(calcobj,parmDict,sampleDict,var,ESD): '''Evaluate an expression derivative with respect to a GSAS-II variable name. Note this likely could be faster if the loop over calcobjs were done inside after the Dict was created. ''' if not ESD: return 0. step = ESD/10 Ddict = dict(zip(['D11','D22','D33','D12','D13','D23'], ['A'+str(i) for i in range(6)]) ) results = [] phaselist = [] VparmDict = sampleDict.copy() for incr in step,-step: VparmDict.update(parmDict.copy()) # as saved, the parmDict has updated 'A[xyz]' values, but 'dA[xyz]' # values are not zeroed: fix that! VparmDict.update({item:0.0 for item in parmDict if 'dA' in item}) VparmDict[var] += incr G2mv.Dict2Map(VparmDict,[]) # apply constraints # generate the atom positions and the direct & reciprocal cell values now, because they might # needed to evaluate the pseudovar for item in VparmDict: if item in sampleDict: continue if ':' not in item: continue key = item.split(':') if len(key) < 3: continue # apply any new shifts to atom positions if key[2].startswith('dA'): VparmDict[''.join(item.split('d'))] += VparmDict[item] VparmDict[item] = 0.0 # compute and update the corrected reciprocal cell terms using the Dij values if key[2] in Ddict: if key[0] not in phaselist: phaselist.append(key[0]) akey = key[0]+'::'+Ddict[key[2]] VparmDict[akey] -= VparmDict[item] for i in phaselist: pId = int(i) # apply cell symmetry A,zeros = G2stIO.cellFill(str(pId)+'::',SGdata[pId],VparmDict,zeroDict[pId]) # convert to direct cell & add the unique terms to the dictionary for i,val in enumerate(G2lat.A2cell(A)): if i in uniqCellIndx[pId]: lbl = str(pId)+'::'+cellUlbl[i] VparmDict[lbl] = val lbl = str(pId)+'::'+'Vol' VparmDict[lbl] = G2lat.calc_V(A) # dict should be fully updated, use it & calculate calcobj.SetupCalc(VparmDict) results.append(calcobj.EvalExpression()) if None in results: return None return (results[0] - results[1]) / (2.*step) def EnableParFitEqMenus(): 'Enables or disables the Parametric Fit menu items that require existing defs' if data['SeqParFitEqList']: val = True else: val = False G2frame.dataWindow.SequentialPfit.Enable(G2G.wxID_DELPARFIT,val) G2frame.dataWindow.SequentialPfit.Enable(G2G.wxID_EDITPARFIT,val) G2frame.dataWindow.SequentialPfit.Enable(G2G.wxID_DOPARFIT,val) def ParEqEval(Values,calcObjList,varyList): '''Evaluate the parametric expression(s) :param list Values: a list of values for each variable parameter :param list calcObjList: a list of :class:`GSASIIobj.ExpressionCalcObj` expression objects to evaluate :param list varyList: a list of variable names for each value in Values ''' result = [] for calcobj in calcObjList: calcobj.UpdateVars(varyList,Values) if calcobj.depSig: result.append((calcobj.depVal-calcobj.EvalExpression())/calcobj.depSig) else: result.append(calcobj.depVal-calcobj.EvalExpression()) return result def DoParEqFit(event,eqObj=None): 'Parametric fit minimizer' varyValueDict = {} # dict of variables and their initial values calcObjList = [] # expression objects, ready to go for each data point if eqObj is not None: eqObjList = [eqObj,] else: eqObjList = data['SeqParFitEqList'] UseFlags = G2frame.SeqTable.GetColValues(0) for obj in eqObjList: # assemble refined vars for this equation varyValueDict.update({var:val for var,val in obj.GetVariedVarVal()}) # lookup dependent var position depVar = obj.GetDepVar() if depVar in colLabels: indx = colLabels.index(depVar) else: raise Exception('Dependent variable '+depVar+' not found') # assemble a list of the independent variables indepVars = obj.GetIndependentVars() # loop over each datapoint for j,row in enumerate(zip(*G2frame.colList)): if not UseFlags[j]: continue # assemble equations to fit calcobj = G2obj.ExpressionCalcObj(obj) # prepare a dict of needed independent vars for this expression indepVarDict = {var:row[i] for i,var in enumerate(colLabels) if var in indepVars} calcobj.SetupCalc(indepVarDict) # values and sigs for current value of dependent var if row[indx] is None: continue calcobj.depVal = row[indx] calcobj.depSig = G2frame.colSigs[indx][j] calcObjList.append(calcobj) # varied parameters varyList = varyValueDict.keys() values = varyValues = [varyValueDict[key] for key in varyList] if not varyList: print 'no variables to refine!' return try: result = so.leastsq(ParEqEval,varyValues,full_output=True, #ftol=Ftol, args=(calcObjList,varyList)) values = result[0] covar = result[1] if covar is None: raise Exception chisq = np.sum(result[2]['fvec']**2) GOF = np.sqrt(chisq/(len(calcObjList)-len(varyList))) esdDict = {} for i,avar in enumerate(varyList): esdDict[avar] = np.sqrt(covar[i,i]) except: print('====> Fit failed') return print('==== Fit Results ====') print ' chisq = %.2f, GOF = %.2f'%(chisq,GOF) for obj in eqObjList: obj.UpdateVariedVars(varyList,values) ind = ' ' print(' '+obj.GetDepVar()+' = '+obj.expression) for var in obj.assgnVars: print(ind+var+' = '+obj.assgnVars[var]) for var in obj.freeVars: avar = "::"+obj.freeVars[var][0] val = obj.freeVars[var][1] if obj.freeVars[var][2]: print(ind+var+' = '+avar + " = " + G2mth.ValEsd(val,esdDict[avar])) else: print(ind+var+' = '+avar + " =" + G2mth.ValEsd(val,0)) # create a plot for each parametric variable for fitnum,obj in enumerate(eqObjList): calcobj = G2obj.ExpressionCalcObj(obj) # lookup dependent var position indx = colLabels.index(obj.GetDepVar()) # assemble a list of the independent variables indepVars = obj.GetIndependentVars() # loop over each datapoint fitvals = [] for j,row in enumerate(zip(*G2frame.colList)): calcobj.SetupCalc({var:row[i] for i,var in enumerate(colLabels) if var in indepVars}) fitvals.append(calcobj.EvalExpression()) G2plt.PlotSelectedSequence(G2frame,[indx],GetColumnInfo,SelectXaxis,fitnum,fitvals) def SingleParEqFit(eqObj): DoParEqFit(None,eqObj) def DelParFitEq(event): 'Ask the user to select function to delete' txtlst = [obj.GetDepVar()+' = '+obj.expression for obj in data['SeqParFitEqList']] selected = G2G.ItemSelector( txtlst,G2frame, multiple=True, title='Select a parametric equation(s) to remove', header='Delete equation') if selected is None: return data['SeqParFitEqList'] = [obj for i,obj in enumerate(data['SeqParFitEqList']) if i not in selected] EnableParFitEqMenus() if data['SeqParFitEqList']: DoParEqFit(event) def EditParFitEq(event): 'Edit an existing parametric equation' txtlst = [obj.GetDepVar()+' = '+obj.expression for obj in data['SeqParFitEqList']] if len(txtlst) == 1: selected = 0 else: selected = G2G.ItemSelector( txtlst,G2frame, multiple=False, title='Select a parametric equation to edit', header='Edit equation') if selected is not None: dlg = G2exG.ExpressionDialog(G2frame.dataDisplay,VarDict, data['SeqParFitEqList'][selected],depVarDict=VarDict, header="Edit the formula for this minimization function", ExtraButton=['Fit',SingleParEqFit]) newobj = dlg.Show(True) if newobj: data['SeqParFitEqList'][selected] = newobj EnableParFitEqMenus() if data['SeqParFitEqList']: DoParEqFit(event) def AddNewParFitEq(event): 'Create a new parametric equation to be fit to sequential results' # compile the variable names used in previous freevars to avoid accidental name collisions usedvarlist = [] for obj in data['SeqParFitEqList']: for var in obj.freeVars: if obj.freeVars[var][0] not in usedvarlist: usedvarlist.append(obj.freeVars[var][0]) dlg = G2exG.ExpressionDialog(G2frame.dataDisplay,VarDict,depVarDict=VarDict, header='Define an equation to minimize in the parametric fit', ExtraButton=['Fit',SingleParEqFit],usedVars=usedvarlist) obj = dlg.Show(True) dlg.Destroy() if obj: data['SeqParFitEqList'].append(obj) EnableParFitEqMenus() if data['SeqParFitEqList']: DoParEqFit(event) def CopyParFitEq(event): 'Copy an existing parametric equation to be fit to sequential results' # compile the variable names used in previous freevars to avoid accidental name collisions usedvarlist = [] for obj in data['SeqParFitEqList']: for var in obj.freeVars: if obj.freeVars[var][0] not in usedvarlist: usedvarlist.append(obj.freeVars[var][0]) txtlst = [obj.GetDepVar()+' = '+obj.expression for obj in data['SeqParFitEqList']] if len(txtlst) == 1: selected = 0 else: selected = G2G.ItemSelector( txtlst,G2frame, multiple=False, title='Select a parametric equation to copy', header='Copy equation') if selected is not None: newEqn = copy.deepcopy(data['SeqParFitEqList'][selected]) for var in newEqn.freeVars: newEqn.freeVars[var][0] = G2obj.MakeUniqueLabel(newEqn.freeVars[var][0],usedvarlist) dlg = G2exG.ExpressionDialog( G2frame.dataDisplay,VarDict,newEqn,depVarDict=VarDict, header="Edit the formula for this minimization function", ExtraButton=['Fit',SingleParEqFit]) newobj = dlg.Show(True) if newobj: data['SeqParFitEqList'].append(newobj) EnableParFitEqMenus() if data['SeqParFitEqList']: DoParEqFit(event) def GridSetToolTip(row,col): '''Routine to show standard uncertainties for each element in table as a tooltip ''' if G2frame.colSigs[col]: return u'\u03c3 = '+str(G2frame.colSigs[col][row]) return '' def GridColLblToolTip(col): '''Define a tooltip for a column. This will be the user-entered value (from data['variableLabels']) or the default name ''' if col < 0 or col > len(colLabels): print 'Illegal column #',col return var = colLabels[col] return variableLabels.get(var,G2obj.fmtVarDescr(var)) def SetLabelString(event): '''Define or edit the label for a column in the table, to be used as a tooltip and for plotting ''' col = event.GetCol() if col < 0 or col > len(colLabels): return var = colLabels[col] lbl = variableLabels.get(var,G2obj.fmtVarDescr(var)) dlg = G2G.SingleStringDialog(G2frame,'Set variable label', 'Set a new name for variable '+var,lbl,size=(400,-1)) if dlg.Show(): variableLabels[var] = dlg.GetValue() dlg.Destroy() def DoSequentialExport(event): '''Event handler for all Sequential Export menu items ''' vals = G2frame.dataWindow.SeqExportLookup.get(event.GetId()) if vals is None: print('Error: Id not found. This should not happen!') G2IO.ExportSequential(G2frame,data,*vals) def onSelectSeqVars(event): '''Select which variables will be shown in table''' dlg = G2G.G2MultiChoiceDialog(G2frame, 'Select columns to hide', 'Hide columns',colLabels[1:]) if dlg.ShowModal() == wx.ID_OK: G2frame.SeqTblHideList = [colLabels[1:][sel] for sel in dlg.GetSelections()] dlg.Destroy() UpdateSeqResults(G2frame,data,G2frame.dataDisplay.GetSize()) # redisplay variables else: dlg.Destroy() #def GridRowLblToolTip(row): return 'Row ='+str(row) # lookup table for unique cell parameters by symmetry cellGUIlist = [ [['m3','m3m'],(0,)], [['3R','3mR'],(0,3)], [['3','3m1','31m','6/m','6/mmm','4/m','4/mmm'],(0,2)], [['mmm'],(0,1,2)], [['2/m'+'a'],(0,1,2,3)], [['2/m'+'b'],(0,1,2,4)], [['2/m'+'c'],(0,1,2,5)], [['-1'],(0,1,2,3,4,5)], ] # cell labels cellUlbl = ('a','b','c',u'\u03B1',u'\u03B2',u'\u03B3') # unicode a,b,c,alpha,beta,gamma #====================================================================== # start processing sequential results here (UpdateSeqResults) #====================================================================== if not data: print 'No sequential refinement results' return variableLabels = data.get('variableLabels',{}) data['variableLabels'] = variableLabels Histograms,Phases = G2frame.GetUsedHistogramsAndPhasesfromTree() Controls = G2frame.GPXtree.GetItemPyData(GetGPXtreeItemId(G2frame,G2frame.root,'Controls')) # create a place to store Pseudo Vars & Parametric Fit functions, if not present if 'SeqPseudoVars' not in data: data['SeqPseudoVars'] = {} if 'SeqParFitEqList' not in data: data['SeqParFitEqList'] = [] histNames = data['histNames'] if G2frame.dataDisplay: G2frame.dataDisplay.Destroy() G2frame.GetStatusBar().SetStatusText("Select column to export; Double click on column to plot data; on row for Covariance",1) sampleParms = GetSampleParms() # make dict of varied atom coords keyed by absolute position newAtomDict = data[histNames[0]].get('newAtomDict',{}) # dict with atom positions; relative & absolute # Possible error: the next might need to be data[histNames[0]]['varyList'] # error will arise if there constraints on coordinates? atomLookup = {newAtomDict[item][0]:item for item in newAtomDict if item in data['varyList']} # make dict of varied cell parameters equivalents ESDlookup = {} # provides the Dij term for each Ak term (where terms are refined) Dlookup = {} # provides the Ak term for each Dij term (where terms are refined) # N.B. These Dij vars are missing a histogram # newCellDict = {} for name in histNames: if name in data and 'newCellDict' in data[name]: newCellDict.update(data[name]['newCellDict']) cellAlist = [] for item in newCellDict: cellAlist.append(newCellDict[item][0]) if item in data.get('varyList',[]): ESDlookup[newCellDict[item][0]] = item Dlookup[item] = newCellDict[item][0] # add coordinate equivalents to lookup table for parm in atomLookup: Dlookup[atomLookup[parm]] = parm ESDlookup[parm] = atomLookup[parm] # get unit cell & symmetry for all phases & initial stuff for later use RecpCellTerms = {} SGdata = {} uniqCellIndx = {} initialCell = {} RcellLbls = {} zeroDict = {} for phase in Phases: phasedict = Phases[phase] pId = phasedict['pId'] pfx = str(pId)+'::' # prefix for A values from phase RcellLbls[pId] = [pfx+'A'+str(i) for i in range(6)] RecpCellTerms[pId] = G2lat.cell2A(phasedict['General']['Cell'][1:7]) zeroDict[pId] = dict(zip(RcellLbls[pId],6*[0.,])) SGdata[pId] = phasedict['General']['SGData'] laue = SGdata[pId]['SGLaue'] if laue == '2/m': laue += SGdata[pId]['SGUniq'] for symlist,celllist in cellGUIlist: if laue in symlist: uniqCellIndx[pId] = celllist break else: # should not happen uniqCellIndx[pId] = range(6) for i in uniqCellIndx[pId]: initialCell[str(pId)+'::A'+str(i)] = RecpCellTerms[pId][i] SetDataMenuBar(G2frame,G2frame.dataWindow.SequentialMenu) #G2frame.dataWindow.SetLabel(G2frame.GetLabel().split('||')[0]+' || '+'Sequential refinement results') G2frame.SetTitle('Sequential refinement results') G2frame.GetStatusBar().SetStatusText('',1) G2frame.Bind(wx.EVT_MENU, OnSelectUse, id=G2G.wxID_SELECTUSE) G2frame.Bind(wx.EVT_MENU, OnRenameSelSeq, id=G2G.wxID_RENAMESEQSEL) G2frame.Bind(wx.EVT_MENU, OnSaveSelSeq, id=G2G.wxID_SAVESEQSEL) G2frame.Bind(wx.EVT_MENU, OnSaveSelSeqCSV, id=G2G.wxID_SAVESEQSELCSV) G2frame.Bind(wx.EVT_MENU, OnSaveSeqCSV, id=G2G.wxID_SAVESEQCSV) G2frame.Bind(wx.EVT_MENU, OnPlotSelSeq, id=G2G.wxID_PLOTSEQSEL) G2frame.Bind(wx.EVT_MENU, OnAveSelSeq, id=G2G.wxID_AVESEQSEL) #G2frame.Bind(wx.EVT_MENU, OnReOrgSelSeq, id=G2G.wxID_ORGSEQSEL) G2frame.Bind(wx.EVT_MENU, onSelectSeqVars, id=G2G.wxID_ORGSEQINC) G2frame.Bind(wx.EVT_MENU, AddNewPseudoVar, id=G2G.wxID_ADDSEQVAR) G2frame.Bind(wx.EVT_MENU, AddNewDistPseudoVar, id=G2G.wxID_ADDSEQDIST) G2frame.Bind(wx.EVT_MENU, AddNewAnglePseudoVar, id=G2G.wxID_ADDSEQANGLE) G2frame.Bind(wx.EVT_MENU, DelPseudoVar, id=G2G.wxID_DELSEQVAR) G2frame.Bind(wx.EVT_MENU, EditPseudoVar, id=G2G.wxID_EDITSEQVAR) G2frame.Bind(wx.EVT_MENU, AddNewParFitEq, id=G2G.wxID_ADDPARFIT) G2frame.Bind(wx.EVT_MENU, CopyParFitEq, id=G2G.wxID_COPYPARFIT) G2frame.Bind(wx.EVT_MENU, DelParFitEq, id=G2G.wxID_DELPARFIT) G2frame.Bind(wx.EVT_MENU, EditParFitEq, id=G2G.wxID_EDITPARFIT) G2frame.Bind(wx.EVT_MENU, DoParEqFit, id=G2G.wxID_DOPARFIT) for id in G2frame.dataWindow.SeqExportLookup: G2frame.Bind(wx.EVT_MENU, DoSequentialExport, id=id) EnablePseudoVarMenus() EnableParFitEqMenus() # scan for locations where the variables change VaryListChanges = [] # histograms where there is a change combinedVaryList = [] firstValueDict = {} vallookup = {} posdict = {} prevVaryList = [] foundNames = [] missing = 0 for i,name in enumerate(histNames): if name not in data: if missing < 5: print(" Warning: "+name+" not found") elif missing == 5: print ' Warning: more are missing' missing += 1 continue foundNames.append(name) maxPWL = 5 for var,val,sig in zip(data[name]['varyList'],data[name]['variables'],data[name]['sig']): svar = striphist(var,'*') # wild-carded if 'PWL' in svar: if int(svar.split(':')[-1]) > maxPWL: continue if svar not in combinedVaryList: # add variables to list as they appear combinedVaryList.append(svar) firstValueDict[svar] = (val,sig) if prevVaryList != data[name]['varyList']: # this refinement has a different refinement list from previous prevVaryList = data[name]['varyList'] vallookup[name] = dict(zip(data[name]['varyList'],data[name]['variables'])) posdict[name] = {} for var in data[name]['varyList']: svar = striphist(var,'*') if 'PWL' in svar: if int(svar.split(':')[-1]) > maxPWL: continue posdict[name][combinedVaryList.index(svar)] = svar VaryListChanges.append(name) if missing: print ' Warning: Total of %d data sets missing from sequential results'%(missing) #if len(VaryListChanges) > 1: # G2frame.dataWindow.SequentialFile.Enable(G2G.wxID_ORGSEQSEL,True) #else: # G2frame.dataWindow.SequentialFile.Enable(G2G.wxID_ORGSEQSEL,False) #----------------------------------------------------------------------------------- # build up the data table by columns ----------------------------------------------- histNames = foundNames nRows = len(histNames) G2frame.colList = [nRows*[True]] G2frame.colSigs = [None,] colLabels = ['Use',] Types = [wg.GRID_VALUE_BOOL,] # start with Rwp values if 'IMG ' not in histNames[0][:4]: G2frame.colList += [[data[name]['Rvals']['Rwp'] for name in histNames]] G2frame.colSigs += [None] colLabels += ['Rwp'] Types += [wg.GRID_VALUE_FLOAT+':10,3',] # add % change in Chi^2 in last cycle if histNames[0][:4] not in ['SASD','IMG ','REFD'] and Controls.get('ShowCell'): G2frame.colList += [[100.*data[name]['Rvals'].get('DelChi2',-1) for name in histNames]] G2frame.colSigs += [None] colLabels += [u'\u0394\u03C7\u00B2 (%)'] Types += [wg.GRID_VALUE_FLOAT+':10,5',] deltaChiCol = len(colLabels)-1 # add changing sample parameters to table for key in sampleParms: G2frame.colList += [sampleParms[key]] G2frame.colSigs += [None] colLabels += [key] Types += [wg.GRID_VALUE_FLOAT,] sampleDict = {} for i,name in enumerate(histNames): sampleDict[name] = dict(zip(sampleParms.keys(),[sampleParms[key][i] for key in sampleParms.keys()])) # add unique cell parameters TODO: review this where the cell symmetry changes (when possible) if Controls.get('ShowCell',False) and len(newCellDict): for pId in sorted(RecpCellTerms): pfx = str(pId)+'::' # prefix for A values from phase cells = [] cellESDs = [] colLabels += [pfx+cellUlbl[i] for i in uniqCellIndx[pId]] colLabels += [pfx+'Vol'] Types += (len(uniqCellIndx[pId]))*[wg.GRID_VALUE_FLOAT+':10,5',] Types += [wg.GRID_VALUE_FLOAT+':10,3',] Albls = [pfx+'A'+str(i) for i in range(6)] for name in histNames: hId = Histograms[name]['hId'] phfx = '%d:%d:'%(pId,hId) esdLookUp = {} dLookup = {} for item in data[name]['newCellDict']: if phfx+item.split('::')[1] in data[name]['varyList']: esdLookUp[newCellDict[item][0]] = item dLookup[item] = newCellDict[item][0] covData = {'varyList': [dLookup.get(striphist(v),v) for v in data[name]['varyList']], 'covMatrix': data[name]['covMatrix']} A = RecpCellTerms[pId][:] # make copy of starting A values # update with refined values for i in range(6): var = str(pId)+'::A'+str(i) if var in cellAlist: try: val = data[name]['newCellDict'][esdLookUp[var]][1] # get refined value A[i] = val # override with updated value except KeyError: A[i] = None # apply symmetry cellDict = dict(zip(Albls,A)) if None in A: c = 6*[None] cE = 6*[None] vol = None else: A,zeros = G2stIO.cellFill(pfx,SGdata[pId],cellDict,zeroDict[pId]) # convert to direct cell & add only unique values to table c = G2lat.A2cell(A) vol = G2lat.calc_V(A) cE = G2stIO.getCellEsd(pfx,SGdata[pId],A,covData) cells += [[c[i] for i in uniqCellIndx[pId]]+[vol]] cellESDs += [[cE[i] for i in uniqCellIndx[pId]]+[cE[-1]]] G2frame.colList += zip(*cells) G2frame.colSigs += zip(*cellESDs) # sort out the variables in their selected order varcols = 0 for d in posdict.itervalues(): varcols = max(varcols,max(d.keys())+1) # get labels for each column for i in range(varcols): lbl = '' for h in VaryListChanges: if posdict[h].get(i): if posdict[h].get(i) in lbl: continue if lbl != "": lbl += '/' lbl += posdict[h].get(i) colLabels.append(lbl) Types += varcols*[wg.GRID_VALUE_FLOAT,] vals = [] esds = [] varsellist = None # will be a list of variable names in the order they are selected to appear # tabulate values for each hist, leaving None for blank columns for name in histNames: if name in posdict: varsellist = [posdict[name].get(i) for i in range(varcols)] # translate variable names to how they will be used in the headings vs = [striphist(v,'*') for v in data[name]['varyList']] # determine the index for each column (or None) in the data[]['variables'] and ['sig'] lists sellist = [vs.index(v) if v is not None else None for v in varsellist] #sellist = [i if striphist(v,'*') in varsellist else None for i,v in enumerate(data[name]['varyList'])] if not varsellist: raise Exception() vals.append([data[name]['variables'][s] if s is not None else None for s in sellist]) esds.append([data[name]['sig'][s] if s is not None else None for s in sellist]) #GSASIIpath.IPyBreak() G2frame.colList += zip(*vals) G2frame.colSigs += zip(*esds) # compute and add weight fractions to table if varied for phase in Phases: var = str(Phases[phase]['pId'])+':*:Scale' if var not in combinedVaryList: continue wtFrList = [] sigwtFrList = [] for i,name in enumerate(histNames): if name not in Phases[phase]['Histograms']: wtFrList.append(None) sigwtFrList.append(0.0) continue wtFrSum = 0. for phase1 in Phases: if name not in Phases[phase1]['Histograms']: continue wtFrSum += Phases[phase1]['Histograms'][name]['Scale'][0]*Phases[phase1]['General']['Mass'] var = str(Phases[phase]['pId'])+':'+str(i)+':Scale' wtFr = Phases[phase]['Histograms'][name]['Scale'][0]*Phases[phase]['General']['Mass']/wtFrSum wtFrList.append(wtFr) if var in data[name]['varyList']: sig = data[name]['sig'][data[name]['varyList'].index(var)]*wtFr/Phases[phase]['Histograms'][name]['Scale'][0] else: sig = 0.0 sigwtFrList.append(sig) colLabels.append(str(Phases[phase]['pId'])+':*:WgtFrac') Types += [wg.GRID_VALUE_FLOAT+':10,5',] G2frame.colList += [wtFrList] G2frame.colSigs += [sigwtFrList] # tabulate constrained variables, removing histogram numbers if needed # from parameter label depValDict = {} depSigDict = {} for name in histNames: for var in data[name].get('depParmDict',{}): val,sig = data[name]['depParmDict'][var] svar = striphist(var,'*') if svar not in depValDict: depValDict[svar] = [val] depSigDict[svar] = [sig] else: depValDict[svar].append(val) depSigDict[svar].append(sig) # add the dependent constrained variables to the table for var in sorted(depValDict): if len(depValDict[var]) != len(histNames): continue colLabels.append(var) Types += [wg.GRID_VALUE_FLOAT+':10,5',] G2frame.colSigs += [depSigDict[var]] G2frame.colList += [depValDict[var]] # add atom parameters to table colLabels += atomLookup.keys() for parm in sorted(atomLookup): G2frame.colList += [[data[name]['newAtomDict'][atomLookup[parm]][1] for name in histNames]] Types += [wg.GRID_VALUE_FLOAT+':10,5',] if atomLookup[parm] in data[histNames[0]]['varyList']: col = data[histNames[0]]['varyList'].index(atomLookup[parm]) G2frame.colSigs += [[data[name]['sig'][col] for name in histNames]] else: G2frame.colSigs += [None] # evaluate Pseudovars, their ESDs and add them to grid for expr in data['SeqPseudoVars']: obj = data['SeqPseudoVars'][expr] calcobj = G2obj.ExpressionCalcObj(obj) valList = [] esdList = [] for seqnum,name in enumerate(histNames): sigs = data[name]['sig'] G2mv.InitVars() parmDict = data[name].get('parmDict') constraintInfo = data[name].get('constraintInfo',[[],[],{},[],seqnum]) groups,parmlist,constrDict,fixedList,ihst = constraintInfo varyList = data[name]['varyList'] parmDict = data[name]['parmDict'] G2mv.GenerateConstraints(groups,parmlist,varyList,constrDict,fixedList,parmDict,SeqHist=ihst) if 'Dist' in expr: derivs = G2mth.CalcDistDeriv(obj.distance_dict,obj.distance_atoms, parmDict) pId = obj.distance_dict['pId'] aId,bId = obj.distance_atoms varyNames = ['%d::dA%s:%d'%(pId,ip,aId) for ip in ['x','y','z']] varyNames += ['%d::dA%s:%d'%(pId,ip,bId) for ip in ['x','y','z']] VCoV = G2mth.getVCov(varyNames,varyList,data[name]['covMatrix']) esdList.append(np.sqrt(np.inner(derivs,np.inner(VCoV,derivs.T)) )) # GSASIIpath.IPyBreak() elif 'Angle' in expr: derivs = G2mth.CalcAngleDeriv(obj.angle_dict,obj.angle_atoms, parmDict) pId = obj.angle_dict['pId'] aId,bId = obj.angle_atoms varyNames = ['%d::dA%s:%d'%(pId,ip,aId) for ip in ['x','y','z']] varyNames += ['%d::dA%s:%d'%(pId,ip,bId[0]) for ip in ['x','y','z']] varyNames += ['%d::dA%s:%d'%(pId,ip,bId[1]) for ip in ['x','y','z']] VCoV = G2mth.getVCov(varyNames,varyList,data[name]['covMatrix']) esdList.append(np.sqrt(np.inner(derivs,np.inner(VCoV,derivs.T)) )) else: derivs = np.array( [EvalPSvarDeriv(calcobj,parmDict.copy(),sampleDict[name],var,ESD) for var,ESD in zip(varyList,sigs)]) if None in list(derivs): esdList.append(None) else: esdList.append(np.sqrt( np.inner(derivs,np.inner(data[name]['covMatrix'],derivs.T)) )) PSvarDict = parmDict.copy() PSvarDict.update(sampleDict[name]) UpdateParmDict(PSvarDict) calcobj.UpdateDict(PSvarDict) valList.append(calcobj.EvalExpression()) # if calcobj.su is not None: esdList[-1] = calcobj.su if not esdList: esdList = None G2frame.colList += [valList] G2frame.colSigs += [esdList] colLabels += [expr] Types += [wg.GRID_VALUE_FLOAT+':10,3'] #---- table build done ------------------------------------------------------------- # Make dict needed for creating & editing pseudovars (PSvarDict). name = histNames[0] parmDict = data[name].get('parmDict',{}) PSvarDict = parmDict.copy() PSvarDict.update(sampleParms) UpdateParmDict(PSvarDict) # Also dicts of variables # for Parametric fitting from the data table parmDict = dict(zip(colLabels,zip(*G2frame.colList)[0])) # scratch dict w/all values in table parmDict.update({var:val for var,val in newCellDict.values()}) # add varied reciprocal cell terms del parmDict['Use'] name = histNames[0] #****************************************************************************** # create a set of values for example evaluation of pseudovars and # this does not work for refinements that have differing numbers of variables. #raise Exception VarDict = {} for i,var in enumerate(colLabels): if var in ['Use','Rwp',u'\u0394\u03C7\u00B2 (%)']: continue if G2frame.colList[i][0] is None: val,sig = firstValueDict.get(var,[None,None]) elif G2frame.colSigs[i]: val,sig = G2frame.colList[i][0],G2frame.colSigs[i][0] else: val,sig = G2frame.colList[i][0],None # if val is None: continue # elif sig is None or sig == 0.: # VarDict[var] = val if striphist(var) not in Dlookup: VarDict[var] = val # add recip cell coeff. values VarDict.update({var:val for var,val in newCellDict.values()}) # remove items to be hidden from table for l in reversed(range(len(colLabels))): if colLabels[l] in G2frame.SeqTblHideList: del colLabels[l] del G2frame.colList[l] del G2frame.colSigs[l] G2frame.dataWindow.ClearData() G2frame.dataWindow.currentGrids = [] G2frame.dataDisplay = G2G.GSGrid(parent=G2frame.dataWindow) G2frame.dataWindow.GetSizer().Add(G2frame.dataDisplay,1,wx.ALL|wx.EXPAND) G2frame.SeqTable = G2G.Table([list(cl) for cl in zip(*G2frame.colList)], # convert from columns to rows colLabels=colLabels,rowLabels=histNames,types=Types) G2frame.dataDisplay.SetTable(G2frame.SeqTable, True) G2frame.dataDisplay.EnableEditing(False) # make all read-only # for c in range(len(colLabels)): # for r in range(nRows): # G2frame.dataDisplay.SetCellReadOnly(r,c) G2frame.dataDisplay.Bind(wg.EVT_GRID_LABEL_LEFT_CLICK, PlotSSelect) G2frame.dataDisplay.Bind(wg.EVT_GRID_LABEL_LEFT_DCLICK, PlotSelect) G2frame.dataDisplay.Bind(wg.EVT_GRID_LABEL_RIGHT_CLICK, SetLabelString) G2frame.dataDisplay.SetRowLabelSize(8*len(histNames[0])) #pretty arbitrary 8 G2frame.dataDisplay.SetMargins(0,0) G2frame.dataDisplay.AutoSizeColumns(False) # highlight unconverged shifts if histNames[0][:4] not in ['SASD','IMG ','REFD',]: for row,name in enumerate(histNames): deltaChi = G2frame.SeqTable.GetValue(row,deltaChiCol) if deltaChi > 10.: G2frame.dataDisplay.SetCellStyle(row,deltaChiCol,color=wx.Colour(255,0,0)) elif deltaChi > 1.0: G2frame.dataDisplay.SetCellStyle(row,deltaChiCol,color=wx.Colour(255,255,0)) G2frame.dataDisplay.InstallGridToolTip(GridSetToolTip,GridColLblToolTip) #G2frame.dataDisplay.SendSizeEvent() # resize needed on mac #G2frame.dataDisplay.Refresh() # shows colored text on mac G2frame.dataWindow.SetDataSize() ################################################################################ ##### Main PWDR panel ################################################################################ def UpdatePWHKPlot(G2frame,kind,item): '''Called when the histogram main tree entry is called. Displays the histogram weight factor, refinement statistics for the histogram and the range of data for a simulation. Also invokes a plot of the histogram. ''' def onEditSimRange(event): 'Edit simulation range' inp = [ min(data[1][0]), max(data[1][0]), None ] inp[2] = (inp[1] - inp[0])/(len(data[1][0])-1.) names = ('start angle', 'end angle', 'step size') dlg = G2G.ScrolledMultiEditor( G2frame,[inp] * len(inp), range(len(inp)), names, header='Edit simulation range', minvals=(0.001,0.001,0.0001), maxvals=(180.,180.,.1), ) dlg.CenterOnParent() val = dlg.ShowModal() dlg.Destroy() if val != wx.ID_OK: return if inp[0] > inp[1]: end,start,step = inp else: start,end,step = inp step = abs(step) N = int((end-start)/step)+1 newdata = np.linspace(start,end,N,True) if len(newdata) < 2: return # too small a range - reject data[1] = [newdata,np.zeros_like(newdata),np.ones_like(newdata), np.zeros_like(newdata),np.zeros_like(newdata),np.zeros_like(newdata)] Tmin = newdata[0] Tmax = newdata[-1] G2frame.GPXtree.SetItemPyData(GetGPXtreeItemId(G2frame,item,'Limits'), [(Tmin,Tmax),[Tmin,Tmax]]) UpdatePWHKPlot(G2frame,kind,item) # redisplay data screen def OnPlot3DHKL(event): refList = data[1]['RefList'] FoMax = np.max(refList.T[8+Super]) Hmin = np.array([int(np.min(refList.T[0])),int(np.min(refList.T[1])),int(np.min(refList.T[2]))]) Hmax = np.array([int(np.max(refList.T[0])),int(np.max(refList.T[1])),int(np.max(refList.T[2]))]) Vpoint = np.array([int(np.mean(refList.T[0])),int(np.mean(refList.T[1])),int(np.mean(refList.T[2]))]) controls = {'Type' : 'Fosq','Iscale' : False,'HKLmax' : Hmax,'HKLmin' : Hmin,'Zone':False,'viewKey':'L', 'FoMax' : FoMax,'Scale' : 1.0,'Drawing':{'viewPoint':[Vpoint,[]],'default':Vpoint[:], 'backColor':[0,0,0],'depthFog':False,'Zclip':10.0,'cameraPos':10.,'Zstep':0.05,'viewUp':[0,1,0], 'Scale':1.0,'oldxy':[],'viewDir':[0,0,1]},'Super':Super,'SuperVec':SuperVec} G2plt.Plot3DSngl(G2frame,newPlot=True,Data=controls,hklRef=refList,Title=phaseName) def OnPlotAll3DHKL(event): choices = GetGPXtreeDataNames(G2frame,['HKLF',]) dlg = G2G.G2MultiChoiceDialog(G2frame, 'Select reflection sets to plot', 'Use data',choices) try: if dlg.ShowModal() == wx.ID_OK: refNames = [choices[i] for i in dlg.GetSelections()] else: return finally: dlg.Destroy() refList = np.zeros(0) for name in refNames: Id = GetGPXtreeItemId(G2frame,G2frame.root, name) reflData = G2frame.GPXtree.GetItemPyData(Id)[1] if len(refList): refList = np.concatenate((refList,reflData['RefList'])) else: refList = reflData['RefList'] FoMax = np.max(refList.T[8+Super]) Hmin = np.array([int(np.min(refList.T[0])),int(np.min(refList.T[1])),int(np.min(refList.T[2]))]) Hmax = np.array([int(np.max(refList.T[0])),int(np.max(refList.T[1])),int(np.max(refList.T[2]))]) Vpoint = [int(np.mean(refList.T[0])),int(np.mean(refList.T[1])),int(np.mean(refList.T[2]))] controls = {'Type' : 'Fosq','Iscale' : False,'HKLmax' : Hmax,'HKLmin' : Hmin,'Zone':False,'viewKey':'L', 'FoMax' : FoMax,'Scale' : 1.0,'Drawing':{'viewPoint':[Vpoint,[]],'default':Vpoint[:], 'backColor':[0,0,0],'depthFog':False,'Zclip':10.0,'cameraPos':10.,'Zstep':0.05,'viewUp':[0,1,0], 'Scale':1.0,'oldxy':[],'viewDir':[1,0,0]},'Super':Super,'SuperVec':SuperVec} G2plt.Plot3DSngl(G2frame,newPlot=True,Data=controls,hklRef=refList,Title=phaseName) def OnMergeHKL(event): Name = G2frame.GPXtree.GetItemText(G2frame.PatternId) Inst = G2frame.GPXtree.GetItemPyData(GetGPXtreeItemId(G2frame, G2frame.PatternId,'Instrument Parameters')) CId = GetGPXtreeItemId(G2frame,G2frame.PatternId,'Comments') if CId: Comments = G2frame.GPXtree.GetItemPyData(CId) else: Comments = [] refList = np.copy(data[1]['RefList']) Comments.append(' Merging %d reflections from %s'%(len(refList),Name)) dlg = MergeDialog(G2frame,data) try: if dlg.ShowModal() == wx.ID_OK: Trans,Cent,Laue = dlg.GetSelection() else: return finally: dlg.Destroy() Super = data[1]['Super'] refList,badRefs = G2lat.transposeHKLF(Trans,Super,refList) if len(badRefs): #do I want to list badRefs? G2frame.ErrorDialog('Failed transformation','Matrix yields fractional hkl indices') return Comments.append(" Transformation M*H = H' applied; M=") Comments.append(str(Trans)) refList = G2lat.LaueUnique(Laue,refList) dlg = wx.ProgressDialog('Build HKL dictonary','',len(refList)+1, style = wx.PD_ELAPSED_TIME|wx.PD_AUTO_HIDE) HKLdict = {} for ih,hkl in enumerate(refList): if str(hkl[:3+Super]) not in HKLdict: HKLdict[str(hkl[:3+Super])] = [hkl[:3+Super],[hkl[3+Super:],]] else: HKLdict[str(hkl[:3+Super])][1].append(hkl[3+Super:]) dlg.Update(ih) dlg.Destroy() mergeRef = [] dlg = wx.ProgressDialog('Processing merge','',len(HKLdict)+1, style = wx.PD_ELAPSED_TIME|wx.PD_AUTO_HIDE) sumDf = 0. sumFo = 0. for ih,hkl in enumerate(HKLdict): HKL = HKLdict[hkl] newHKL = list(HKL[0])+list(HKL[1][0]) if len(HKL[1]) > 1: fos = np.array(HKL[1]) wFo = 1/fos[:,3]**2 Fo = np.average(fos[:,2],weights=wFo) std = np.std(fos[:,2]) sig = np.sqrt(np.mean(fos[:,3])**2+std**2) sumFo += np.sum(fos[:,2]) sumDf += np.sum(np.abs(fos[:,2]-Fo)) dlg.Update(ih) newHKL[5+Super] = Fo newHKL[6+Super] = sig newHKL[8+Super] = Fo if newHKL[5+Super] > 0.: mergeRef.append(list(newHKL)) dlg.Destroy() if Super: mergeRef = G2mth.sortArray(G2mth.sortArray(G2mth.sortArray(G2mth.sortArray(mergeRef,3),2),1),0) else: mergeRef = G2mth.sortArray(G2mth.sortArray(G2mth.sortArray(mergeRef,2),1),0) mergeRef = np.array(mergeRef) if sumFo: mtext = ' merge R = %6.2f%s for %d reflections in %s'%(100.*sumDf/sumFo,'%',mergeRef.shape[0],Laue) print mtext Comments.append(mtext) else: print 'nothing to merge for %s reflections'%(mergeRef.shape[0]) HKLFlist = [] newName = Name+' '+Laue if G2frame.GPXtree.GetCount(): item, cookie = G2frame.GPXtree.GetFirstChild(G2frame.root) while item: name = G2frame.GPXtree.GetItemText(item) if name.startswith('HKLF ') and name not in HKLFlist: HKLFlist.append(name) item, cookie = G2frame.GPXtree.GetNextChild(G2frame.root, cookie) newName = G2obj.MakeUniqueLabel(newName,HKLFlist) newData = copy.deepcopy(data) newData[0]['ranId'] = ran.randint(0,sys.maxint) newData[1]['RefList'] = mergeRef Id = G2frame.GPXtree.AppendItem(parent=G2frame.root,text=newName) G2frame.GPXtree.SetItemPyData( G2frame.GPXtree.AppendItem(Id,text='Comments'),Comments) G2frame.GPXtree.SetItemPyData(Id,newData) G2frame.GPXtree.SetItemPyData( G2frame.GPXtree.AppendItem(Id,text='Instrument Parameters'),Inst) G2frame.GPXtree.SetItemPyData( G2frame.GPXtree.AppendItem(Id,text='Reflection List'),{}) #dummy entry for GUI use def OnErrorAnalysis(event): G2plt.PlotDeltSig(G2frame,kind) # def OnCompression(event): # data[0] = int(comp.GetValue()) def onCopyPlotCtrls(event): '''Respond to menu item to copy multiple sections from a histogram. Need this here to pass on the G2frame object. ''' G2pdG.CopyPlotCtrls(G2frame) def onCopySelectedItems(event): '''Respond to menu item to copy multiple sections from a histogram. Need this here to pass on the G2frame object. ''' G2pdG.CopySelectedHistItems(G2frame) data = G2frame.GPXtree.GetItemPyData(item) #G2frame.SetLabel(G2frame.GetLabel().split('||')[0]+' || '+G2frame.GPXtree.GetItemText(item)) G2frame.SetTitle(G2frame.GPXtree.GetItemText(item)) #patches if not data: return if 'wtFactor' not in data[0]: data[0] = {'wtFactor':1.0} # if kind == 'PWDR' and 'Compression' not in data[0]: # data[0]['Compression'] = 1 #if isinstance(data[1],list) and kind == 'HKLF': if 'list' in str(type(data[1])) and kind == 'HKLF': RefData = {'RefList':[],'FF':[]} for ref in data[1]: RefData['RefList'].append(ref[:11]+[ref[13],]) RefData['FF'].append(ref[14]) data[1] = RefData G2frame.GPXtree.SetItemPyData(item,data) #end patches if kind in ['PWDR','SASD','REFD']: SetDataMenuBar(G2frame,G2frame.dataWindow.PWDRMenu) G2frame.Bind(wx.EVT_MENU, OnErrorAnalysis, id=G2G.wxID_PWDANALYSIS) G2frame.Bind(wx.EVT_MENU, onCopySelectedItems, id=G2G.wxID_PWDCOPY) G2frame.Bind(wx.EVT_MENU, onCopyPlotCtrls, id=G2G.wxID_PLOTCTRLCOPY) elif kind in ['HKLF',]: SetDataMenuBar(G2frame,G2frame.dataWindow.HKLFMenu) G2frame.Bind(wx.EVT_MENU, OnErrorAnalysis, id=G2G.wxID_PWDANALYSIS) G2frame.Bind(wx.EVT_MENU, OnMergeHKL, id=G2G.wxID_MERGEHKL) G2frame.Bind(wx.EVT_MENU, OnPlot3DHKL, id=G2G.wxID_PWD3DHKLPLOT) G2frame.Bind(wx.EVT_MENU, OnPlotAll3DHKL, id=G2G.wxID_3DALLHKLPLOT) G2frame.dataWindow.ClearData() mainSizer = G2frame.dataWindow.GetSizer() mainSizer.Add((5,5),) wtSizer = wx.BoxSizer(wx.HORIZONTAL) wtSizer.Add(wx.StaticText(G2frame.dataWindow,-1,' Weight factor: '),0,WACV) wtval = G2G.ValidatedTxtCtrl(G2frame.dataWindow,data[0],'wtFactor',nDig=(10,3),min=1.e-9) wtSizer.Add(wtval,0,WACV) # if kind == 'PWDR': #possible future compression feature; NB above patch as well # wtSizer.Add(wx.StaticText(G2frame.dataWindow,-1,' Compression factor: '),0,WACV) # choice = ['1','2','3','4','5','6'] # comp = wx.ComboBox(parent=G2frame.dataWindow,choices=choice, # style=wx.CB_READONLY|wx.CB_DROPDOWN) # comp.SetValue(str(data[0]['Compression'])) # comp.Bind(wx.EVT_COMBOBOX, OnCompression) # wtSizer.Add(comp,0,WACV) mainSizer.Add(wtSizer) if data[0].get('Dummy'): simSizer = wx.BoxSizer(wx.HORIZONTAL) Tmin = min(data[1][0]) Tmax = max(data[1][0]) num = len(data[1][0]) step = (Tmax - Tmin)/(num-1) t = u'2\u03b8' # 2theta lbl = u'Simulation range: {:.2f} to {:.2f} {:s}\nwith {:.4f} steps ({:d} points)' lbl += u'\n(Edit range resets observed intensities).' lbl = lbl.format(Tmin,Tmax,t,step,num) simSizer.Add(wx.StaticText(G2frame.dataWindow,wx.ID_ANY,lbl), 0,WACV) but = wx.Button(G2frame.dataWindow,wx.ID_ANY,"Edit range") but.Bind(wx.EVT_BUTTON,onEditSimRange) simSizer.Add(but,0,WACV) mainSizer.Add(simSizer) if 'Nobs' in data[0]: mainSizer.Add(wx.StaticText(G2frame.dataWindow,-1, ' Data residual wR: %.3f%% on %d observations'%(data[0]['wR'],data[0]['Nobs']))) if kind == 'PWDR': mainSizer.Add(wx.StaticText(G2frame.dataWindow,-1, ' Durbin-Watson statistic: %.3f'%(data[0].get('Durbin-Watson',0.)))) for value in data[0]: if 'Nref' in value: pfx = value.split('Nref')[0] name = data[0].get(pfx.split(':')[0]+'::Name','?') if 'SS' in value: mainSizer.Add((5,5),) mainSizer.Add(wx.StaticText(G2frame.dataWindow,-1,' For incommensurate phase '+name+':')) for m,(Rf2,Rf,Nobs) in enumerate(zip(data[0][pfx+'Rf^2'],data[0][pfx+'Rf'],data[0][value])): mainSizer.Add(wx.StaticText(G2frame.dataWindow,-1, u' m = +/- %d: RF\u00b2: %.3f%%, RF: %.3f%% on %d reflections '% \ (m,Rf2,Rf,Nobs))) else: mainSizer.Add((5,5),) mainSizer.Add(wx.StaticText(G2frame.dataWindow,-1,' For phase '+name+':')) mainSizer.Add(wx.StaticText(G2frame.dataWindow,-1, u' Unweighted phase residuals RF\u00b2: %.3f%%, RF: %.3f%% on %d reflections '% \ (data[0][pfx+'Rf^2'],data[0][pfx+'Rf'],data[0][value]))) G2frame.GPXtree.SetItemPyData(item,data) G2frame.PatternId = item if kind in ['PWDR','SASD','REFD',]: NewPlot = True if 'xylim' in dir(G2frame): NewPlot = False G2plt.PlotPatterns(G2frame,plotType=kind,newPlot=NewPlot) elif kind == 'HKLF': Name = G2frame.GPXtree.GetItemText(item) phaseName = G2pdG.IsHistogramInAnyPhase(G2frame,Name) if phaseName: pId = GetGPXtreeItemId(G2frame,G2frame.root,'Phases') phaseId = GetGPXtreeItemId(G2frame,pId,phaseName) General = G2frame.GPXtree.GetItemPyData(phaseId)['General'] Super = General.get('Super',0) SuperVec = General.get('SuperVec',[]) else: Super = 0 SuperVec = [] refList = data[1]['RefList'] # GSASIIpath.IPyBreak() FoMax = np.max(refList.T[5+data[1].get('Super',0)]) page = G2frame.G2plotNB.nb.GetSelection() tab = '' if page >= 0: tab = G2frame.G2plotNB.nb.GetPageText(page) if '3D' in tab: Page = G2frame.G2plotNB.nb.GetPage(page) controls = Page.controls G2plt.Plot3DSngl(G2frame,newPlot=False,Data=controls,hklRef=refList,Title=phaseName) else: controls = {'Type' : 'Fo','ifFc' : True, 'HKLmax' : [int(np.max(refList.T[0])),int(np.max(refList.T[1])),int(np.max(refList.T[2]))], 'HKLmin' : [int(np.min(refList.T[0])),int(np.min(refList.T[1])),int(np.min(refList.T[2]))], 'FoMax' : FoMax,'Zone' : '001','Layer' : 0,'Scale' : 1.0,'Super':Super,'SuperVec':SuperVec} G2plt.PlotSngl(G2frame,newPlot=True,Data=controls,hklRef=refList) ################################################################################ ##### Data (GPX) tree routines ################################################################################ def GetGPXtreeDataNames(G2frame,dataTypes): '''Finds all items in tree that match a 4 character prefix :param wx.Frame G2frame: Data tree frame object :param list dataTypes: Contains one or more data tree item types to be matched such as ['IMG '] or ['PWDR','HKLF'] :returns: a list of tree item names for the matching items ''' names = [] item, cookie = G2frame.GPXtree.GetFirstChild(G2frame.root) while item: name = G2frame.GPXtree.GetItemText(item) if name[:4] in dataTypes: names.append(name) item, cookie = G2frame.GPXtree.GetNextChild(G2frame.root, cookie) return names def GetGPXtreeItemId(G2frame, parentId, itemText): '''Find the tree item that matches the text in itemText starting with parentId :param wx.Frame G2frame: Data tree frame object :param wx.TreeItemId parentId: tree item to start search with :param str itemText: text for tree item ''' item, cookie = G2frame.GPXtree.GetFirstChild(parentId) while item: if G2frame.GPXtree.GetItemText(item) == itemText: return item item, cookie = G2frame.GPXtree.GetNextChild(parentId, cookie) return 0 def SelectDataTreeItem(G2frame,item,oldFocus=None): '''Called from :meth:`GSASIIdataGUI.GSASII.OnDataTreeSelChanged` when a item is selected on the tree. Also called from GSASII.OnGPXtreeEndDrag, OnAddPhase -- might be better to select item, triggering the the bind to SelectDataTreeItem Also Called in GSASIIphsGUI.UpdatePhaseData by OnTransform callback. ''' if G2frame.PickIdText == G2frame.GetTreeItemsList(item): # don't redo the current data tree item return oldPage = None # will be set later if already on a Phase item # save or finish processing of outstanding events for grid in G2frame.dataWindow.currentGrids: # complete any open wx.Grid edits #if GSASIIpath.GetConfigValue('debug'): print 'Testing grid edit in',grid try: if grid.IsCellEditControlEnabled(): # complete any grid edits in progress if GSASIIpath.GetConfigValue('debug'): print 'Completing grid edit in',grid grid.HideCellEditControl() grid.DisableCellEditControl() except: pass if G2frame.dataWindow.GetLabel() == 'Comments': # save any recently entered comments try: data = [G2frame.dataDisplay.GetValue()] G2frame.dataDisplay.ClearData() Id = GetGPXtreeItemId(G2frame,G2frame.root, 'Comments') if Id: G2frame.GPXtree.SetItemPyData(Id,data) except: #clumsy but avoids dead window problem when opening another project pass elif G2frame.dataWindow.GetLabel() == 'Notebook': # save any recent notebook entries try: data = [G2frame.dataDisplay.GetValue()] G2frame.dataDisplay.ClearData() Id = GetGPXtreeItemId(G2frame,G2frame.root, 'Notebook') if Id: G2frame.GPXtree.SetItemPyData(Id,data) except: #clumsy but avoids dead window problem when opening another project pass elif 'Phase Data for' in G2frame.dataWindow.GetLabel(): if G2frame.dataDisplay: oldPage = G2frame.dataDisplay.GetSelection() G2frame.SetLabel('') SetDataMenuBar(G2frame) G2frame.PickId = item G2frame.PickIdText = None parentID = G2frame.root if item == G2frame.root: G2frame.dataWindow.ClearData() G2frame.helpKey = "Data tree" G2frame.dataWindow.GetSizer().Add( wx.StaticText(G2frame.dataWindow, wx.ID_ANY, 'Select an item from the tree to see/edit parameters')) G2frame.dataWindow.SetDataSize() return else: # Set up the help entry for the current selected tree item try: #don't know why we get here when opening new project parentID = G2frame.GPXtree.GetItemParent(item) # save name of calling tree item for help. N.B. may want to override this later prfx = G2frame.GPXtree.GetItemText(item).split()[0].upper() prfx1 = G2frame.GPXtree.GetItemText(parentID).split()[0] if prfx in ('IMG','PKS','PWDR','SASD','HKLF','PDF','REFD',): G2frame.dataWindow.helpKey = prfx elif prfx1 == 'Phases': G2frame.dataWindow.helpKey = 'Phases' elif prfx1 in ('IMG','PKS','PWDR','SASD','HKLF','PDF','REFD',): suffix = G2frame.GPXtree.GetItemText(item) suffix1 = suffix.split()[0] if '(Q)' in suffix1 or '(R)' in suffix1: suffix = suffix1 G2frame.dataWindow.helpKey = prfx1 + '_' + suffix else: G2frame.dataWindow.helpKey = G2frame.GPXtree.GetItemText(item) # save name of calling tree item for help except IndexError: G2frame.dataWindow.helpKey = '' if GSASIIpath.GetConfigValue('debug'): print 'bug: why here?' G2obj.HowDidIgetHere() # clear out the old panel contents G2frame.dataWindow.ClearData() # process first-level entries in tree if G2frame.GPXtree.GetItemParent(item) == G2frame.root: G2frame.PatternId = 0 if G2frame.GPXtree.GetItemText(item) == 'Notebook': SetDataMenuBar(G2frame,G2frame.dataWindow.DataNotebookMenu) data = G2frame.GPXtree.GetItemPyData(item) UpdateNotebook(G2frame,data) elif G2frame.GPXtree.GetItemText(item) == 'Controls': data = G2frame.GPXtree.GetItemPyData(item) if not data: #fill in defaults data = copy.copy(G2obj.DefaultControls) #least squares controls G2frame.GPXtree.SetItemPyData(item,data) for i in G2frame.Refine: i.Enable(True) G2frame.EnableSeqRefineMenu() UpdateControls(G2frame,data) elif G2frame.GPXtree.GetItemText(item).startswith('Sequential '): G2frame.dataWindow.helpKey = 'Sequential' # for now all sequential refinements are documented in one place data = G2frame.GPXtree.GetItemPyData(item) UpdateSeqResults(G2frame,data) elif G2frame.GPXtree.GetItemText(item) == 'Covariance': data = G2frame.GPXtree.GetItemPyData(item) text = '' if 'Rvals' in data: Nvars = len(data['varyList']) Rvals = data['Rvals'] text = ('Residuals after last refinement:\n'+ '\twR = {:.3f}\n\tchi**2 = {:.1f}\n\tGOF = {:.2f}').format( Rvals['Rwp'],Rvals['chisq'],Rvals['GOF']) text += '\n\tNobs = {}\n\tNvals = {}\n\tSVD zeros = {}'.format( Rvals['Nobs'],Nvars,Rvals.get('SVD0',0.)) if 'lamMax' in Rvals: text += '\n\tlog10 MaxLambda = {:.1f}'.format(np.log10(Rvals['lamMax'])) G2frame.dataWindow.GetSizer().Add( wx.StaticText(G2frame.dataWindow,wx.ID_ANY,text) ) G2plt.PlotCovariance(G2frame,data) elif G2frame.GPXtree.GetItemText(item) == 'Constraints': data = G2frame.GPXtree.GetItemPyData(item) G2cnstG.UpdateConstraints(G2frame,data) elif G2frame.GPXtree.GetItemText(item) == 'Rigid bodies': data = G2frame.GPXtree.GetItemPyData(item) G2cnstG.UpdateRigidBodies(G2frame,data) elif G2frame.GPXtree.GetItemText(item) == 'Restraints': data = G2frame.GPXtree.GetItemPyData(item) Phases = G2frame.GetPhaseData() phaseName = '' if Phases: phaseName = Phases.keys()[0] G2restG.UpdateRestraints(G2frame,data,Phases,phaseName) elif G2frame.GPXtree.GetItemText(item).startswith('IMG '): G2frame.Image = item G2frame.SetTitle('Image Data') data = G2frame.GPXtree.GetItemPyData(GetGPXtreeItemId( G2frame,item,'Image Controls')) G2imG.UpdateImageData(G2frame,data) G2plt.PlotImage(G2frame,newPlot=True) elif G2frame.GPXtree.GetItemText(item).startswith('PKS '): G2plt.PlotPowderLines(G2frame) elif G2frame.GPXtree.GetItemText(item).startswith('PWDR '): G2frame.PatternId = item #for i in G2frame.ExportPattern: i.Enable(True) if G2frame.EnablePlot: UpdatePWHKPlot(G2frame,'PWDR',item) elif G2frame.GPXtree.GetItemText(item).startswith('SASD '): G2frame.PatternId = item #for i in G2frame.ExportPattern: i.Enable(True) if G2frame.EnablePlot: UpdatePWHKPlot(G2frame,'SASD',item) elif G2frame.GPXtree.GetItemText(item).startswith('REFD '): G2frame.PatternId = item #for i in G2frame.ExportPattern: i.Enable(True) if G2frame.EnablePlot: UpdatePWHKPlot(G2frame,'REFD',item) elif G2frame.GPXtree.GetItemText(item).startswith('HKLF '): G2frame.Sngl = True UpdatePWHKPlot(G2frame,'HKLF',item) elif G2frame.GPXtree.GetItemText(item).startswith('PDF '): G2frame.PatternId = item for i in G2frame.ExportPDF: i.Enable(True) # this should be done on .gpx load; is done on OnMakePDFs (GSASII.py) data = G2frame.GPXtree.GetItemPyData(GetGPXtreeItemId(G2frame,item,'PDF Controls')) G2pdG.UpdatePDFGrid(G2frame,data) if len(data['G(R)']): G2plt.PlotISFG(G2frame,data,plotType='G(R)') elif G2frame.GPXtree.GetItemText(item) == 'Phases': G2frame.dataWindow.GetSizer().Add( wx.StaticText(G2frame.dataWindow,wx.ID_ANY, 'Select one phase to see its parameters') ) ############################################################################ # process second-level entries in tree elif G2frame.GPXtree.GetItemText(item) == 'PDF Peaks': G2frame.PatternId = G2frame.GPXtree.GetItemParent(item) peaks = G2frame.GPXtree.GetItemPyData(GetGPXtreeItemId(G2frame,G2frame.PatternId,'PDF Peaks')) data = G2frame.GPXtree.GetItemPyData(GetGPXtreeItemId(G2frame,G2frame.PatternId,'PDF Controls')) G2pdG.UpdatePDFPeaks(G2frame,peaks,data) if len(data['G(R)']): G2plt.PlotISFG(G2frame,data,plotType='G(R)',newPlot=True,peaks=peaks) elif G2frame.GPXtree.GetItemText(item) == 'PDF Controls': for i in G2frame.ExportPDF: i.Enable(True) # this should be done on .gpx load; is done on OnMakePDFs (GSASII.py) G2frame.dataWindow.helpKey = G2frame.GPXtree.GetItemText(item) # special treatment to avoid PDF_PDF Controls G2frame.PatternId = G2frame.GPXtree.GetItemParent(item) data = G2frame.GPXtree.GetItemPyData(item) G2pdG.UpdatePDFGrid(G2frame,data) if len(data['G(R)']): if 'I(Q)' in data: G2plt.PlotISFG(G2frame,data,plotType='I(Q)') if 'S(Q)' in data: G2plt.PlotISFG(G2frame,data,plotType='S(Q)') if 'F(Q)' in data: G2plt.PlotISFG(G2frame,data,plotType='F(Q)') G2plt.PlotISFG(G2frame,data,plotType='G(R)') elif G2frame.GPXtree.GetItemText(parentID) == 'Phases': data = G2frame.GPXtree.GetItemPyData(item) G2phG.UpdatePhaseData(G2frame,item,data,oldPage) elif G2frame.GPXtree.GetItemText(item) == 'Comments': SetDataMenuBar(G2frame,G2frame.dataWindow.DataCommentsMenu) G2frame.PatternId = G2frame.GPXtree.GetItemParent(item) data = G2frame.GPXtree.GetItemPyData(item) UpdateComments(G2frame,data) elif G2frame.GPXtree.GetItemText(item) == 'Image Controls': G2frame.SetTitle('Image Controls') G2frame.Image = G2frame.GPXtree.GetItemParent(item) masks = G2frame.GPXtree.GetItemPyData( GetGPXtreeItemId(G2frame,G2frame.Image, 'Masks')) data = G2frame.GPXtree.GetItemPyData(item) G2frame.ImageZ = G2imG.GetImageZ(G2frame,data) G2imG.UpdateImageControls(G2frame,data,masks) G2plt.PlotImage(G2frame,newPlot=False) elif G2frame.GPXtree.GetItemText(item) == 'Masks': G2frame.SetTitle('Masks') G2frame.Image = G2frame.GPXtree.GetItemParent(item) masks = G2frame.GPXtree.GetItemPyData(item) data = G2frame.GPXtree.GetItemPyData( GetGPXtreeItemId(G2frame,G2frame.Image, 'Image Controls')) G2frame.ImageZ = G2imG.GetImageZ(G2frame,data) G2imG.UpdateMasks(G2frame,masks) G2plt.PlotImage(G2frame,newPlot=False) elif G2frame.GPXtree.GetItemText(item) == 'Stress/Strain': G2frame.SetTitle('Stress/Strain') G2frame.Image = G2frame.GPXtree.GetItemParent(item) data = G2frame.GPXtree.GetItemPyData( GetGPXtreeItemId(G2frame,G2frame.Image, 'Image Controls')) G2frame.ImageZ = G2imG.GetImageZ(G2frame,data,newRange=False) strsta = G2frame.GPXtree.GetItemPyData(item) G2plt.PlotStrain(G2frame,strsta,newPlot=True) G2plt.PlotImage(G2frame,newPlot=False) G2imG.UpdateStressStrain(G2frame,strsta) elif G2frame.GPXtree.GetItemText(item) == 'Peak List': G2frame.PatternId = G2frame.GPXtree.GetItemParent(item) for i in G2frame.ExportPeakList: i.Enable(True) data = G2frame.GPXtree.GetItemPyData(item) #patch if 'list' in str(type(data)): data = {'peaks':data,'sigDict':{}} G2frame.GPXtree.SetItemPyData(item,data) #end patch G2pdG.UpdatePeakGrid(G2frame,data) G2plt.PlotPatterns(G2frame) elif G2frame.GPXtree.GetItemText(item) == 'Background': G2frame.PatternId = G2frame.GPXtree.GetItemParent(item) data = G2frame.GPXtree.GetItemPyData(item) G2pdG.UpdateBackground(G2frame,data) G2plt.PlotPatterns(G2frame) elif G2frame.GPXtree.GetItemText(item) == 'Limits': G2frame.PatternId = G2frame.GPXtree.GetItemParent(item) datatype = G2frame.GPXtree.GetItemText(G2frame.PatternId)[:4] data = G2frame.GPXtree.GetItemPyData(item) G2pdG.UpdateLimitsGrid(G2frame,data,datatype) G2plt.PlotPatterns(G2frame,plotType=datatype) elif G2frame.GPXtree.GetItemText(item) == 'Instrument Parameters': G2frame.PatternId = G2frame.GPXtree.GetItemParent(item) data = G2frame.GPXtree.GetItemPyData(item)[0] G2pdG.UpdateInstrumentGrid(G2frame,data) if 'P' in data['Type'][0]: #powder data only G2plt.PlotPeakWidths(G2frame) elif G2frame.GPXtree.GetItemText(item) == 'Models': G2frame.PatternId = G2frame.GPXtree.GetItemParent(item) data = G2frame.GPXtree.GetItemPyData(item) if prfx1 == 'SASD': G2pdG.UpdateModelsGrid(G2frame,data) elif prfx1 == 'REFD': G2pdG.UpdateREFDModelsGrid(G2frame,data) G2plt.PlotPatterns(G2frame,plotType=prfx1) if prfx1 == 'SASD' and len(data['Size']['Distribution']): G2plt.PlotSASDSizeDist(G2frame) elif G2frame.GPXtree.GetItemText(item) == 'Substances': G2frame.PatternId = G2frame.GPXtree.GetItemParent(item) data = G2frame.GPXtree.GetItemPyData(item) G2pdG.UpdateSubstanceGrid(G2frame,data) elif G2frame.GPXtree.GetItemText(item) == 'Sample Parameters': G2frame.PatternId = G2frame.GPXtree.GetItemParent(item) data = G2frame.GPXtree.GetItemPyData(item) datatype = G2frame.GPXtree.GetItemPyData(G2frame.PatternId)[2][:4] if 'Temperature' not in data: #temp fix for old gpx files data = {'Scale':[1.0,True],'Type':'Debye-Scherrer','Absorption':[0.0,False],'DisplaceX':[0.0,False], 'DisplaceY':[0.0,False],'Diffuse':[],'Temperature':300.,'Pressure':1.0, 'FreePrm1':0.,'FreePrm2':0.,'FreePrm3':0., 'Gonio. radius':200.0} G2frame.GPXtree.SetItemPyData(item,data) G2pdG.UpdateSampleGrid(G2frame,data) G2plt.PlotPatterns(G2frame,plotType=datatype) elif G2frame.GPXtree.GetItemText(item) == 'Index Peak List': G2frame.PatternId = G2frame.GPXtree.GetItemParent(item) for i in G2frame.ExportPeakList: i.Enable(True) data = G2frame.GPXtree.GetItemPyData(item) #patch if len(data) != 2: data = [data,[]] G2frame.GPXtree.SetItemPyData(item,data) #end patch G2pdG.UpdateIndexPeaksGrid(G2frame,data) if 'PKS' in G2frame.GPXtree.GetItemText(G2frame.PatternId): G2plt.PlotPowderLines(G2frame) else: G2plt.PlotPatterns(G2frame) elif G2frame.GPXtree.GetItemText(item) == 'Unit Cells List': G2frame.PatternId = G2frame.GPXtree.GetItemParent(item) data = G2frame.GPXtree.GetItemPyData(item) if not data: data.append([0,0.0,4,25.0,0,'P1',1,1,1,90,90,90]) #zero error flag, zero value, max Nc/No, start volume data.append([0,0,0,0,0,0,0,0,0,0,0,0,0,0]) #Bravais lattice flags data.append([]) #empty cell list data.append([]) #empty dmin data.append({}) #empty superlattice stuff G2frame.GPXtree.SetItemPyData(item,data) #patch if len(data) < 5: data.append({'Use':False,'ModVec':[0,0,0.1],'maxH':1,'ssSymb':''}) #empty superlattice stuff G2frame.GPXtree.SetItemPyData(item,data) #end patch G2pdG.UpdateUnitCellsGrid(G2frame,data) if 'PKS' in G2frame.GPXtree.GetItemText(G2frame.PatternId): G2plt.PlotPowderLines(G2frame) else: G2plt.PlotPatterns(G2frame) elif G2frame.GPXtree.GetItemText(item) == 'Reflection Lists': #powder reflections G2frame.PatternId = G2frame.GPXtree.GetItemParent(item) data = G2frame.GPXtree.GetItemPyData(item) G2frame.RefList = '' if len(data): G2frame.RefList = data.keys()[0] G2pdG.UpdateReflectionGrid(G2frame,data) G2plt.PlotPatterns(G2frame) elif G2frame.GPXtree.GetItemText(item) == 'Reflection List': #HKLF reflections G2frame.PatternId = G2frame.GPXtree.GetItemParent(item) name = G2frame.GPXtree.GetItemText(G2frame.PatternId) data = G2frame.GPXtree.GetItemPyData(G2frame.PatternId) G2pdG.UpdateReflectionGrid(G2frame,data,HKLF=True,Name=name) if G2frame.PickId: G2frame.PickIdText = G2frame.GetTreeItemsList(G2frame.PickId) # window has been filled, now resize scroll bars G2frame.dataWindow.SetDataSize() G2frame.Raise() if oldFocus: oldFocus.GetTopLevelParent().Raise() oldFocus.SetFocus() #debug code # print 'Got here!' # def FillWindow(panel,size=1.): # sizer = panel.GetSizer() # sizer.Add(wx.StaticText(panel, wx.ID_ANY, "Panel Two: long line "+int(size*40)*'*', (5,5))) # for i in range(int(size*15)): sizer.Add(wx.StaticText(panel, wx.ID_ANY, "Line "+str(2+i), (5,5))) # panel.Layout() # panel.SendSizeEvent() # G2frame.dataWindow.ClearData() # FillWindow(G2frame.dataWindow) def SetDataMenuBar(G2frame,menu=None): '''Set the menu for the data frame. Note that data frame items do not have menus, for these (menu=None) display the standard main menu for the data tree window. ''' if menu is None: G2frame.SetMenuBar(G2frame.GSASIIMenu) else: G2frame.SetMenuBar(menu)