Source code for GSASIIdataGUI

# -*- coding: utf-8 -*-
#GSASIIdataGUI - Main GUI routines
#========== SVN repository information ###################
# $Date: 2021-07-28 20:04:06 +0000 (Wed, 28 Jul 2021) $
# $Author: toby $
# $Revision: 5003 $
# $URL: https://subversion.xray.aps.anl.gov/pyGSAS/trunk/GSASIIdataGUI.py $
# $Id: GSASIIdataGUI.py 5003 2021-07-28 20:04:06Z toby $
#=========- 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. 
'''
from __future__ import division, print_function
import platform
import time
import math
import random as ran
import copy
import sys
import os
import inspect
if '2' in platform.python_version_tuple()[0]:
    import cPickle
else:
    try:
        import _pickle as cPickle
    except:
        print('Warning: failed to import the optimized Py3 pickle (_pickle)')
        import pickle as cPickle
import re
import numpy as np
import numpy.ma as ma
import matplotlib as mpl
try:
    import OpenGL as ogl
    try:
        import OpenGL.GL   # this fails in <=2020 versions of Python on OS X 11.x
    except ImportError:
        print('Drat, patching for Big Sur')
        from ctypes import util
        orig_util_find_library = util.find_library
        def new_util_find_library( name ):
            res = orig_util_find_library( name )
            if res: return res
            return '/System/Library/Frameworks/'+name+'.framework/'+name
        util.find_library = new_util_find_library
except ImportError:
    pass
import scipy as sp
#import scipy.optimize as so
try:
    import wx
#    import wx.grid as wg
    #import wx.wizard as wz
    #import wx.aui
    import wx.lib.scrolledpanel as wxscroll
except ImportError:
    pass
import GSASIIpath
GSASIIpath.SetVersionNumber("$Revision: 5003 $")
import GSASIImath as G2mth
import GSASIIIO as G2IO
import GSASIIfiles as G2fil
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 GSASIIlog as log
import GSASIIctrlGUI as G2G
import GSASIIElem as G2elem
import GSASIIpwd as G2pwd
import GSASIIstrMain as G2stMn
import defaultIparms as dI
import GSASIIfpaGUI as G2fpa
import GSASIIseqGUI as G2seq
import GSASIIddataGUI as G2ddG

try:
    wx.NewIdRef
    wx.NewId = wx.NewIdRef
except AttributeError:
    pass

# 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]}}
        
[docs]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 ######################################
[docs]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)','trigonal(R)','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',],'trigonal(R)':['-3','-3 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',],'trigonal(R)':['3','3 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) 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) mainSizer.Add(wx.StaticText(self.panel,label=' Target Laue symmetry:'),0) 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() if parent is not None: parent.Raise() self.EndModal(wx.ID_OK) def OnCancel(self,event): parent = self.GetParent() if parent is not None: parent.Raise() self.EndModal(wx.ID_CANCEL)
[docs]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 (u"Install of '+package+u' 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
[docs]def convVersion(version): '''Convert a version string ("x", "x.y", "x.y.z") into a series of ints. :returns: [i0, i1, i2] where None is used if a value is not specified and 0 is used if a field cannot be parsed. ''' vIntList = [None,None,None] for i,v in enumerate(version.split('.')): if i >= 3: break if len(v) == 0: break v = list(filter(None,re.split('(\\d+)',v)))[0] # conv '1b2' to '1' try: vIntList[i] = int(v) except: vIntList[i] = 0 return vIntList
[docs]def compareVersions(version1,version2): '''Compare two version strings ("x", "x.y", "x.y.z") Note that '3.' matches '3.1', and '3.0' matches '3.0.1' but '3.0.0' does not match '3.0.1' :returns: 0 if the versions match, -1 if version1 < version2, or 1 if version1 > version2 ''' for v1,v2 in zip(convVersion(version1),convVersion(version2)): if v1 is None or v2 is None: return 0 if v1 < v2: return -1 if v1 > v2: return 1 return 0
# tabulate package versions that users should be warned about versionDict = {} '''Variable versionDict is used to designate versions of packages that should generate warnings or error messages. * ``versionDict['tooOld']`` is a dict with module versions that are too old and are known to cause serious errors * ``versionDict['tooOldWarn']`` is a dict with module versions that are significantly out of date and should be updated, but will probably function OK. * ``versionDict['badVersionWarn']`` is a dict of with lists of package versions that are known to have bugs. One should select an older or newer version of the package. * ``versionDict['tooNewWarn']`` is a dict with module versions that have not been tested but have changes that lead us to believe that errors are likely to happen. **Packages/versions to be avoided** * wxPython: * <=2.x.x: while most of GSAS-II has been written to be compatible with older versions of wxpython, we are now testing with version 4.0 only. Version 3.0 is pretty similar to 4.0 and should not have problems. wxpython 4.1 seems to create a lot of errors for conflicting options that will need to be checked up upon. * Matplotlib: * 1.x: there have been significant API changes since these versions and significant graphics errors will occur. * 3.1.x and 3.2.x: these versions have a known bug for plotting 3-D surfaces, such as microstrain vs crystal axes. The plots may appear distorted as the lengths of x, y & z will not be constrained as equal. Preferably use 3.0.x as 3.3.x is not fully tested. * numpy: * 1.16.0: produces .gpx files that are not compatible with older version numpy versions. This is a pretty outmoded version; upgrade. ''' # add comments above when changing anything below versionDict['tooOld'] = {'matplotlib': '1.'} 'modules that will certainly fail' versionDict['tooOldWarn'] = {'wx': '2.'} 'modules that may fail but should be updated' versionDict['badVersionWarn'] = {'numpy':['1.16.0'], 'matplotlib': ['3.1','3.2']} 'versions of modules that are known to have bugs' versionDict['tooNewWarn'] = {'wx':'4.1'} #'matplotlib': '3.4', 'module versions newer than what we have tested where problems are suspected'
[docs]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: %s from %s"%(sys.version.split()[0],sys.executable)) Image = None version = '?' versionDict['errors'] = '' warn = False for s,m in [('wx',wx), ('matplotlib', mpl), ('numpy',np), ('scipy',sp), ('OpenGL',ogl)]: msg = '' if s in versionDict['tooOld']: match = compareVersions(m.__version__,versionDict['tooOld'][s]) if match <= 0: msg = "version will cause problems" warn = True if versionDict['errors']: versionDict['errors'] += '\n' versionDict['errors'] += 'Package {} version {} is too old for GSAS-II. An update is required'.format(s,m.__version__) if s in versionDict['tooOldWarn']: match = compareVersions(m.__version__,versionDict['tooOldWarn'][s]) if match <= 0: msg = "version can cause problems" warn = True if s in versionDict['tooNewWarn']: match = compareVersions(m.__version__,versionDict['tooNewWarn'][s]) if match >= 0: msg = "version is too new and could cause problems" warn = True if s in versionDict['badVersionWarn']: for v in versionDict['badVersionWarn'][s]: if compareVersions(m.__version__,v) == 0: msg = "version is known to be buggy" warn = True break print(" {:12s}{} {}".format(s+':',m.__version__,msg)) try: from PIL import Image except ImportError: try: import Image except ImportError: pass if Image is None: print ("Image module not present; Note that PIL (Python Imaging Library) or pillow is needed for some image operations") else: # version # can be in various places, try standard dunderscore first for ver in '__version__','VERSION','PILLOW_VERSION': if hasattr(Image,ver): try: version = eval('Image.'+ver) break except: pass print (" Image: %s (PIL or Pillow)"%version) print (" Platform: %s %s %s"%(sys.platform,platform.architecture()[0],platform.machine())) try: import mkl print (" Max threads:%s"%mkl.get_max_threads()) except: pass rev = GSASIIpath.svnGetRev() if rev is None: "no SVN" else: rev = "SVN version {}".format(rev) print ("Latest GSAS-II revision (from .py files): {} ({})\n".format( GSASIIpath.GetVersionNumber(),rev)) # patch 11/2020: warn if GSASII path has not been updated past v4576. # For unknown reasons on Mac with gsas2full, there have been checksum # errors in the .so files that prevented svn from completing updates. # If GSASIIpath.svnChecksumPatch is not present, then the fix for that # has not been retrieved, so warn. Keep for a year or so. try: GSASIIpath.svnChecksumPatch except: print('Warning GSAS-II incompletely updated. Please contact toby@anl.gov') # end patch if warn: print('You are suggested to install a new version of GSAS-II.\nSee https://bit.ly/G2install', '\n\nFor information on packages see\nhttps://gsas-ii.readthedocs.io/en/latest/packages.html and', '\nhttps://gsas-ii.readthedocs.io/en/latest/GSASIIGUI.html#GSASIIdataGUI.versionDict')
#### GUI creation #############################################################
[docs]def GSASIImain(application): '''Start up the GSAS-II GUI''' ShowVersions() GUIpatches() if platform.python_version()[:3] == '2.7': msg = '''The end-of-life for python 2.7 was January 1, 2020. We strongly recommend reinstalling GSAS-II from a new installation kit as we may not be able to offer support for operation of GSAS-II in python 2.7. See instructions for details. ''' download = '' cmds = [] instructions = 'https://subversion.xray.aps.anl.gov/trac/pyGSAS' if sys.platform == "win32": download = 'https://subversion.xray.aps.anl.gov/admin_pyGSAS/downloads/gsas2full-Latest-Windows-x86_64.exe' instructions = 'https://subversion.xray.aps.anl.gov/trac/pyGSAS/wiki/SingleStepWindowsIllustrated' elif sys.platform == "darwin": cmds = ['echo starting download, please wait...', '''echo 'curl "https://subversion.xray.aps.anl.gov/admin_pyGSAS/downloads/gsas2full-Latest-MacOSX-x86_64.sh" > /tmp/g2.sh; bash /tmp/g2.sh' ''', 'curl "https://subversion.xray.aps.anl.gov/admin_pyGSAS/downloads/gsas2full-Latest-MacOSX-x86_64.sh" > /tmp/g2.sh; bash /tmp/g2.sh' ] instructions = 'https://subversion.xray.aps.anl.gov/trac/pyGSAS/wiki/MacSingleStepInstallerFigs' elif sys.platform.startswith("linux"): download = 'https://subversion.xray.aps.anl.gov/admin_pyGSAS/downloads/gsas2full-Latest-Linux-x86_64.sh' instructions = 'https://subversion.xray.aps.anl.gov/trac/pyGSAS/wiki/LinuxSingleStepInstaller' else: print(u'Unknown platform: '+sys.platform) if platform.architecture()[0] != '64bit' and sys.platform == "win32": msg += '''\nYou are currently using 32-bit Python. Please check if you are running 32-bit windows or 64-bit windows (use Start/Settings/System/About & look for "System type". We recommend using the 64-bit installer if you have 64-bit windows.''' download = '' elif platform.architecture()[0] != '64bit' and sys.platform.startswith("linux"): msg += '''\nYou are using 32-bit Python. We now only package for 64-bit linux. If you are running 32-bit linux you will need to install Python yourself. See instructions at https://subversion.xray.aps.anl.gov/trac/pyGSAS/wiki/InstallLinux''' instructions = 'https://subversion.xray.aps.anl.gov/trac/pyGSAS/wiki/InstallLinux' dlg = wx.Dialog(None,wx.ID_ANY,'End-Of-Life warning for Python 2.7', style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER) mainSizer = wx.BoxSizer(wx.VERTICAL) txt = wx.StaticText(dlg,wx.ID_ANY,G2G.StripIndents(msg)) mainSizer.Add(txt) txt.Wrap(400) dlg.SetSizer(mainSizer) btnsizer = wx.BoxSizer(wx.HORIZONTAL) btnsizer.Add((1,1),1,wx.EXPAND,1) OKbtn = wx.Button(dlg, wx.ID_OK,'Continue') OKbtn.SetDefault() OKbtn.Bind(wx.EVT_BUTTON,lambda event: dlg.EndModal(wx.ID_OK)) btnsizer.Add(OKbtn) btn = wx.Button(dlg, wx.ID_ANY,'Show Instructions') def openInstructions(event): G2G.ShowWebPage(instructions,None) btn.Bind(wx.EVT_BUTTON, openInstructions) btnsizer.Add(btn) if download: btn = wx.Button(dlg, wx.ID_ANY,'Start Download') btn.Bind(wx.EVT_BUTTON,lambda event: dlg.EndModal(wx.ID_YES)) btnsizer.Add(btn) elif cmds: btn = wx.Button(dlg, wx.ID_ANY,'Start Install') btn.Bind(wx.EVT_BUTTON,lambda event: dlg.EndModal(wx.ID_CANCEL)) btnsizer.Add(btn) #btn = wx.Button(dlg, wx.ID_CANCEL) #btnsizer.AddButton(btn) btnsizer.Add((1,1),1,wx.EXPAND,1) #btnsizer.Realize() mainSizer.Add((-1,5),1,wx.EXPAND,1) mainSizer.Add(btnsizer,0,wx.ALIGN_CENTER,0) mainSizer.Add((-1,10)) res = 0 try: res = dlg.ShowModal() finally: dlg.Destroy() if res == wx.ID_YES: G2G.ShowWebPage(download,None) G2G.ShowWebPage(instructions,None) wx.Sleep(1) dlg = wx.MessageDialog(None,G2G.StripIndents( '''Download has been started in your browser; installation instructions will also be shown in a web page\n\nPress OK to exit GSAS-II, Cancel to continue.'''), 'start install',wx.OK|wx.CANCEL) if dlg.ShowModal() == wx.ID_OK: sys.exit() elif res == wx.ID_CANCEL: dlg = wx.MessageDialog(None,G2G.StripIndents( '''Press OK to continue. Instructions will be shown in a web page. Download and installation will start in the terminal window after you press OK. Respond to questions there.'''), 'start install',wx.OK|wx.CANCEL) if dlg.ShowModal() == wx.ID_OK: G2G.ShowWebPage(instructions,None) GSASIIpath.runScript(cmds, wait=True) sys.exit() if versionDict['errors']: dlg = wx.MessageDialog(None, versionDict['errors']+ '\n\nThe simplest solution is to install a new version of GSAS-II. '+ 'See https://bit.ly/G2install', 'Python package problem', wx.OK) try: dlg.ShowModal() finally: dlg.Destroy() sys.exit() elif platform.python_version()[:3] not in ['2.7','3.6','3.7','3.8','3.9']: dlg = wx.MessageDialog(None, 'GSAS-II requires Python 2.7.x or 3.6+\n Yours is '+sys.version.split()[0], 'Python version error', wx.OK) try: dlg.ShowModal() finally: dlg.Destroy() sys.exit() application.main = GSASII(None) # application.main is the main wx.Frame (G2frame in most places) application.SetTopWindow(application.main) # save the current package versions application.main.PackageVersions = G2fil.get_python_versions([wx, mpl, np, sp, ogl]) if GSASIIpath.GetConfigValue('wxInspector'): import wx.lib.inspection as wxeye wxeye.InspectionTool().Show() try: application.SetAppDisplayName('GSAS-II') except: pass #application.GetTopWindow().SendSizeEvent() application.GetTopWindow().Show(True)
#### Create main frame (window) for GUI #######################################
[docs]class GSASII(wx.Frame): '''Define the main GSAS-II frame and its associated menu items. :param parent: reference to parent application '''
[docs] 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): '''Add items to File menu ''' item = parent.Append(wx.ID_ANY,'&Open project...\tCtrl+O','Open a GSAS-II project file (*.gpx)') self.Bind(wx.EVT_MENU, self.OnFileOpen, id=item.GetId()) if sys.platform == "darwin": item = parent.Append(wx.ID_ANY,'&Open in new window...','Open a GSAS-II project file (*.gpx) in a separate process') self.Bind(wx.EVT_MENU, self.OnNewGSASII, id=item.GetId()) item = parent.Append(wx.ID_ANY,'Reopen recent...\tCtrl+E','Reopen a previously used GSAS-II project file (*.gpx)') self.Bind(wx.EVT_MENU, self.OnFileReopen, id=item.GetId()) item = parent.Append(wx.ID_ANY,'&Save project\tCtrl+S','Save project under current name') self.Bind(wx.EVT_MENU, self.OnFileSave, id=item.GetId()) item = parent.Append(wx.ID_ANY,'Save project as...','Save current project to new file') self.Bind(wx.EVT_MENU, self.OnFileSaveas, id=item.GetId()) item = parent.Append(wx.ID_ANY,'&New project','Create empty new project, saving current is optional') self.Bind(wx.EVT_MENU, self.OnFileClose, id=item.GetId()) item = parent.Append(wx.ID_PREFERENCES,"&Preferences",'') self.Bind(wx.EVT_MENU, self.OnPreferences, item) if GSASIIpath.whichsvn(): item = parent.Append(wx.ID_ANY,'Edit proxy...','Edit proxy internet information (used for updates)') self.Bind(wx.EVT_MENU, self.EditProxyInfo, id=item.GetId()) if GSASIIpath.GetConfigValue('debug'): def OnIPython(event): GSASIIpath.IPyBreak() item = parent.Append(wx.ID_ANY,"IPython Console",'') self.Bind(wx.EVT_MENU, OnIPython, item) def OnwxInspect(event): import wx.lib.inspection as wxeye wxeye.InspectionTool().Show() item = parent.Append(wx.ID_ANY,"wx inspection tool",'') self.Bind(wx.EVT_MENU, OnwxInspect, item) item = parent.Append(wx.ID_EXIT,'Exit\tALT+F4','Exit from GSAS-II') self.Bind(wx.EVT_MENU, self.ExitMain, id=item.GetId()) def _Add_DataMenuItems(self,parent): '''Add items to Data menu ''' # 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(wx.ID_ANY,'Read Powder Pattern Peaks...','') self.Bind(wx.EVT_MENU, self.OnReadPowderPeaks, id=item.GetId()) item = parent.Append(wx.ID_ANY,'Sum or Average powder data','') self.Bind(wx.EVT_MENU, self.OnPwdrSum, id=item.GetId()) item = parent.Append(wx.ID_ANY,'Sum image data','') self.Bind(wx.EVT_MENU, self.OnImageSum, id=item.GetId()) item = parent.Append(wx.ID_ANY,'Add new phase','') self.Bind(wx.EVT_MENU, self.OnAddPhase, id=item.GetId()) item = parent.Append(wx.ID_ANY,'Delete phase entries','') self.Bind(wx.EVT_MENU, self.OnDeletePhase, id=item.GetId()) item = parent.Append(wx.ID_ANY,'Rename data entry', 'Rename the selected data tree item (PWDR, HKLF or IMG)') self.Bind(wx.EVT_MENU, self.OnRenameData, id=item.GetId()) item = parent.Append(wx.ID_ANY,'Delete data entries', 'Delete selected data items from data tree') self.Bind(wx.EVT_MENU, self.OnDataDelete, id=item.GetId()) item = parent.Append(wx.ID_ANY,'Delete plots','Delete selected plots') self.Bind(wx.EVT_MENU, self.OnPlotDelete, id=item.GetId()) expandmenu = wx.Menu() item = parent.AppendSubMenu(expandmenu,'Expand tree items', '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,s,help) self.Bind(wx.EVT_MENU,self.ExpandAll,id=item.GetId()) movemenu = wx.Menu() item = parent.AppendSubMenu(movemenu,'Move tree items', '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,s,help) self.Bind(wx.EVT_MENU,self.MoveTreeItems,id=item.GetId()) def _Add_CalculateMenuItems(self,parent): item = parent.Append(wx.ID_ANY,'Setup PDFs','Create PDF tree entries for selected powder patterns') self.MakePDF.append(item) self.Bind(wx.EVT_MENU, self.OnMakePDFs, id=item.GetId()) item = parent.Append(wx.ID_ANY,'&View LS parms\tCTRL+L','View least squares parameters') self.Bind(wx.EVT_MENU, self.OnShowLSParms, id=item.GetId()) item = parent.Append(wx.ID_ANY,'&Refine\tCTRL+R','Perform a refinement') if len(self.Refine): # extend state for new menus to match main 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(wx.ID_ANY,'&Le Bail fit\tCTRL+B','Fit Le Bail intensities only') item.Enable(state) self.Refine.append(item) self.Bind(wx.EVT_MENU, self.OnLeBail, id=item.GetId()) item = parent.Append(wx.ID_ANY,'&Run Fprime','X-ray resonant scattering') self.Bind(wx.EVT_MENU, self.OnRunFprime, id=item.GetId()) item = parent.Append(wx.ID_ANY,'&Run Absorb','x-ray absorption') self.Bind(wx.EVT_MENU, self.OnRunAbsorb, id=item.GetId()) # 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 = G2fil.LoadImportRoutines('phase','Phase') self.ImportSfactReaderlist = G2fil.LoadImportRoutines('sfact','Struct_Factor') self.ImportPowderReaderlist = G2fil.LoadImportRoutines('pwd','Powder_Data') self.ImportSmallAngleReaderlist = G2fil.LoadImportRoutines('sad','SmallAngle_Data') self.ImportReflectometryReaderlist = G2fil.LoadImportRoutines('rfd','Reflectometry_Data') self.ImportPDFReaderlist = G2fil.LoadImportRoutines('pdf','PDF_Data') self.ImportImageReaderlist = G2fil.LoadImportRoutines('img','Images') self.ImportMenuId = {}
[docs] def testSeqRefineMode(self): '''Returns the list of histograms included in a sequential refinement or an empty list if a standard (non-sequential) refinement. Also sets Menu item status depending on mode ''' cId = GetGPXtreeItemId(self,self.root, 'Controls') if cId: controls = self.GPXtree.GetItemPyData(cId) seqSetting = controls.get('Seq Data',[]) else: seqSetting = None for item in self.Refine: if 'Le Bail' in item.GetItemLabel(): if seqSetting: item.Enable(False) elif seqSetting: item.SetItemLabel('Se&quential refine\tCtrl+R') #might fail on old wx else: item.SetItemLabel('&Refine\tCtrl+R') #might fail on old wx if seqSetting: seqMode = True else: seqMode = False for menu,Id in self.ExportSeq: menu.Enable(Id,seqMode) for menu,Id in self.ExportNonSeq: menu.Enable(Id,not seqMode) return seqSetting
[docs] def PreviewFile(self,filename): 'utility to confirm we have the right file' fp = open(filename,'r') rdmsg = u'File '+ filename +u' begins:\n\n' try: rdmsg += fp.read(80) rdmsg += '\n\nDo you want to read this file?' except UnicodeDecodeError: rdmsg = None fp.close() if rdmsg is None or not all([ord(c) < 128 and ord(c) != 0 for c in rdmsg]): # show only if ASCII rdmsg = u'File '+ filename +u' 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
[docs] 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(),key=lambda k: k.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.FD_OPEN|wx.FD_MULTIPLE else: mode = wx.FD_OPEN if len(readerlist) > 1: typ = ' (type to be guessed)' else: typ = '( type '+readerlist[0].formatName+')' filelist = G2G.GetImportFile(self, message="Choose "+label+" input file"+typ, 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 = '' if len(filelist) == 1 and Preview: if self.PreviewFile(filename): 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 rd.errors = "" # clear out any old errors if not rd.ContentsValidator(filename): # 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 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,self,buffer=rdbuffer,blocknum=block, usedRanIdList=usedRanIdList,) else: try: flag = rd.Reader(filename,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 # Load generic metadata, as configured G2fil.GetColumnMetadata(rd) 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: msg += '\n'+rd.warnings print(u'The '+ rd.formatName+u' reader was not able to read file '+filename+msg) try: print(u'\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.AppendSubMenu(submenu,'Phase','Import phase data') for reader in self.ImportPhaseReaderlist: item = submenu.Append(wx.ID_ANY,u'from '+reader.formatName+u' file',reader.longFormatName) self.ImportMenuId[item.GetId()] = reader self.Bind(wx.EVT_MENU, self.OnImportPhase, id=item.GetId()) item = submenu.Append(wx.ID_ANY,'guess format from file','Import phase data, use file to try to determine format') self.Bind(wx.EVT_MENU, self.OnImportPhase, id=item.GetId())
[docs] 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 = list(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) if rd.Phase['General']['SGData']['SpGrp'] in G2spc.spg2origins: try: choice = G2G.ChooseOrigin(self,rd) if choice is None: return # dialog cancelled rd.Phase = choice except: print('ChooseOrigin failed. Check your atom types') PhaseName = rd.Phase['General']['Name'][:] newPhaseList.append(PhaseName) print(u'Read phase {} from file {}'.format(PhaseName,self.lastimport)) sub = FindPhaseItem(self) psub = self.GPXtree.AppendItem(parent=sub,text=PhaseName) self.GPXtree.SetItemPyData(psub,rd.Phase) wx.CallAfter(self.GPXtree.SelectItem,psub) # should call SelectDataTreeItem try: rd.MPhase['General']['Name'] = G2obj.MakeUniqueLabel(PhaseName+' mag',phaseNameList) PhaseName = rd.MPhase['General']['Name'][:] newPhaseList.append(PhaseName) psub = self.GPXtree.AppendItem(parent=sub,text=PhaseName) self.GPXtree.SetItemPyData(psub,rd.MPhase) wx.CallAfter(self.GPXtree.SelectItem,psub) # should call SelectDataTreeItem except (AttributeError,TypeError): pass self.GPXtree.Expand(self.root) # make sure phases are seen self.GPXtree.Expand(sub) self.GPXtree.Expand(psub) self.PickIdText = None # add constraints imported with phase to tree # at present, constraints are generated only in ISODISTORT_proc in the # CIF import if rd.Constraints: sub = GetGPXtreeItemId(self,self.root,'Constraints') # was created in CheckNotebook if needed Constraints = self.GPXtree.GetItemPyData(sub) for i in rd.Constraints: if type(i) is dict: if '_Explain' not in Constraints: Constraints['_Explain'] = {} Constraints['_Explain'].update(i) else: 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.AppendSubMenu(submenu, 'Image','Import image file') for reader in self.ImportImageReaderlist: item = submenu.Append(wx.ID_ANY,u'from '+reader.formatName+u' file',reader.longFormatName) self.ImportMenuId[item.GetId()] = reader self.Bind(wx.EVT_MENU, self.OnImportImage, id=item.GetId()) item = submenu.Append(wx.ID_ANY,'guess format from file','Import image data, use file to try to determine format') self.Bind(wx.EVT_MENU, self.OnImportImage, id=item.GetId())
[docs] 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.AppendSubMenu(submenu,'Structure Factor','Import Structure Factor data') for reader in self.ImportSfactReaderlist: item = submenu.Append(wx.ID_ANY,u'from '+reader.formatName+u' file',reader.longFormatName) self.ImportMenuId[item.GetId()] = reader self.Bind(wx.EVT_MENU, self.OnImportSfact, id=item.GetId()) item = submenu.Append(wx.ID_ANY,'guess format from file','Import Structure Factor, use file to try to determine format') self.Bind(wx.EVT_MENU, self.OnImportSfact, id=item.GetId())
[docs] 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.maxsize),} HistName = G2obj.MakeUniqueLabel(HistName,HKLFlist) print (u'Read structure factor table '+HistName+u' 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.maxsize),} HistName = G2obj.MakeUniqueLabel(HistName,HKLFlist) print (u'Read structure factor table '+HistName+u' 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 = list(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.AppendSubMenu(submenu,'Powder Data','Import Powder data') for reader in self.ImportPowderReaderlist: item = submenu.Append(wx.ID_ANY,u'from '+reader.formatName+u' file',reader.longFormatName) self.ImportMenuId[item.GetId()] = reader self.Bind(wx.EVT_MENU, self.OnImportPowder, id=item.GetId()) item = submenu.Append(wx.ID_ANY,'guess format from file','Import powder data, use file to try to determine format') self.Bind(wx.EVT_MENU, self.OnImportPowder, id=item.GetId()) submenu.AppendSeparator() item = submenu.Append(wx.ID_ANY,'Simulate a dataset','Create a powder data set entry that will be simulated') self.Bind(wx.EVT_MENU, self.OnDummyPowder, id=item.GetId()) item = submenu.Append(wx.ID_ANY,'Auto Import','Import data files as found') def OnAutoImport(event): G2G.AutoLoadFiles(self,FileTyp='pwd') self.Bind(wx.EVT_MENU, OnAutoImport, id=item.GetId()) item = submenu.Append(wx.ID_ANY,'Fit instr. profile from fundamental parms...','') self.Bind(wx.EVT_MENU, self.OnPowderFPA, id=item.GetId())
[docs] 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
[docs] 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? Note that this routine performs a similar role to :func:`GSASIIfiles.ReadPowderInstprm`, but this will call a GUI routine for selection when needed. TODO: refactor to combine :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,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 if 'Lam1' in newItems: 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]}) return [G2fil.makeInstDict(newItems,newVals,len(newVals)*[False,]),{}]
[docs] 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,'r') 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 + G2G.BlockSelector( choices, self, title=u'Select an instrument parameter bank for '+ os.path.split(rd.powderentry[0])[1]+u' BANK '+str(bank)+ u'\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
[docs] 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 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.) 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 = G2G.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.MultiDataDialog(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] inst1,inst2 = self.ReadPowderInstprm(dI.defaultIparms[res],bank,numbanks,rd) if rd.instdict.get('wave'): inst1['Lam'][0] = rd.instdict.get('wave') inst1['Lam'][1] = rd.instdict.get('wave') return [inst1,inst2] # 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 G2fil.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 = G2fil.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 ' +u'{} 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 = os.path.dirname(filename) #look in same place data was found # pth = G2G.GetImportPath(self) if not pth: pth = '.' extOrd = [0,1] if GSASIIpath.GetConfigValue('Instprm_default',False): extOrd = [1,0] extList = ['GSAS iparm file (*.prm,*.inst,*.ins)|*.prm;*.inst;*.ins|','GSAS-II iparm file (*.instprm)|*.instprm|'] dlg = wx.FileDialog(self, u'Choose inst. param file for "'+rd.idstring+u'" (or Cancel for default)', pth, '',extList[extOrd[0]]+extList[extOrd[1]]+'All files (*.*)|*.*', wx.FD_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 G2fil.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 sub: 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)
[docs] 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] if 'phoenix' in wx.version(): HistName = 'PWDR '+rd.idstring else: 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) try: print('Read powder data '+HistName+ ' from file '+G2obj.StripUnicode(rd.readfilename) + ' (format: '+ rd.formatName + '). Inst parameters from '+G2obj.StripUnicode(rd.instmsg)) except: print('Read powder data') # 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[1] = np.where(np.isinf(rd.powderdata[1]),0.,rd.powderdata[1]) 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.maxsize), 'Offset':[0.0,0.0],'delOffset':0.02*Ymax,'refOffset':-.1*Ymax,'refDelt':0.1*Ymax, '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-1',True,3,1.0,0.0,0.0],{'nDebye':0,'debyeTerms':[],'nPeaks':0,'peaksList':[], 'background PWDR':['',1.0,False]}])) 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 = list(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
[docs] 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 Iparm = self.GetPowderIparm(rd, Iparm, '', lastdatafile) if Iparm is None: return Iparm1, Iparm2 = Iparm if 'T' in Iparm1['Type'][0]: rd.idstring = ' TOF neutron simulation' simType = 'TOF' else: # need to get name, 2theta start, end, step rd.idstring = ' CW' simType = '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 if 'TOF' in rd.idstring: names = ('dataset name', 'start TOF(ms)', 'end TOF(ms)', 'DT/T') inp = [rd.idstring, 10.,80.,0.0005] # 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,.5,1.0,0.0001), maxvals=(None,200.,200.,.001), sizevals=((225,-1),) ) else: 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 if 'TOF' in rd.idstring: N = (np.log(end)-np.log(start))/step x = np.exp((np.arange(0,N))*step+np.log(start*1000.)) N = len(x) else: 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,'simType':simType, 'ranId':ran.randint(0,sys.maxsize), 'Offset':[0.0,0.0],'delOffset':0.02*Ymax,'refOffset':-.1*Ymax,'refDelt':0.1*Ymax, '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-1',True,3,1.0,0.0,0.0], {'nDebye':0,'debyeTerms':[],'nPeaks':0,'peaksList':[],'background PWDR':['',1.0,False]}]) 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 = list(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']] = [] cId = GetGPXtreeItemId(self,self.root, 'Controls') Controls = self.GPXtree.GetItemPyData(cId) Controls['max cyc'] = 0 self.EnableRefineCommand() return # success
[docs] def AddSimulatedPowder(self,ttArr,intArr,HistName,Lam1,Lam2): '''Create a PWDR entry for a computed powder pattern ''' # 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 = 'FPA Simulated dataset', longFormatName = 'Fundamental Parameters 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 powder pattern simulated with Fundamental Parameters') self.CheckNotebook() #self.zipfile = None # get instrument parameters for it rd.Sample.update({'Type':'Bragg-Brentano','Shift':[0.,False],'Transparency':[0.,False], 'SurfRoughA':[0.,False],'SurfRoughB':[0.,False]}) Iparm1, Iparm2 = G2fil.ReadPowderInstprm(dI.defaultIparms[0],1,1,rd) rd.idstring = ' CW' simType = 'CW' # set wavelength if Lam2: Iparm1['Lam1'][0] = Lam1 Iparm1['Lam2'][0] = Lam2 Iparm1['Lam1'][1] = Lam1 Iparm1['Lam2'][1] = Lam2 else: Iparm1['Lam'] = Iparm1['Lam1'] del Iparm1['Lam1'],Iparm1['Lam2'] Iparm1['Lam'][0] = Lam1 Iparm1['Lam'][1] = Lam1 rd.powderdata = [ np.array(ttArr), # x-axis values np.array(intArr), # powder pattern intensities np.ones_like(ttArr), # 1/sig(intensity)^2 values (weights) np.zeros_like(intArr), # calc. intensities (zero) np.zeros_like(ttArr), # calc. background (zero) np.zeros_like(ttArr), # obs-calc profiles ] Tmin = rd.powderdata[0][0] Tmax = rd.powderdata[0][-1] # data are read, now store them in the tree 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,'simType':simType, 'ranId':ran.randint(0,sys.maxsize), 'Offset':[0.0,0.0],'delOffset':0.02*Ymax,'refOffset':-.1*Ymax,'refDelt':0.1*Ymax, '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-1',True,3,1.0,0.0,0.0], {'nDebye':0,'debyeTerms':[],'nPeaks':0,'peaksList':[],'background PWDR':['',1.0,False]}]) 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)) return Id
[docs] def OnPreferences(self,event): 'Edit the GSAS-II configuration variables' dlg = G2G.SelectConfigSetting(self) dlg.ShowModal() == wx.ID_OK dlg.Destroy()
[docs] def EditProxyInfo(self,event): '''Edit the proxy information used by subversion ''' h,p,e = host,port,etc = GSASIIpath.getsvnProxy() labels = ['Proxy address','proxy port'] values = [host,port] i = 1 for item in etc: i += 1 labels.append('extra svn arg #'+str(i)) values.append(item) msg = '''This dialog allows customization of the subversion (svn) command. If a proxy server is needed, the address/host and port can be added supplied here. This will generate command-line options %t% --config-option servers:global:http-proxy-host=*host* %t% --config-option servers:global:http-proxy-port=*port* %% where *host* will be a network name (proxy.subnet.org) or IP address (102.3.123.23) and *port* will be a port number (integer such as 80, 8080, etc) or will be blank. %% Additional subversion command line options can be supplied here by pressing the '+' button. Two lines are needed for each option where the first svn option name (starting with two dashes) and the second line will be the value. As examples of options that might be of value, use two extra lines to add: %t% --config-dir %t% DIR %% to specify an alternate configuration location. %% Or, use four extra lines to add %t% --config-option %t% servers:global:http-proxy-username=*account* %t% --config-option %t% servers:global:http-proxy-password=*password* %% to specify a proxy user name (*account*) and password (*password*). Note that this information will be stored in a plain-text file. %% See http://svnbook.red-bean.com for more information on subversion. ''' dlg = G2G.MultiStringDialog(self,'Enter proxy values', labels,values,size=300,addRows=True,hlp=msg) if dlg.Show(): values = dlg.GetValues() h,p = values[:2] e = values[2:] dlg.Destroy() if h != host or p != port or etc != e: localproxy = proxyinfo = os.path.join( os.path.expanduser('~/.G2local/'), "proxyinfo.txt") if not os.path.exists(proxyinfo): proxyinfo = os.path.join(GSASIIpath.path2GSAS2,"proxyinfo.txt") GSASIIpath.setsvnProxy(h,p,e) if not h.strip() and not e: if os.path.exists(localproxy): os.remove(localproxy) if os.path.exists(proxyinfo): os.remove(proxyinfo) return try: fp = open(proxyinfo,'w') except: fp = open(localproxy,'w') proxyinfo = localproxy try: fp.write(h.strip()+'\n') fp.write(p.strip()+'\n') for i in e: if i.strip(): fp.write(i.strip()+'\n') fp.close() except Exception as err: print('Error writing file {}:\n{}'.format(proxyinfo,err)) print('File {} written'.format(proxyinfo))
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.AppendSubMenu(submenu,'Small Angle Data','Import small angle data') for reader in self.ImportSmallAngleReaderlist: item = submenu.Append(wx.ID_ANY,u'from '+reader.formatName+u' file',reader.longFormatName) 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())
[docs] 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.maxsize), '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.AppendSubMenu(submenu,'Reflectometry Data','Import reflectometry data') for reader in self.ImportReflectometryReaderlist: item = submenu.Append(wx.ID_ANY,u'from '+reader.formatName+u' file',reader.longFormatName) 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())
[docs] 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.maxsize), '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.AppendSubMenu(submenu,'PDF G(R) Data','Import PDF G(R) data') for reader in self.ImportPDFReaderlist: item = submenu.Append(wx.ID_ANY,u'from '+reader.formatName+u' file',reader.longFormatName) self.ImportMenuId[item.GetId()] = reader self.Bind(wx.EVT_MENU, self.OnImportPDF, id=item.GetId()) submenu.AppendSeparator() item = submenu.Append(wx.ID_ANY,'Auto Import','Import PDF files as found') def OnAutoImport(event): G2G.AutoLoadFiles(self,FileTyp='gr') self.Bind(wx.EVT_MENU, OnAutoImport, 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())
[docs] 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.maxsize), 'Offset':[0.0,0.0],'delOffset':0.02*Ymax, 'Yminmax':[Ymin,Ymax], } self.GPXtree.SetItemPyData( self.GPXtree.AppendItem(Id,text='PDF Controls'), {'G(R)':[valuesdict,rd.pdfdata,HistName], 'diffGRname':'','diffMult':1.0,'Rmax':Ymax,}) 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
def AddToNotebook(self,text): Id = GetGPXtreeItemId(self,self.root,'Notebook') data = self.GPXtree.GetItemPyData(Id) data.append('Notebook entry @ %s: %s'%(time.ctime(),text)) ### Command logging ###########################################################
[docs] 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 ('%d %s'%(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): 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? 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.FD_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) # End of logging ############################################################## def _init_Exports(self,menu): '''Find exporter routines and add them into menus ''' # set up the top-level menus projectmenu = wx.Menu() item = menu.AppendSubMenu(projectmenu,'Entire project as','Export entire project') self.ExportNonSeq.append([menu,item.Id]) phasemenu = wx.Menu() item = menu.AppendSubMenu(phasemenu,'Phase as','Export phase or sometimes phases') powdermenu = wx.Menu() item = menu.AppendSubMenu(powdermenu,'Powder data as','Export powder diffraction histogram(s)') sasdmenu = wx.Menu() item = menu.AppendSubMenu(sasdmenu,'Small angle data as','Export small angle histogram(s)') refdmenu = wx.Menu() item = menu.AppendSubMenu(refdmenu,'Reflectometry data as','Export reflectometry histogram(s)') singlemenu = wx.Menu() item = menu.AppendSubMenu(singlemenu,'Single crystal data as','Export single crystal histogram(s)') imagemenu = wx.Menu() item = menu.AppendSubMenu(imagemenu,'Image data as','Export powder image(s) data') mapmenu = wx.Menu() item = menu.AppendSubMenu(mapmenu,'Maps as','Export density map(s)') # sequential exports are handled differently; N.B. enabled in testSeqRefineMode seqPhasemenu = wx.Menu() item = menu.AppendSubMenu(seqPhasemenu,'Sequential phases','Export phases from sequential fit') self.ExportSeq.append([menu,item.Id]) seqHistmenu = wx.Menu() item = menu.AppendSubMenu(seqHistmenu,'Sequential histograms','Export histograms from sequential fit') self.ExportSeq.append([menu,item.Id]) # find all the exporter files if not self.exporterlist: # this only needs to be done once self.exporterlist = G2fil.LoadExportRoutines(self) # 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 == "sasd": submenu = sasdmenu elif typ == "refd": submenu = refdmenu # elif typ == "pdf": # submenu = pdfmenu else: print("Error, unknown type in "+str(obj)) break item = submenu.Append(wx.ID_ANY,obj.formatName,obj.longFormatName) self.Bind(wx.EVT_MENU, obj.Exporter, id=item.GetId()) self.ExportLookup[item.GetId()] = typ # lookup table for submenu item for lbl,submenu in (('Phase',seqPhasemenu), ('Powder',seqHistmenu), ): if lbl.lower() in obj.exporttype: try: obj.Writer except AttributeError: continue # define a unique event handler for this menu item def seqMenuItemEventHandler(event,obj=obj,typ=lbl): 'This handler has the needed exporter/type embedded' # lookup sequential table Id = GetGPXtreeItemId(self,self.root,'Sequential results') if not Id: print('Error in Seq seqMenuItemEventHandler for ',typ,'without Seq Res table') return data = self.GPXtree.GetItemPyData(Id) G2IO.ExportSequential(self,data,obj,typ) if '2' in platform.python_version_tuple()[0]: if 'mode' in inspect.getargspec(obj.Writer)[0]: item = submenu.Append(wx.ID_ANY,obj.formatName,obj.longFormatName) self.Bind(wx.EVT_MENU, seqMenuItemEventHandler, item) else: if 'mode' in inspect.getfullargspec(obj.Writer)[0]: item = submenu.Append(wx.ID_ANY,obj.formatName,obj.longFormatName) self.Bind(wx.EVT_MENU, seqMenuItemEventHandler, item) # self.SeqExportLookup[item.GetId()] = (obj,lbl) # lookup table for submenu item # Bind is in UpdateSeqResults item = imagemenu.Append(wx.ID_ANY,'Multiple image controls and masks', 'Export image controls and masks for multiple images') 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(wx.ID_ANY,'Export All Peak Lists...','') self.ExportPeakList.append(item) item.Enable(True) self.Bind(wx.EVT_MENU, self.OnExportPeakList, id=item.GetId()) item = parent.Append(wx.ID_ANY,'Export HKLs...','') self.ExportHKL.append(item) self.Bind(wx.EVT_MENU, self.OnExportHKL, id=item.GetId()) item = parent.Append(wx.ID_ANY,'Export PDF...','Select PDF item to enable') self.ExportPDF.append(item) item.Enable(False) self.Bind(wx.EVT_MENU, self.OnExportPDF, id=item.GetId())
[docs] 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) item = Import.Append(wx.ID_ANY,'Column metadata test','Test Column (.par) metadata import') self.Bind(wx.EVT_MENU, self.OnColMetaTest, id=item.GetId()) #====================================================================== # 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' # if not rd.ContentsValidator(filename): # 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,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\tCtrl+T','Tutorials'),]) menubar.Append(menu=HelpMenu,title='&Help')
def _init_ctrls(self, parent): try: size = GSASIIpath.GetConfigValue('Main_Size') if type(size) is tuple: pass elif type(size) is str: size = eval(size) else: raise Exception except: size = wx.Size(700,450) wx.Frame.__init__(self, name='GSASII', parent=parent, size=size,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.ExportSeq = [] self.ExportNonSeq = [] #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 try: size = GSASIIpath.GetConfigValue('Plot_Size') if type(size) is tuple: pass elif type(size) is str: size = eval(size) else: raise Exception except: size = wx.Size(700,600) self.plotFrame = wx.Frame(None,-1,'GSASII Plots',size=size, style=wx.DEFAULT_FRAME_STYLE ^ wx.CLOSE_BOX) self.G2plotNB = G2plt.G2PlotNoteBook(self.plotFrame,G2frame=self) self.plotFrame.Show() for win,var in ((self,'Main_Pos'),(self.plotFrame,'Plot_Pos')): try: pos = GSASIIpath.GetConfigValue(var) if type(pos) is str: pos = eval(pos) win.SetPosition(pos) if GetDisplay(pos) is None: win.Center() except: if GSASIIpath.GetConfigValue(var): print('Value for config {} {} is invalid'.format(var,GSASIIpath.GetConfigValue(var))) win.Center() #### init_vars ################################################################ def init_vars(self): # initialize default values for GSAS-II "global" variables (saved in main Frame) self.oldFocus = None self.undofile = '' self.TreeItemDelete = 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 = [] # lines used for data limits & excluded regions self.MagLines = [] # lines used for plot magnification 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.TforYaxis = 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.dataDisplayPhaseText = '' self.lastTreeSetting = [] # used to track the selected Tree item before a refinement self.ExpandingAll = False self.SeqTblHideList = None self.newGPXfile = '' self.lastSelectedPhaseTab = None # track the last tab pressed on a phase window self.testRBObjSizers = {} #rigid body sizer datafile contents self.RMCchoice = 'RMCProfile' 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() if 'phoenix' in wx.version(): self.SetIcon(wx.Icon(img)) else: self.SetIcon(wx.IconFromBitmap(img)) self.Bind(wx.EVT_CLOSE, self.ExitMain) self.GSASprojectfile = '' 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.init_vars() 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')) arg = sys.argv if len(arg) > 1 and arg[1]: try: self.GSASprojectfile = os.path.splitext(arg[1])[0]+u'.gpx' except: self.GSASprojectfile = os.path.splitext(arg[1])[0]+'.gpx' self.dirname = os.path.abspath(os.path.dirname(arg[1])) if self.dirname: self.GSASprojectfile = os.path.split(self.GSASprojectfile)[1] os.chdir(self.dirname) self.LastGPXdir = self.dirname try: #open the file if possible if sys.platform == "darwin": # on Mac delay a bit so GUI can open wx.CallAfter(self.StartProject) else: self.StartProject() return except Exception: print ('Error opening or reading file'+arg[1]) import traceback print (traceback.format_exc()) elif any('SPYDER' in name for name in os.environ): self.OnFileReopen(None) 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())
[docs] 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()
[docs] def OnDataTreeSelChanged(self, event): '''Called when a data tree item is selected. May be called on item deletion as well. ''' 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)
[docs] def OnGPXtreeItemCollapsed(self, event): 'Called when a tree item is collapsed - all children will be collapsed' self.GPXtree.CollapseAllChildren(event.GetItem())
[docs] def OnGPXtreeItemExpanded(self, event): 'Called when a tree item is expanded' event.Skip()
[docs] def OnGPXtreeItemDelete(self, event): 'Called when a tree item is deleted, inhibit the next tree item selection action' self.TreeItemDelete = True
[docs] 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)
[docs] 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: prev = self.GPXtree.GetNextSibling(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.GetNextSibling(item) self.GPXtree.SelectItem(item) else: item = self.GPXtree.GetNextSibling(item) if item.IsOk(): self.GPXtree.SelectItem(item)
[docs] def OnColMetaTest(self,event): 'Test the .par/.*lbls pair for contents' G2imG.testColumnMetadata(self)
[docs] def OnPowderFPA(self,event): 'Perform FPA simulation/peak fitting' # if GSASIIpath.GetConfigValue('debug'): # print('Debug: reloading G2fpa') # import imp # imp.reload(G2fpa) G2fpa.GetFPAInput(self)
[docs] 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.FD_MULTIPLE) try: if dlg.ShowModal() == wx.ID_OK: for file_ajk in dlg.GetPaths(): self.HKL = [] self.powderfile = file_ajk 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 = [G2fil.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()
[docs] def CheckNotebook(self): '''Make sure the data tree has the minimally expected controls. ''' new = False if not GetGPXtreeItemId(self,self.root,'Notebook'): new = True sub = self.GPXtree.AppendItem(parent=self.root,text='Notebook') self.GPXtree.SetItemPyData(sub,['']) if not GetGPXtreeItemId(self,self.root,'Controls'): new = True sub = self.GPXtree.AppendItem(parent=self.root,text='Controls') self.GPXtree.SetItemPyData(sub,copy.copy(G2obj.DefaultControls)) if not GetGPXtreeItemId(self,self.root,'Covariance'): new = True sub = self.GPXtree.AppendItem(parent=self.root,text='Covariance') self.GPXtree.SetItemPyData(sub,{}) if not GetGPXtreeItemId(self,self.root,'Constraints'): new = True sub = self.GPXtree.AppendItem(parent=self.root,text='Constraints') self.GPXtree.SetItemPyData(sub,{'Hist':[],'HAP':[],'Phase':[]}) if not GetGPXtreeItemId(self,self.root,'Restraints'): new = True sub = self.GPXtree.AppendItem(parent=self.root,text='Restraints') self.GPXtree.SetItemPyData(sub,{}) if not GetGPXtreeItemId(self,self.root,'Rigid bodies'): new = True sub = self.GPXtree.AppendItem(parent=self.root,text='Rigid bodies') self.GPXtree.SetItemPyData(sub,{'Vector':{'AtInfo':{}}, 'Residue':{'AtInfo':{}},'RBIds':{'Vector':[],'Residue':[]}}) if new: self.GPXtree.Expand(self.GPXtree.root)
[docs] 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() if parent is not None: parent.Raise() self.EndModal(wx.ID_OK) def OnCancel(self,event): parent = self.GetParent() if parent is not None: parent.Raise() self.EndModal(wx.ID_CANCEL) def GetData(self): return self.data
[docs] class SumDialog(wx.Dialog): '''Allows user to supply scale factor(s) when summing data ''' def __init__(self,parent,title,text,dataType,data,dataList,Limits=None): 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.text = text self.data = data self.average = False self.selectData = copy.copy(data[:-1]) self.selectVals = len(data)*[0.0,] self.dataList = dataList self.Limits = Limits self.filterlist = range(len(self.dataList)) # list of the choice numbers that have been filtered (list of int indices) self.dataType = dataType self.filterVal = '' self.panel = None self.Draw() def Draw(self): if self.panel: self.panel.DestroyChildren() #safe: wx.Panel self.panel.Destroy() size = (480,350) self.panel = wxscroll.ScrolledPanel(self, wx.ID_ANY,size=size, style = wx.TAB_TRAVERSAL|wx.SUNKEN_BORDER) mainSizer = wx.BoxSizer(wx.VERTICAL) mainSizer.Add(wx.StaticText(self.panel,label=self.text),0) mainSizer.Add((10,10)) self.dataGridSizer = wx.FlexGridSizer(cols=2,hgap=2,vgap=2) self.dataGridSizer.Add((-1,-1)) topSizer = wx.BoxSizer(wx.HORIZONTAL) topSizer.Add((-1,-1),1,wx.EXPAND,1) topSizer.Add(wx.StaticText(self.panel,label='Filter: '),0,WACV) self.timer = wx.Timer() self.timer.Bind(wx.EVT_TIMER,self.OnFilter) self.filterBox = wx.TextCtrl(self.panel, wx.ID_ANY, self.filterVal, size=(80,-1),style=wx.TE_PROCESS_ENTER) self.filterBox.Bind(wx.EVT_TEXT,self.onChar) self.filterBox.Bind(wx.EVT_TEXT_ENTER,self.OnFilter) topSizer.Add(self.filterBox,0,WACV) self.dataGridSizer.Add(topSizer,1,wx.RIGHT|wx.BOTTOM|wx.EXPAND,1) self.dataGridSizer.Add((-1,10)) self.dataGridSizer.Add((-1,10)) for Id,item in enumerate(self.selectData): name = wx.TextCtrl(self.panel,-1,item,size=wx.Size(300,20)) name.SetEditable(False) scale = G2G.ValidatedTxtCtrl(self.panel,self.selectVals,Id,nDig=(10,3),typeHint=float) self.dataGridSizer.Add(scale,0,wx.LEFT,10) self.dataGridSizer.Add(name,0,wx.RIGHT,10) if self.dataType: ScaleAll = wx.Button(self.panel,wx.ID_ANY,'Set all above') ScaleAll.Bind(wx.EVT_BUTTON, self.OnAllScale) if self.dataType == 'PWDR': self.Avg = wx.CheckBox(self.panel,label=' Make average?') self.Avg.Bind(wx.EVT_CHECKBOX,self.OnAve) self.dataGridSizer.Add(ScaleAll,0,wx.LEFT,10) if self.dataType == 'PWDR': self.dataGridSizer.Add(self.Avg,0,wx.RIGHT,10) self.dataGridSizer.Add(wx.StaticText(self.panel,-1,' Result type: '+self.dataType),1, wx.LEFT|wx.ALIGN_CENTER_VERTICAL,1) mainSizer.Add(self.dataGridSizer,0,wx.EXPAND) self.name = G2G.ValidatedTxtCtrl(self.panel,self.data,-1,size=wx.Size(300,20)) mainSizer.Add(self.name,0,wx.RIGHT|wx.TOP,10) self.OkBtn = wx.Button(self.panel,-1,"Ok") self.OkBtn.Bind(wx.EVT_BUTTON, self.OnOk) cancelBtn = wx.Button(self.panel,-1,"Cancel") cancelBtn.Bind(wx.EVT_BUTTON, self.OnCancel) btnSizer = wx.FlexGridSizer(0,3,10,20) if self.dataType =='PWDR': TestBtn = wx.Button(self.panel,-1,"Test") TestBtn.Bind(wx.EVT_BUTTON, self.OnTest) btnSizer.Add(TestBtn) btnSizer.Add(self.OkBtn) btnSizer.Add(cancelBtn) btnSizer.Add((5,5)) self.panel.SetSizer(mainSizer) self.panel.SetAutoLayout(1) self.panel.SetupScrolling() mainSizer.Add((10,10),1) mainSizer.Add(btnSizer,0,wx.CENTER) self.panel.SetSizer(mainSizer) self.panel.Fit() self.Fit() def OnAve(self,event): self.average = self.Avg.GetValue()
[docs] def OnFilter(self,event): '''Read text from filter control and select entries that match. ''' if self.timer.IsRunning(): self.timer.Stop() self.filterVal = txt = self.filterBox.GetValue() if txt: txt = txt.lower() ChoiceList = [] ChoiceVals = [] for i,item in enumerate(self.selectData): if item.lower().find(txt) != -1: ChoiceList.append(item) ChoiceVals.append(self.selectVals[i]) self.selectData = ChoiceList self.selectVals = ChoiceVals else: # self.selectData = copy.copy(self.data[:-1]) self.selectVals = len(self.data)*[0.0,] wx.CallAfter(self.Draw)
def GetData(self): if self.dataType == 'PWDR': return self.selectData+[self.data[-1],],self.result else: return self.selectData+[self.data[-1],],self.selectVals
[docs] def onChar(self,event): 'Respond to keyboard events in the Filter box' self.filterVal = self.filterBox.GetValue() if self.timer.IsRunning(): self.timer.Stop() self.timer.Start(1000,oneShot=True) if event: event.Skip()
def OnAllScale(self,event): dlg = G2G.SingleFloatDialog(self,'New scale', 'Enter new value for all scale factors',1.) dlg.CenterOnParent() if dlg.ShowModal() == wx.ID_OK: val = dlg.GetValue() dlg.Destroy() else: dlg.Destroy() return for Id,item in enumerate(self.selectData): self.selectVals[Id] = val wx.CallAfter(self.Draw) def OnTest(self,event): lenX = 0 Xminmax = [0,0] XY = [] Xsum = [] Ysum = [] Vsum = [] for i,item in enumerate(self.selectData): name = item scale = self.selectVals[i] Id = self.data.index(name) data = self.dataList[Id] if scale: x,y,w,yc,yb,yd = data #numpy arrays! if self.Limits is not None: xMin = np.searchsorted(x,self.Limits[1][0]) xMax = np.searchsorted(x,self.Limits[1][1]) x = x[xMin:xMax+1] y = y[xMin:xMax+1] lenX = xMax-xMin+1 XY.append([x,scale*y]) v = 1./w[xMin:xMax+1] if lenX: if lenX != len(x): self.GetParent().ErrorDialog('Data length error','Data to be summed must have same number of points'+ '\nExpected:'+str(lenX)+ '\nFound: '+str(len(x))+'\nfor '+name) return # self.OnCancel(event) else: lenX = len(x) if Xminmax[1]: if Xminmax != [x[0],x[-1]]: self.GetParent().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) return # self.OnCancel(event) else: Xminmax = [x[0],x[-1]] Xsum = x if self.dataType == 'PWDR' and self.average: Ysum.append(scale*y) Vsum.append(abs(scale)*v) else: try: Ysum += scale*y Vsum += abs(scale)*v except ValueError: Ysum = scale*y Vsum = abs(scale)*v if self.dataType =='PWDR' and self.average: maYsum = ma.masked_equal(Ysum,0) Ysum = ma.mean(maYsum,axis=0) Wsum = 1./np.array(Ysum) else: Wsum = 1./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. if len(XY[0][0]): G2plt.PlotXY(self,XY,lines=True,Title='Sum:'+self.data[-1],labelY='Intensity',) self.plotFrame.Show() return True def OnOk(self,event): if self.dataType == 'PWDR': if not self.OnTest(event): return parent = self.GetParent() if parent is not None: parent.Raise() self.EndModal(wx.ID_OK) def OnCancel(self,event): parent = self.GetParent() if parent is not None: parent.Raise() self.EndModal(wx.ID_CANCEL)
[docs] def OnPwdrSum(self,event): 'Sum or Average together powder data(?)' TextList = [] DataList = [] Limits = [] Names = [] Inst = None Comments = ['Sum/Average 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(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')) if not Limits: Limits = self.GPXtree.GetItemPyData(GetGPXtreeItemId(self,item, 'Limits')) item, cookie = self.GPXtree.GetNextChild(self.root, cookie) if len(TextList) < 2: self.ErrorDialog('Not enough data to sum/average','There must be more than one "PWDR" pattern') return TextList.append('default_ave_name') dlg = self.SumDialog(self,'Sum/Average data',''' Enter scale for each pattern to be summed/averaged Limits for first pattern used sets range for the sum All patterns used must extend over this range ''','PWDR', TextList,DataList,Limits) 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.maxsize), 'Offset':[0.0,0.0],'delOffset':0.02*Ymax,'refOffset':-.1*Ymax,'refDelt':0.1*Ymax, '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-1',True,3,1.0,0.0,0.0], {'nDebye':0,'debyeTerms':[],'nPeaks':0,'peaksList':[],'background PWDR':['',1.0,False]}]) 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()
[docs] 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(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 to be summed','IMG', TextList,DataList) try: if dlg.ShowModal() == wx.ID_OK: imSize = 0 result,scales = dlg.GetData() First = True Found = False for name,scale in zip(result,scales): if scale: Found = True Comments.append("%10.3f %s" % (scale,' * '+name)) i = TextList.index(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 = os.path.split(os.path.abspath(imagefile))[0] # pth = G2G.GetExportPath(self) dlg = wx.FileDialog(self, 'Choose sum image filename', pth,outname.split('IMG ')[1], 'G2img files (*.G2img)|*.G2img', wx.FD_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.update(copy.deepcopy(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]], 'SpotMask':{'esdMul':2.,'spotMask':None}} 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()
[docs] def OnAddPhase(self,event): 'Add a new, empty phase to the tree. Called by Data/Add Phase menu' 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() self.CheckNotebook() sub = FindPhaseItem(self) dlg.Destroy() else: dlg.Destroy() return if not GetGPXtreeItemId(self,self.root,'Restraints'): subr = self.GPXtree.AppendItem(parent=self.root,text='Restraints') self.GPXtree.SetItemPyData(subr,{PhaseName:{}}) else: subr = GetGPXtreeItemId(self,self.root,'Restraints') self.GPXtree.GetItemPyData(subr).update({PhaseName:{}}) self.GPXtree.AppendItem(parent=subr,text=PhaseName) newphase = self.GPXtree.AppendItem(parent=sub,text=PhaseName) E,SGData = G2spc.SpcGroup('P 1') self.GPXtree.SetItemPyData(newphase,G2obj.SetNewPhase(Name=PhaseName,SGData=SGData)) self.GPXtree.Expand(sub) SelectDataTreeItem(self,newphase) #bring up new phase General tab
[docs] def OnDeletePhase(self,event): '''Delete one or more phases from the tree. Called by Data/Delete Phase menu. Also delete this phase from Reflection Lists for each PWDR histogram; removes the phase from restraints and deletes any constraints with variables from the phase. If any deleted phase is marked as Used in a histogram, a more rigorous "deep clean" is done and histogram refinement results are cleared, as well as the covariance information and all plots are deleted ''' selItem = self.GPXtree.GetSelection() if self.dataWindow: self.dataWindow.ClearData() TextList = [] DelList = [] DelItemList = [] consDeleted = 0 usedPhase = False if GetGPXtreeItemId(self,self.root,'Phases'): sub = GetGPXtreeItemId(self,self.root,'Phases') else: return if GetGPXtreeItemId(self,self.root,'Restraints'): subr = GetGPXtreeItemId(self,self.root,'Restraints') else: subr = 0 if GetGPXtreeItemId(self,self.root,'Constraints'): id = GetGPXtreeItemId(self,self.root,'Constraints') constr = self.GPXtree.GetItemPyData(id) else: constr = {} 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(s) 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: phase = self.GPXtree.GetItemPyData(item) for h in phase['Histograms']: if 'Use' not in phase['Histograms'][h]: continue if phase['Histograms'][h]['Use']: usedPhase = True break if 'pId' in phase: p = phase['pId'] else: p = '?' self.GPXtree.Delete(item) if item == selItem: selItem = self.root # look for constraints to remove for key in constr: delThis = [] if key.startswith('_'): continue for i,cons in enumerate(constr[key]): for var in cons[0:-3]: if str(var[1]).startswith(str(p)): delThis.append(i) break for i in reversed(delThis): consDeleted += 1 del constr[key][i] # delete refinement results from histograms item, cookie = self.GPXtree.GetFirstChild(self.root) while item: name = self.GPXtree.GetItemText(item) if 'PWDR' in name: data = self.GPXtree.GetItemPyData(item) if usedPhase: # remove r-factors dellist = [value for value in data[0] if ':' in value] for v in dellist+['Durbin-Watson', 'R', 'wR', 'Rb', 'wRb', 'wRmin','Nobs']: if v in data[0]: del data[0][v] # could wipe out computed & difference patterns, but does not work #data[1][3] = np.zeros_like(data[1][3]) #data[1][5] = np.zeros_like(data[1][5]) # always get rid of reflection lists 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]) elif 'HKLF' in name and usedPhase: # probably not needed if phase is not used data = self.GPXtree.GetItemPyData(item) data[0] = {} item, cookie = self.GPXtree.GetNextChild(self.root, cookie) finally: dlg.Destroy() if usedPhase: # clear info from last refinement for "deep clean" if a used phase is deleted id = GetGPXtreeItemId(self,self.root,'Covariance') if DelItemList and id: self.GPXtree.SetItemPyData(id,{}) id = GetGPXtreeItemId(self,self.root,'Sequential results') if DelItemList and id: self.GPXtree.Delete(id) if id == selItem: selItem = self.root # delete all plots for lbl in self.G2plotNB.plotList: self.G2plotNB.Delete(lbl) if subr and DelList: #remove restraints for deleted phase DelList = [itm[1] for itm in DelList] item, cookie = self.GPXtree.GetFirstChild(subr) while item: name = self.GPXtree.GetItemText(item) if name in DelList: self.GPXtree.Delete(item) if item == selItem: selItem = self.root item, cookie = self.GPXtree.GetNextChild(subr, cookie) # force redisplay of current tree item if it was not deleted self.PickId = 0 self.PatternId = 0 self.PickIdText = None SelectDataTreeItem(self,selItem) wx.CallAfter(self.GPXtree.SelectItem,selItem) if consDeleted: print('\n',consDeleted,'constraints were deleted')
[docs] def OnRenameData(self,event): '''Renames an existing histogram. Called by Data/Rename Phase menu. Must be used before a histogram is used in a phase. ''' name = self.GPXtree.GetItemText(self.PickId) Histograms,Phases = self.GetUsedHistogramsAndPhasesfromTree() if name in Histograms: G2G.G2MessageBox(self, 'Histogram is used. You must remove it from all phases before it can be renamed', 'Rename not allowed') return 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 = G2G.SingleStringDialog(self,'Change tree name', 'Data name: '+name,names[0][names[0].index(' ')+1:]) #if dlg.ShowModal() == wx.ID_OK: if dlg.Show(): name = dataType+dlg.GetValue().strip()+names[1] self.GPXtree.SetItemText(self.PickId,name) if 'PWDR' in name: self.GPXtree.GetItemPyData(self.PickId)[2] = name dlg.Destroy()
[docs] 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
[docs] 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 = [] selItem = self.GPXtree.GetSelection() Histograms,Phases = self.GetUsedHistogramsAndPhasesfromTree() if not self.GPXtree.GetCount(): G2G.G2MessageBox(self,'No tree items to be deleted', 'Nothing to delete') return item, cookie = self.GPXtree.GetFirstChild(self.root) used = False seqUse = False while item: name = self.GPXtree.GetItemText(item) item, cookie = self.GPXtree.GetNextChild(self.root, cookie) if name in ['Notebook','Controls','Covariance','Constraints', 'Restraints','Phases','Rigid bodies','Hist/Phase']: continue if 'Sequential' in name: continue if name in self.testSeqRefineMode(): seqUse = True continue if 'PWDR' in name[:4]: nItems['PWDR'] += 1 if name in Histograms: used = True continue 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 name in Histograms: used = True continue if 'PDF' in name[:3]: PDFnames.append(name) nItems['PDF'] += 1 TextList.append(name) for pdfName in PDFnames: try: TextList.remove('PWDR'+pdfName[4:]) except ValueError: print (u'PWDR'+pdfName[4:]+u' for '+pdfName+u' not found') if len(TextList) == 0: if used: msg = 'All histograms are associated with at least one phase. You must unset a histogram "use" flag in all phase(s) where it is referenced before it can be deleted' elif seqUse: msg = 'All histograms are in used in the sequential list. You must remove it from the list (in Controls) before it can be deleted' else: msg = 'No data items found in tree to delete' G2G.G2MessageBox(self,msg,'Nothing to delete') return 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) if item == selItem: selItem = self.root if DelList: self.PickId = 0 self.PickIdText = None self.PatternId = 0 if nItems['PWDR']: wx.CallAfter(G2plt.PlotPatterns,self,True) else: self.G2plotNB.Delete('Powder Patterns') self.lastPlotType = None 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() if DelList: SelectDataTreeItem(self,selItem) self.GPXtree.UpdateSelection()
# self.GPXtree.SelectItem(self.root) # self.GPXtree.SelectItem(selItem)
[docs] def OnPlotDelete(self,event): '''Delete one or more plots from plot window. Called by the Data/DeletePlots menu ''' plotNames = self.G2plotNB.plotList if len(plotNames): dlg = G2G.G2MultiChoiceDialog(self, 'Which plots to delete?', 'Delete plots', plotNames, wx.CHOICEDLG_STYLE) try: if dlg.ShowModal() == wx.ID_OK: result = dlg.GetSelections() result.sort(reverse=True) for i in result: self.G2plotNB.Delete(plotNames[i]) finally: dlg.Destroy()
def OnFileReopen(self, event): files = GSASIIpath.GetConfigValue('previous_GPX_files') if not files: print('no previous projects found') return sellist = [] for f in files: dirname,filroot = os.path.split(f) if os.path.exists(f) and '.gpx' in f: sellist.append("{} from {}".format(filroot,dirname)) # else: # sellist.append("not found: {}".format(f)) dlg = G2G.G2SingleChoiceDialog(self, 'Select previous project to open', 'Select project',sellist) if dlg.ShowModal() == wx.ID_OK: sel = dlg.GetSelection() dlg.Destroy() else: dlg.Destroy() return filroot,dirname = sellist[sel].split(' from ') f = os.path.join(dirname,filroot) if os.path.exists(f): self.OnFileOpen(event, filename=f) self.LastGPXdir = dirname else: print('file not found',f)
[docs] def OnFileOpen(self, event, filename=None): '''Gets a GSAS-II .gpx project file in response to the File/Open Project menu button ''' def SaveOld(): '''See if we should save current project and continue to read another. returns True if the project load should continue ''' if self.dataWindow: self.dataWindow.ClearData() dlg = wx.MessageDialog(self, 'Do you want to save and replace the current project?\n(Use No to read without saving or Cancel to continue with current project)', 'Save & Overwrite?', wx.YES|wx.NO|wx.CANCEL) try: result = dlg.ShowModal() finally: dlg.Destroy() if result == wx.ID_NO: result = True elif result == wx.ID_CANCEL: return False else: if not self.OnFileSave(None): return False self.GPXtree.DeleteChildren(self.root) self.GSASprojectfile = '' self.HKL = [] if self.G2plotNB.plotList: self.G2plotNB.clear() return True def GetGPX(): if self.LastGPXdir: pth = self.LastGPXdir else: pth = '.' #if GSASIIpath.GetConfigValue('debug'): print('debug: open from '+pth) dlg = wx.FileDialog(self, 'Choose GSAS-II project file', pth, wildcard='GSAS-II project file (*.gpx)|*.gpx',style=wx.FD_OPEN) try: if dlg.ShowModal() != wx.ID_OK: return self.GSASprojectfile = dlg.GetPath() self.GSASprojectfile = G2IO.FileDlgFixExt(dlg,self.GSASprojectfile) self.LastGPXdir = dlg.GetDirectory() finally: dlg.Destroy() self.EnablePlot = False if self.GPXtree.GetChildrenCount(self.root,False): if not SaveOld(): return if not filename: GetGPX() filename = self.GSASprojectfile else: try: self.GSASprojectfile = os.path.splitext(filename)[0]+u'.gpx' except: self.GSASprojectfile = os.path.splitext(filename)[0]+'.gpx' self.dirname = os.path.split(filename)[0] # if self.G2plotNB.plotList: # self.G2plotNB.clear() self.init_vars() try: self.StartProject() #open the file if possible except: print ('\nError opening file '+filename) import traceback print (traceback.format_exc())
[docs] 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 seqId = 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: name = self.GPXtree.GetItemText(item) if name[:4] in ['PWDR','HKLF','IMG ','PDF ','SASD','REFD']: if not Id: if name[:4] == 'IMG ': Id = GetGPXtreeItemId(self,item,'Image Controls') else: Id = item elif name.startswith("Sequential") and self.testSeqRefineMode(): seqId = item elif name == "Phases": phaseId = item elif name == 'Controls': data = self.GPXtree.GetItemPyData(item) if data: for item in self.Refine: item.Enable(True) item, cookie = self.GPXtree.GetNextChild(self.root, cookie) if phaseId: # show all phases self.GPXtree.Expand(phaseId) if seqId: self.EnablePlot = True SelectDataTreeItem(self,seqId) self.GPXtree.SelectItem(seqId) # needed on OSX or item is not selected in tree; perhaps not needed elsewhere elif Id: self.EnablePlot = True self.GPXtree.Expand(Id) SelectDataTreeItem(self,Id) self.GPXtree.SelectItem(Id) # needed on OSX or item is not selected in tree; perhaps not needed elsewhere elif phaseId: Id = phaseId # open 1st phase Id, unused = self.GPXtree.GetFirstChild(phaseId) SelectDataTreeItem(self,Id) self.GPXtree.SelectItem(Id) # as before for OSX 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,write=False) config = G2G.GetConfigValsDocs() GSASIIpath.addPrevGPX(self.GSASprojectfile,config) G2G.SaveConfigVars(config) self.LastGPXdir = pth
[docs] 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, 'Do you want to save the current project and start with an empty one?\n(Use No to clear without saving or Cancel to continue with current project)', 'Save & Clear?', 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) self.dataWindow.ClearData() if len(self.HKL): self.HKL = [] if self.G2plotNB.plotList: self.G2plotNB.clear() self.SetTitleByGPX() self.EnableRefineCommand() self.init_vars() finally: dlg.Destroy()
[docs] 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) return True else: return self.OnFileSaveas(event)
[docs] def OnNewGSASII(self, event): '''Gets a GSAS-II .gpx project file in response to the File/Open new window menu button. Runs only on Mac. ''' if self.LastGPXdir: pth = self.LastGPXdir else: pth = '.' GSASprojectfile = '' dlg = wx.FileDialog(self, 'Choose GSAS-II project file', pth, wildcard='GSAS-II project file (*.gpx)|*.gpx',style=wx.FD_OPEN) try: if dlg.ShowModal() == wx.ID_OK: GSASprojectfile = dlg.GetPath() GSASprojectfile = G2IO.FileDlgFixExt(dlg,GSASprojectfile) self.LastGPXdir = dlg.GetDirectory() finally: dlg.Destroy() G2script = os.path.join(os.path.split(__file__)[0],'GSASII.py') GSASIIpath.MacStartGSASII(G2script,GSASprojectfile)
[docs] def SetTitleByGPX(self): '''Set the title for the two window frames ''' projName = os.path.split(self.GSASprojectfile)[1] if not projName: projName = "<unnamed project>" if self.testSeqRefineMode(): s = u' (sequential refinement)' else: s = u'' self.SetTitle("GSAS-II project: "+projName + s) self.plotFrame.SetTitle("GSAS-II plots: "+projName)
[docs] 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, self.newGPXfile, 'GSAS-II project file (*.gpx)|*.gpx',wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT) try: if dlg.ShowModal() == wx.ID_OK: #TODO: what about Cancel? self.GSASprojectfile = dlg.GetPath() self.GSASprojectfile = G2IO.FileDlgFixExt(dlg,self.GSASprojectfile) self.GPXtree.SetItemText(self.root,'Project: '+self.GSASprojectfile) self.CheckNotebook() G2IO.ProjFileSave(self) self.SetTitleByGPX() os.chdir(dlg.GetDirectory()) # to get Mac/Linux to change directory! config = G2G.GetConfigValsDocs() GSASIIpath.addPrevGPX(self.GSASprojectfile,config) G2G.SaveConfigVars(config) return True else: return False finally: dlg.Destroy()
[docs] 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
[docs] 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)
[docs] def ExitMain(self, event): '''Called if exit selected or the main window is closed rescord last position of data & plot windows; saved to config.py file NB: not called if console window closed ''' if self.GPXtree.GetCount() > 1: dlg = wx.MessageDialog(self, 'Do you want to save and exit?\n(Use No to exit without save or Cancel to prevent exiting)', 'Confirm exit/save?', wx.YES|wx.NO|wx.CANCEL) try: dlg.CenterOnParent() result = dlg.ShowModal() finally: dlg.Destroy() else: result = wx.ID_NO if result == wx.ID_NO: pass elif result == wx.ID_CANCEL: return else: if not self.OnFileSave(event): return FrameInfo = {'Main_Pos':tuple(self.GetPosition()), 'Main_Size':tuple(self.GetSize()), 'Plot_Pos':tuple(self.plotFrame.GetPosition()), 'Plot_Size':tuple(self.plotFrame.GetSize())} GSASIIpath.SetConfigValue(FrameInfo) # FramePos = {'Main_Pos':tuple(self.GetPosition()),'Plot_Pos':tuple(self.plotFrame.GetPosition())} # GSASIIpath.SetConfigValue(FramePos) config = G2G.GetConfigValsDocs() G2G.SaveConfigVars(config) if self.G2plotNB: self.G2plotNB.Destroy() if self.undofile: os.remove(self.undofile) sys.exit()
def OnExportPeakList(self,event): 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 %10s\n'%('pos','dsp','esd','int','esd','alp','bet','sig','gam','FWHM')) else: file.write('#%9s %10s %10s %12s %10s %10s %10s %10s\n'%('pos','dsp','esd','int','esd','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 list(esds.keys()): esds[name] = sigDict.get('%s%d'%(name,ip),0.) sig = np.sqrt(peak[8]) gam = peak[10] esddsp = abs(G2lat.Pos2dsp(Inst,peak[0]-esds['pos'])-G2lat.Pos2dsp(Inst,peak[0]+esds['pos']))/2. FWHM = G2pwd.getgamFW(gam,sig) +(peak[4]+peak[6])*np.log(2.)/(peak[4]*peak[6]) #to get delta-TOF from Gam(peak) file.write("%10.2f %10.5f %10.5f %12.2f%10.2f %10.3f %10.3f %10.3f %10.3f %10.3f\n" % \ (peak[0],dsp,esddsp,peak[2],esds['int'],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 list(esds.keys()): esds[name] = sigDict.get('%s%d'%(name,ip),0.) sig = np.sqrt(peak[4]) #var -> sig gam = peak[6] esddsp = abs(G2lat.Pos2dsp(Inst,peak[0]-esds['pos'])-G2lat.Pos2dsp(Inst,peak[0]+esds['pos']))/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.2f %10.5f %10.5f %10.5f \n" % \ (peak[0],dsp,esddsp,peak[2],esds['int'],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()
[docs] def OnExportPDF(self,event): 'Save S(Q), G(R),... as selected by user' def PDFSave(G2frame,exports,PDFsaves): 'Save a PDF I(Q), S(Q), F(Q), G(r) and g(r) in column formats' if len(exports) > 1: dirname = G2G.askSaveDirectory(G2frame) if not dirname: return else: defnam = exports[0].replace(' ','_')[5:] filename = G2G.askSaveFile(G2frame,defnam,'.gr','G(r) file, etc.') if not filename: return dirname,filename = os.path.split(filename) filename = os.path.splitext(filename)[0] Inst = None Limits = None for export in exports: if len(exports) > 1: filename = export.replace(' ','_')[5:] PickId = GetGPXtreeItemId(G2frame, G2frame.root, export) PDFControls = G2frame.GPXtree.GetItemPyData( GetGPXtreeItemId(G2frame, PickId,'PDF Controls')) if PDFsaves[4]: #pdfGUI file for G(R) pId = GetGPXtreeItemId(G2frame, G2frame.root, 'PWDR'+export[4:]) Inst = G2frame.GPXtree.GetItemPyData( GetGPXtreeItemId(G2frame, pId,'Instrument Parameters'))[0] Limits = G2frame.GPXtree.GetItemPyData( GetGPXtreeItemId(G2frame, pId,'Limits')) G2fil.PDFWrite(export,os.path.join(dirname,filename), PDFsaves,PDFControls,Inst,Limits) 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, 'label_6':'Make F(Q) & g(r) for RMCProfile','value_6':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'],od['value_6']] PDFSave(self,exports,PDFsaves)
[docs] 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].strip('"\n').split() try: if len(formula) < 2: raise ValueError 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: G2G.G2MessageBox(self,'Carbon-based (and wrong) PDF will be generated','Missing chemical formula') ElData = G2elem.GetElInfo('C',Parms) sumnum = 1.0 ElData['FormulaNo'] = 1.0 ElList['C'] = 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()
[docs] 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.maxsize) if 'ranId' not in PWDRdata['Sample Parameters']: # I hope this becomes obsolete at some point PWDRdata['Sample Parameters']['ranId'] = PWDRdata['ranId'] return PWDRdata
[docs] 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
[docs] 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.maxsize) item, cookie = self.GPXtree.GetNextChild(sub, cookie) return phaseData
[docs] def GetPhaseInfofromTree(self, Used=False): '''Get the phase names and their rId values, also the histograms referenced in each phase. :param bool Used: if Used is True, only histograms that are referenced in the histogram are returned :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 = []