# -*- coding: utf-8 -*-
'''
*GSASIIplot: plotting routines*
===============================
'''
########### SVN repository information ###################
# $Date: 2015-03-10 11:35:24 -0500 (Tue, 10 Mar 2015) $
# $Author: vondreele $
# $Revision: 1694 $
# $URL: https://subversion.xray.aps.anl.gov/pyGSAS/trunk/GSASIIplot.py $
# $Id: GSASIIplot.py 1694 2015-03-10 16:35:24Z vondreele $
########### SVN repository information ###################
import math
import time
import copy
import sys
import os.path
import numpy as np
import numpy.ma as ma
import numpy.linalg as nl
import wx
import wx.aui
import wx.glcanvas
import matplotlib as mpl
import mpl_toolkits.mplot3d.axes3d as mp3d
import GSASIIpath
GSASIIpath.SetVersionNumber("$Revision: 1694 $")
import GSASIIgrid as G2gd
import GSASIIimage as G2img
import GSASIIpwd as G2pwd
import GSASIIIO as G2IO
import GSASIIpwdGUI as G2pdG
import GSASIIimgGUI as G2imG
import GSASIIphsGUI as G2phG
import GSASIIlattice as G2lat
import GSASIIspc as G2spc
import GSASIImath as G2mth
import GSASIIctrls as G2G
import pytexture as ptx
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLE import *
import gltext
from matplotlib.backends.backend_wx import _load_bitmap
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as Canvas
from matplotlib.backends.backend_wxagg import NavigationToolbar2Wx as Toolbar
# useful degree trig functions
sind = lambda x: math.sin(x*math.pi/180.)
cosd = lambda x: math.cos(x*math.pi/180.)
tand = lambda x: math.tan(x*math.pi/180.)
asind = lambda x: 180.*math.asin(x)/math.pi
acosd = lambda x: 180.*math.acos(x)/math.pi
atan2d = lambda x,y: 180.*math.atan2(y,x)/math.pi
atand = lambda x: 180.*math.atan(x)/math.pi
# numpy versions
npsind = lambda x: np.sin(x*np.pi/180.)
npcosd = lambda x: np.cos(x*np.pi/180.)
nptand = lambda x: np.tan(x*np.pi/180.)
npacosd = lambda x: 180.*np.arccos(x)/np.pi
npasind = lambda x: 180.*np.arcsin(x)/np.pi
npatand = lambda x: 180.*np.arctan(x)/np.pi
npatan2d = lambda x,y: 180.*np.arctan2(x,y)/np.pi
GkDelta = unichr(0x0394)
[docs]class G2PlotMpl(wx.Panel):
'needs a doc string'
def __init__(self,parent,id=-1,dpi=None,**kwargs):
wx.Panel.__init__(self,parent,id=id,**kwargs)
mpl.rcParams['legend.fontsize'] = 10
self.figure = mpl.figure.Figure(dpi=dpi,figsize=(5,6))
self.canvas = Canvas(self,-1,self.figure)
self.toolbar = GSASIItoolbar(self.canvas)
self.toolbar.Realize()
sizer=wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.canvas,1,wx.EXPAND)
sizer.Add(self.toolbar,0,wx.LEFT|wx.EXPAND)
self.SetSizer(sizer)
[docs]class G2PlotOgl(wx.Panel):
'needs a doc string'
def __init__(self,parent,id=-1,dpi=None,**kwargs):
self.figure = wx.Panel.__init__(self,parent,id=id,**kwargs)
if 'win' in sys.platform: #Windows (& Mac) already double buffered
self.canvas = wx.glcanvas.GLCanvas(self,-1,**kwargs)
else: #fix from Jim Hester for X systems
attribs = (wx.glcanvas.WX_GL_DOUBLEBUFFER,)
self.canvas = wx.glcanvas.GLCanvas(self,-1,attribList=attribs,**kwargs)
# create GL context for wx > 2.8
i,j= wx.__version__.split('.')[0:2]
if int(i)+int(j)/10. > 2.8:
self.context = wx.glcanvas.GLContext(self.canvas)
self.canvas.SetCurrent(self.context)
else:
self.context = None
self.camera = {}
sizer=wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.canvas,1,wx.EXPAND)
self.SetSizer(sizer)
[docs]class G2Plot3D(wx.Panel):
'needs a doc string'
def __init__(self,parent,id=-1,dpi=None,**kwargs):
wx.Panel.__init__(self,parent,id=id,**kwargs)
self.figure = mpl.figure.Figure(dpi=dpi,figsize=(6,6))
self.canvas = Canvas(self,-1,self.figure)
self.toolbar = GSASIItoolbar(self.canvas)
self.toolbar.Realize()
sizer=wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.canvas,1,wx.EXPAND)
sizer.Add(self.toolbar,0,wx.LEFT|wx.EXPAND)
self.SetSizer(sizer)
[docs]class G2PlotNoteBook(wx.Panel):
'create a tabbed window for plotting'
def __init__(self,parent,id=-1):
wx.Panel.__init__(self,parent,id=id)
#so one can't delete a plot page!!
self.nb = wx.aui.AuiNotebook(self, \
style=wx.aui.AUI_NB_DEFAULT_STYLE ^ wx.aui.AUI_NB_CLOSE_ON_ACTIVE_TAB)
sizer = wx.BoxSizer()
sizer.Add(self.nb,1,wx.EXPAND)
self.SetSizer(sizer)
self.status = parent.CreateStatusBar()
self.status.SetFieldsCount(2)
self.status.SetStatusWidths([150,-1])
self.Bind(wx.aui.EVT_AUINOTEBOOK_PAGE_CHANGED, self.OnPageChanged)
self.nb.Bind(wx.EVT_KEY_UP,self.OnNotebookKey)
self.plotList = []
[docs] def OnNotebookKey(self,event):
'''Called when a keystroke event gets picked up by the notebook window
rather the child. This is not expected, but somehow it does sometimes
on the Mac and perhaps Linux.
Assume that the page associated with the currently displayed tab
has a child, .canvas; give that child the focus and pass it the event.
'''
try:
Page = self.nb.GetPage(self.nb.GetSelection())
except ValueError: # occurs with no plot tabs
return
try:
Page.canvas.SetFocus()
wx.PostEvent(Page.canvas,event)
except AttributeError:
pass
[docs] def addMpl(self,name=""):
'Add a tabbed page with a matplotlib plot'
page = G2PlotMpl(self.nb)
self.nb.AddPage(page,name)
self.plotList.append(name)
return page.figure
[docs] def add3D(self,name=""):
'Add a tabbed page with a 3D plot'
page = G2Plot3D(self.nb)
self.nb.AddPage(page,name)
self.plotList.append(name)
return page.figure
[docs] def addOgl(self,name=""):
'Add a tabbed page with an openGL plot'
page = G2PlotOgl(self.nb)
self.nb.AddPage(page,name)
self.plotList.append(name)
return page.figure
[docs] def Delete(self,name):
'delete a tabbed page'
try:
item = self.plotList.index(name)
del self.plotList[item]
self.nb.DeletePage(item)
except ValueError: #no plot of this name - do nothing
return
[docs] def clear(self):
'clear all pages from plot window'
while self.nb.GetPageCount():
self.nb.DeletePage(0)
self.plotList = []
self.status.DestroyChildren()
[docs] def Rename(self,oldName,newName):
'rename a tab'
try:
item = self.plotList.index(oldName)
self.plotList[item] = newName
self.nb.SetPageText(item,newName)
except ValueError: #no plot of this name - do nothing
return
[docs] def OnPageChanged(self,event):
'respond to someone pressing a tab on the plot window'
if self.plotList:
self.status.SetStatusText('Better to select this from GSAS-II data tree',1)
self.status.DestroyChildren() #get rid of special stuff on status bar
[docs]def PlotSngl(G2frame,newPlot=False,Data=None,hklRef=None,Title=''):
'''Structure factor plotting package - displays zone of reflections as rings proportional
to F, F**2, etc. as requested
'''
from matplotlib.patches import Circle,CirclePolygon
global HKL,HKLF
def OnSCKeyPress(event):
i = zones.index(Data['Zone'])
newPlot = False
pwdrChoice = {'f':'Fo','s':'Fosq','u':'Unit Fc'}
hklfChoice = {'1':'|DFsq|>sig','3':'|DFsq|>3sig','w':'|DFsq|/sig','f':'Fo','s':'Fosq','i':'Unit Fc'}
if event.key == 'h':
Data['Zone'] = '100'
newPlot = True
elif event.key == 'k':
Data['Zone'] = '010'
newPlot = True
elif event.key == 'l':
Data['Zone'] = '001'
newPlot = True
elif event.key == 'i':
Data['Scale'] *= 1.1
elif event.key == 'd':
Data['Scale'] /= 1.1
elif event.key in ['+','=']:
Data['Layer'] = min(Data['Layer']+1,HKLmax[i])
elif event.key == '-':
Data['Layer'] = max(Data['Layer']-1,HKLmin[i])
elif event.key == '0':
Data['Layer'] = 0
Data['Scale'] = 1.0
elif event.key in hklfChoice and 'HKLF' in Name:
Data['Type'] = hklfChoice[event.key]
newPlot = True
elif event.key in pwdrChoice and 'PWDR' in Name:
Data['Type'] = pwdrChoice[event.key]
newPlot = True
PlotSngl(G2frame,newPlot,Data,hklRef,Title)
def OnSCMotion(event):
xpos = event.xdata
if xpos:
xpos = round(xpos) #avoid out of frame mouse position
ypos = round(event.ydata)
zpos = Data['Layer']
if '100' in Data['Zone']:
HKLtxt = '(%3d,%3d,%3d)'%(zpos,xpos,ypos)
elif '010' in Data['Zone']:
HKLtxt = '(%3d,%3d,%3d)'%(xpos,zpos,ypos)
elif '001' in Data['Zone']:
HKLtxt = '(%3d,%3d,%3d)'%(xpos,ypos,zpos)
Page.canvas.SetToolTipString(HKLtxt)
G2frame.G2plotNB.status.SetStatusText('HKL = '+HKLtxt,0)
G2frame.G2plotNB.status.SetStatusText('Use K-box to set plot controls',1)
def OnSCPress(event):
zpos = Data['Layer']
xpos = event.xdata
if xpos:
pos = int(round(event.xdata)),int(round(event.ydata))
if '100' in Data['Zone']:
Page.canvas.SetToolTipString('(picked:(%3d,%3d,%3d))'%(zpos,pos[0],pos[1]))
hkl = np.array([zpos,pos[0],pos[1]])
elif '010' in Data['Zone']:
Page.canvas.SetToolTipString('(picked:(%3d,%3d,%3d))'%(pos[0],zpos,pos[1]))
hkl = np.array([pos[0],zpos,pos[1]])
elif '001' in Data['Zone']:
Page.canvas.SetToolTipString('(picked:(%3d,%3d,%3d))'%(pos[0],pos[1],zpos))
hkl = np.array([pos[0],pos[1],zpos])
h,k,l = hkl
hklf = HKLF[np.where(np.all(HKL-hkl == [0,0,0],axis=1))]
if len(hklf):
Fosq,sig,Fcsq = hklf[0]
HKLtxt = '( %.2f %.3f %.2f %.2f)'%(Fosq,sig,Fcsq,(Fosq-Fcsq)/(scale*sig))
G2frame.G2plotNB.status.SetStatusText('Fosq, sig, Fcsq, delFsq/sig = '+HKLtxt,1)
Name = G2frame.PatternTree.GetItemText(G2frame.PatternId)
if not Title:
Title = Name
try:
plotNum = G2frame.G2plotNB.plotList.index('Structure Factors')
Page = G2frame.G2plotNB.nb.GetPage(plotNum)
if not newPlot:
Plot = Page.figure.gca() #get previous powder plot & get limits
xylim = Plot.get_xlim(),Plot.get_ylim()
Page.figure.clf()
Plot = Page.figure.gca() #get a fresh plot after clf()
except ValueError:
Plot = G2frame.G2plotNB.addMpl('Structure Factors').gca()
plotNum = G2frame.G2plotNB.plotList.index('Structure Factors')
Page = G2frame.G2plotNB.nb.GetPage(plotNum)
Page.canvas.mpl_connect('button_press_event', OnSCPress)
Page.canvas.mpl_connect('motion_notify_event', OnSCMotion)
Page.canvas.mpl_connect('key_press_event', OnSCKeyPress)
Page.keyPress = OnSCKeyPress
Page.Choice = (' key press','i: increase scale','d: decrease scale',
'h: select 100 zone','k: select 010 zone','l: select 001 zone',
'f: select Fo','s: select Fosq','u: select unit Fc',
'+: increase index','-: decrease index','0: zero layer',)
if 'HKLF' in Name:
Page.Choice += ('w: select |DFsq|/sig','1: select |DFsq|>sig','3: select |DFsq|>3sig',)
Page.SetFocus()
G2frame.G2plotNB.status.SetStatusText('Use K-box to set plot controls',1)
Plot.set_aspect(aspect='equal')
Type = Data['Type']
scale = Data['Scale']
HKLmax = Data['HKLmax']
HKLmin = Data['HKLmin']
FosqMax = Data['FoMax']
Super = Data['Super']
SuperVec = []
if Super:
SuperVec = np.array(Data['SuperVec'][0])
FoMax = math.sqrt(FosqMax)
xlabel = ['k, h=','h, k=','h, l=']
ylabel = ['l','l','k']
zones = ['100','010','001']
pzone = [[1,2],[0,2],[0,1]]
izone = zones.index(Data['Zone'])
Plot.set_title(Data['Type']+' for '+Title)
HKL = []
HKLF = []
time0 = time.time()
for refl in hklRef:
H = refl[:3]
if 'HKLF' in Name:
Fosq,sig,Fcsq = refl[5+Super:8+Super]
else:
Fosq,sig,Fcsq = refl[8+Super],1.0,refl[9+Super]
if Super:
HKL.append(H+SuperVec*refl[3])
else:
HKL.append(H)
HKLF.append([Fosq,sig,Fcsq])
if H[izone] == Data['Layer']:
A = 0
B = 0
if Type == 'Fosq':
A = scale*Fosq/FosqMax
B = scale*Fcsq/FosqMax
C = abs(A-B)
elif Type == 'Fo':
A = scale*math.sqrt(max(0,Fosq))/FoMax
B = scale*math.sqrt(max(0,Fcsq))/FoMax
C = abs(A-B)
elif Type == 'Unit Fc':
A = scale/2
B = scale/2
C = 0.0
if Fcsq and Fosq > 0:
A *= min(1.0,Fosq/Fcsq)
C = abs(A-B)
elif Type == '|DFsq|/sig':
if sig > 0.:
A = (Fosq-Fcsq)/(3*sig)
B = 0
elif Type == '|DFsq|>sig':
if sig > 0.:
A = (Fosq-Fcsq)/(3*sig)
if abs(A) < 1.0: A = 0
B = 0
elif Type == '|DFsq|>3sig':
if sig > 0.:
A = (Fosq-Fcsq)/(3*sig)
if abs(A) < 3.0: A = 0
B = 0
if Super:
h = H+SuperVec*refl[3]
else:
h = H
xy = (h[pzone[izone][0]],h[pzone[izone][1]])
if Type in ['|DFsq|/sig','|DFsq|>sig','|DFsq|>3sig']:
if A > 0.0:
Plot.add_artist(Circle(xy,radius=A,ec='g',fc='w'))
else:
Plot.add_artist(Circle(xy,radius=-A,ec='r',fc='w'))
else:
if A > 0.0 and A > B:
Plot.add_artist(Circle(xy,radius=A,ec='g',fc='w'))
if B:
Plot.add_artist(Circle(xy,radius=B,ec='b',fc='w'))
if A < B:
Plot.add_artist(Circle(xy,radius=A,ec='g',fc='w'))
radius = C
if radius > 0:
if A > B:
Plot.add_artist(Circle(xy,radius=radius,ec='g',fc='g'))
else:
Plot.add_artist(Circle(xy,radius=radius,ec='r',fc='r'))
# print 'plot time: %.3f'%(time.time()-time0)
HKL = np.array(HKL)
HKLF = np.array(HKLF)
Plot.set_xlabel(xlabel[izone]+str(Data['Layer']),fontsize=12)
Plot.set_ylabel(ylabel[izone],fontsize=12)
if not newPlot:
Page.toolbar.push_current()
Plot.set_xlim(xylim[0])
Plot.set_ylim(xylim[1])
# xylim = []
Page.toolbar.push_current()
Page.toolbar.draw()
else:
Plot.set_xlim((HKLmin[pzone[izone][0]],HKLmax[pzone[izone][0]]))
Plot.set_ylim((HKLmin[pzone[izone][1]],HKLmax[pzone[izone][1]]))
Page.canvas.draw()
################################################################################
##### Plot3DSngl
################################################################################
[docs]def Plot3DSngl(G2frame,newPlot=False,Data=None,hklRef=None,Title=False):
'''3D Structure factor plotting package - displays reflections as rings proportional
to F, F**2, etc. as requested as 3D array
'''
global ifBox
ifBox = False
def OnKeyBox(event):
mode = cb.GetValue()
if mode in ['jpeg','bmp','tiff',]:
try:
import Image as Im
except ImportError:
try:
from PIL import Image as Im
except ImportError:
print "PIL/pillow Image module not present. Cannot save images without this"
raise Exception("PIL/pillow Image module not found")
try:
Fname = os.path.join(Mydir,generalData['Name']+'.'+mode)
except NameError: #for when generalData doesn't exist!
Fname = os.path.join(Mydir,'unknown'+'.'+mode)
print Fname+' saved'
size = Page.canvas.GetSize()
glPixelStorei(GL_UNPACK_ALIGNMENT, 1)
if mode in ['jpeg',]:
Pix = glReadPixels(0,0,size[0],size[1],GL_RGBA, GL_UNSIGNED_BYTE)
im = Im.new("RGBA", (size[0],size[1]))
else:
Pix = glReadPixels(0,0,size[0],size[1],GL_RGB, GL_UNSIGNED_BYTE)
im = Im.new("RGB", (size[0],size[1]))
im.fromstring(Pix)
im.save(Fname,mode)
cb.SetValue(' save as/key:')
G2frame.G2plotNB.status.SetStatusText('Drawing saved to: '+Fname,1)
else:
event.key = cb.GetValue()[0]
cb.SetValue(' save as/key:')
wx.CallAfter(OnKey,event)
Page.canvas.SetFocus() # redirect the Focus from the button back to the plot
def OnKey(event): #on key UP!!
global ifBox
Choice = {'F':'Fo','S':'Fosq','U':'Unit','D':'dFsq','W':'dFsq/sig'}
try:
keyCode = event.GetKeyCode()
if keyCode > 255:
keyCode = 0
key = chr(keyCode)
except AttributeError: #if from OnKeyBox above
key = str(event.key).upper()
if key in ['C']:
drawingData['viewPoint'][0] = drawingData['default']
drawingData['viewDir'] = [0,0,1]
drawingData['oldxy'] = []
V0 = np.array([0,0,1])
V = np.inner(Amat,V0)
V /= np.sqrt(np.sum(V**2))
A = np.arccos(np.sum(V*V0))
Q = G2mth.AV2Q(A,[0,1,0])
drawingData['Quaternion'] = Q
Q = drawingData['Quaternion']
elif key in 'B':
ifBox = not ifBox
elif key in ['+','=']:
Data['Scale'] *= 1.25
elif key == '-':
Data['Scale'] /= 1.25
elif key == '0':
drawingData['viewPoint'][0] = [0,0,0]
Data['Scale'] = 1.0
elif key == 'I':
Data['Iscale'] = not Data['Iscale']
elif key in Choice:
Data['Type'] = Choice[key]
Draw('key')
Name = G2frame.PatternTree.GetItemText(G2frame.PatternId)
if Title: #NB: save image as e.g. jpeg will fail if False; MyDir is unknown
generalData = G2frame.GetPhaseData()[Title]['General']
cell = generalData['Cell'][1:7]
Mydir = generalData['Mydir']
else:
cell = [10,10,10,90,90,90]
Mydir = G2frame.dirname
drawingData = Data['Drawing']
Super = Data['Super']
SuperVec = []
if Super:
SuperVec = np.array(Data['SuperVec'][0])
defaultViewPt = copy.copy(drawingData['viewPoint'])
Amat,Bmat = G2lat.cell2AB(cell) #Amat - crystal to cartesian, Bmat - inverse
Gmat,gmat = G2lat.cell2Gmat(cell)
invcell = G2lat.Gmat2cell(Gmat)
A4mat = np.concatenate((np.concatenate((Amat,[[0],[0],[0]]),axis=1),[[0,0,0,1],]),axis=0)
B4mat = np.concatenate((np.concatenate((Bmat,[[0],[0],[0]]),axis=1),[[0,0,0,1],]),axis=0)
drawingData['Quaternion'] = G2mth.AV2Q(2*np.pi,np.inner(Bmat,[0,0,1]))
Wt = np.array([255,255,255])
Rd = np.array([255,0,0])
Gr = np.array([0,255,0])
wxGreen = wx.Colour(0,255,0)
Bl = np.array([0,0,255])
Or = np.array([255,128,0])
wxOrange = wx.Colour(255,128,0)
uBox = np.array([[0,0,0],[1,0,0],[1,1,0],[0,1,0],[0,0,1],[1,0,1],[1,1,1],[0,1,1]])
uEdges = np.array([
[uBox[0],uBox[1]],[uBox[0],uBox[3]],[uBox[0],uBox[4]],[uBox[1],uBox[2]],
[uBox[2],uBox[3]],[uBox[1],uBox[5]],[uBox[2],uBox[6]],[uBox[3],uBox[7]],
[uBox[4],uBox[5]],[uBox[5],uBox[6]],[uBox[6],uBox[7]],[uBox[7],uBox[4]]])
uColors = [Rd,Gr,Bl, Wt,Wt,Wt, Wt,Wt,Wt, Wt,Wt,Wt]
def FillHKLRC():
R = np.zeros(len(hklRef))
C = []
HKL = []
RC = []
for i,refl in enumerate(hklRef):
H = refl[:3]
if 'HKLF' in Name:
Fosq,sig,Fcsq = refl[5+Super:8+Super]
else:
Fosq,sig,Fcsq = refl[8+Super],1.0,refl[9+Super]
if Super:
HKL.append(H+SuperVec*refl[3])
else:
HKL.append(H)
if Data['Type'] == 'Unit':
R[i] = 0.1
C.append(Gr)
elif Data['Type'] == 'Fosq':
if Fosq > 0:
R[i] = Fosq
C.append(Gr)
else:
R[i] = -Fosq
C.append(Rd)
elif Data['Type'] == 'Fo':
if Fosq > 0:
R[i] = np.sqrt(Fosq)
C.append(Gr)
else:
R[i] = np.sqrt(-Fosq)
C.append(Rd)
elif Data['Type'] == 'dFsq/sig':
dFsig = (Fosq-Fcsq)/sig
if dFsig > 0:
R[i] = dFsig
C.append(Gr)
else:
R[i] = -dFsig
C.append(Rd)
elif Data['Type'] == 'dFsq':
dF = Fosq-Fcsq
if dF > 0:
R[i] = dF
C.append(Gr)
else:
R[i] = -dF
C.append(Rd)
R /= np.max(R)
R *= Data['Scale']
R = np.where(R<1.e-5,1.e-5,R)
if Data['Iscale']:
R = np.where(R<=1.,R,1.)
C = np.array(C)
C = (C.T*R).T
R = np.ones_like(R)*0.05
return HKL,zip(list(R),C)
def SetTranslation(newxy):
#first get translation vector in screen coords.
oldxy = drawingData['oldxy']
if not len(oldxy): oldxy = list(newxy)
dxy = newxy-oldxy
drawingData['oldxy'] = list(newxy)
V = np.array([-dxy[0],dxy[1],0.])
#then transform to rotated crystal coordinates & apply to view point
Q = drawingData['Quaternion']
V = np.inner(Bmat,G2mth.prodQVQ(G2mth.invQ(Q),V))
Tx,Ty,Tz = drawingData['viewPoint'][0]
Tx += V[0]*0.1
Ty += V[1]*0.1
Tz += V[2]*0.1
drawingData['viewPoint'][0] = Tx,Ty,Tz
def SetRotation(newxy):
'Perform a rotation in x-y space due to a left-mouse drag'
#first get rotation vector in screen coords. & angle increment
oldxy = drawingData['oldxy']
if not len(oldxy): oldxy = list(newxy)
dxy = newxy-oldxy
drawingData['oldxy'] = list(newxy)
V = np.array([dxy[1],dxy[0],0.])
A = 0.25*np.sqrt(dxy[0]**2+dxy[1]**2)
if not A: return # nothing changed, nothing to do
# next transform vector back to xtal coordinates via inverse quaternion
# & make new quaternion
Q = drawingData['Quaternion']
V = G2mth.prodQVQ(G2mth.invQ(Q),np.inner(Bmat,V))
DQ = G2mth.AVdeg2Q(A,V)
Q = G2mth.prodQQ(Q,DQ)
drawingData['Quaternion'] = Q
# finally get new view vector - last row of rotation matrix
VD = np.inner(Bmat,G2mth.Q2Mat(Q)[2])
VD /= np.sqrt(np.sum(VD**2))
drawingData['viewDir'] = VD
def SetRotationZ(newxy):
#first get rotation vector (= view vector) in screen coords. & angle increment
View = glGetIntegerv(GL_VIEWPORT)
cent = [View[2]/2,View[3]/2]
oldxy = drawingData['oldxy']
if not len(oldxy): oldxy = list(newxy)
dxy = newxy-oldxy
drawingData['oldxy'] = list(newxy)
V = drawingData['viewDir']
A = [0,0]
A[0] = dxy[1]*.25
A[1] = dxy[0]*.25
if newxy[0] > cent[0]:
A[0] *= -1
if newxy[1] < cent[1]:
A[1] *= -1
# next transform vector back to xtal coordinates & make new quaternion
Q = drawingData['Quaternion']
V = np.inner(Amat,V)
Qx = G2mth.AVdeg2Q(A[0],V)
Qy = G2mth.AVdeg2Q(A[1],V)
Q = G2mth.prodQQ(Q,Qx)
Q = G2mth.prodQQ(Q,Qy)
drawingData['Quaternion'] = Q
def OnMouseDown(event):
xy = event.GetPosition()
drawingData['oldxy'] = list(xy)
def OnMouseMove(event):
if event.ShiftDown(): #don't want any inadvertant moves when picking
return
newxy = event.GetPosition()
if event.Dragging():
if event.LeftIsDown():
SetRotation(newxy)
Q = drawingData['Quaternion']
elif event.RightIsDown():
SetTranslation(newxy)
Tx,Ty,Tz = drawingData['viewPoint'][0]
elif event.MiddleIsDown():
SetRotationZ(newxy)
Q = drawingData['Quaternion']
Draw('move')
def OnMouseWheel(event):
if event.ShiftDown():
return
drawingData['cameraPos'] += event.GetWheelRotation()/120.
drawingData['cameraPos'] = max(0.1,min(20.00,drawingData['cameraPos']))
Draw('wheel')
def SetBackground():
R,G,B,A = Page.camera['backColor']
glClearColor(R,G,B,A)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
def SetLights():
glEnable(GL_DEPTH_TEST)
glShadeModel(GL_SMOOTH)
glEnable(GL_LIGHTING)
glEnable(GL_LIGHT0)
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,0)
glLightfv(GL_LIGHT0,GL_AMBIENT,[1,1,1,.8])
glLightfv(GL_LIGHT0,GL_DIFFUSE,[1,1,1,1])
def RenderBox(x,y,z):
xyz = np.array([x,y,z])
glEnable(GL_COLOR_MATERIAL)
glLineWidth(1)
glPushMatrix()
glTranslate(x,y,z)
glColor4ubv([0,0,0,0])
glBegin(GL_LINES)
for line,color in zip(uEdges,uColors):
glColor3ubv(color)
glVertex3fv(line[0])
glVertex3fv(line[1])
glEnd()
glPopMatrix()
glColor4ubv([0,0,0,0])
glDisable(GL_COLOR_MATERIAL)
def RenderUnitVectors(x,y,z):
xyz = np.array([x,y,z])
glEnable(GL_COLOR_MATERIAL)
glLineWidth(1)
glPushMatrix()
glTranslate(x,y,z)
glBegin(GL_LINES)
for line,color in zip(uEdges,uColors)[:3]:
glColor3ubv(color)
glVertex3fv(-line[1])
glVertex3fv(line[1])
glEnd()
glPopMatrix()
glColor4ubv([0,0,0,0])
glDisable(GL_COLOR_MATERIAL)
def RenderDots(XYZ,RC):
glEnable(GL_COLOR_MATERIAL)
XYZ = np.array(XYZ)
glPushMatrix()
for xyz,rc in zip(XYZ,RC):
x,y,z = xyz
r,c = rc
glMaterialfv(GL_FRONT_AND_BACK,GL_EMISSION,c)
glPointSize(r*50)
glBegin(GL_POINTS)
glVertex3fv(xyz)
glEnd()
glPopMatrix()
glColor4ubv([0,0,0,0])
glDisable(GL_COLOR_MATERIAL)
def Draw(caller=''):
#useful debug?
# if caller:
# print caller
# end of useful debug
G2frame.G2plotNB.status.SetStatusText('Plot type = %s for %s'%(Data['Type'],Name),1)
VS = np.array(Page.canvas.GetSize())
aspect = float(VS[0])/float(VS[1])
cPos = drawingData['cameraPos']
Zclip = drawingData['Zclip']*cPos/20.
Q = drawingData['Quaternion']
Tx,Ty,Tz = drawingData['viewPoint'][0]
G,g = G2lat.cell2Gmat(cell)
GS = G
GS[0][1] = GS[1][0] = math.sqrt(GS[0][0]*GS[1][1])
GS[0][2] = GS[2][0] = math.sqrt(GS[0][0]*GS[2][2])
GS[1][2] = GS[2][1] = math.sqrt(GS[1][1]*GS[2][2])
HKL,RC = FillHKLRC()
SetBackground()
glInitNames()
glPushName(0)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
glViewport(0,0,VS[0],VS[1])
gluPerspective(20.,aspect,cPos-Zclip,cPos+Zclip)
gluLookAt(0,0,cPos,0,0,0,0,1,0)
SetLights()
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
matRot = G2mth.Q2Mat(Q)
matRot = np.concatenate((np.concatenate((matRot,[[0],[0],[0]]),axis=1),[[0,0,0,1],]),axis=0)
glMultMatrixf(matRot.T)
glMultMatrixf(B4mat.T)
glTranslate(-Tx,-Ty,-Tz)
x,y,z = drawingData['viewPoint'][0]
if ifBox:
RenderBox(x,y,z)
else:
RenderUnitVectors(x,y,z)
RenderUnitVectors(0,0,0)
RenderDots(HKL,RC)
time0 = time.time()
if Page.context: Page.canvas.SetCurrent(Page.context) # wx 2.9 fix
Page.canvas.SwapBuffers()
# PlotStructure execution starts here (N.B. initialization above)
try:
plotNum = G2frame.G2plotNB.plotList.index('3D Structure Factors')
Page = G2frame.G2plotNB.nb.GetPage(plotNum)
except ValueError:
Plot = G2frame.G2plotNB.addOgl('3D Structure Factors')
plotNum = G2frame.G2plotNB.plotList.index('3D Structure Factors')
Page = G2frame.G2plotNB.nb.GetPage(plotNum)
Page.views = False
view = False
altDown = False
Font = Page.GetFont()
Page.SetFocus()
Page.Choice = None
choice = [' save as/key:','jpeg','tiff','bmp','c: recenter to default','b: toggle box ','+: increase scale',
'-: decrease scale','f: Fobs','s: Fobs**2','u: unit','d: Fo-Fc','w: DF/sig','i: toggle intensity scaling']
cb = wx.ComboBox(G2frame.G2plotNB.status,style=wx.CB_DROPDOWN|wx.CB_READONLY,choices=choice)
cb.Bind(wx.EVT_COMBOBOX, OnKeyBox)
cb.SetValue(' save as/key:')
Page.canvas.Bind(wx.EVT_MOUSEWHEEL, OnMouseWheel)
Page.canvas.Bind(wx.EVT_LEFT_DOWN, OnMouseDown)
Page.canvas.Bind(wx.EVT_RIGHT_DOWN, OnMouseDown)
Page.canvas.Bind(wx.EVT_MIDDLE_DOWN, OnMouseDown)
Page.canvas.Bind(wx.EVT_KEY_UP, OnKey)
Page.canvas.Bind(wx.EVT_MOTION, OnMouseMove)
# Page.canvas.Bind(wx.EVT_SIZE, OnSize)
Page.camera['position'] = drawingData['cameraPos']
Page.camera['viewPoint'] = np.inner(Amat,drawingData['viewPoint'][0])
Page.camera['backColor'] = np.array(list(drawingData['backColor'])+[0,])/255.
Page.controls = Data
try:
Page.canvas.SetCurrent()
except:
pass
Draw('main')
# if firstCall: Draw('main') # draw twice the first time that graphics are displayed
################################################################################
##### PlotPatterns
################################################################################
[docs]def PlotPatterns(G2frame,newPlot=False,plotType='PWDR'):
'''Powder pattern plotting package - displays single or multiple powder patterns as intensity vs
2-theta, q or TOF. Can display multiple patterns as "waterfall plots" or contour plots. Log I
plotting available.
'''
global HKL
global exclLines
global DifLine
global Ymax
plottype = plotType
#patch
data = G2frame.PatternTree.GetItemPyData(G2frame.PatternId)
if 'Offset' not in data[0] and plotType in ['PWDR','SASD']: #plot offset data
data[0].update({'Offset':[0.0,0.0],'delOffset':0.02,'refOffset':-1.0,
'refDelt':0.01,'qPlot':False,'dPlot':False,'sqrtPlot':False})
G2frame.PatternTree.SetItemPyData(G2frame.PickId,data)
#end patch
def OnPlotKeyPress(event):
try: #one way to check if key stroke will work on plot
Parms,Parms2 = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Instrument Parameters'))
except TypeError:
G2frame.G2plotNB.status.SetStatusText('Select '+plottype+' pattern first',1)
return
newPlot = False
if event.key == 'w':
G2frame.Weight = not G2frame.Weight
if not G2frame.Weight and 'PWDR' in plottype:
G2frame.SinglePlot = True
newPlot = True
elif event.key == 'e' and 'SASD' in plottype:
G2frame.ErrorBars = not G2frame.ErrorBars
elif event.key == 'b':
G2frame.SubBack = not G2frame.SubBack
if not G2frame.SubBack:
G2frame.SinglePlot = True
elif event.key == 'n':
if G2frame.Contour:
pass
else:
G2frame.logPlot = not G2frame.logPlot
if not G2frame.logPlot:
Pattern[0]['Offset'][0] = 0
newPlot = True
elif event.key == 's' and 'PWDR' in plottype:
if G2frame.Contour:
choice = [m for m in mpl.cm.datad.keys() if not m.endswith("_r")]
choice.sort()
dlg = wx.SingleChoiceDialog(G2frame,'Select','Color scheme',choice)
if dlg.ShowModal() == wx.ID_OK:
sel = dlg.GetSelection()
G2frame.ContourColor = choice[sel]
else:
G2frame.ContourColor = 'Paired'
dlg.Destroy()
elif G2frame.SinglePlot:
Pattern[0]['sqrtPlot'] = not Pattern[0]['sqrtPlot']
if Pattern[0]['sqrtPlot']:
Pattern[0]['delOffset'] = .002
Pattern[0]['refOffset'] = -1.0
Pattern[0]['refDelt'] = .001
else:
Pattern[0]['delOffset'] = .02
Pattern[0]['refOffset'] = -1.0
Pattern[0]['refDelt'] = .01
newPlot = True
elif event.key == 'u' and (G2frame.Contour or not G2frame.SinglePlot):
if G2frame.Contour:
G2frame.Cmax = min(1.0,G2frame.Cmax*1.2)
elif Pattern[0]['Offset'][0] < 100.:
Pattern[0]['Offset'][0] += 1.
elif event.key == 'd' and (G2frame.Contour or not G2frame.SinglePlot):
if G2frame.Contour:
G2frame.Cmax = max(0.0,G2frame.Cmax*0.8)
elif Pattern[0]['Offset'][0] > 0.:
Pattern[0]['Offset'][0] -= 1.
elif event.key == 'l' and not G2frame.SinglePlot:
Pattern[0]['Offset'][1] -= 1.
elif event.key == 'r' and not G2frame.SinglePlot:
Pattern[0]['Offset'][1] += 1.
elif event.key == 'o' and not G2frame.SinglePlot:
G2frame.Cmax = 1.0
Pattern[0]['Offset'] = [0,0]
elif event.key == 'c' and 'PWDR' in plottype:
newPlot = True
if not G2frame.Contour:
G2frame.SinglePlot = False
Pattern[0]['Offset'] = [0.,0.]
else:
G2frame.SinglePlot = True
G2frame.Contour = not G2frame.Contour
elif event.key == 'q':
if 'PWDR' in plottype:
newPlot = True
Pattern[0]['qPlot'] = not Pattern[0]['qPlot']
Pattern[0]['dPlot'] = False
elif 'SASD' in plottype:
newPlot = True
G2frame.sqPlot = not G2frame.sqPlot
elif event.key == 't' and 'PWDR' in plottype:
Pattern[0]['dPlot'] = not Pattern[0]['dPlot']
Pattern[0]['qPlot'] = False
newPlot = True
elif event.key == 'm':
Pattern[0]['sqrtPlot'] = False
G2frame.SinglePlot = not G2frame.SinglePlot
newPlot = True
elif event.key in ['+','=']:
if G2frame.PickId:
G2frame.PickId = False
elif event.key == 'i' and G2frame.Contour: #for smoothing contour plot
choice = ['nearest','bilinear','bicubic','spline16','spline36','hanning',
'hamming','hermite','kaiser','quadric','catrom','gaussian','bessel',
'mitchell','sinc','lanczos']
dlg = wx.SingleChoiceDialog(G2frame,'Select','Interpolation',choice)
if dlg.ShowModal() == wx.ID_OK:
sel = dlg.GetSelection()
G2frame.Interpolate = choice[sel]
else:
G2frame.Interpolate = 'nearest'
dlg.Destroy()
else:
# print 'no binding for key',event.key
#GSASIIpath.IPyBreak()
return
wx.CallAfter(PlotPatterns,G2frame,newPlot=newPlot,plotType=plottype)
def OnMotion(event):
xpos = event.xdata
if xpos: #avoid out of frame mouse position
ypos = event.ydata
Page.canvas.SetCursor(wx.CROSS_CURSOR)
try:
Parms,Parms2 = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Instrument Parameters'))
if Pattern[0]['qPlot'] and 'PWDR' in plottype:
q = xpos
dsp = 2.*np.pi/q
try:
xpos = G2lat.Dsp2pos(Parms,2.0*np.pi/xpos)
except ValueError: #avoid bad value in asin beyond upper limit
pass
elif 'SASD' in plottype:
q = xpos
dsp = 2.*np.pi/q
elif Pattern[0]['dPlot']:
dsp = xpos
q = 2.*np.pi/dsp
xpos = G2lat.Dsp2pos(Parms,xpos)
elif G2frame.Contour and 'T' in Parms['Type'][0]:
xpos = X[xpos]
dsp = G2lat.Pos2dsp(Parms,xpos)
q = 2.*np.pi/dsp
else:
dsp = G2lat.Pos2dsp(Parms,xpos)
q = 2.*np.pi/dsp
if G2frame.Contour: #PWDR only
if 'C' in Parms['Type'][0]:
G2frame.G2plotNB.status.SetStatusText('2-theta =%9.3f d =%9.5f q = %9.5f pattern ID =%5d'%(xpos,dsp,q,int(ypos)),1)
else:
G2frame.G2plotNB.status.SetStatusText('TOF =%9.3f d =%9.5f q = %9.5f pattern ID =%5d'%(xpos,dsp,q,int(ypos)),1)
else:
if 'C' in Parms['Type'][0]:
if 'PWDR' in plottype:
if Pattern[0]['sqrtPlot']:
G2frame.G2plotNB.status.SetStatusText('2-theta =%9.3f d =%9.5f q = %9.5f sqrt(Intensity) =%9.2f'%(xpos,dsp,q,ypos),1)
else:
G2frame.G2plotNB.status.SetStatusText('2-theta =%9.3f d =%9.5f q = %9.5f Intensity =%9.2f'%(xpos,dsp,q,ypos),1)
elif 'SASD' in plottype:
G2frame.G2plotNB.status.SetStatusText('q =%12.5g Intensity =%12.5g d =%9.1f'%(q,ypos,dsp),1)
else:
if Pattern[0]['sqrtPlot']:
G2frame.G2plotNB.status.SetStatusText('TOF =%9.3f d =%9.5f q =%9.5f sqrt(Intensity) =%9.2f'%(xpos,dsp,q,ypos),1)
else:
G2frame.G2plotNB.status.SetStatusText('TOF =%9.3f d =%9.5f q =%9.5f Intensity =%9.2f'%(xpos,dsp,q,ypos),1)
if G2frame.itemPicked:
Page.canvas.SetToolTipString('%9.5f'%(xpos))
if G2frame.PickId:
found = []
pickIdText = G2frame.PatternTree.GetItemText(G2frame.PickId)
if pickIdText in ['Index Peak List','Unit Cells List','Reflection Lists'] or \
'PWDR' in pickIdText:
indx = -1
if pickIdText in ['Index Peak List','Unit Cells List',]:
indx = -2
if len(HKL):
view = Page.toolbar._views.forward()[0][:2]
wid = view[1]-view[0]
found = HKL[np.where(np.fabs(HKL.T[indx]-xpos) < 0.002*wid)]
if len(found):
if len(found[0]) > 6: #SS reflections
h,k,l,m = found[0][:4]
Page.canvas.SetToolTipString('%d,%d,%d,%d'%(int(h),int(k),int(l),int(m)))
else:
h,k,l = found[0][:3]
Page.canvas.SetToolTipString('%d,%d,%d'%(int(h),int(k),int(l)))
else:
Page.canvas.SetToolTipString('')
except TypeError:
G2frame.G2plotNB.status.SetStatusText('Select '+plottype+' pattern first',1)
def OnPress(event): #ugh - this removes a matplotlib error for mouse clicks in log plots
olderr = np.seterr(invalid='ignore')
def OnPick(event):
if G2frame.itemPicked is not None: return
PatternId = G2frame.PatternId
try:
Parms,Parms2 = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Instrument Parameters'))
except TypeError:
return
PickId = G2frame.PickId
pick = event.artist
mouse = event.mouseevent
xpos = pick.get_xdata()
ypos = pick.get_ydata()
ind = event.ind
xy = list(zip(np.take(xpos,ind),np.take(ypos,ind))[0])
if G2frame.PatternTree.GetItemText(PickId) == 'Peak List':
if ind.all() != [0] and ObsLine[0].get_label() in str(pick): #picked a data point
data = G2frame.PatternTree.GetItemPyData(G2frame.PickId)
if Pattern[0]['qPlot']: #qplot - convert back to 2-theta
xy[0] = G2lat.Dsp2pos(Parms,2*np.pi/xy[0])
elif Pattern[0]['dPlot']: #dplot - convert back to 2-theta
xy[0] = G2lat.Dsp2pos(Parms,xy[0])
XY = G2mth.setPeakparms(Parms,Parms2,xy[0],xy[1])
data['peaks'].append(XY)
data['sigDict'] = {} #now invalid
G2pdG.UpdatePeakGrid(G2frame,data)
PlotPatterns(G2frame,plotType=plottype)
else: #picked a peak list line
G2frame.itemPicked = pick
elif G2frame.PatternTree.GetItemText(PickId) == 'Limits':
if ind.all() != [0]: #picked a data point
LimitId = G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Limits')
data = G2frame.PatternTree.GetItemPyData(LimitId)
if Pattern[0]['qPlot']: #qplot - convert back to 2-theta
xy[0] = G2lat.Dsp2pos(Parms,2*np.pi/xy[0])
elif Pattern[0]['dPlot']: #dplot - convert back to 2-theta
xy[0] = G2lat.Dsp2pos(Parms,xy[0])
if G2frame.ifGetExclude:
excl = [0,0]
excl[0] = max(data[1][0],min(xy[0],data[1][1]))
excl[1] = excl[0]+0.1
data.append(excl)
G2frame.ifGetExclude = False
else:
if mouse.button==1:
data[1][0] = min(xy[0],data[1][1])
if mouse.button==3:
data[1][1] = max(xy[0],data[1][0])
G2frame.PatternTree.SetItemPyData(LimitId,data)
G2pdG.UpdateLimitsGrid(G2frame,data,plottype)
wx.CallAfter(PlotPatterns,G2frame,plotType=plottype)
else: #picked a limit line
G2frame.itemPicked = pick
elif G2frame.PatternTree.GetItemText(PickId) == 'Models':
if ind.all() != [0]: #picked a data point
LimitId = G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Limits')
data = G2frame.PatternTree.GetItemPyData(LimitId)
if mouse.button==1:
data[1][0] = min(xy[0],data[1][1])
if mouse.button==3:
data[1][1] = max(xy[0],data[1][0])
G2frame.PatternTree.SetItemPyData(LimitId,data)
wx.CallAfter(PlotPatterns,G2frame,plotType=plottype)
else: #picked a limit line
G2frame.itemPicked = pick
elif G2frame.PatternTree.GetItemText(PickId) == 'Reflection Lists' or \
'PWDR' in G2frame.PatternTree.GetItemText(PickId):
G2frame.itemPicked = pick
pick = str(pick)
def OnRelease(event):
if G2frame.itemPicked is None: return
PickId = G2frame.PickId
if str(DifLine[0]) == str(G2frame.itemPicked):
data = G2frame.PatternTree.GetItemPyData(PickId)
ypos = event.ydata
data[0]['delOffset'] = -ypos/Ymax
G2frame.itemPicked = None
G2frame.PatternTree.SetItemPyData(PickId,data)
PlotPatterns(G2frame,plotType=plottype)
return
Parms,Parms2 = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Instrument Parameters'))
xpos = event.xdata
if G2frame.PatternTree.GetItemText(PickId) in ['Peak List','Limits'] and xpos:
lines = []
for line in G2frame.Lines:
lines.append(line.get_xdata()[0])
try:
lineNo = lines.index(G2frame.itemPicked.get_xdata()[0])
except ValueError:
lineNo = -1
if lineNo in [0,1] or lineNo in exclLines:
LimitId = G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Limits')
data = G2frame.PatternTree.GetItemPyData(LimitId)
id = lineNo/2+1
id2 = lineNo%2
if Pattern[0]['qPlot'] and 'PWDR' in plottype:
data[id][id2] = G2lat.Dsp2pos(Parms,2.*np.pi/xpos)
elif Pattern[0]['dPlot'] and 'PWDR' in plottype:
data[id][id2] = G2lat.Dsp2pos(Parms,xpos)
else:
data[id][id2] = xpos
if id > 1 and data[id][0] > data[id][1]:
data[id].reverse()
data[1][0] = min(max(data[0][0],data[1][0]),data[1][1])
data[1][1] = max(min(data[0][1],data[1][1]),data[1][0])
G2frame.PatternTree.SetItemPyData(LimitId,data)
if G2frame.PatternTree.GetItemText(G2frame.PickId) == 'Limits':
G2pdG.UpdateLimitsGrid(G2frame,data,plottype)
elif lineNo > 1:
PeakId = G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Peak List')
data = G2frame.PatternTree.GetItemPyData(PeakId)
if event.button == 3:
del data['peaks'][lineNo-2]
else:
if Pattern[0]['qPlot']:
data['peaks'][lineNo-2][0] = G2lat.Dsp2pos(Parms,2.*np.pi/xpos)
elif Pattern[0]['dPlot']:
data['peaks'][lineNo-2][0] = G2lat.Dsp2pos(Parms,xpos)
else:
data['peaks'][lineNo-2][0] = xpos
data['sigDict'] = {} #no longer valid
G2frame.PatternTree.SetItemPyData(PeakId,data)
G2pdG.UpdatePeakGrid(G2frame,data)
elif G2frame.PatternTree.GetItemText(PickId) in ['Models',] and xpos:
lines = []
for line in G2frame.Lines:
lines.append(line.get_xdata()[0])
try:
lineNo = lines.index(G2frame.itemPicked.get_xdata()[0])
except ValueError:
lineNo = -1
if lineNo in [0,1]:
LimitId = G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Limits')
data = G2frame.PatternTree.GetItemPyData(LimitId)
data[1][lineNo] = xpos
data[1][0] = min(max(data[0][0],data[1][0]),data[1][1])
data[1][1] = max(min(data[0][1],data[1][1]),data[1][0])
G2frame.PatternTree.SetItemPyData(LimitId,data)
elif (G2frame.PatternTree.GetItemText(PickId) == 'Reflection Lists' or \
'PWDR' in G2frame.PatternTree.GetItemText(PickId)) and xpos:
Phases = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId,'Reflection Lists'))
pick = str(G2frame.itemPicked).split('(')[1].strip(')')
if 'line' not in pick: #avoid data points, etc.
data = G2frame.PatternTree.GetItemPyData(PickId)
num = Phases.keys().index(pick)
if num:
data[0]['refDelt'] = -(event.ydata-Pattern[0]['refOffset'])/(num*Ymax)
else: #1st row of refl ticks
data[0]['refOffset'] = event.ydata
G2frame.PatternTree.SetItemPyData(PickId,data)
PlotPatterns(G2frame,plotType=plottype)
G2frame.itemPicked = None
try:
plotNum = G2frame.G2plotNB.plotList.index('Powder Patterns')
Page = G2frame.G2plotNB.nb.GetPage(plotNum)
if not newPlot:
Plot = Page.figure.gca() #get previous powder plot & get limits
xylim = Plot.get_xlim(),Plot.get_ylim()
Page.figure.clf()
Plot = Page.figure.gca() #get a fresh plot after clf()
except ValueError:
if plottype == 'SASD':
G2frame.logPlot = True
G2frame.ErrorBars = True
newPlot = True
G2frame.Cmax = 1.0
Plot = G2frame.G2plotNB.addMpl('Powder Patterns').gca()
plotNum = G2frame.G2plotNB.plotList.index('Powder Patterns')
Page = G2frame.G2plotNB.nb.GetPage(plotNum)
Page.canvas.mpl_connect('key_press_event', OnPlotKeyPress)
Page.canvas.mpl_connect('motion_notify_event', OnMotion)
Page.canvas.mpl_connect('pick_event', OnPick)
Page.canvas.mpl_connect('button_release_event', OnRelease)
Page.canvas.mpl_connect('button_press_event',OnPress)
if plottype == 'PWDR': # avoids a very nasty clash with KILL_FOCUS in SASD TextCtrl?
Page.SetFocus()
G2frame.G2plotNB.status.DestroyChildren()
if G2frame.Contour:
Page.Choice = (' key press','d: lower contour max','u: raise contour max','o: reset contour max',
'i: interpolation method','s: color scheme','c: contour off')
else:
if G2frame.logPlot:
if 'PWDR' in plottype:
if G2frame.SinglePlot:
Page.Choice = (' key press','n: log(I) off',
'c: contour on','q: toggle q plot','t: toggle d-spacing plot',
'm: toggle multidata plot','w: toggle divide by sig','+: no selection')
else:
Page.Choice = (' key press','n: log(I) off',
'd: offset down','l: offset left','r: offset right','u: offset up','o: reset offset',
'c: contour on','q: toggle q plot','t: toggle d-spacing plot',
'm: toggle multidata plot','w: toggle divide by sig','+: no selection')
elif 'SASD' in plottype:
if G2frame.SinglePlot:
Page.Choice = (' key press','b: toggle subtract background file','n: semilog on',
'q: toggle S(q) plot','m: toggle multidata plot','w: toggle (Io-Ic)/sig plot','+: no selection')
else:
Page.Choice = (' key press','b: toggle subtract background file','n: semilog on',
'd: offset down','l: offset left','r: offset right','u: offset up','o: reset offset',
'q: toggle S(q) plot','m: toggle multidata plot','w: toggle (Io-Ic)/sig plot','+: no selection')
else:
if 'PWDR' in plottype:
if G2frame.SinglePlot:
Page.Choice = (' key press',
'b: toggle subtract background','n: log(I) on','s: toggle sqrt plot','c: contour on',
'q: toggle q plot','t: toggle d-spacing plot','m: toggle multidata plot',
'w: toggle divide by sig','+: no selection')
else:
Page.Choice = (' key press','l: offset left','r: offset right','d: offset down',
'u: offset up','o: reset offset','b: toggle subtract background','n: log(I) on','c: contour on',
'q: toggle q plot','t: toggle d-spacing plot','m: toggle multidata plot',
'w: toggle divide by sig','+: no selection')
elif 'SASD' in plottype:
if G2frame.SinglePlot:
Page.Choice = (' key press','b: toggle subtract background file','n: loglog on','e: toggle error bars',
'q: toggle S(q) plot','m: toggle multidata plot','w: toggle (Io-Ic)/sig plot','+: no selection')
else:
Page.Choice = (' key press','b: toggle subtract background file','n: loglog on','e: toggle error bars',
'd: offset down','l: offset left','r: offset right','u: offset up','o: reset offset',
'q: toggle S(q) plot','m: toggle multidata plot','w: toggle (Io-Ic)/sig plot','+: no selection')
Page.keyPress = OnPlotKeyPress
PickId = G2frame.PickId
PatternId = G2frame.PatternId
colors=['b','g','r','c','m','k']
Lines = []
exclLines = []
if G2frame.SinglePlot and PatternId:
Pattern = G2frame.PatternTree.GetItemPyData(PatternId)
Pattern.append(G2frame.PatternTree.GetItemText(PatternId))
PlotList = [Pattern,]
Parms,Parms2 = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,
G2frame.PatternId, 'Instrument Parameters'))
Sample = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Sample Parameters'))
ParmList = [Parms,]
SampleList = [Sample,]
Title = Pattern[-1]
else:
Title = os.path.split(G2frame.GSASprojectfile)[1]
PlotList = []
ParmList = []
SampleList = []
item, cookie = G2frame.PatternTree.GetFirstChild(G2frame.root)
while item:
if plottype in G2frame.PatternTree.GetItemText(item):
Pattern = G2frame.PatternTree.GetItemPyData(item)
if len(Pattern) < 3: # put name on end if needed
Pattern.append(G2frame.PatternTree.GetItemText(item))
PlotList.append(Pattern)
ParmList.append(G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,
item,'Instrument Parameters'))[0])
SampleList.append(G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,
item, 'Sample Parameters')))
item, cookie = G2frame.PatternTree.GetNextChild(G2frame.root, cookie)
lenX = 0
if PickId:
if G2frame.PatternTree.GetItemText(PickId) in ['Reflection Lists']:
Phases = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId,'Reflection Lists'))
HKL = []
if Phases:
try:
for peak in Phases[G2frame.RefList]['RefList']:
if len(peak) > 15:
HKL.append(peak[:7]) #SS reflection list - need peak[:7]
else:
HKL.append(peak[:6])
except TypeError: #old style patch
for peak in Phases[G2frame.RefList]:
HKL.append(peak[:6])
HKL = np.array(HKL)
else:
HKL = np.array(G2frame.HKL)
Ymax = None
for Pattern in PlotList:
xye = Pattern[1]
if xye[1] is None: continue
if Ymax is None: Ymax = max(xye[1])
Ymax = max(Ymax,max(xye[1]))
if Ymax is None: return # nothing to plot
offsetX = Pattern[0]['Offset'][1]
offsetY = Pattern[0]['Offset'][0]
if G2frame.logPlot:
Title = 'log('+Title+')'
Plot.set_title(Title)
if Pattern[0]['qPlot'] or 'SASD' in plottype and not G2frame.Contour:
Plot.set_xlabel(r'$Q, \AA^{-1}$',fontsize=16)
elif Pattern[0]['dPlot'] and 'PWDR' in plottype and not G2frame.Contour:
Plot.set_xlabel(r'$d, \AA$',fontsize=16)
else:
if 'C' in ParmList[0]['Type'][0]:
Plot.set_xlabel(r'$\mathsf{2\theta}$',fontsize=16)
else:
if G2frame.Contour:
Plot.set_xlabel(r'Channel no.',fontsize=16)
else:
Plot.set_xlabel(r'$TOF, \mathsf{\mu}$s',fontsize=16)
if G2frame.Weight:
if 'PWDR' in plottype:
Plot.set_ylabel(r'$\mathsf{I/\sigma(I)}$',fontsize=16)
elif 'SASD' in plottype:
Plot.set_ylabel(r'$\mathsf{\Delta(I)/\sigma(I)}$',fontsize=16)
else:
if 'C' in ParmList[0]['Type'][0]:
if 'PWDR' in plottype:
if Pattern[0]['sqrtPlot']:
Plot.set_ylabel(r'$\sqrt{Intensity}$',fontsize=16)
else:
Plot.set_ylabel(r'$Intensity$',fontsize=16)
elif 'SASD' in plottype:
if G2frame.sqPlot:
Plot.set_ylabel(r'$S(Q)=I*Q^{4}$',fontsize=16)
else:
Plot.set_ylabel(r'$Intensity, cm^{-1}$',fontsize=16)
else:
if Pattern[0]['sqrtPlot']:
Plot.set_ylabel(r'$\sqrt{Normalized\ intensity}$',fontsize=16)
else:
Plot.set_ylabel(r'$Normalized\ intensity$',fontsize=16)
if G2frame.Contour:
ContourZ = []
ContourY = []
Nseq = 0
for N,Pattern in enumerate(PlotList):
Parms = ParmList[N]
Sample = SampleList[N]
if 'C' in Parms['Type'][0]:
wave = G2mth.getWave(Parms)
else:
difC = Parms['difC'][1]
ifpicked = False
LimitId = 0
if Pattern[1] is None: continue # skip over uncomputed simulations
xye = ma.array(ma.getdata(Pattern[1]))
Zero = Parms.get('Zero',[0.,0.])[1]
if PickId:
ifpicked = Pattern[2] == G2frame.PatternTree.GetItemText(PatternId)
LimitId = G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Limits')
limits = np.array(G2frame.PatternTree.GetItemPyData(LimitId))
excls = limits[2:]
for excl in excls:
xye[0] = ma.masked_inside(xye[0],excl[0],excl[1])
if Pattern[0]['qPlot'] and 'PWDR' in plottype:
Id = G2gd.GetPatternTreeItemId(G2frame,G2frame.root, Pattern[2])
X = 2.*np.pi/G2lat.Pos2dsp(Parms,xye[0])
elif Pattern[0]['dPlot'] and 'PWDR' in plottype:
Id = G2gd.GetPatternTreeItemId(G2frame,G2frame.root, Pattern[2])
X = G2lat.Pos2dsp(Parms,xye[0])
else:
X = xye[0]
if not lenX:
lenX = len(X)
if 'PWDR' in plottype:
if Pattern[0]['sqrtPlot']:
olderr = np.seterr(invalid='ignore') #get around sqrt(-ve) error
Y = np.where(xye[1]>=0.,np.sqrt(xye[1]),-np.sqrt(-xye[1]))
np.seterr(invalid=olderr['invalid'])
else:
Y = xye[1]+offsetY*N*Ymax/100.0
elif 'SASD' in plottype:
B = xye[5]
if G2frame.sqPlot:
Y = xye[1]*Sample['Scale'][0]*(1.05)**(offsetY*N)*X**4
else:
Y = xye[1]*Sample['Scale'][0]*(1.05)**(offsetY*N)
if LimitId and ifpicked:
limits = np.array(G2frame.PatternTree.GetItemPyData(LimitId))
lims = limits[1]
if Pattern[0]['qPlot'] and 'PWDR' in plottype:
lims = 2.*np.pi/G2lat.Pos2dsp(Parms,lims)
elif Pattern[0]['dPlot'] and 'PWDR' in plottype:
lims = G2lat.Pos2dsp(Parms,lims)
Lines.append(Plot.axvline(lims[0],color='g',dashes=(5,5),picker=3.))
Lines.append(Plot.axvline(lims[1],color='r',dashes=(5,5),picker=3.))
for i,item in enumerate(limits[2:]):
Lines.append(Plot.axvline(item[0],color='m',dashes=(5,5),picker=3.))
Lines.append(Plot.axvline(item[1],color='m',dashes=(5,5),picker=3.))
exclLines += [2*i+2,2*i+3]
if G2frame.Contour:
if lenX == len(X):
ContourY.append(N)
ContourZ.append(Y)
if 'C' in ParmList[0]['Type'][0]:
ContourX = X
else: #'T'OF
ContourX = range(lenX)
Nseq += 1
Plot.set_ylabel('Data sequence',fontsize=12)
else:
if 'SASD' in plottype and G2frame.logPlot:
X *= (1.01)**(offsetX*N)
else:
X += offsetX*.005*N
Xum = ma.getdata(X)
DifLine = ['']
if ifpicked:
if Pattern[0]['sqrtPlot']:
olderr = np.seterr(invalid='ignore') #get around sqrt(-ve) error
Z = np.where(xye[3]>=0.,np.sqrt(xye[3]),-np.sqrt(-xye[3]))
np.seterr(invalid=olderr['invalid'])
else:
Z = xye[3]+offsetY*N*Ymax/100.0
if 'PWDR' in plottype:
if Pattern[0]['sqrtPlot']:
olderr = np.seterr(invalid='ignore') #get around sqrt(-ve) error
W = np.where(xye[4]>=0.,np.sqrt(xye[4]),-np.sqrt(-xye[4]))
np.seterr(invalid=olderr['invalid'])
D = np.where(xye[5],(Y-Z),0.)-Ymax*Pattern[0]['delOffset']
else:
W = xye[4]+offsetY*N*Ymax/100.0
D = xye[5]-Ymax*Pattern[0]['delOffset'] #powder background
elif 'SASD' in plottype:
if G2frame.sqPlot:
W = xye[4]*X**4
Z = xye[3]*X**4
B = B*X**4
else:
W = xye[4]
if G2frame.SubBack:
YB = Y-B
ZB = Z
else:
YB = Y
ZB = Z+B
Plot.set_yscale("log",nonposy='mask')
if np.any(W>0.):
Plot.set_ylim(bottom=np.min(np.trim_zeros(W))/2.,top=np.max(Y)*2.)
else:
Plot.set_ylim(bottom=np.min(np.trim_zeros(YB))/2.,top=np.max(Y)*2.)
if G2frame.logPlot:
if 'PWDR' in plottype:
Plot.set_yscale("log",nonposy='mask')
Plot.plot(X,Y,colors[N%6]+'+',picker=3.,clip_on=False)
Plot.plot(X,Z,colors[(N+1)%6],picker=False)
Plot.plot(X,W,colors[(N+2)%6],picker=False) #background
elif 'SASD' in plottype:
Plot.set_xscale("log",nonposx='mask')
Ibeg = np.searchsorted(X,limits[1][0])
Ifin = np.searchsorted(X,limits[1][1])
if G2frame.Weight:
Plot.set_yscale("linear")
DS = (YB-ZB)*np.sqrt(xye[2])
Plot.plot(X[Ibeg:Ifin],DS[Ibeg:Ifin],colors[(N+3)%6],picker=False)
Plot.axhline(0.,color=wx.BLACK)
Plot.set_ylim(bottom=np.min(DS[Ibeg:Ifin])*1.2,top=np.max(DS[Ibeg:Ifin])*1.2)
else:
Plot.set_yscale("log",nonposy='mask')
if G2frame.ErrorBars:
if G2frame.sqPlot:
Plot.errorbar(X,YB,yerr=X**4*Sample['Scale'][0]*np.sqrt(1./(Pattern[0]['wtFactor']*xye[2])),
ecolor=colors[N%6],picker=3.,clip_on=False)
else:
Plot.errorbar(X,YB,yerr=Sample['Scale'][0]*np.sqrt(1./(Pattern[0]['wtFactor']*xye[2])),
ecolor=colors[N%6],picker=3.,clip_on=False)
else:
Plot.plot(X,YB,colors[N%6]+'+',picker=3.,clip_on=False)
Plot.plot(X,W,colors[(N+2)%6],picker=False) #const. background
Plot.plot(X,ZB,colors[(N+1)%6],picker=False)
elif G2frame.Weight and 'PWDR' in plottype:
DY = xye[1]*np.sqrt(xye[2])
Ymax = max(DY)
DZ = xye[3]*np.sqrt(xye[2])
DS = xye[5]*np.sqrt(xye[2])-Ymax*Pattern[0]['delOffset']
ObsLine = Plot.plot(X,DY,colors[N%6]+'+',picker=3.,clip_on=False) #Io/sig(Io)
Plot.plot(X,DZ,colors[(N+1)%6],picker=False) #Ic/sig(Io)
DifLine = Plot.plot(X,DS,colors[(N+3)%6],picker=1.) #(Io-Ic)/sig(Io)
Plot.axhline(0.,color=wx.BLACK)
else:
if G2frame.SubBack:
if 'PWDR' in plottype:
Plot.plot(Xum,Y-W,colors[N%6]+'+',picker=False,clip_on=False) #Io-Ib
Plot.plot(X,Z-W,colors[(N+1)%6],picker=False) #Ic-Ib
else:
Plot.plot(X,YB,colors[N%6]+'+',picker=3.,clip_on=False)
Plot.plot(X,ZB,colors[(N+1)%6],picker=False)
else:
if 'PWDR' in plottype:
ObsLine = Plot.plot(Xum,Y,colors[N%6]+'+',picker=3.,clip_on=False) #Io
Plot.plot(X,Z,colors[(N+1)%6],picker=False) #Ic
else:
Plot.plot(X,YB,colors[N%6]+'+',picker=3.,clip_on=False)
Plot.plot(X,ZB,colors[(N+1)%6],picker=False)
if 'PWDR' in plottype:
Plot.plot(X,W,colors[(N+2)%6],picker=False) #Ib
DifLine = Plot.plot(X,D,colors[(N+3)%6],picker=1.) #Io-Ic
Plot.axhline(0.,color=wx.BLACK)
Page.canvas.SetToolTipString('')
if G2frame.PatternTree.GetItemText(PickId) == 'Peak List':
tip = 'On data point: Pick peak - L or R MB. On line: L-move, R-delete'
Page.canvas.SetToolTipString(tip)
data = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Peak List'))
for item in data['peaks']:
if Pattern[0]['qPlot']:
Lines.append(Plot.axvline(2.*np.pi/G2lat.Pos2dsp(Parms,item[0]),color=colors[N%6],picker=2.))
elif Pattern[0]['dPlot']:
Lines.append(Plot.axvline(G2lat.Pos2dsp(Parms,item[0]),color=colors[N%6],picker=2.))
else:
Lines.append(Plot.axvline(item[0],color=colors[N%6],picker=2.))
if G2frame.PatternTree.GetItemText(PickId) == 'Limits':
tip = 'On data point: Lower limit - L MB; Upper limit - R MB. On limit: MB down to move'
Page.canvas.SetToolTipString(tip)
data = G2frame.LimitsTable.GetData()
else: #not picked
if G2frame.logPlot:
if 'PWDR' in plottype:
Plot.semilogy(X,Y,colors[N%6],picker=False,nonposy='mask')
elif 'SASD' in plottype:
Plot.semilogy(X,Y,colors[N%6],picker=False,nonposy='mask')
else:
if 'PWDR' in plottype:
Plot.plot(X,Y,colors[N%6],picker=False)
elif 'SASD' in plottype:
Plot.loglog(X,Y,colors[N%6],picker=False,nonposy='mask')
Plot.set_ylim(bottom=np.min(np.trim_zeros(Y))/2.,top=np.max(Y)*2.)
if G2frame.logPlot and 'PWDR' in plottype:
Plot.set_ylim(bottom=np.min(np.trim_zeros(Y))/2.,top=np.max(Y)*2.)
if PickId and not G2frame.Contour:
Parms,Parms2 = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Instrument Parameters'))
if G2frame.PatternTree.GetItemText(PickId) in ['Index Peak List','Unit Cells List']:
peaks = np.array((G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Index Peak List'))))
if not len(peaks): return # are there any peaks?
for peak in peaks[0]:
if peak[2]:
if Pattern[0]['qPlot']:
Plot.axvline(2.*np.pi/G2lat.Pos2dsp(Parms,peak[0]),color='b')
if Pattern[0]['dPlot']:
Plot.axvline(G2lat.Pos2dsp(Parms,peak[0]),color='b')
else:
Plot.axvline(peak[0],color='b')
for hkl in G2frame.HKL:
clr = 'r'
if len(hkl) > 6 and hkl[3]:
clr = 'g'
if Pattern[0]['qPlot']:
Plot.axvline(2.*np.pi/G2lat.Pos2dsp(Parms,hkl[-2]),color=clr,dashes=(5,5))
if Pattern[0]['dPlot']:
Plot.axvline(G2lat.Pos2dsp(Parms,hkl[-2]),color=clr,dashes=(5,5))
else:
Plot.axvline(hkl[-2],color=clr,dashes=(5,5))
elif G2frame.PatternTree.GetItemText(PickId) in ['Reflection Lists'] or \
'PWDR' in G2frame.PatternTree.GetItemText(PickId):
refColors=['b','r','c','g','m','k']
Phases = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId,'Reflection Lists'))
for pId,phase in enumerate(Phases):
try: #patch for old style reflection lists
peaks = Phases[phase]['RefList']
except TypeError:
peaks = Phases[phase]
if not len(peaks):
continue
if Phases[phase].get('Super',False):
peak = np.array([[peak[5],peak[6]] for peak in peaks])
else:
peak = np.array([[peak[4],peak[5]] for peak in peaks])
pos = Pattern[0]['refOffset']-pId*Ymax*Pattern[0]['refDelt']*np.ones_like(peak)
if Pattern[0]['qPlot']:
Plot.plot(2*np.pi/peak.T[0],pos,refColors[pId%6]+'|',mew=1,ms=8,picker=3.,label=phase)
elif Pattern[0]['dPlot']:
Plot.plot(peak.T[0],pos,refColors[pId%6]+'|',mew=1,ms=8,picker=3.,label=phase)
else:
Plot.plot(peak.T[1],pos,refColors[pId%6]+'|',mew=1,ms=8,picker=3.,label=phase)
if len(Phases):
handles,legends = Plot.get_legend_handles_labels() #got double entries in the legends for some reason
if handles:
Plot.legend(handles[::2],legends[::2],title='Phases',loc='best') #skip every other one
if G2frame.Contour:
acolor = mpl.cm.get_cmap(G2frame.ContourColor)
Img = Plot.imshow(ContourZ,cmap=acolor,vmin=0,vmax=Ymax*G2frame.Cmax,interpolation=G2frame.Interpolate,
extent=[ContourX[0],ContourX[-1],ContourY[0],ContourY[-1]],aspect='auto',origin='lower')
Page.figure.colorbar(Img)
else:
G2frame.Lines = Lines
if not newPlot:
Page.toolbar.push_current()
Plot.set_xlim(xylim[0])
Plot.set_ylim(xylim[1])
# xylim = []
Page.toolbar.push_current()
Page.toolbar.draw()
else:
Page.canvas.draw()
olderr = np.seterr(invalid='ignore') #ugh - this removes a matplotlib error for mouse clicks in log plots
# and sqrt(-ve) in np.where usage
# G2frame.Pwdr = True
################################################################################
##### PlotDeltSig
################################################################################
[docs]def PlotDeltSig(G2frame,kind):
'needs a doc string'
try:
plotNum = G2frame.G2plotNB.plotList.index('Error analysis')
Page = G2frame.G2plotNB.nb.GetPage(plotNum)
Page.figure.clf()
Plot = Page.figure.gca() #get a fresh plot after clf()
except ValueError:
newPlot = True
G2frame.Cmax = 1.0
Plot = G2frame.G2plotNB.addMpl('Error analysis').gca()
plotNum = G2frame.G2plotNB.plotList.index('Error analysis')
Page = G2frame.G2plotNB.nb.GetPage(plotNum)
Page.Choice = None
PatternId = G2frame.PatternId
Pattern = G2frame.PatternTree.GetItemPyData(PatternId)
Pattern.append(G2frame.PatternTree.GetItemText(PatternId))
wtFactor = Pattern[0]['wtFactor']
if kind == 'PWDR':
limits = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Limits'))[1]
xye = np.array(Pattern[1])
xmin = np.searchsorted(xye[0],limits[0])
xmax = np.searchsorted(xye[0],limits[1])
DS = xye[5][xmin:xmax]*np.sqrt(wtFactor*xye[2][xmin:xmax])
elif kind == 'HKLF':
refl = Pattern[1]
DS = []
for ref in refl:
if ref[6] > 0.:
DS.append((ref[5]-ref[7])/ref[6])
Page.SetFocus()
G2frame.G2plotNB.status.DestroyChildren()
DS.sort()
EDS = np.zeros_like(DS)
DX = np.linspace(0.,1.,num=len(DS),endpoint=True)
oldErr = np.seterr(invalid='ignore') #avoid problem at DX==0
T = np.sqrt(np.log(1.0/DX**2))
top = 2.515517+0.802853*T+0.010328*T**2
bot = 1.0+1.432788*T+0.189269*T**2+0.001308*T**3
EDS = np.where(DX>0,-(T-top/bot),(T-top/bot))
low1 = np.searchsorted(EDS,-1.)
hi1 = np.searchsorted(EDS,1.)
slp,intcp = np.polyfit(EDS[low1:hi1],DS[low1:hi1],deg=1)
frac = 100.*(hi1-low1)/len(DS)
G2frame.G2plotNB.status.SetStatusText( \
'Over range -1. to 1. :'+' slope = %.3f, intercept = %.3f for %.2f%% of the fitted data'%(slp,intcp,frac),1)
Plot.set_title('Normal probability for '+Pattern[-1])
Plot.set_xlabel(r'expected $\mathsf{\Delta/\sigma}$',fontsize=14)
Plot.set_ylabel(r'observed $\mathsf{\Delta/\sigma}$',fontsize=14)
Plot.plot(EDS,DS,'r+',label='result')
Plot.plot([-2,2],[-2,2],'k',dashes=(5,5),label='ideal')
Plot.legend(loc='upper left')
np.seterr(invalid='warn')
Page.canvas.draw()
################################################################################
##### PlotISFG
################################################################################
[docs]def PlotISFG(G2frame,newPlot=False,type=''):
''' Plotting package for PDF analysis; displays I(q), S(q), F(q) and G(r) as single
or multiple plots with waterfall and contour plots as options
'''
if not type:
type = G2frame.G2plotNB.plotList[G2frame.G2plotNB.nb.GetSelection()]
if type not in ['I(Q)','S(Q)','F(Q)','G(R)']:
return
superMinusOne = unichr(0xaf)+unichr(0xb9)
def OnPlotKeyPress(event):
newPlot = False
if event.key == 'u':
if G2frame.Contour:
G2frame.Cmax = min(1.0,G2frame.Cmax*1.2)
elif Pattern[0]['Offset'][0] < 100.:
Pattern[0]['Offset'][0] += 1.
elif event.key == 'd':
if G2frame.Contour:
G2frame.Cmax = max(0.0,G2frame.Cmax*0.8)
elif Pattern[0]['Offset'][0] > 0.:
Pattern[0]['Offset'][0] -= 1.
elif event.key == 'l':
Pattern[0]['Offset'][1] -= 1.
elif event.key == 'r':
Pattern[0]['Offset'][1] += 1.
elif event.key == 'o':
Pattern[0]['Offset'] = [0,0]
elif event.key == 'c':
newPlot = True
G2frame.Contour = not G2frame.Contour
if not G2frame.Contour:
G2frame.SinglePlot = False
Pattern[0]['Offset'] = [0.,0.]
elif event.key == 's':
if G2frame.Contour:
choice = [m for m in mpl.cm.datad.keys() if not m.endswith("_r")]
choice.sort()
dlg = wx.SingleChoiceDialog(G2frame,'Select','Color scheme',choice)
if dlg.ShowModal() == wx.ID_OK:
sel = dlg.GetSelection()
G2frame.ContourColor = choice[sel]
else:
G2frame.ContourColor = 'Paired'
dlg.Destroy()
else:
G2frame.SinglePlot = not G2frame.SinglePlot
elif event.key == 'i': #for smoothing contour plot
choice = ['nearest','bilinear','bicubic','spline16','spline36','hanning',
'hamming','hermite','kaiser','quadric','catrom','gaussian','bessel',
'mitchell','sinc','lanczos']
dlg = wx.SingleChoiceDialog(G2frame,'Select','Interpolation',choice)
if dlg.ShowModal() == wx.ID_OK:
sel = dlg.GetSelection()
G2frame.Interpolate = choice[sel]
else:
G2frame.Interpolate = 'nearest'
dlg.Destroy()
elif event.key == 't' and not G2frame.Contour:
G2frame.Legend = not G2frame.Legend
PlotISFG(G2frame,newPlot=newPlot,type=type)
def OnKeyBox(event):
if G2frame.G2plotNB.nb.GetSelection() == G2frame.G2plotNB.plotList.index(type):
event.key = cb.GetValue()[0]
cb.SetValue(' key press')
wx.CallAfter(OnPlotKeyPress,event)
Page.canvas.SetFocus() # redirect the Focus from the button back to the plot
def OnMotion(event):
xpos = event.xdata
if xpos: #avoid out of frame mouse position
ypos = event.ydata
Page.canvas.SetCursor(wx.CROSS_CURSOR)
try:
if G2frame.Contour:
G2frame.G2plotNB.status.SetStatusText('R =%.3fA pattern ID =%5d'%(xpos,int(ypos)),1)
else:
G2frame.G2plotNB.status.SetStatusText('R =%.3fA %s =%.2f'%(xpos,type,ypos),1)
except TypeError:
G2frame.G2plotNB.status.SetStatusText('Select '+type+' pattern first',1)
xylim = []
try:
plotNum = G2frame.G2plotNB.plotList.index(type)
Page = G2frame.G2plotNB.nb.GetPage(plotNum)
if not newPlot:
Plot = Page.figure.gca() #get previous plot & get limits
xylim = Plot.get_xlim(),Plot.get_ylim()
Page.figure.clf()
Plot = Page.figure.gca()
except ValueError:
newPlot = True
G2frame.Cmax = 1.0
Plot = G2frame.G2plotNB.addMpl(type).gca()
plotNum = G2frame.G2plotNB.plotList.index(type)
Page = G2frame.G2plotNB.nb.GetPage(plotNum)
Page.canvas.mpl_connect('key_press_event', OnPlotKeyPress)
Page.canvas.mpl_connect('motion_notify_event', OnMotion)
Page.SetFocus()
G2frame.G2plotNB.status.DestroyChildren()
if G2frame.Contour:
Page.Choice = (' key press','d: lower contour max','u: raise contour max',
'i: interpolation method','s: color scheme','c: contour off')
else:
Page.Choice = (' key press','l: offset left','r: offset right','d: offset down','u: offset up',
'o: reset offset','t: toggle legend','c: contour on','s: toggle single plot')
Page.keyPress = OnPlotKeyPress
PatternId = G2frame.PatternId
PickId = G2frame.PickId
Plot.set_title(type)
if type == 'G(R)':
Plot.set_xlabel(r'$R,\AA$',fontsize=14)
else:
Plot.set_xlabel(r'$Q,\AA$'+superMinusOne,fontsize=14)
Plot.set_ylabel(r''+type,fontsize=14)
colors=['b','g','r','c','m','k']
name = G2frame.PatternTree.GetItemText(PatternId)[4:]
Pattern = []
if G2frame.SinglePlot:
name = G2frame.PatternTree.GetItemText(PatternId)
name = type+name[4:]
Id = G2gd.GetPatternTreeItemId(G2frame,PatternId,name)
Pattern = G2frame.PatternTree.GetItemPyData(Id)
if Pattern:
Pattern.append(name)
PlotList = [Pattern,]
else:
PlotList = []
item, cookie = G2frame.PatternTree.GetFirstChild(G2frame.root)
while item:
if 'PDF' in G2frame.PatternTree.GetItemText(item):
name = type+G2frame.PatternTree.GetItemText(item)[4:]
Id = G2gd.GetPatternTreeItemId(G2frame,item,name)
Pattern = G2frame.PatternTree.GetItemPyData(Id)
if Pattern:
Pattern.append(name)
PlotList.append(Pattern)
item, cookie = G2frame.PatternTree.GetNextChild(G2frame.root, cookie)
PDFdata = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'PDF Controls'))
numbDen = G2pwd.GetNumDensity(PDFdata['ElList'],PDFdata['Form Vol'])
Xb = [0.,10.]
Yb = [0.,-40.*np.pi*numbDen]
Ymax = 1.0
lenX = 0
for Pattern in PlotList:
try:
xye = Pattern[1]
except IndexError:
return
Ymax = max(Ymax,max(xye[1]))
offset = Pattern[0]['Offset'][0]*Ymax/100.0
if G2frame.Contour:
ContourZ = []
ContourY = []
Nseq = 0
for N,Pattern in enumerate(PlotList):
xye = Pattern[1]
if PickId:
ifpicked = Pattern[2] == G2frame.PatternTree.GetItemText(PatternId)
X = xye[0]
if not lenX:
lenX = len(X)
Y = xye[1]+offset*N
if G2frame.Contour:
if lenX == len(X):
ContourY.append(N)
ContourZ.append(Y)
ContourX = X
Nseq += 1
Plot.set_ylabel('Data sequence',fontsize=12)
else:
X = xye[0]+Pattern[0]['Offset'][1]*.005*N
if ifpicked:
Plot.plot(X,Y,colors[N%6]+'+',picker=3.,clip_on=False)
Page.canvas.SetToolTipString('')
else:
if G2frame.Legend:
Plot.plot(X,Y,colors[N%6],picker=False,label='Azm:'+Pattern[2].split('=')[1])
else:
Plot.plot(X,Y,colors[N%6],picker=False)
if type == 'G(R)':
Plot.plot(Xb,Yb,color='k',dashes=(5,5))
elif type == 'F(Q)':
Plot.axhline(0.,color=wx.BLACK)
elif type == 'S(Q)':
Plot.axhline(1.,color=wx.BLACK)
if G2frame.Contour:
acolor = mpl.cm.get_cmap(G2frame.ContourColor)
Img = Plot.imshow(ContourZ,cmap=acolor,vmin=0,vmax=Ymax*G2frame.Cmax,interpolation=G2frame.Interpolate,
extent=[ContourX[0],ContourX[-1],ContourY[0],ContourY[-1]],aspect='auto',origin='lower')
Page.figure.colorbar(Img)
elif G2frame.Legend:
Plot.legend(loc='best')
if not newPlot:
Page.toolbar.push_current()
Plot.set_xlim(xylim[0])
Plot.set_ylim(xylim[1])
xylim = []
Page.toolbar.push_current()
Page.toolbar.draw()
else:
Page.canvas.draw()
################################################################################
##### PlotCalib
################################################################################
[docs]def PlotCalib(G2frame,Inst,XY,Sigs,newPlot=False):
'''plot of CW or TOF peak calibration
'''
def OnMotion(event):
xpos = event.xdata
if xpos: #avoid out of frame mouse position
ypos = event.ydata
Page.canvas.SetCursor(wx.CROSS_CURSOR)
try:
G2frame.G2plotNB.status.SetStatusText('X =%9.3f %s =%9.3g'%(xpos,Title,ypos),1)
except TypeError:
G2frame.G2plotNB.status.SetStatusText('Select '+Title+' pattern first',1)
found = []
wid = 1
view = Page.toolbar._views.forward()
if view:
view = view[0][:2]
wid = view[1]-view[0]
found = XY[np.where(np.fabs(XY.T[0]-xpos) < 0.005*wid)]
if len(found):
pos = found[0][1]
if 'C' in Inst['Type'][0]:
Page.canvas.SetToolTipString('position=%.4f'%(pos))
else:
Page.canvas.SetToolTipString('position=%.2f'%(pos))
else:
Page.canvas.SetToolTipString('')
Title = 'Position calibration'
try:
plotNum = G2frame.G2plotNB.plotList.index(Title)
Page = G2frame.G2plotNB.nb.GetPage(plotNum)
if not newPlot:
Plot = Page.figure.gca()
xylim = Plot.get_xlim(),Plot.get_ylim()
Page.figure.clf()
Plot = Page.figure.gca()
except ValueError:
newPlot = True
Plot = G2frame.G2plotNB.addMpl(Title).gca()
plotNum = G2frame.G2plotNB.plotList.index(Title)
Page = G2frame.G2plotNB.nb.GetPage(plotNum)
Page.canvas.mpl_connect('motion_notify_event', OnMotion)
Page.Choice = None
Page.SetFocus()
G2frame.G2plotNB.status.DestroyChildren()
Plot.set_title(Title)
Plot.set_xlabel(r'd-spacing',fontsize=14)
if 'C' in Inst['Type'][0]:
Plot.set_ylabel(r'$\mathsf{\Delta(2\theta)}$',fontsize=14)
else:
Plot.set_ylabel(r'$\mathsf{\Delta}T/T$',fontsize=14)
for ixy,xyw in enumerate(XY):
if len(xyw) > 2:
X,Y,W = xyw
else:
X,Y = xyw
W = 0.
Yc = G2lat.Dsp2pos(Inst,X)
if 'C' in Inst['Type'][0]:
Y = Y-Yc
E = Sigs[ixy]
bin = W/2.
else:
Y = (Y-Yc)/Yc
E = Sigs[ixy]/Yc
bin = W/(2.*Yc)
if E:
Plot.errorbar(X,Y,ecolor='k',yerr=E)
if ixy:
Plot.plot(X,Y,'kx',picker=3)
else:
Plot.plot(X,Y,'kx',label='peak')
if W:
if ixy:
Plot.plot(X,bin,'b+')
else:
Plot.plot(X,bin,'b+',label='bin width')
Plot.plot(X,-bin,'b+')
Plot.axhline(0.,color='r',linestyle='--')
Plot.legend(loc='best')
if not newPlot:
Page.toolbar.push_current()
Plot.set_xlim(xylim[0])
Plot.set_ylim(xylim[1])
# xylim = []
Page.toolbar.push_current()
Page.toolbar.draw()
else:
Page.canvas.draw()
################################################################################
##### PlotXY
################################################################################
[docs]def PlotXY(G2frame,XY,XY2=None,labelX=None,labelY=None,newPlot=False,Title=''):
'''simple plot of xy data, used for diagnostic purposes
'''
def OnMotion(event):
xpos = event.xdata
if xpos: #avoid out of frame mouse position
ypos = event.ydata
Page.canvas.SetCursor(wx.CROSS_CURSOR)
try:
G2frame.G2plotNB.status.SetStatusText('X =%9.3f %s =%9.3f'%(xpos,Title,ypos),1)
except TypeError:
G2frame.G2plotNB.status.SetStatusText('Select '+Title+' pattern first',1)
try:
plotNum = G2frame.G2plotNB.plotList.index(Title)
Page = G2frame.G2plotNB.nb.GetPage(plotNum)
if not newPlot:
Plot = Page.figure.gca()
xylim = Plot.get_xlim(),Plot.get_ylim()
Page.figure.clf()
Plot = Page.figure.gca()
except ValueError:
newPlot = True
Plot = G2frame.G2plotNB.addMpl(Title).gca()
plotNum = G2frame.G2plotNB.plotList.index(Title)
Page = G2frame.G2plotNB.nb.GetPage(plotNum)
Page.canvas.mpl_connect('motion_notify_event', OnMotion)
Page.Choice = None
Page.SetFocus()
G2frame.G2plotNB.status.DestroyChildren()
Plot.set_title(Title)
if labelX:
Plot.set_xlabel(r''+labelX,fontsize=14)
else:
Plot.set_xlabel(r'X',fontsize=14)
if labelY:
Plot.set_ylabel(r''+labelY,fontsize=14)
else:
Plot.set_ylabel(r'Y',fontsize=14)
colors=['b','g','r','c','m','k']
for ixy,xy in enumerate(XY):
X,Y = xy
Plot.plot(X,Y,colors[ixy%6]+'+',picker=False)
if len(XY2):
for ixy,xy in enumerate(XY2):
X,Y = xy
Plot.plot(X,Y,colors[ixy%6],picker=False)
if not newPlot:
Page.toolbar.push_current()
Plot.set_xlim(xylim[0])
Plot.set_ylim(xylim[1])
xylim = []
Page.toolbar.push_current()
Page.toolbar.draw()
else:
Page.canvas.draw()
################################################################################
##### PlotStrain
################################################################################
[docs]def PlotStrain(G2frame,data,newPlot=False):
'''plot of strain data, used for diagnostic purposes
'''
def OnMotion(event):
xpos = event.xdata
if xpos: #avoid out of frame mouse position
ypos = event.ydata
Page.canvas.SetCursor(wx.CROSS_CURSOR)
try:
G2frame.G2plotNB.status.SetStatusText('d-spacing =%9.5f Azimuth =%9.3f'%(ypos,xpos),1)
except TypeError:
G2frame.G2plotNB.status.SetStatusText('Select Strain pattern first',1)
try:
plotNum = G2frame.G2plotNB.plotList.index('Strain')
Page = G2frame.G2plotNB.nb.GetPage(plotNum)
if not newPlot:
Plot = Page.figure.gca()
xylim = Plot.get_xlim(),Plot.get_ylim()
Page.figure.clf()
Plot = Page.figure.gca()
except ValueError:
newPlot = True
Plot = G2frame.G2plotNB.addMpl('Strain').gca()
plotNum = G2frame.G2plotNB.plotList.index('Strain')
Page = G2frame.G2plotNB.nb.GetPage(plotNum)
Page.canvas.mpl_connect('motion_notify_event', OnMotion)
Page.Choice = None
Page.SetFocus()
G2frame.G2plotNB.status.DestroyChildren()
Plot.set_title('Strain')
Plot.set_ylabel(r'd-spacing',fontsize=14)
Plot.set_xlabel(r'Azimuth',fontsize=14)
colors=['b','g','r','c','m','k']
for N,item in enumerate(data['d-zero']):
Y,X = np.array(item['ImtaObs']) #plot azimuth as X & d-spacing as Y
Plot.plot(X,Y,colors[N%6]+'+',picker=False)
Y,X = np.array(item['ImtaCalc'])
Plot.plot(X,Y,colors[N%6],picker=False)
if not newPlot:
Page.toolbar.push_current()
Plot.set_xlim(xylim[0])
Plot.set_ylim(xylim[1])
xylim = []
Page.toolbar.push_current()
Page.toolbar.draw()
else:
Page.canvas.draw()
################################################################################
##### PlotSASDSizeDist
################################################################################
def PlotSASDSizeDist(G2frame):
def OnPageChanged(event):
PlotText = G2frame.G2plotNB.nb.GetPageText(G2frame.G2plotNB.nb.GetSelection())
if 'Powder' in PlotText:
PlotPatterns(G2frame,plotType='SASD',newPlot=True)
elif 'Size' in PlotText:
PlotSASDSizeDist(G2frame)
def OnMotion(event):
xpos = event.xdata
if xpos: #avoid out of frame mouse position
ypos = event.ydata
Page.canvas.SetCursor(wx.CROSS_CURSOR)
try:
G2frame.G2plotNB.status.SetStatusText('diameter =%9.3f f(D) =%9.3g'%(xpos,ypos),1)
except TypeError:
G2frame.G2plotNB.status.SetStatusText('Select Strain pattern first',1)
try:
plotNum = G2frame.G2plotNB.plotList.index('Size Distribution')
Page = G2frame.G2plotNB.nb.GetPage(plotNum)
Page.figure.clf()
Plot = Page.figure.gca() #get a fresh plot after clf()
except ValueError:
newPlot = True
Plot = G2frame.G2plotNB.addMpl('Size Distribution').gca()
G2frame.G2plotNB.Bind(wx.aui.EVT_AUINOTEBOOK_PAGE_CHANGED,OnPageChanged)
plotNum = G2frame.G2plotNB.plotList.index('Size Distribution')
Page = G2frame.G2plotNB.nb.GetPage(plotNum)
Page.canvas.mpl_connect('motion_notify_event', OnMotion)
Page.Choice = None
Page.SetFocus()
PatternId = G2frame.PatternId
data = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Models'))
Bins,Dbins,BinMag = data['Size']['Distribution']
Plot.set_title('Size Distribution')
Plot.set_xlabel(r'$D, \AA$',fontsize=14)
Plot.set_ylabel(r'$Volume distribution f(D)$',fontsize=14)
if data['Size']['logBins']:
Plot.set_xscale("log",nonposy='mask')
Plot.set_xlim([np.min(2.*Bins)/2.,np.max(2.*Bins)*2.])
Plot.bar(2.*Bins-Dbins,BinMag,2.*Dbins,facecolor='white') #plot diameters
if 'Size Calc' in data:
Rbins,Dist = data['Size Calc']
for i in range(len(Rbins)):
if len(Rbins[i]):
Plot.plot(2.*Rbins[i],Dist[i]) #plot diameters
Page.canvas.draw()
################################################################################
##### PlotPowderLines
################################################################################
[docs]def PlotPowderLines(G2frame):
''' plotting of powder lines (i.e. no powder pattern) as sticks
'''
global HKL
def OnMotion(event):
xpos = event.xdata
if xpos: #avoid out of frame mouse position
Page.canvas.SetCursor(wx.CROSS_CURSOR)
G2frame.G2plotNB.status.SetFields(['','2-theta =%9.3f '%(xpos,)])
if G2frame.PickId and G2frame.PatternTree.GetItemText(G2frame.PickId) in ['Index Peak List','Unit Cells List']:
found = []
if len(HKL):
view = Page.toolbar._views.forward()[0][:2]
wid = view[1]-view[0]
found = HKL[np.where(np.fabs(HKL.T[-1]-xpos) < 0.002*wid)]
if len(found):
h,k,l = found[0][:3]
Page.canvas.SetToolTipString('%d,%d,%d'%(int(h),int(k),int(l)))
else:
Page.canvas.SetToolTipString('')
try:
plotNum = G2frame.G2plotNB.plotList.index('Powder Lines')
Page = G2frame.G2plotNB.nb.GetPage(plotNum)
Page.figure.clf()
Plot = Page.figure.gca()
except ValueError:
Plot = G2frame.G2plotNB.addMpl('Powder Lines').gca()
plotNum = G2frame.G2plotNB.plotList.index('Powder Lines')
Page = G2frame.G2plotNB.nb.GetPage(plotNum)
Page.canvas.mpl_connect('motion_notify_event', OnMotion)
Page.Choice = None
Page.SetFocus()
Plot.set_title('Powder Pattern Lines')
Plot.set_xlabel(r'$\mathsf{2\theta}$',fontsize=14)
PickId = G2frame.PickId
PatternId = G2frame.PatternId
peaks = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Index Peak List'))[0]
for peak in peaks:
Plot.axvline(peak[0],color='b')
HKL = np.array(G2frame.HKL)
for hkl in G2frame.HKL:
Plot.axvline(hkl[-1],color='r',dashes=(5,5))
xmin = peaks[0][0]
xmax = peaks[-1][0]
delt = xmax-xmin
xlim = [max(0,xmin-delt/20.),min(180.,xmax+delt/20.)]
Plot.set_xlim(xlim)
Page.canvas.draw()
Page.toolbar.push_current()
################################################################################
##### PlotPeakWidths
################################################################################
[docs]def PlotPeakWidths(G2frame):
''' Plotting of instrument broadening terms as function of 2-theta
Seen when "Instrument Parameters" chosen from powder pattern data tree
'''
# sig = lambda Th,U,V,W: 1.17741*math.sqrt(U*tand(Th)**2+V*tand(Th)+W)*math.pi/18000.
# gam = lambda Th,X,Y: (X/cosd(Th)+Y*tand(Th))*math.pi/18000.
gamFW = lambda s,g: np.exp(np.log(s**5+2.69269*s**4*g+2.42843*s**3*g**2+4.47163*s**2*g**3+0.07842*s*g**4+g**5)/5.)
# gamFW2 = lambda s,g: math.sqrt(s**2+(0.4654996*g)**2)+.5345004*g #Ubaldo Bafile - private communication
PatternId = G2frame.PatternId
limitID = G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Limits')
if limitID:
limits = G2frame.PatternTree.GetItemPyData(limitID)[:2]
else:
return
Parms,Parms2 = G2frame.PatternTree.GetItemPyData( \
G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Instrument Parameters'))
if 'C' in Parms['Type'][0]:
lam = G2mth.getWave(Parms)
else:
difC = Parms['difC'][0]
try: # PATCH: deal with older peak lists, before changed to dict to implement TOF
peaks = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Peak List'))['peaks']
except TypeError:
print "Your peak list needs reformatting...",
item = G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Peak List')
G2frame.PatternTree.SelectItem(item)
item = G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Instrument Parameters')
G2frame.PatternTree.SelectItem(item)
print "done"
return
try:
plotNum = G2frame.G2plotNB.plotList.index('Peak Widths')
Page = G2frame.G2plotNB.nb.GetPage(plotNum)
Page.figure.clf()
Plot = Page.figure.gca()
except ValueError:
Plot = G2frame.G2plotNB.addMpl('Peak Widths').gca()
plotNum = G2frame.G2plotNB.plotList.index('Peak Widths')
Page = G2frame.G2plotNB.nb.GetPage(plotNum)
Page.Choice = None
Page.SetFocus()
Page.canvas.SetToolTipString('')
colors=['b','g','r','c','m','k']
X = []
Y = []
Z = []
W = []
if 'C' in Parms['Type'][0]:
Plot.set_title('Instrument and sample peak widths')
Plot.set_xlabel(r'$Q, \AA^{-1}$',fontsize=14)
Plot.set_ylabel(r'$\Delta Q/Q, \Delta d/d$',fontsize=14)
try:
Xmin,Xmax = limits[1]
X = np.linspace(Xmin,Xmax,num=101,endpoint=True)
Q = 4.*np.pi*npsind(X/2.)/lam
Z = np.ones_like(X)
data = G2mth.setPeakparms(Parms,Parms2,X,Z)
s = 1.17741*np.sqrt(data[4])*np.pi/18000.
g = data[6]*np.pi/18000.
G = G2pwd.getgamFW(g,s)
Y = s/nptand(X/2.)
Z = g/nptand(X/2.)
W = G/nptand(X/2.)
Plot.plot(Q,Y,color='r',label='Gaussian')
Plot.plot(Q,Z,color='g',label='Lorentzian')
Plot.plot(Q,W,color='b',label='G+L')
fit = G2mth.setPeakparms(Parms,Parms2,X,Z,useFit=True)
sf = 1.17741*np.sqrt(fit[4])*np.pi/18000.
gf = fit[6]*np.pi/18000.
Gf = G2pwd.getgamFW(gf,sf)
Yf = sf/nptand(X/2.)
Zf = gf/nptand(X/2.)
Wf = Gf/nptand(X/2.)
Plot.plot(Q,Yf,color='r',dashes=(5,5),label='Gaussian fit')
Plot.plot(Q,Zf,color='g',dashes=(5,5),label='Lorentzian fit')
Plot.plot(Q,Wf,color='b',dashes=(5,5),label='G+L fit')
X = []
Y = []
Z = []
W = []
V = []
for peak in peaks:
X.append(4.0*math.pi*sind(peak[0]/2.0)/lam)
try:
s = 1.17741*math.sqrt(peak[4])*math.pi/18000.
except ValueError:
s = 0.01
g = peak[6]*math.pi/18000.
G = G2pwd.getgamFW(g,s)
Y.append(s/tand(peak[0]/2.))
Z.append(g/tand(peak[0]/2.))
W.append(G/tand(peak[0]/2.))
if len(peaks):
Plot.plot(X,Y,'+',color='r',label='G peak')
Plot.plot(X,Z,'+',color='g',label='L peak')
Plot.plot(X,W,'+',color='b',label='G+L peak')
Plot.legend(loc='best')
Page.canvas.draw()
except ValueError:
print '**** ERROR - default U,V,W profile coefficients yield sqrt of negative value at 2theta =', \
'%.3f'%(2*theta)
G2frame.G2plotNB.Delete('Peak Widths')
else: #'T'OF
Plot.set_title('Instrument and sample peak coefficients')
Plot.set_xlabel(r'$Q, \AA^{-1}$',fontsize=14)
Plot.set_ylabel(r'$\alpha, \beta, \Delta Q/Q, \Delta d/d$',fontsize=14)
Xmin,Xmax = limits[1]
T = np.linspace(Xmin,Xmax,num=101,endpoint=True)
Z = np.ones_like(T)
data = G2mth.setPeakparms(Parms,Parms2,T,Z)
ds = T/difC
Q = 2.*np.pi/ds
A = data[4]
B = data[6]
S = 1.17741*np.sqrt(data[8])/T
G = data[10]/T
Plot.plot(Q,A,color='r',label='Alpha')
Plot.plot(Q,B,color='g',label='Beta')
Plot.plot(Q,S,color='b',label='Gaussian')
Plot.plot(Q,G,color='m',label='Lorentzian')
fit = G2mth.setPeakparms(Parms,Parms2,T,Z)
ds = T/difC
Q = 2.*np.pi/ds
Af = fit[4]
Bf = fit[6]
Sf = 1.17741*np.sqrt(fit[8])/T
Gf = fit[10]/T
Plot.plot(Q,Af,color='r',dashes=(5,5),label='Alpha fit')
Plot.plot(Q,Bf,color='g',dashes=(5,5),label='Beta fit')
Plot.plot(Q,Sf,color='b',dashes=(5,5),label='Gaussian fit')
Plot.plot(Q,Gf,color='m',dashes=(5,5),label='Lorentzian fit')
T = []
A = []
B = []
S = []
G = []
W = []
Q = []
V = []
for peak in peaks:
T.append(peak[0])
A.append(peak[4])
B.append(peak[6])
Q.append(2.*np.pi*difC/peak[0])
S.append(1.17741*np.sqrt(peak[8])/peak[0])
G.append(peak[10]/peak[0])
Plot.plot(Q,A,'+',color='r',label='Alpha peak')
Plot.plot(Q,B,'+',color='g',label='Beta peak')
Plot.plot(Q,S,'+',color='b',label='Gaussian peak')
Plot.plot(Q,G,'+',color='m',label='Lorentzian peak')
Plot.legend(loc='best')
Page.canvas.draw()
################################################################################
##### PlotSizeStrainPO
################################################################################
[docs]def PlotSizeStrainPO(G2frame,data,Start=False):
'''Plot 3D mustrain/size/preferred orientation figure. In this instance data is for a phase
'''
PatternId = G2frame.PatternId
generalData = data['General']
SGData = generalData['SGData']
SGLaue = SGData['SGLaue']
if Start: #initialize the spherical harmonics qlmn arrays
ptx.pyqlmninit()
Start = False
# MuStrKeys = G2spc.MustrainNames(SGData)
cell = generalData['Cell'][1:]
A,B = G2lat.cell2AB(cell[:6])
Vol = cell[6]
useList = data['Histograms']
phase = generalData['Name']
plotType = generalData['Data plot type']
plotDict = {'Mustrain':'Mustrain','Size':'Size','Preferred orientation':'Pref.Ori.'}
for ptype in plotDict:
G2frame.G2plotNB.Delete(ptype)
if plotType in ['None']:
return
for item in useList:
if useList[item]['Show']:
break
else:
return #nothing to show!!
numPlots = len(useList)
if plotType in ['Mustrain','Size']:
Plot = mp3d.Axes3D(G2frame.G2plotNB.add3D(plotType))
else:
Plot = G2frame.G2plotNB.addMpl(plotType).gca()
plotNum = G2frame.G2plotNB.plotList.index(plotType)
Page = G2frame.G2plotNB.nb.GetPage(plotNum)
Page.Choice = None
Page.SetFocus()
G2frame.G2plotNB.status.SetStatusText('',1)
if not Page.IsShown():
Page.Show()
for item in useList:
if useList[item]['Show']:
PHI = np.linspace(0.,360.,30,True)
PSI = np.linspace(0.,180.,30,True)
X = np.outer(npsind(PHI),npsind(PSI))
Y = np.outer(npcosd(PHI),npsind(PSI))
Z = np.outer(np.ones(np.size(PHI)),npcosd(PSI))
try: #temp patch instead of 'mustrain' for old files with 'microstrain'
coeff = useList[item][plotDict[plotType]]
except KeyError:
break
if plotType in ['Mustrain','Size']:
if coeff[0] == 'isotropic':
X *= coeff[1][0]
Y *= coeff[1][0]
Z *= coeff[1][0]
elif coeff[0] == 'uniaxial':
def uniaxCalc(xyz,iso,aniso,axes):
Z = np.array(axes)
cp = abs(np.dot(xyz,Z))
sp = np.sqrt(1.-cp**2)
R = iso*aniso/np.sqrt((iso*cp)**2+(aniso*sp)**2)
return R*xyz
iso,aniso = coeff[1][:2]
axes = np.inner(A,np.array(coeff[3]))
axes /= nl.norm(axes)
Shkl = np.array(coeff[1])
XYZ = np.dstack((X,Y,Z))
XYZ = np.nan_to_num(np.apply_along_axis(uniaxCalc,2,XYZ,iso,aniso,axes))
X,Y,Z = np.dsplit(XYZ,3)
X = X[:,:,0]
Y = Y[:,:,0]
Z = Z[:,:,0]
elif coeff[0] == 'ellipsoidal':
def ellipseCalc(xyz,E,R):
XYZ = xyz*E.T
return np.inner(XYZ.T,R)
S6 = coeff[4]
Sij = G2lat.U6toUij(S6)
E,R = nl.eigh(Sij)
XYZ = np.dstack((X,Y,Z))
XYZ = np.nan_to_num(np.apply_along_axis(ellipseCalc,2,XYZ,E,R))
X,Y,Z = np.dsplit(XYZ,3)
X = X[:,:,0]
Y = Y[:,:,0]
Z = Z[:,:,0]
elif coeff[0] == 'generalized':
def genMustrain(xyz,SGData,A,Shkl):
uvw = np.inner(A.T,xyz)
Strm = np.array(G2spc.MustrainCoeff(uvw,SGData))
Sum = np.sum(np.multiply(Shkl,Strm))
Sum = np.where(Sum > 0.01,Sum,0.01)
Sum = np.sqrt(Sum)
return Sum*xyz
Shkl = np.array(coeff[4])
if np.any(Shkl):
XYZ = np.dstack((X,Y,Z))
XYZ = np.nan_to_num(np.apply_along_axis(genMustrain,2,XYZ,SGData,A,Shkl))
X,Y,Z = np.dsplit(XYZ,3)
X = X[:,:,0]
Y = Y[:,:,0]
Z = Z[:,:,0]
if np.any(X) and np.any(Y) and np.any(Z):
errFlags = np.seterr(all='ignore')
Plot.plot_surface(X,Y,Z,rstride=1,cstride=1,color='g',linewidth=1)
np.seterr(all='ignore')
xyzlim = np.array([Plot.get_xlim3d(),Plot.get_ylim3d(),Plot.get_zlim3d()]).T
XYZlim = [min(xyzlim[0]),max(xyzlim[1])]
Plot.set_xlim3d(XYZlim)
Plot.set_ylim3d(XYZlim)
Plot.set_zlim3d(XYZlim)
Plot.set_aspect('equal')
if plotType == 'Size':
Plot.set_title('Crystallite size for '+phase+'\n'+coeff[0]+' model')
Plot.set_xlabel(r'X, $\mu$m')
Plot.set_ylabel(r'Y, $\mu$m')
Plot.set_zlabel(r'Z, $\mu$m')
else:
Plot.set_title(r'$\mu$strain for '+phase+'\n'+coeff[0]+' model')
Plot.set_xlabel(r'X, $\mu$strain')
Plot.set_ylabel(r'Y, $\mu$strain')
Plot.set_zlabel(r'Z, $\mu$strain')
else:
h,k,l = generalData['POhkl']
if coeff[0] == 'MD':
print 'March-Dollase preferred orientation plot'
else:
PH = np.array(generalData['POhkl'])
phi,beta = G2lat.CrsAng(PH,cell[:6],SGData)
SHCoef = {}
for item in coeff[5]:
L,N = eval(item.strip('C'))
SHCoef['C%d,0,%d'%(L,N)] = coeff[5][item]
ODFln = G2lat.Flnh(Start,SHCoef,phi,beta,SGData)
X = np.linspace(0,90.0,26)
Y = G2lat.polfcal(ODFln,'0',X,0.0)
Plot.plot(X,Y,color='k',label=str(PH))
Plot.legend(loc='best')
Plot.set_title('Axial distribution for HKL='+str(PH)+' in '+phase)
Plot.set_xlabel(r'$\psi$',fontsize=16)
Plot.set_ylabel('MRD',fontsize=14)
Page.canvas.draw()
################################################################################
##### PlotTexture
################################################################################
[docs]def PlotTexture(G2frame,data,Start=False):
'''Pole figure, inverse pole figure, 3D pole distribution and 3D inverse pole distribution
plotting.
dict generalData contains all phase info needed which is in data
'''
shModels = ['cylindrical','none','shear - 2/m','rolling - mmm']
SamSym = dict(zip(shModels,['0','-1','2/m','mmm']))
PatternId = G2frame.PatternId
generalData = data['General']
SGData = generalData['SGData']
textureData = generalData['SH Texture']
G2frame.G2plotNB.Delete('Texture')
if not textureData['Order']:
return #no plot!!
SHData = generalData['SH Texture']
SHCoef = SHData['SH Coeff'][1]
cell = generalData['Cell'][1:7]
Amat,Bmat = G2lat.cell2AB(cell)
sq2 = 1.0/math.sqrt(2.0)
def rp2xyz(r,p):
z = npcosd(r)
xy = np.sqrt(1.-z**2)
return xy*npsind(p),xy*npcosd(p),z
def OnMotion(event):
SHData = data['General']['SH Texture']
if event.xdata and event.ydata: #avoid out of frame errors
xpos = event.xdata
ypos = event.ydata
if 'Inverse' in SHData['PlotType']:
r = xpos**2+ypos**2
if r <= 1.0:
if 'equal' in G2frame.Projection:
r,p = 2.*npasind(np.sqrt(r)*sq2),npatan2d(ypos,xpos)
else:
r,p = 2.*npatand(np.sqrt(r)),npatan2d(ypos,xpos)
ipf = G2lat.invpolfcal(IODFln,SGData,np.array([r,]),np.array([p,]))
xyz = np.inner(Amat.T,np.array([rp2xyz(r,p)]))
y,x,z = list(xyz/np.max(np.abs(xyz)))
G2frame.G2plotNB.status.SetFields(['',
'psi =%9.3f, beta =%9.3f, MRD =%9.3f hkl=%5.2f,%5.2f,%5.2f'%(r,p,ipf,x,y,z)])
elif 'Axial' in SHData['PlotType']:
pass
else: #ordinary pole figure
z = xpos**2+ypos**2
if z <= 1.0:
z = np.sqrt(z)
if 'equal' in G2frame.Projection:
r,p = 2.*npasind(z*sq2),npatan2d(ypos,xpos)
else:
r,p = 2.*npatand(z),npatan2d(ypos,xpos)
pf = G2lat.polfcal(ODFln,SamSym[textureData['Model']],np.array([r,]),np.array([p,]))
G2frame.G2plotNB.status.SetFields(['','phi =%9.3f, gam =%9.3f, MRD =%9.3f'%(r,p,pf)])
try:
plotNum = G2frame.G2plotNB.plotList.index('Texture')
Page = G2frame.G2plotNB.nb.GetPage(plotNum)
Page.figure.clf()
Plot = Page.figure.gca()
if not Page.IsShown():
Page.Show()
except ValueError:
Plot = G2frame.G2plotNB.addMpl('Texture').gca()
plotNum = G2frame.G2plotNB.plotList.index('Texture')
Page = G2frame.G2plotNB.nb.GetPage(plotNum)
Page.canvas.mpl_connect('motion_notify_event', OnMotion)
Page.Choice = None
Page.SetFocus()
G2frame.G2plotNB.status.SetFields(['',''])
PH = np.array(SHData['PFhkl'])
phi,beta = G2lat.CrsAng(PH,cell,SGData)
ODFln = G2lat.Flnh(Start,SHCoef,phi,beta,SGData)
PX = np.array(SHData['PFxyz'])
gam = atan2d(PX[0],PX[1])
xy = math.sqrt(PX[0]**2+PX[1]**2)
xyz = math.sqrt(PX[0]**2+PX[1]**2+PX[2]**2)
psi = asind(xy/xyz)
IODFln = G2lat.Glnh(Start,SHCoef,psi,gam,SamSym[textureData['Model']])
if 'Axial' in SHData['PlotType']:
X = np.linspace(0,90.0,26)
Y = G2lat.polfcal(ODFln,SamSym[textureData['Model']],X,0.0)
Plot.plot(X,Y,color='k',label=str(SHData['PFhkl']))
Plot.legend(loc='best')
Plot.set_title('Axial distribution for HKL='+str(SHData['PFhkl']))
Plot.set_xlabel(r'$\psi$',fontsize=16)
Plot.set_ylabel('MRD',fontsize=14)
else:
npts = 201
if 'Inverse' in SHData['PlotType']:
X,Y = np.meshgrid(np.linspace(1.,-1.,npts),np.linspace(-1.,1.,npts))
R,P = np.sqrt(X**2+Y**2).flatten(),npatan2d(X,Y).flatten()
if 'equal' in G2frame.Projection:
R = np.where(R <= 1.,2.*npasind(R*sq2),0.0)
else:
R = np.where(R <= 1.,2.*npatand(R),0.0)
Z = np.zeros_like(R)
Z = G2lat.invpolfcal(IODFln,SGData,R,P)
Z = np.reshape(Z,(npts,npts))
CS = Plot.contour(Y,X,Z,aspect='equal')
Plot.clabel(CS,fontsize=9,inline=1)
try:
Img = Plot.imshow(Z.T,aspect='equal',cmap=G2frame.ContourColor,extent=[-1,1,-1,1])
except ValueError:
pass
Page.figure.colorbar(Img)
Plot.set_title('Inverse pole figure for XYZ='+str(SHData['PFxyz']))
Plot.set_xlabel(G2frame.Projection.capitalize()+' projection')
else:
X,Y = np.meshgrid(np.linspace(1.,-1.,npts),np.linspace(-1.,1.,npts))
R,P = np.sqrt(X**2+Y**2).flatten(),npatan2d(X,Y).flatten()
if 'equal' in G2frame.Projection:
R = np.where(R <= 1.,2.*npasind(R*sq2),0.0)
else:
R = np.where(R <= 1.,2.*npatand(R),0.0)
Z = np.zeros_like(R)
Z = G2lat.polfcal(ODFln,SamSym[textureData['Model']],R,P)
Z = np.reshape(Z,(npts,npts))
try:
CS = Plot.contour(Y,X,Z,aspect='equal')
Plot.clabel(CS,fontsize=9,inline=1)
except ValueError:
pass
Img = Plot.imshow(Z.T,aspect='equal',cmap=G2frame.ContourColor,extent=[-1,1,-1,1])
Page.figure.colorbar(Img)
Plot.set_title('Pole figure for HKL='+str(SHData['PFhkl']))
Plot.set_xlabel(G2frame.Projection.capitalize()+' projection')
Page.canvas.draw()
################################################################################
##### Plot Modulation
################################################################################
def ModulationPlot(G2frame,data,atom,ax,off=0):
global Off,Atom,Ax
Off = off
Atom = atom
Ax = ax
def OnMotion(event):
xpos = event.xdata
if xpos: #avoid out of frame mouse position
ypos = event.ydata
Page.canvas.SetCursor(wx.CROSS_CURSOR)
try:
G2frame.G2plotNB.status.SetStatusText('t =%9.3f %s =%9.3f'%(xpos,GkDelta+Ax,ypos),1)
except TypeError:
G2frame.G2plotNB.status.SetStatusText('Select '+Title+' pattern first',1)
def OnPlotKeyPress(event):
global Off,Atom,Ax
newPlot = False
if event.key == '0':
Off = 0
elif event.key in ['+','=']:
Off += 1
elif event.key == '-':
Off -= 1
elif event.key in ['l','r',] and mapData['Flip']:
roll = 1
if event.key == 'l':
roll = -1
rho = Map['rho']
Map['rho'] = np.roll(rho,roll,axis=3)
wx.CallAfter(ModulationPlot,G2frame,data,Atom,Ax,Off)
try:
plotNum = G2frame.G2plotNB.plotList.index('Modulation')
Page = G2frame.G2plotNB.nb.GetPage(plotNum)
Page.figure.clf()
Plot = Page.figure.gca()
if not Page.IsShown():
Page.Show()
except ValueError:
Plot = G2frame.G2plotNB.addMpl('Modulation').gca()
plotNum = G2frame.G2plotNB.plotList.index('Modulation')
Page = G2frame.G2plotNB.nb.GetPage(plotNum)
Page.canvas.mpl_connect('motion_notify_event', OnMotion)
Page.canvas.mpl_connect('key_press_event', OnPlotKeyPress)
Page.SetFocus()
General = data['General']
cx,ct,cs,cia = General['AtomPtrs']
mapData = General['Map']
if mapData['Flip']:
Page.Choice = ['+: shift up','-: shift down','0: reset shift','l: move left','r: move right']
else:
Page.Choice = ['+: shift up','-: shift down','0: reset shift']
Page.keyPress = OnPlotKeyPress
Map = General['4DmapData']
MapType = Map['MapType']
rhoSize = np.array(Map['rho'].shape)
atxyz = np.array(atom[cx:cx+3])
waveType = atom[-1]['SS1']['waveType']
Spos = atom[-1]['SS1']['Spos']
tau = np.linspace(0.,2.,101)
wave = np.zeros((3,101))
if len(Spos):
scof = []
ccof = []
for i,spos in enumerate(Spos):
if waveType in ['Sawtooth','ZigZag'] and not i:
Toff = spos[0][0]
slopes = np.array(spos[0][1:])
if waveType == 'Sawtooth':
wave = G2mth.posSawtooth(tau,Toff,slopes)
elif waveType == 'ZigZag':
wave = G2mth.posZigZag(tau,Toff,slopes)
else:
scof.append(spos[0][:3])
ccof.append(spos[0][3:])
wave += G2mth.posFourier(tau,np.array(scof),np.array(ccof))
if mapData['Flip']:
Title = 'Charge flip'
else:
Title = MapType
Title += ' map for atom '+atom[0]+ \
' at %.4f %.4f %.4f'%(atxyz[0],atxyz[1],atxyz[2])
ix = -np.array(np.rint(rhoSize[:3]*atxyz),dtype='i')
ix += (rhoSize[:3]/2)
ix = ix%rhoSize[:3]
rho = np.roll(np.roll(np.roll(Map['rho'],ix[0],axis=0),ix[1],axis=1),ix[2],axis=2)
ix = rhoSize[:3]/2
ib = 4
if Ax == 'x':
slab = np.sum(np.sum(rho[:,ix[1]-ib:ix[1]+ib,ix[2]-ib:ix[2]+ib,:],axis=2),axis=1)
Plot.plot(tau,wave[0])
elif Ax == 'y':
slab = np.sum(np.sum(rho[ix[0]-ib:ix[0]+ib,:,ix[2]-ib:ix[2]+ib,:],axis=2),axis=0)
Plot.plot(tau,wave[1])
elif Ax == 'z':
slab = np.sum(np.sum(rho[ix[0]-ib:ix[0]+ib,ix[1]-ib:ix[1]+ib,:,:],axis=1),axis=0)
Plot.plot(tau,wave[2])
Plot.set_title(Title)
Plot.set_xlabel('t')
Plot.set_ylabel(r'$\mathsf{\Delta}$%s'%(Ax))
Slab = np.hstack((slab,slab,slab))
Plot.contour(Slab[:,:21],20,extent=(0.,2.,-.5+Off*.005,.5+Off*.005))
Page.canvas.draw()
################################################################################
##### PlotCovariance
################################################################################
[docs]def PlotCovariance(G2frame,Data):
'needs a doc string'
if not Data:
print 'No covariance matrix available'
return
varyList = Data['varyList']
values = Data['variables']
Xmax = len(varyList)
covMatrix = Data['covMatrix']
sig = np.sqrt(np.diag(covMatrix))
xvar = np.outer(sig,np.ones_like(sig))
covArray = np.divide(np.divide(covMatrix,xvar),xvar.T)
title = ' for\n'+Data['title']
newAtomDict = Data.get('newAtomDict',{})
def OnPlotKeyPress(event):
newPlot = False
if event.key == 's':
choice = [m for m in mpl.cm.datad.keys() if not m.endswith("_r")]
choice.sort()
dlg = wx.SingleChoiceDialog(G2frame,'Select','Color scheme',choice)
if dlg.ShowModal() == wx.ID_OK:
sel = dlg.GetSelection()
G2frame.VcovColor = choice[sel]
else:
G2frame.VcovColor = 'RdYlGn'
dlg.Destroy()
PlotCovariance(G2frame,Data)
def OnMotion(event):
#there is a problem here - reports wrong values
if event.button:
ytics = imgAx.get_yticks()
ytics = np.where(ytics<len(varyList),ytics,-1)
ylabs = [np.where(0<=i ,varyList[int(i)],' ') for i in ytics]
imgAx.set_yticklabels(ylabs)
if event.xdata and event.ydata: #avoid out of frame errors
xpos = int(event.xdata+.5)
ypos = int(event.ydata+.5)
if -1 < xpos < len(varyList) and -1 < ypos < len(varyList):
if xpos == ypos:
value = values[xpos]
name = varyList[xpos]
if varyList[xpos] in newAtomDict:
name,value = newAtomDict[name]
msg = '%s value = %.4g, esd = %.4g'%(name,value,sig[xpos])
else:
msg = '%s - %s: %5.3f'%(varyList[xpos],varyList[ypos],covArray[xpos][ypos])
Page.canvas.SetToolTipString(msg)
G2frame.G2plotNB.status.SetFields(['',msg])
try:
plotNum = G2frame.G2plotNB.plotList.index('Covariance')
Page = G2frame.G2plotNB.nb.GetPage(plotNum)
Page.figure.clf()
Plot = Page.figure.gca()
if not Page.IsShown():
Page.Show()
except ValueError:
Plot = G2frame.G2plotNB.addMpl('Covariance').gca()
plotNum = G2frame.G2plotNB.plotList.index('Covariance')
Page = G2frame.G2plotNB.nb.GetPage(plotNum)
Page.canvas.mpl_connect('motion_notify_event', OnMotion)
Page.canvas.mpl_connect('key_press_event', OnPlotKeyPress)
Page.Choice = ['s: to change colors']
Page.keyPress = OnPlotKeyPress
Page.SetFocus()
G2frame.G2plotNB.status.SetFields(['',''])
acolor = mpl.cm.get_cmap(G2frame.VcovColor)
Img = Plot.imshow(covArray,aspect='equal',cmap=acolor,interpolation='nearest',origin='lower',
vmin=-1.,vmax=1.)
imgAx = Img.get_axes()
ytics = imgAx.get_yticks()
ylabs = [varyList[int(i)] for i in ytics[:-1]]
imgAx.set_yticklabels(ylabs)
colorBar = Page.figure.colorbar(Img)
Plot.set_title('V-Cov matrix'+title)
Plot.set_xlabel('Variable number')
Plot.set_ylabel('Variable name')
Page.canvas.draw()
################################################################################
##### PlotTorsion
################################################################################
[docs]def PlotTorsion(G2frame,phaseName,Torsion,TorName,Names=[],Angles=[],Coeff=[]):
'needs a doc string'
global names
names = Names
sum = np.sum(Torsion)
torsion = np.log(2*Torsion+1.)/sum
tMin = np.min(torsion)
tMax = np.max(torsion)
torsion = 3.*(torsion-tMin)/(tMax-tMin)
X = np.linspace(0.,360.,num=45)
def OnPick(event):
ind = event.ind[0]
msg = 'atoms:'+names[ind]
Page.canvas.SetToolTipString(msg)
try:
page = G2frame.dataDisplay.GetSelection()
except:
return
if G2frame.dataDisplay.GetPageText(page) == 'Torsion restraints':
torGrid = G2frame.dataDisplay.GetPage(page).Torsions
torGrid.ClearSelection()
for row in range(torGrid.GetNumberRows()):
if names[ind] in torGrid.GetCellValue(row,0):
torGrid.SelectRow(row)
torGrid.ForceRefresh()
def OnMotion(event):
if event.xdata and event.ydata: #avoid out of frame errors
xpos = event.xdata
ypos = event.ydata
msg = 'torsion,energy: %5.3f %5.3f'%(xpos,ypos)
Page.canvas.SetToolTipString(msg)
try:
plotNum = G2frame.G2plotNB.plotList.index('Torsion')
Page = G2frame.G2plotNB.nb.GetPage(plotNum)
Page.figure.clf()
Plot = Page.figure.gca()
if not Page.IsShown():
Page.Show()
except ValueError:
Plot = G2frame.G2plotNB.addMpl('Torsion').gca()
plotNum = G2frame.G2plotNB.plotList.index('Torsion')
Page = G2frame.G2plotNB.nb.GetPage(plotNum)
Page.canvas.mpl_connect('pick_event', OnPick)
Page.canvas.mpl_connect('motion_notify_event', OnMotion)
Page.SetFocus()
G2frame.G2plotNB.status.SetFields(['','Use mouse LB to identify torsion atoms'])
Plot.plot(X,torsion,'b+')
if len(Coeff):
X2 = np.linspace(0.,360.,45)
Y2 = np.array([-G2mth.calcTorsionEnergy(x,Coeff)[1] for x in X2])
Plot.plot(X2,Y2,'r')
if len(Angles):
Eval = np.array([-G2mth.calcTorsionEnergy(x,Coeff)[1] for x in Angles])
Plot.plot(Angles,Eval,'ro',picker=5)
Plot.set_xlim((0.,360.))
Plot.set_title('Torsion angles for '+TorName+' in '+phaseName)
Plot.set_xlabel('angle',fontsize=16)
Plot.set_ylabel('Energy',fontsize=16)
Page.canvas.draw()
################################################################################
##### PlotRama
################################################################################
[docs]def PlotRama(G2frame,phaseName,Rama,RamaName,Names=[],PhiPsi=[],Coeff=[]):
'needs a doc string'
global names
names = Names
rama = np.log(2*Rama+1.)
ramaMax = np.max(rama)
rama = np.reshape(rama,(45,45))
global Phi,Psi
Phi = []
Psi = []
def OnPlotKeyPress(event):
newPlot = False
if event.key == 's':
choice = [m for m in mpl.cm.datad.keys() if not m.endswith("_r")]
choice.sort()
dlg = wx.SingleChoiceDialog(G2frame,'Select','Color scheme',choice)
if dlg.ShowModal() == wx.ID_OK:
sel = dlg.GetSelection()
G2frame.RamaColor = choice[sel]
else:
G2frame.RamaColor = 'RdYlGn'
dlg.Destroy()
PlotRama(G2frame,phaseName,Rama)
def OnPick(event):
ind = event.ind[0]
msg = 'atoms:'+names[ind]
Page.canvas.SetToolTipString(msg)
try:
page = G2frame.dataDisplay.GetSelection()
except:
return
if G2frame.dataDisplay.GetPageText(page) == 'Ramachandran restraints':
ramaGrid = G2frame.dataDisplay.GetPage(page).Ramas
ramaGrid.ClearSelection()
for row in range(ramaGrid.GetNumberRows()):
if names[ind] in ramaGrid.GetCellValue(row,0):
ramaGrid.SelectRow(row)
ramaGrid.ForceRefresh()
def OnMotion(event):
if event.xdata and event.ydata: #avoid out of frame errors
xpos = event.xdata
ypos = event.ydata
msg = 'phi/psi: %5.3f %5.3f'%(xpos,ypos)
Page.canvas.SetToolTipString(msg)
try:
plotNum = G2frame.G2plotNB.plotList.index('Ramachandran')
Page = G2frame.G2plotNB.nb.GetPage(plotNum)
Page.figure.clf()
Plot = Page.figure.gca()
if not Page.IsShown():
Page.Show()
except ValueError:
Plot = G2frame.G2plotNB.addMpl('Ramachandran').gca()
plotNum = G2frame.G2plotNB.plotList.index('Ramachandran')
Page = G2frame.G2plotNB.nb.GetPage(plotNum)
Page.canvas.mpl_connect('pick_event', OnPick)
Page.canvas.mpl_connect('motion_notify_event', OnMotion)
Page.canvas.mpl_connect('key_press_event', OnPlotKeyPress)
Page.Choice = ['s: to change colors']
Page.keyPress = OnPlotKeyPress
Page.SetFocus()
G2frame.G2plotNB.status.SetFields(['','Use mouse LB to identify phi/psi atoms'])
acolor = mpl.cm.get_cmap(G2frame.RamaColor)
if RamaName == 'All' or '-1' in RamaName:
if len(Coeff):
X,Y = np.meshgrid(np.linspace(-180.,180.,45),np.linspace(-180.,180.,45))
Z = np.array([-G2mth.calcRamaEnergy(x,y,Coeff)[1] for x,y in zip(X.flatten(),Y.flatten())])
Plot.contour(X,Y,np.reshape(Z,(45,45)))
Img = Plot.imshow(rama,aspect='equal',cmap=acolor,interpolation='nearest',
extent=[-180,180,-180,180],origin='lower')
if len(PhiPsi):
Phi,Psi = PhiPsi.T
Phi = np.where(Phi>180.,Phi-360.,Phi)
Psi = np.where(Psi>180.,Psi-360.,Psi)
Plot.plot(Phi,Psi,'ro',picker=5)
Plot.set_xlim((-180.,180.))
Plot.set_ylim((-180.,180.))
else:
if len(Coeff):
X,Y = np.meshgrid(np.linspace(0.,360.,45),np.linspace(0.,360.,45))
Z = np.array([-G2mth.calcRamaEnergy(x,y,Coeff)[1] for x,y in zip(X.flatten(),Y.flatten())])
Plot.contour(X,Y,np.reshape(Z,(45,45)))
Img = Plot.imshow(rama,aspect='equal',cmap=acolor,interpolation='nearest',
extent=[0,360,0,360],origin='lower')
if len(PhiPsi):
Phi,Psi = PhiPsi.T
Plot.plot(Phi,Psi,'ro',picker=5)
Plot.set_xlim((0.,360.))
Plot.set_ylim((0.,360.))
Plot.set_title('Ramachandran for '+RamaName+' in '+phaseName)
Plot.set_xlabel(r'$\phi$',fontsize=16)
Plot.set_ylabel(r'$\psi$',fontsize=16)
colorBar = Page.figure.colorbar(Img)
Page.canvas.draw()
################################################################################
##### PlotSeq
################################################################################
[docs]def PlotSelectedSequence(G2frame,ColumnList,TableGet,SelectX,fitnum=None,fitvals=None):
'''Plot a result from a sequential refinement
:param wx.Frame G2frame: The main GSAS-II tree "window"
:param list ColumnList: list of int values corresponding to columns
selected as y values
:param function TableGet: a function that takes a column number
as argument and returns the column label, the values and there ESDs (or None)
:param function SelectX: a function that returns a selected column
number (or None) as the X-axis selection
'''
global Title,xLabel,yLabel
xLabel = yLabel = Title = ''
def OnMotion(event):
if event.xdata and event.ydata: #avoid out of frame errors
xpos = event.xdata
ypos = event.ydata
msg = '%5.3f %.6g'%(xpos,ypos)
Page.canvas.SetToolTipString(msg)
def OnKeyPress(event):
global Title,xLabel,yLabel
if event.key == 's':
G2frame.seqXaxis = G2frame.seqXselect()
Draw()
elif event.key == 't':
dlg = G2gd.MultiStringDialog(G2frame,'Set titles & labels',[' Title ',' x-Label ',' y-Label '],
[Title,xLabel,yLabel])
if dlg.Show():
Title,xLabel,yLabel = dlg.GetValues()
dlg.Destroy()
Draw()
def Draw():
global Title,xLabel,yLabel
Page.SetFocus()
G2frame.G2plotNB.status.SetStatusText('press s to select X axis, t to change titles',1)
Plot.clear()
if G2frame.seqXaxis is not None:
xName,X,Xsig = Page.seqTableGet(G2frame.seqXaxis)
else:
X = np.arange(0,G2frame.SeqTable.GetNumberRows(),1)
xName = 'Data sequence number'
for col in Page.seqYaxisList:
name,Y,sig = Page.seqTableGet(col)
# deal with missing (None) values
Xnew = []
Ynew = []
Ysnew = []
for i in range(len(X)):
if X[i] is None or Y[i] is None: continue
Xnew.append(X[i])
Ynew.append(Y[i])
if sig: Ysnew.append(sig[i])
if Ysnew:
if G2frame.seqReverse and not G2frame.seqXaxis:
Ynew = Ynew[::-1]
Ysnew = Ysnew[::-1]
Plot.errorbar(Xnew,Ynew,yerr=Ysnew,label=name)
else:
if G2frame.seqReverse and not G2frame.seqXaxis:
Ynew = Ynew[::-1]
Plot.plot(Xnew,Ynew)
Plot.plot(Xnew,Ynew,'o',label=name)
if Page.fitvals: # TODO: deal with fitting of None values
if G2frame.seqReverse and not G2frame.seqXaxis:
Page.fitvals = Page.fitvals[::-1]
Plot.plot(X,Page.fitvals,label='Fit')
Plot.legend(loc='best')
print Title,xLabel,yLabel
if Title:
Plot.set_title(Title)
else:
Plot.set_title('')
if xLabel:
Plot.set_xlabel(xLabel)
else:
Plot.set_xlabel(xName)
if yLabel:
Plot.set_ylabel(yLabel)
else:
Plot.set_ylabel('Parameter values')
Page.canvas.draw()
G2frame.seqXselect = SelectX
try:
G2frame.seqXaxis
except:
G2frame.seqXaxis = None
if fitnum is None:
label = 'Sequential refinement'
else:
label = 'Parametric fit #'+str(fitnum+1)
try:
plotNum = G2frame.G2plotNB.plotList.index(label)
Page = G2frame.G2plotNB.nb.GetPage(plotNum)
Page.figure.clf()
Plot = Page.figure.gca()
if not Page.IsShown():
Page.Show()
except ValueError:
Plot = G2frame.G2plotNB.addMpl(label).gca()
plotNum = G2frame.G2plotNB.plotList.index(label)
Page = G2frame.G2plotNB.nb.GetPage(plotNum)
Page.canvas.mpl_connect('key_press_event', OnKeyPress)
Page.canvas.mpl_connect('motion_notify_event', OnMotion)
Page.Choice = ['s - select x-axis','t - change titles',]
Page.keyPress = OnKeyPress
Page.seqYaxisList = ColumnList
Page.seqTableGet = TableGet
Page.fitvals = fitvals
Draw()
G2frame.G2plotNB.nb.SetSelection(plotNum) # raises plot tab
################################################################################
##### PlotExposedImage & PlotImage
################################################################################
[docs]def PlotExposedImage(G2frame,newPlot=False,event=None):
'''General access module for 2D image plotting
'''
plotNo = G2frame.G2plotNB.nb.GetSelection()
if G2frame.G2plotNB.nb.GetPageText(plotNo) == '2D Powder Image':
PlotImage(G2frame,newPlot,event,newImage=True)
elif G2frame.G2plotNB.nb.GetPageText(plotNo) == '2D Integration':
PlotIntegration(G2frame,newPlot,event)
[docs]def OnStartMask(G2frame):
'''Initiate the start of a Frame or Polygon map
:param wx.Frame G2frame: The main GSAS-II tree "window"
:param str eventkey: a single letter ('f' or 'p') that
determines what type of mask is created.
'''
Masks = G2frame.PatternTree.GetItemPyData(
G2gd.GetPatternTreeItemId(G2frame,G2frame.Image, 'Masks'))
if G2frame.MaskKey == 'f':
Masks['Frames'] = []
elif G2frame.MaskKey == 'p':
Masks['Polygons'].append([])
elif G2frame.MaskKey == 's':
Masks['Points'].append([])
elif G2frame.MaskKey == 'a':
Masks['Arcs'].append([])
elif G2frame.MaskKey == 'r':
Masks['Rings'].append([])
G2imG.UpdateMasks(G2frame,Masks)
PlotImage(G2frame,newImage=True)
[docs]def OnStartNewDzero(G2frame):
'''Initiate the start of adding a new d-zero to a strain data set
:param wx.Frame G2frame: The main GSAS-II tree "window"
:param str eventkey: a single letter ('a') that
triggers the addition of a d-zero.
'''
G2frame.dataFrame.GetStatusBar().SetStatusText('Add strain ring active - LB pick d-zero value',0)
G2frame.PickId = G2gd.GetPatternTreeItemId(G2frame,G2frame.Image, 'Stress/Strain')
data = G2frame.PatternTree.GetItemPyData(G2frame.PickId)
return data
[docs]def PlotImage(G2frame,newPlot=False,event=None,newImage=True):
'''Plot of 2D detector images as contoured plot. Also plot calibration ellipses,
masks, etc.
'''
from matplotlib.patches import Ellipse,Arc,Circle,Polygon
import numpy.ma as ma
Dsp = lambda tth,wave: wave/(2.*npsind(tth/2.))
global Data,Masks,StrSta
colors=['b','g','r','c','m','k']
Data = G2frame.PatternTree.GetItemPyData(
G2gd.GetPatternTreeItemId(G2frame,G2frame.Image, 'Image Controls'))
# patch
if 'invert_x' not in Data:
Data['invert_x'] = False
Data['invert_y'] = True
# end patch
Masks = G2frame.PatternTree.GetItemPyData(
G2gd.GetPatternTreeItemId(G2frame,G2frame.Image, 'Masks'))
try: #may be absent
StrSta = G2frame.PatternTree.GetItemPyData(
G2gd.GetPatternTreeItemId(G2frame,G2frame.Image, 'Stress/Strain'))
except TypeError: #is missing
StrSta = {}
def OnImMotion(event):
Page.canvas.SetToolTipString('')
sizexy = Data['size']
if event.xdata and event.ydata and len(G2frame.ImageZ): #avoid out of frame errors
Page.canvas.SetToolTipString('%8.2f %8.2fmm'%(event.xdata,event.ydata))
Page.canvas.SetCursor(wx.CROSS_CURSOR)
item = G2frame.itemPicked
pixelSize = Data['pixelSize']
scalex = 1000./pixelSize[0]
scaley = 1000./pixelSize[1]
if item and G2frame.PatternTree.GetItemText(G2frame.PickId) == 'Image Controls':
if 'Text' in str(item):
Page.canvas.SetToolTipString('%8.3f %8.3fmm'%(event.xdata,event.ydata))
else:
xcent,ycent = Data['center']
xpos = event.xdata-xcent
ypos = event.ydata-ycent
tth,azm = G2img.GetTthAzm(event.xdata,event.ydata,Data)
if 'line3' in str(item) or 'line4' in str(item) and not Data['fullIntegrate']:
Page.canvas.SetToolTipString('%6d deg'%(azm))
elif 'line1' in str(item) or 'line2' in str(item):
Page.canvas.SetToolTipString('%8.3f deg'%(tth))
else:
xpos = event.xdata
ypos = event.ydata
xpix = xpos*scalex
ypix = ypos*scaley
Int = 0
if (0 <= xpix <= sizexy[0]) and (0 <= ypix <= sizexy[1]):
Int = G2frame.ImageZ[ypix][xpix]
tth,azm,D,dsp = G2img.GetTthAzmDsp(xpos,ypos,Data)
Q = 2.*math.pi/dsp
fields = ['','Detector 2-th =%9.3fdeg, dsp =%9.3fA, Q = %6.5fA-1, azm = %7.2fdeg, I = %6d'%(tth,dsp,Q,azm,Int)]
if G2frame.MaskKey in ['p','f']:
fields[1] = 'Polygon/frame mask pick - LB next point, RB close polygon'
elif G2frame.StrainKey:
fields[0] = 'd-zero pick active'
G2frame.G2plotNB.status.SetFields(fields)
def OnImPlotKeyPress(event):
try:
PickName = G2frame.PatternTree.GetItemText(G2frame.PickId)
except TypeError:
return
if PickName == 'Masks':
if event.key in ['l','p','f','s','a','r']:
G2frame.MaskKey = event.key
OnStartMask(G2frame)
PlotImage(G2frame,newPlot=False)
elif PickName == 'Stress/Strain':
if event.key in ['a',]:
G2frame.StrainKey = event.key
StrSta = OnStartNewDzero(G2frame)
PlotImage(G2frame,newPlot=False)
elif PickName == 'Image Controls':
if event.key in ['c',]:
Xpos = event.xdata
if not Xpos: #got point out of frame
return
Ypos = event.ydata
dlg = wx.MessageDialog(G2frame,'Are you sure you want to change the center?',
'Center change',style=wx.OK|wx.CANCEL)
try:
if dlg.ShowModal() == wx.ID_OK:
print 'move center to: ',Xpos,Ypos
Data['center'] = [Xpos,Ypos]
G2imG.UpdateImageControls(G2frame,Data,Masks)
PlotImage(G2frame,newPlot=False)
finally:
dlg.Destroy()
return
elif event.key == 'l':
G2frame.logPlot = not G2frame.logPlot
elif event.key in ['x',]:
Data['invert_x'] = not Data['invert_x']
elif event.key in ['y',]:
Data['invert_y'] = not Data['invert_y']
PlotImage(G2frame,newPlot=True)
def OnKeyBox(event):
if G2frame.G2plotNB.nb.GetSelection() == G2frame.G2plotNB.plotList.index('2D Powder Image'):
event.key = cb.GetValue()[0]
cb.SetValue(' key press')
if event.key in ['l','s','a','r','p','x','y']:
wx.CallAfter(OnImPlotKeyPress,event)
Page.canvas.SetFocus() # redirect the Focus from the button back to the plot
def OnImPick(event):
if G2frame.PatternTree.GetItemText(G2frame.PickId) not in ['Image Controls','Masks']:
return
if G2frame.itemPicked is not None: return
G2frame.itemPicked = event.artist
G2frame.mousePicked = event.mouseevent
def OnImRelease(event):
try:
PickName = G2frame.PatternTree.GetItemText(G2frame.PickId)
except TypeError:
return
if PickName not in ['Image Controls','Masks','Stress/Strain']:
return
pixelSize = Data['pixelSize']
scalex = 1000./pixelSize[0]
scaley = 1000./pixelSize[1]
# pixLimit = Data['pixLimit'] #can be too tight
pixLimit = 20 #this makes the search box 40x40 pixels
if G2frame.itemPicked is None and PickName == 'Image Controls' and len(G2frame.ImageZ):
Xpos = event.xdata
if not (Xpos and G2frame.ifGetRing): #got point out of frame
return
Ypos = event.ydata
if Ypos and not Page.toolbar._active: #make sure zoom/pan not selected
if event.button == 1:
Xpix = Xpos*scalex
Ypix = Ypos*scaley
xpos,ypos,I,J = G2img.ImageLocalMax(G2frame.ImageZ,pixLimit,Xpix,Ypix)
if I and J:
xpos += .5 #shift to pixel center
ypos += .5
xpos /= scalex #convert to mm
ypos /= scaley
Data['ring'].append([xpos,ypos])
elif event.button == 3:
G2frame.dataFrame.GetStatusBar().SetStatusText('Calibrating...',0)
if G2img.ImageCalibrate(G2frame,Data):
G2frame.dataFrame.GetStatusBar().SetStatusText('Calibration successful - Show ring picks to check',0)
print 'Calibration successful'
else:
G2frame.dataFrame.GetStatusBar().SetStatusText('Calibration failed - Show ring picks to diagnose',0)
print 'Calibration failed'
G2frame.ifGetRing = False
G2imG.UpdateImageControls(G2frame,Data,Masks)
return
PlotImage(G2frame,newImage=False)
return
elif G2frame.MaskKey and PickName == 'Masks':
Xpos,Ypos = [event.xdata,event.ydata]
if not Xpos or not Ypos or Page.toolbar._active: #got point out of frame or zoom/pan selected
return
if G2frame.MaskKey == 's' and event.button == 1:
Masks['Points'][-1] = [Xpos,Ypos,1.]
G2frame.MaskKey = ''
elif G2frame.MaskKey == 'r' and event.button == 1:
tth = G2img.GetTth(Xpos,Ypos,Data)
Masks['Rings'][-1] = [tth,0.1]
G2frame.MaskKey = ''
elif G2frame.MaskKey == 'a' and event.button == 1:
tth,azm = G2img.GetTthAzm(Xpos,Ypos,Data)
azm = int(azm)
Masks['Arcs'][-1] = [tth,[azm-5,azm+5],0.1]
G2frame.MaskKey = ''
elif G2frame.MaskKey =='p':
polygon = Masks['Polygons'][-1]
if len(polygon) > 2 and event.button == 3:
x0,y0 = polygon[0]
polygon.append([x0,y0])
G2frame.MaskKey = ''
G2frame.G2plotNB.status.SetFields(['','Polygon closed'])
else:
G2frame.G2plotNB.status.SetFields(['','New polygon point: %.1f,%.1f'%(Xpos,Ypos)])
polygon.append([Xpos,Ypos])
elif G2frame.MaskKey =='f':
frame = Masks['Frames']
if len(frame) > 2 and event.button == 3:
x0,y0 = frame[0]
frame.append([x0,y0])
G2frame.MaskKey = ''
G2frame.G2plotNB.status.SetFields(['','Frame closed'])
else:
G2frame.G2plotNB.status.SetFields(['','New frame point: %.1f,%.1f'%(Xpos,Ypos)])
frame.append([Xpos,Ypos])
G2imG.UpdateMasks(G2frame,Masks)
PlotImage(G2frame,newImage=False)
elif PickName == 'Stress/Strain' and G2frame.StrainKey:
Xpos,Ypos = [event.xdata,event.ydata]
if not Xpos or not Ypos or Page.toolbar._active: #got point out of frame or zoom/pan selected
return
dsp = G2img.GetDsp(Xpos,Ypos,Data)
StrSta['d-zero'].append({'Dset':dsp,'Dcalc':0.0,'pixLimit':10,'cutoff':1.0,
'ImxyObs':[[],[]],'ImtaObs':[[],[]],'ImtaCalc':[[],[]],'Emat':[1.0,1.0,1.0]})
R,r = G2img.MakeStrStaRing(StrSta['d-zero'][-1],G2frame.ImageZ,Data)
if not len(R):
del StrSta['d-zero'][-1]
G2frame.ErrorDialog('Strain peak selection','WARNING - No points found for this ring selection')
StrSta['d-zero'] = G2mth.sortArray(StrSta['d-zero'],'Dset',reverse=True)
G2frame.StrainKey = ''
G2imG.UpdateStressStrain(G2frame,StrSta)
PlotStrain(G2frame,StrSta)
PlotImage(G2frame,newPlot=False)
else:
Xpos,Ypos = [event.xdata,event.ydata]
if not Xpos or not Ypos or Page.toolbar._active: #got point out of frame or zoom/pan selected
return
if G2frame.ifGetRing: #delete a calibration ring pick
xypos = [Xpos,Ypos]
rings = Data['ring']
for ring in rings:
if np.allclose(ring,xypos,.01,0):
rings.remove(ring)
else:
tth,azm,dsp = G2img.GetTthAzmDsp(Xpos,Ypos,Data)[:3]
itemPicked = str(G2frame.itemPicked)
if 'Line2D' in itemPicked and PickName == 'Image Controls':
if 'line1' in itemPicked:
Data['IOtth'][0] = max(tth,0.001)
elif 'line2' in itemPicked:
Data['IOtth'][1] = tth
elif 'line3' in itemPicked:
Data['LRazimuth'][0] = int(azm)
elif 'line4' in itemPicked and not Data['fullIntegrate']:
Data['LRazimuth'][1] = int(azm)
Data['LRazimuth'][0] %= 360
Data['LRazimuth'][1] %= 360
if Data['LRazimuth'][0] > Data['LRazimuth'][1]:
Data['LRazimuth'][1] += 360
if Data['fullIntegrate']:
Data['LRazimuth'][1] = Data['LRazimuth'][0]+360
if Data['IOtth'][0] > Data['IOtth'][1]:
Data['IOtth'][0],Data['IOtth'][1] = Data['IOtth'][1],Data['IOtth'][0]
G2frame.InnerTth.SetValue("%8.2f" % (Data['IOtth'][0]))
G2frame.OuterTth.SetValue("%8.2f" % (Data['IOtth'][1]))
G2frame.Lazim.SetValue("%6d" % (Data['LRazimuth'][0]))
G2frame.Razim.SetValue("%6d" % (Data['LRazimuth'][1]))
elif 'Circle' in itemPicked and PickName == 'Masks':
spots = Masks['Points']
newPos = itemPicked.split(')')[0].split('(')[2].split(',')
newPos = np.array([float(newPos[0]),float(newPos[1])])
for spot in spots:
if spot and np.allclose(np.array([spot[:2]]),newPos):
spot[:2] = Xpos,Ypos
G2imG.UpdateMasks(G2frame,Masks)
elif 'Line2D' in itemPicked and PickName == 'Masks':
Obj = G2frame.itemPicked.findobj()
rings = Masks['Rings']
arcs = Masks['Arcs']
polygons = Masks['Polygons']
frame = Masks['Frames']
for ring in G2frame.ringList:
if Obj == ring[0]:
rN = ring[1]
if ring[2] == 'o':
rings[rN][0] = G2img.GetTth(Xpos,Ypos,Data)-rings[rN][1]/2.
else:
rings[rN][0] = G2img.GetTth(Xpos,Ypos,Data)+rings[rN][1]/2.
for arc in G2frame.arcList:
if Obj == arc[0]:
aN = arc[1]
if arc[2] == 'o':
arcs[aN][0] = G2img.GetTth(Xpos,Ypos,Data)-arcs[aN][2]/2
elif arc[2] == 'i':
arcs[aN][0] = G2img.GetTth(Xpos,Ypos,Data)+arcs[aN][2]/2
elif arc[2] == 'l':
arcs[aN][1][0] = int(G2img.GetAzm(Xpos,Ypos,Data))
else:
arcs[aN][1][1] = int(G2img.GetAzm(Xpos,Ypos,Data))
for poly in G2frame.polyList: #merging points problem here?
if Obj == poly[0]:
ind = G2frame.itemPicked.contains(G2frame.mousePicked)[1]['ind'][0]
oldPos = np.array([G2frame.mousePicked.xdata,G2frame.mousePicked.ydata])
pN = poly[1]
for i,xy in enumerate(polygons[pN]):
if np.allclose(np.array([xy]),oldPos,atol=1.0):
if event.button == 1:
polygons[pN][i] = Xpos,Ypos
elif event.button == 3:
polygons[pN].insert(i,[Xpos,Ypos])
break
if frame:
oldPos = np.array([G2frame.mousePicked.xdata,G2frame.mousePicked.ydata])
for i,xy in enumerate(frame):
if np.allclose(np.array([xy]),oldPos,atol=1.0):
if event.button == 1:
frame[i] = Xpos,Ypos
elif event.button == 3:
frame.insert(i,[Xpos,Ypos])
break
G2imG.UpdateMasks(G2frame,Masks)
# else: #keep for future debugging
# print str(G2frame.itemPicked),event.xdata,event.ydata,event.button
PlotImage(G2frame,newImage=True)
G2frame.itemPicked = None
try:
plotNum = G2frame.G2plotNB.plotList.index('2D Powder Image')
Page = G2frame.G2plotNB.nb.GetPage(plotNum)
if not newPlot:
Plot = Page.figure.gca() #get previous powder plot & get limits
xylim = Plot.get_xlim(),Plot.get_ylim()
if newImage:
Page.figure.clf()
Plot = Page.figure.gca() #get a fresh plot after clf()
except ValueError:
Plot = G2frame.G2plotNB.addMpl('2D Powder Image').gca()
plotNum = G2frame.G2plotNB.plotList.index('2D Powder Image')
Page = G2frame.G2plotNB.nb.GetPage(plotNum)
Page.canvas.mpl_connect('key_press_event', OnImPlotKeyPress)
Page.canvas.mpl_connect('motion_notify_event', OnImMotion)
Page.canvas.mpl_connect('pick_event', OnImPick)
Page.canvas.mpl_connect('button_release_event', OnImRelease)
xylim = []
Page.Choice = None
if not event: #event from GUI TextCtrl - don't want focus to change to plot!!!
Page.SetFocus()
Title = G2frame.PatternTree.GetItemText(G2frame.Image)[4:]
G2frame.G2plotNB.status.DestroyChildren()
if G2frame.logPlot:
Title = 'log('+Title+')'
Plot.set_title(Title)
try:
if G2frame.PatternTree.GetItemText(G2frame.PickId) in ['Image Controls',]:
Page.Choice = (' key press','l: log(I) on','x: flip x','y: flip y',)
if G2frame.logPlot:
Page.Choice[1] = 'l: log(I) off'
Page.keyPress = OnImPlotKeyPress
elif G2frame.PatternTree.GetItemText(G2frame.PickId) in ['Masks',]:
Page.Choice = (' key press','l: log(I) on','s: spot mask','a: arc mask','r: ring mask',
'p: polygon mask','f: frame mask',)
if G2frame.logPlot:
Page.Choice[1] = 'l: log(I) off'
Page.keyPress = OnImPlotKeyPress
elif G2frame.PatternTree.GetItemText(G2frame.PickId) in ['Stress/Strain',]:
Page.Choice = (' key press','a: add new ring',)
Page.keyPress = OnImPlotKeyPress
except TypeError:
pass
size,imagefile = G2frame.PatternTree.GetItemPyData(G2frame.Image)
dark = Data.get('dark image',[0,''])
if dark[0]:
darkfile = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,
G2frame.root,dark[0]))[1]
if imagefile != G2frame.oldImagefile:
imagefile = G2IO.CheckImageFile(G2frame,imagefile)
if not imagefile:
G2frame.G2plotNB.Delete('2D Powder Image')
return
G2frame.PatternTree.SetItemPyData(G2frame.Image,[size,imagefile])
G2frame.ImageZ = G2IO.GetImageData(G2frame,imagefile,imageOnly=True)
if dark[0]:
darkImg = G2IO.GetImageData(G2frame,darkfile,imageOnly=True)
G2frame.ImageZ += dark[1]*darkImg
G2frame.oldImagefile = imagefile
imScale = 1
if len(G2frame.ImageZ) > 1024:
imScale = len(G2frame.ImageZ)/1024
sizexy = Data['size']
pixelSize = Data['pixelSize']
scalex = 1000./pixelSize[0]
scaley = 1000./pixelSize[1]
Xmax = sizexy[0]*pixelSize[0]/1000.
Ymax = sizexy[1]*pixelSize[1]/1000.
xlim = (0,Xmax)
ylim = (Ymax,0)
Imin,Imax = Data['range'][1]
acolor = mpl.cm.get_cmap(Data['color'])
xcent,ycent = Data['center']
Plot.set_xlabel('Image x-axis, mm',fontsize=12)
Plot.set_ylabel('Image y-axis, mm',fontsize=12)
#do threshold mask - "real" mask - others are just bondaries
Zlim = Masks['Thresholds'][1]
wx.BeginBusyCursor()
try:
if newImage:
Imin,Imax = Data['range'][1]
MA = ma.masked_greater(ma.masked_less(G2frame.ImageZ,Zlim[0]),Zlim[1])
MaskA = ma.getmaskarray(MA)
A = G2img.ImageCompress(MA,imScale)
AM = G2img.ImageCompress(MaskA,imScale)
if G2frame.logPlot:
A = np.where(A>Imin,np.where(A<Imax,A,0),0)
A = np.where(A>0,np.log(A),0)
AM = np.where(AM>0,np.log(AM),0)
Imin,Imax = [np.amin(A),np.amax(A)]
ImgM = Plot.imshow(AM,aspect='equal',cmap='Reds',
interpolation='nearest',vmin=0,vmax=2,extent=[0,Xmax,Ymax,0])
Img = Plot.imshow(A,aspect='equal',cmap=acolor,
interpolation='nearest',vmin=Imin,vmax=Imax,extent=[0,Xmax,Ymax,0])
Plot.plot(xcent,ycent,'x')
#G2frame.PatternTree.GetItemText(item)
if Data['showLines']:
LRAzim = Data['LRazimuth'] #NB: integers
Nazm = Data['outAzimuths']
delAzm = float(LRAzim[1]-LRAzim[0])/Nazm
AzmthOff = Data['azmthOff']
IOtth = Data['IOtth']
wave = Data['wavelength']
dspI = wave/(2.0*sind(IOtth[0]/2.0))
ellI = G2img.GetEllipse(dspI,Data) #=False if dsp didn't yield an ellipse (ugh! a parabola or a hyperbola)
dspO = wave/(2.0*sind(IOtth[1]/2.0))
ellO = G2img.GetEllipse(dspO,Data) #Ditto & more likely for outer ellipse
Azm = np.array(range(LRAzim[0],LRAzim[1]+1))-AzmthOff
if ellI:
xyI = []
for azm in Azm:
xy = G2img.GetDetectorXY(dspI,azm,Data)
if np.any(xy):
xyI.append(xy)
if len(xyI):
xyI = np.array(xyI)
arcxI,arcyI = xyI.T
Plot.plot(arcxI,arcyI,picker=3)
if ellO:
xyO = []
for azm in Azm:
xy = G2img.GetDetectorXY(dspO,azm,Data)
if np.any(xy):
xyO.append(xy)
if len(xyO):
xyO = np.array(xyO)
arcxO,arcyO = xyO.T
Plot.plot(arcxO,arcyO,picker=3)
if ellO and ellI:
Plot.plot([arcxI[0],arcxO[0]],[arcyI[0],arcyO[0]],picker=3)
Plot.plot([arcxI[-1],arcxO[-1]],[arcyI[-1],arcyO[-1]],picker=3)
for i in range(Nazm):
cake = LRAzim[0]+i*delAzm-AzmthOff
if Data['centerAzm']:
cake += delAzm/2.
ind = np.searchsorted(Azm,cake)
Plot.plot([arcxI[ind],arcxO[ind]],[arcyI[ind],arcyO[ind]],color='k',dashes=(5,5))
if G2frame.PatternTree.GetItemText(G2frame.PickId) in 'Image Controls':
for xring,yring in Data['ring']:
Plot.plot(xring,yring,'r+',picker=3)
if Data['setRings']:
N = 0
for ring in Data['rings']:
xring,yring = np.array(ring).T[:2]
Plot.plot(xring,yring,'.',color=colors[N%6])
N += 1
for ellipse in Data['ellipses']: #what about hyperbola?
cent,phi,[width,height],col = ellipse
if width > 0: #ellipses
Plot.add_artist(Ellipse([cent[0],cent[1]],2*width,2*height,phi,ec=col,fc='none'))
Plot.text(cent[0],cent[1],'+',color=col,ha='center',va='center')
if G2frame.PatternTree.GetItemText(G2frame.PickId) in 'Stress/Strain':
for N,ring in enumerate(StrSta['d-zero']):
xring,yring = ring['ImxyObs']
Plot.plot(xring,yring,colors[N%6]+'.')
#masks - mask lines numbered after integration limit lines
spots = Masks['Points']
rings = Masks['Rings']
arcs = Masks['Arcs']
polygons = Masks['Polygons']
if 'Frames' not in Masks:
Masks['Frames'] = []
frame = Masks['Frames']
for spot in spots:
if spot:
x,y,d = spot
Plot.add_artist(Circle((x,y),radius=d/2,fc='none',ec='r',picker=3))
G2frame.ringList = []
for iring,ring in enumerate(rings):
if ring:
tth,thick = ring
wave = Data['wavelength']
xy1 = []
xy2 = []
Azm = np.linspace(0,362,181)
for azm in Azm:
xy1.append(G2img.GetDetectorXY(Dsp(tth+thick/2.,wave),azm,Data)) #what about hyperbola
xy2.append(G2img.GetDetectorXY(Dsp(tth-thick/2.,wave),azm,Data)) #what about hyperbola
x1,y1 = np.array(xy1).T
x2,y2 = np.array(xy2).T
G2frame.ringList.append([Plot.plot(x1,y1,'r',picker=3),iring,'o'])
G2frame.ringList.append([Plot.plot(x2,y2,'r',picker=3),iring,'i'])
G2frame.arcList = []
for iarc,arc in enumerate(arcs):
if arc:
tth,azm,thick = arc
wave = Data['wavelength']
xy1 = []
xy2 = []
aR = azm[0],azm[1],azm[1]-azm[0]
if azm[1]-azm[0] > 180:
aR[2] /= 2
Azm = np.linspace(aR[0],aR[1],aR[2])
for azm in Azm:
xy1.append(G2img.GetDetectorXY(Dsp(tth+thick/2.,wave),azm,Data)) #what about hyperbola
xy2.append(G2img.GetDetectorXY(Dsp(tth-thick/2.,wave),azm,Data)) #what about hyperbola
x1,y1 = np.array(xy1).T
x2,y2 = np.array(xy2).T
G2frame.arcList.append([Plot.plot(x1,y1,'r',picker=3),iarc,'o'])
G2frame.arcList.append([Plot.plot(x2,y2,'r',picker=3),iarc,'i'])
G2frame.arcList.append([Plot.plot([x1[0],x2[0]],[y1[0],y2[0]],'r',picker=3),iarc,'l'])
G2frame.arcList.append([Plot.plot([x1[-1],x2[-1]],[y1[-1],y2[-1]],'r',picker=3),iarc,'u'])
G2frame.polyList = []
for ipoly,polygon in enumerate(polygons):
if polygon:
x,y = np.hsplit(np.array(polygon),2)
G2frame.polyList.append([Plot.plot(x,y,'r+',picker=10),ipoly])
Plot.plot(x,y,'r')
G2frame.frameList = []
if frame:
x,y = np.hsplit(np.array(frame),2)
G2frame.frameList.append([Plot.plot(x,y,'g+',picker=10),0])
Plot.plot(x,y,'g')
if newImage:
colorBar = Page.figure.colorbar(Img)
Plot.set_xlim(xlim)
Plot.set_ylim(ylim)
if Data['invert_x']:
Plot.invert_xaxis()
if Data['invert_y']:
Plot.invert_yaxis()
if not newPlot and xylim:
Page.toolbar.push_current()
Plot.set_xlim(xylim[0])
Plot.set_ylim(xylim[1])
xylim = []
Page.toolbar.push_current()
Page.toolbar.draw()
# patch for wx 2.9 on Mac, to force a redraw
i,j= wx.__version__.split('.')[0:2]
if int(i)+int(j)/10. > 2.8 and 'wxOSX' in wx.PlatformInfo:
Page.canvas.draw()
else:
Page.canvas.draw()
finally:
wx.EndBusyCursor()
################################################################################
##### PlotIntegration
################################################################################
[docs]def PlotIntegration(G2frame,newPlot=False,event=None):
'''Plot of 2D image after image integration with 2-theta and azimuth as coordinates
'''
def OnMotion(event):
Page.canvas.SetToolTipString('')
Page.canvas.SetCursor(wx.CROSS_CURSOR)
azm = event.ydata
tth = event.xdata
if azm and tth:
G2frame.G2plotNB.status.SetFields(\
['','Detector 2-th =%9.3fdeg, azm = %7.2fdeg'%(tth,azm)])
try:
plotNum = G2frame.G2plotNB.plotList.index('2D Integration')
Page = G2frame.G2plotNB.nb.GetPage(plotNum)
if not newPlot:
Plot = Page.figure.gca() #get previous plot & get limits
xylim = Plot.get_xlim(),Plot.get_ylim()
Page.figure.clf()
Plot = Page.figure.gca() #get a fresh plot after clf()
except ValueError:
Plot = G2frame.G2plotNB.addMpl('2D Integration').gca()
plotNum = G2frame.G2plotNB.plotList.index('2D Integration')
Page = G2frame.G2plotNB.nb.GetPage(plotNum)
Page.canvas.mpl_connect('motion_notify_event', OnMotion)
Page.views = False
view = False
Page.Choice = None
if not event:
Page.SetFocus()
Data = G2frame.PatternTree.GetItemPyData(
G2gd.GetPatternTreeItemId(G2frame,G2frame.Image, 'Image Controls'))
image = G2frame.Integrate[0]
xsc = G2frame.Integrate[1]
ysc = G2frame.Integrate[2]
Imin,Imax = Data['range'][1]
acolor = mpl.cm.get_cmap(Data['color'])
Plot.set_title(G2frame.PatternTree.GetItemText(G2frame.Image)[4:])
Plot.set_ylabel('azimuth',fontsize=12)
Plot.set_xlabel('2-theta',fontsize=12)
Img = Plot.imshow(image,cmap=acolor,vmin=Imin,vmax=Imax,interpolation='nearest', \
extent=[ysc[0],ysc[-1],xsc[-1],xsc[0]],aspect='auto')
colorBar = Page.figure.colorbar(Img)
# if Data['ellipses']:
# for ellipse in Data['ellipses']:
# x,y = np.array(G2img.makeIdealRing(ellipse[:3])) #skip color
# tth,azm = G2img.GetTthAzm(x,y,Data)
## azm = np.where(azm < 0.,azm+360,azm)
# Plot.plot(tth,azm,'b,')
if not newPlot:
Page.toolbar.push_current()
Plot.set_xlim(xylim[0])
Plot.set_ylim(xylim[1])
xylim = []
Page.toolbar.push_current()
Page.toolbar.draw()
else:
Page.canvas.draw()
################################################################################
##### PlotTRImage
################################################################################
[docs]def PlotTRImage(G2frame,tax,tay,taz,newPlot=False):
'''a test plot routine - not normally used
'''
def OnMotion(event):
Page.canvas.SetToolTipString('')
Page.canvas.SetCursor(wx.CROSS_CURSOR)
azm = event.xdata
tth = event.ydata
if azm and tth:
G2frame.G2plotNB.status.SetFields(\
['','Detector 2-th =%9.3fdeg, azm = %7.2fdeg'%(tth,azm)])
try:
plotNum = G2frame.G2plotNB.plotList.index('2D Transformed Powder Image')
Page = G2frame.G2plotNB.nb.GetPage(plotNum)
if not newPlot:
Plot = Page.figure.gca() #get previous plot & get limits
xylim = Plot.get_xlim(),Plot.get_ylim()
Page.figure.clf()
Plot = Page.figure.gca() #get a fresh plot after clf()
except ValueError:
Plot = G2frame.G2plotNB.addMpl('2D Transformed Powder Image').gca()
plotNum = G2frame.G2plotNB.plotList.index('2D Transformed Powder Image')
Page = G2frame.G2plotNB.nb.GetPage(plotNum)
Page.canvas.mpl_connect('motion_notify_event', OnMotion)
Page.views = False
view = False
Page.Choice = None
Page.SetFocus()
Data = G2frame.PatternTree.GetItemPyData(
G2gd.GetPatternTreeItemId(G2frame,G2frame.Image, 'Image Controls'))
Imin,Imax = Data['range'][1]
step = (Imax-Imin)/5.
V = np.arange(Imin,Imax,step)
acolor = mpl.cm.get_cmap(Data['color'])
Plot.set_title(G2frame.PatternTree.GetItemText(G2frame.Image)[4:])
Plot.set_xlabel('azimuth',fontsize=12)
Plot.set_ylabel('2-theta',fontsize=12)
Plot.contour(tax,tay,taz,V,cmap=acolor)
if Data['showLines']:
IOtth = Data['IOtth']
if Data['fullIntegrate']:
LRAzim = [-180,180]
else:
LRAzim = Data['LRazimuth'] #NB: integers
Plot.plot([LRAzim[0],LRAzim[1]],[IOtth[0],IOtth[0]],picker=True)
Plot.plot([LRAzim[0],LRAzim[1]],[IOtth[1],IOtth[1]],picker=True)
if not Data['fullIntegrate']:
Plot.plot([LRAzim[0],LRAzim[0]],[IOtth[0],IOtth[1]],picker=True)
Plot.plot([LRAzim[1],LRAzim[1]],[IOtth[0],IOtth[1]],picker=True)
if Data['setRings']:
rings = np.concatenate((Data['rings']),axis=0)
for xring,yring,dsp in rings:
x,y = G2img.GetTthAzm(xring,yring,Data)
Plot.plot(y,x,'r+')
if Data['ellipses']:
for ellipse in Data['ellipses']:
ring = np.array(G2img.makeIdealRing(ellipse[:3])) #skip color
x,y = np.hsplit(ring,2)
tth,azm = G2img.GetTthAzm(x,y,Data)
Plot.plot(azm,tth,'b,')
if not newPlot:
Page.toolbar.push_current()
Plot.set_xlim(xylim[0])
Plot.set_ylim(xylim[1])
xylim = []
Page.toolbar.push_current()
Page.toolbar.draw()
else:
Page.canvas.draw()
################################################################################
##### PlotStructure
################################################################################
[docs]def PlotStructure(G2frame,data,firstCall=False):
'''Crystal structure plotting package. Can show structures as balls, sticks, lines,
thermal motion ellipsoids and polyhedra
'''
def FindPeaksBonds(XYZ):
rFact = data['Drawing'].get('radiusFactor',0.85) #data['Drawing'] could be empty!
Bonds = [[] for x in XYZ]
for i,xyz in enumerate(XYZ):
Dx = XYZ-xyz
dist = np.sqrt(np.sum(np.inner(Dx,Amat)**2,axis=1))
IndB = ma.nonzero(ma.masked_greater(dist,rFact*2.2))
for j in IndB[0]:
Bonds[i].append(Dx[j]/2.)
Bonds[j].append(-Dx[j]/2.)
return Bonds
# PlotStructure initialization here
ForthirdPI = 4.0*math.pi/3.0
generalData = data['General']
cell = generalData['Cell'][1:7]
Vol = generalData['Cell'][7:8][0]
Amat,Bmat = G2lat.cell2AB(cell) #Amat - crystal to cartesian, Bmat - inverse
Gmat,gmat = G2lat.cell2Gmat(cell)
A4mat = np.concatenate((np.concatenate((Amat,[[0],[0],[0]]),axis=1),[[0,0,0,1],]),axis=0)
B4mat = np.concatenate((np.concatenate((Bmat,[[0],[0],[0]]),axis=1),[[0,0,0,1],]),axis=0)
SGData = generalData['SGData']
if generalData['Type'] in ['modulated','magnetic']:
SSGData = generalData['SSGData']
Mydir = generalData['Mydir']
atomData = data['Atoms']
mapPeaks = []
drawingData = data['Drawing']
if not drawingData:
return #nothing setup, nothing to draw
if 'Map Peaks' in data:
mapPeaks = np.array(data['Map Peaks'])
peakMax = 100.
if len(mapPeaks):
peakMax = np.max(mapPeaks.T[0])
resRBData = data['RBModels'].get('Residue',[])
vecRBData = data['RBModels'].get('Vector',[])
rbAtmDict = {}
for rbObj in resRBData+vecRBData:
exclList = ['X' for i in range(len(rbObj['Ids']))]
rbAtmDict.update(dict(zip(rbObj['Ids'],exclList)))
testRBObj = data.get('testRBObj',{})
rbObj = testRBObj.get('rbObj',{})
MCSA = data.get('MCSA',{})
mcsaModels = MCSA.get('Models',[])
if len(mcsaModels) > 1:
XYZs,Types = G2mth.UpdateMCSAxyz(Bmat,MCSA)
mcsaXYZ = []
mcsaTypes = []
neqv = 0
for xyz,atyp in zip(XYZs,Types):
equiv = G2spc.GenAtom(xyz,SGData,All=True,Move=False)
neqv = max(neqv,len(equiv))
for item in equiv:
mcsaXYZ.append(item[0])
mcsaTypes.append(atyp)
mcsaXYZ = np.array(mcsaXYZ)
mcsaTypes = np.array(mcsaTypes)
nuniq = mcsaXYZ.shape[0]/neqv
mcsaXYZ = np.reshape(mcsaXYZ,(nuniq,neqv,3))
mcsaTypes = np.reshape(mcsaTypes,(nuniq,neqv))
cent = np.fix(np.sum(mcsaXYZ+2.,axis=0)/nuniq)-2
cent[0] = [0,0,0] #make sure 1st one isn't moved
mcsaXYZ = np.swapaxes(mcsaXYZ,0,1)-cent[:,np.newaxis,:]
mcsaTypes = np.swapaxes(mcsaTypes,0,1)
mcsaXYZ = np.reshape(mcsaXYZ,(nuniq*neqv,3))
mcsaTypes = np.reshape(mcsaTypes,(nuniq*neqv))
mcsaBonds = FindPeaksBonds(mcsaXYZ)
drawAtoms = drawingData.get('Atoms',[])
mapData = {}
flipData = {}
rhoXYZ = []
showBonds = False
if 'Map' in generalData:
mapData = generalData['Map']
showBonds = mapData.get('Show bonds',False)
if 'Flip' in generalData:
flipData = generalData['Flip']
Wt = np.array([255,255,255])
Rd = np.array([255,0,0])
Gr = np.array([0,255,0])
wxGreen = wx.Colour(0,255,0)
Bl = np.array([0,0,255])
Or = np.array([255,128,0])
wxOrange = wx.Colour(255,128,0)
uBox = np.array([[0,0,0],[1,0,0],[1,1,0],[0,1,0],[0,0,1],[1,0,1],[1,1,1],[0,1,1]])
uEdges = np.array([
[uBox[0],uBox[1]],[uBox[0],uBox[3]],[uBox[0],uBox[4]],[uBox[1],uBox[2]],
[uBox[2],uBox[3]],[uBox[1],uBox[5]],[uBox[2],uBox[6]],[uBox[3],uBox[7]],
[uBox[4],uBox[5]],[uBox[5],uBox[6]],[uBox[6],uBox[7]],[uBox[7],uBox[4]]])
mD = 0.1
mV = np.array([[[-mD,0,0],[mD,0,0]],[[0,-mD,0],[0,mD,0]],[[0,0,-mD],[0,0,mD]]])
mapPeakVecs = np.inner(mV,Bmat)
backColor = np.array(list(drawingData['backColor'])+[0,])
Bc = np.array(list(drawingData['backColor']))
uColors = [Rd,Gr,Bl,Wt-Bc, Wt-Bc,Wt-Bc,Wt-Bc,Wt-Bc, Wt-Bc,Wt-Bc,Wt-Bc,Wt-Bc]
altDown = False
shiftDown = False
ctrlDown = False
G2frame.tau = 0.
def OnKeyBox(event):
mode = cb.GetValue()
if mode in ['jpeg','bmp','tiff',]:
try:
import Image as Im
except ImportError:
try:
from PIL import Image as Im
except ImportError:
print "PIL/pillow Image module not present. Cannot save images without this"
raise Exception("PIL/pillow Image module not found")
Fname = os.path.join(Mydir,generalData['Name']+'.'+mode)
size = Page.canvas.GetSize()
glPixelStorei(GL_UNPACK_ALIGNMENT, 1)
if mode in ['jpeg',]:
Pix = glReadPixels(0,0,size[0],size[1],GL_RGBA, GL_UNSIGNED_BYTE)
im = Im.new("RGBA", (size[0],size[1]))
else:
Pix = glReadPixels(0,0,size[0],size[1],GL_RGB, GL_UNSIGNED_BYTE)
im = Im.new("RGB", (size[0],size[1]))
im.fromstring(Pix)
im.save(Fname,mode)
cb.SetValue(' save as/key:')
G2frame.G2plotNB.status.SetStatusText('Drawing saved to: '+Fname,1)
else:
event.key = cb.GetValue()[0]
cb.SetValue(' save as/key:')
wx.CallAfter(OnKey,event)
Page.canvas.SetFocus() # redirect the Focus from the button back to the plot
def OnKey(event): #on key UP!!
try:
keyCode = event.GetKeyCode()
if keyCode > 255:
keyCode = 0
key = chr(keyCode)
except AttributeError: #if from OnKeyBox above
key = str(event.key).upper()
indx = drawingData['selectedAtoms']
cx,ct = drawingData['atomPtrs'][:2]
if key in ['C']:
drawingData['viewPoint'] = [[.5,.5,.5],[0,0]]
drawingData['viewDir'] = [0,0,1]
drawingData['oldxy'] = []
V0 = np.array([0,0,1])
V = np.inner(Amat,V0)
V /= np.sqrt(np.sum(V**2))
A = np.arccos(np.sum(V*V0))
Q = G2mth.AV2Q(A,[0,1,0])
drawingData['Quaternion'] = Q
SetViewPointText(drawingData['viewPoint'][0])
SetViewDirText(drawingData['viewDir'])
Q = drawingData['Quaternion']
G2frame.G2plotNB.status.SetStatusText('New quaternion: %.2f+, %.2fi+ ,%.2fj+, %.2fk'%(Q[0],Q[1],Q[2],Q[3]),1)
elif key in ['N']:
drawAtoms = drawingData['Atoms']
if not len(drawAtoms): #no atoms
return
pI = drawingData['viewPoint'][1]
if not len(pI):
pI = [0,0]
if indx:
pI[0] = indx[pI[1]]
Tx,Ty,Tz = drawAtoms[pI[0]][cx:cx+3]
pI[1] += 1
if pI[1] >= len(indx):
pI[1] = 0
else:
Tx,Ty,Tz = drawAtoms[pI[0]][cx:cx+3]
pI[0] += 1
if pI[0] >= len(drawAtoms):
pI[0] = 0
drawingData['viewPoint'] = [[Tx,Ty,Tz],pI]
SetViewPointText(drawingData['viewPoint'][0])
G2frame.G2plotNB.status.SetStatusText('View point at atom '+drawAtoms[pI[0]][ct-1]+str(pI),1)
elif key in ['P']:
drawAtoms = drawingData['Atoms']
if not len(drawAtoms): #no atoms
return
pI = drawingData['viewPoint'][1]
if not len(pI):
pI = [0,0]
if indx:
pI[0] = indx[pI[1]]
Tx,Ty,Tz = drawAtoms[pI[0]][cx:cx+3]
pI[1] -= 1
if pI[1] < 0:
pI[1] = len(indx)-1
else:
Tx,Ty,Tz = drawAtoms[pI[0]][cx:cx+3]
pI[0] -= 1
if pI[0] < 0:
pI[0] = len(drawAtoms)-1
drawingData['viewPoint'] = [[Tx,Ty,Tz],pI]
SetViewPointText(drawingData['viewPoint'][0])
G2frame.G2plotNB.status.SetStatusText('View point at atom '+drawAtoms[pI[0]][ct-1]+str(pI),1)
elif key in ['U','D','L','R'] and mapData['Flip'] == True:
dirDict = {'U':[0,1],'D':[0,-1],'L':[-1,0],'R':[1,0]}
SetMapRoll(dirDict[key])
if 'rho' in generalData.get('4DmapData',{}):
Set4DMapRoll(dirDict[key])
SetPeakRoll(dirDict[key])
SetMapPeaksText(mapPeaks)
elif key in ['+','-','=','0'] and generalData['Type'] in ['modulated','magnetic']:
if key == '0':
G2frame.tau = 0.
elif key in ['+','=']:
G2frame.tau += 0.05
elif key == '-':
G2frame.tau -= 0.05
G2frame.tau %= 1. #force 0-1 range
Draw('key')
def GetTruePosition(xy,Add=False):
View = glGetIntegerv(GL_VIEWPORT)
Proj = glGetDoublev(GL_PROJECTION_MATRIX)
Model = glGetDoublev(GL_MODELVIEW_MATRIX)
Zmax = 1.
if Add:
Indx = GetSelectedAtoms()
if G2frame.dataDisplay.GetPageText(getSelection()) == 'Map peaks':
for i,peak in enumerate(mapPeaks):
x,y,z = peak[1:4]
X,Y,Z = gluProject(x,y,z,Model,Proj,View)
XY = [int(X),int(View[3]-Y)]
if np.allclose(xy,XY,atol=10) and Z < Zmax:
Zmax = Z
try:
Indx.remove(i)
ClearSelectedAtoms()
for id in Indx:
SetSelectedAtoms(id,Add)
except:
SetSelectedAtoms(i,Add)
else:
cx = drawingData['atomPtrs'][0]
for i,atom in enumerate(drawAtoms):
x,y,z = atom[cx:cx+3]
X,Y,Z = gluProject(x,y,z,Model,Proj,View)
XY = [int(X),int(View[3]-Y)]
if np.allclose(xy,XY,atol=10) and Z < Zmax:
Zmax = Z
try:
Indx.remove(i)
ClearSelectedAtoms()
for id in Indx:
SetSelectedAtoms(id,Add)
except:
SetSelectedAtoms(i,Add)
def OnMouseDown(event):
xy = event.GetPosition()
if event.ShiftDown():
if event.LeftIsDown():
GetTruePosition(xy)
elif event.RightIsDown():
GetTruePosition(xy,True)
else:
drawingData['oldxy'] = list(xy)
def OnMouseMove(event):
if event.ShiftDown(): #don't want any inadvertant moves when picking
return
newxy = event.GetPosition()
if event.Dragging():
if event.AltDown() and rbObj:
if event.LeftIsDown():
SetRBRotation(newxy)
Q = rbObj['Orient'][0]
G2frame.G2plotNB.status.SetStatusText('New quaternion: %.2f+, %.2fi+ ,%.2fj+, %.2fk'%(Q[0],Q[1],Q[2],Q[3]),1)
elif event.RightIsDown():
SetRBTranslation(newxy)
Tx,Ty,Tz = rbObj['Orig'][0]
G2frame.G2plotNB.status.SetStatusText('New view point: %.4f, %.4f, %.4f'%(Tx,Ty,Tz),1)
elif event.MiddleIsDown():
SetRBRotationZ(newxy)
Q = rbObj['Orient'][0]
G2frame.G2plotNB.status.SetStatusText('New quaternion: %.2f+, %.2fi+ ,%.2fj+, %.2fk'%(Q[0],Q[1],Q[2],Q[3]),1)
Draw('move')
elif not event.ControlDown():
if event.LeftIsDown():
SetRotation(newxy)
Q = drawingData['Quaternion']
G2frame.G2plotNB.status.SetStatusText('New quaternion: %.2f+, %.2fi+ ,%.2fj+, %.2fk'%(Q[0],Q[1],Q[2],Q[3]),1)
elif event.RightIsDown():
SetTranslation(newxy)
Tx,Ty,Tz = drawingData['viewPoint'][0]
G2frame.G2plotNB.status.SetStatusText('New view point: %.4f, %.4f, %.4f'%(Tx,Ty,Tz),1)
elif event.MiddleIsDown():
SetRotationZ(newxy)
Q = drawingData['Quaternion']
G2frame.G2plotNB.status.SetStatusText('New quaternion: %.2f+, %.2fi+ ,%.2fj+, %.2fk'%(Q[0],Q[1],Q[2],Q[3]),1)
Draw('move')
def OnMouseWheel(event):
if event.ShiftDown():