source: trunk/GSASIIplot.py @ 296

Last change on this file since 296 was 296, checked in by vondreele, 12 years ago

major change to peak fitting in GSASIIpwd.py & GSASIIpwdGUI.py
"Auto peakfit" removed from GSASIIgrid.py
ValSig? & Fesd moved from GSASIIimage.py to GSASIIIO.py
Change listing output for image calibration - now shows esds for parameters
GSASIIlattice.py - rebin removed - not to be used ever

  • Property svn:keywords set to Date Author Revision URL Id
File size: 96.9 KB
Line 
1#GSASII plotting routines
2########### SVN repository information ###################
3# $Date: 2011-06-09 21:02:38 +0000 (Thu, 09 Jun 2011) $
4# $Author: vondreele $
5# $Revision: 296 $
6# $URL: trunk/GSASIIplot.py $
7# $Id: GSASIIplot.py 296 2011-06-09 21:02:38Z vondreele $
8########### SVN repository information ###################
9import math
10import time
11import copy
12import os.path
13import numpy as np
14import numpy.linalg as nl
15import wx
16import wx.aui
17import wx.glcanvas
18import matplotlib as mpl
19import mpl_toolkits.mplot3d.axes3d as mp3d
20import GSASIIpath
21import GSASIIgrid as G2gd
22import GSASIIimage as G2img
23import GSASIIpwd as G2pwd
24import GSASIIIO as G2IO
25import GSASIIpwdGUI as G2pdG
26import GSASIIimgGUI as G2imG
27import GSASIIphsGUI as G2phG
28import GSASIIlattice as G2lat
29import GSASIIspc as G2spc
30from  OpenGL.GL import *
31from OpenGL.GLU import *
32from OpenGL.GLUT import *
33from OpenGL.GLE import *
34from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as Canvas
35from matplotlib.backends.backend_wxagg import NavigationToolbar2Wx as Toolbar
36
37# useful degree trig functions
38sind = lambda x: math.sin(x*math.pi/180.)
39cosd = lambda x: math.cos(x*math.pi/180.)
40tand = lambda x: math.tan(x*math.pi/180.)
41asind = lambda x: 180.*math.asin(x)/math.pi
42acosd = lambda x: 180.*math.acos(x)/math.pi
43atan2d = lambda x,y: 180.*math.atan2(y,x)/math.pi
44atand = lambda x: 180.*math.atan(x)/math.pi
45# numpy versions
46npsind = lambda x: np.sin(x*np.pi/180.)
47npcosd = lambda x: np.cos(x*np.pi/180.)
48npacosd = lambda x: 180.*np.arccos(x)/np.pi
49   
50class G2PlotMpl(wx.Panel):   
51    def __init__(self,parent,id=-1,dpi=None,**kwargs):
52        wx.Panel.__init__(self,parent,id=id,**kwargs)
53        mpl.rcParams['legend.fontsize'] = 8
54        self.figure = mpl.figure.Figure(dpi=dpi,figsize=(5,7))
55        self.canvas = Canvas(self,-1,self.figure)
56        self.toolbar = Toolbar(self.canvas)
57
58        self.toolbar.Realize()
59       
60        sizer=wx.BoxSizer(wx.VERTICAL)
61        sizer.Add(self.canvas,1,wx.EXPAND)
62        sizer.Add(self.toolbar,0,wx.LEFT|wx.EXPAND)
63        self.SetSizer(sizer)
64       
65class G2PlotOgl(wx.Panel):
66    def __init__(self,parent,id=-1,dpi=None,**kwargs):
67        self.figure = wx.Panel.__init__(self,parent,id=id,**kwargs)
68        self.canvas = wx.glcanvas.GLCanvas(self,-1,**kwargs)
69        self.camera = {}
70        sizer=wx.BoxSizer(wx.VERTICAL)
71        sizer.Add(self.canvas,1,wx.EXPAND)
72        self.SetSizer(sizer)
73       
74class G2Plot3D(wx.Panel):
75    def __init__(self,parent,id=-1,dpi=None,**kwargs):
76        wx.Panel.__init__(self,parent,id=id,**kwargs)
77        self.figure = mpl.figure.Figure(dpi=dpi,figsize=(6,6))
78        self.canvas = Canvas(self,-1,self.figure)
79        self.toolbar = Toolbar(self.canvas)
80
81        self.toolbar.Realize()
82       
83        sizer=wx.BoxSizer(wx.VERTICAL)
84        sizer.Add(self.canvas,1,wx.EXPAND)
85        sizer.Add(self.toolbar,0,wx.LEFT|wx.EXPAND)
86        self.SetSizer(sizer)
87                             
88class G2PlotNoteBook(wx.Panel):
89    def __init__(self,parent,id=-1):
90        wx.Panel.__init__(self,parent,id=id)
91        #so one can't delete a plot page!!
92        self.nb = wx.aui.AuiNotebook(self, \
93            style=wx.aui.AUI_NB_DEFAULT_STYLE ^ wx.aui.AUI_NB_CLOSE_ON_ACTIVE_TAB)
94        sizer = wx.BoxSizer()
95        sizer.Add(self.nb,1,wx.EXPAND)
96        self.SetSizer(sizer)
97        self.status = parent.CreateStatusBar()
98        self.status.SetFieldsCount(2)
99        self.status.SetStatusWidths([150,-1])
100        self.Bind(wx.aui.EVT_AUINOTEBOOK_PAGE_CHANGED, self.OnPageChanged)
101       
102        self.plotList = []
103           
104    def addMpl(self,name=""):
105        page = G2PlotMpl(self.nb)
106        self.nb.AddPage(page,name)
107       
108        self.plotList.append(name)
109       
110        return page.figure
111       
112    def add3D(self,name=""):
113        page = G2Plot3D(self.nb)
114        self.nb.AddPage(page,name)
115       
116        self.plotList.append(name)
117       
118        return page.figure
119       
120    def addOgl(self,name=""):
121        page = G2PlotOgl(self.nb)
122        self.nb.AddPage(page,name)
123       
124        self.plotList.append(name)
125       
126        return page.figure
127       
128    def Delete(self,name):
129        try:
130            item = self.plotList.index(name)
131            del self.plotList[item]
132            self.nb.DeletePage(item)
133        except ValueError:          #no plot of this name - do nothing
134            return     
135               
136    def clear(self):
137        while self.nb.GetPageCount():
138            self.nb.DeletePage(0)
139        self.plotList = []
140        self.status.DestroyChildren()
141       
142    def Rename(self,oldName,newName):
143        try:
144            item = self.plotList.index(oldName)
145            self.plotList[item] = newName
146            self.nb.SetPageText(item,newName)
147        except ValueError:          #no plot of this name - do nothing
148            return     
149       
150    def OnPageChanged(self,event):       
151        if self.plotList:
152            self.status.SetStatusText('Better to select this from GSAS-II data tree',1)
153        self.status.DestroyChildren()                           #get rid of special stuff on status bar
154       
155def PlotSngl(self,newPlot=False):
156    from matplotlib.patches import Circle
157    global HKL,HKLF
158
159    def OnSCMotion(event):
160        xpos = event.xdata
161        if xpos:
162            xpos = round(xpos)                                        #avoid out of frame mouse position
163            ypos = round(event.ydata)
164            zpos = Data['Layer']
165            if '100' in Data['Zone']:
166                HKLtxt = '(%3d,%3d,%3d)'%(zpos,xpos,ypos)
167            elif '010' in Data['Zone']:
168                HKLtxt = '(%3d,%3d,%3d)'%(xpos,zpos,ypos)
169            elif '001' in Data['Zone']:
170                HKLtxt = '(%3d,%3d,%3d)'%(xpos,ypos,zpos)
171            Page.canvas.SetToolTipString(HKLtxt)
172            self.G2plotNB.status.SetFields(['HKL = '+HKLtxt,''])
173               
174    def OnSCPick(event):
175        zpos = Data['Layer']
176        pos = event.artist.center
177        if '100' in Data['Zone']:
178            Page.canvas.SetToolTipString('(picked:(%3d,%3d,%3d))'%(zpos,pos[0],pos[1]))
179            hkl = np.array([zpos,pos[0],pos[1]])
180        elif '010' in Data['Zone']:
181            Page.canvas.SetToolTipString('(picked:(%3d,%3d,%3d))'%(pos[0],zpos,pos[1]))
182            hkl = np.array([pos[0],zpos,pos[1]])
183        elif '001' in Data['Zone']:
184            Page.canvas.SetToolTipString('(picked:(%3d,%3d,%3d))'%(pos[0],pos[1],zpos))
185            hkl = np.array([pos[0],pos[1],zpos])
186        h,k,l = hkl
187        hklf = HKLF[np.where(np.all(HKL-hkl == [0,0,0],axis=1))]
188        if len(hklf):
189            Fosq,sig,Fcsq = hklf[0]
190            HKLtxt = '(%3d,%3d,%3d %.2f %.3f %.2f %.2f)'%(h,k,l,Fosq,sig,Fcsq,(Fosq-Fcsq)/(scale*sig))
191            self.G2plotNB.status.SetFields(['','HKL, Fosq, sig, Fcsq, delFsq/sig = '+HKLtxt])
192                                 
193    def OnSCKeyPress(event):
194        print event.key
195
196    try:
197        plotNum = self.G2plotNB.plotList.index('Structure Factors')
198        Page = self.G2plotNB.nb.GetPage(plotNum)
199        if not newPlot:
200            Plot = Page.figure.gca()          #get previous powder plot & get limits
201            xylim = Plot.get_xlim(),Plot.get_ylim()
202        Page.figure.clf()
203        Plot = Page.figure.gca()          #get a fresh plot after clf()
204    except ValueError:
205        Plot = self.G2plotNB.addMpl('Structure Factors').gca()
206        plotNum = self.G2plotNB.plotList.index('Structure Factors')
207        Page = self.G2plotNB.nb.GetPage(plotNum)
208#        Page.canvas.mpl_connect('key_press_event', OnSCKeyPress)
209        Page.canvas.mpl_connect('pick_event', OnSCPick)
210        Page.canvas.mpl_connect('motion_notify_event', OnSCMotion)
211    Page.SetFocus()
212   
213    Plot.set_aspect(aspect='equal')
214    HKLref = self.PatternTree.GetItemPyData(self.Sngl)
215    Data = self.PatternTree.GetItemPyData( \
216        G2gd.GetPatternTreeItemId(self,self.Sngl, 'HKL Plot Controls'))
217    Type = Data['Type']           
218    scale = Data['Scale']
219    HKLmax = Data['HKLmax']
220    HKLmin = Data['HKLmin']
221    FosqMax = Data['FoMax']
222    FoMax = math.sqrt(FosqMax)
223    ifFc = Data['ifFc']
224    xlabel = ['k, h=','h, k=','h, l=']
225    ylabel = ['l','l','k']
226    zones = ['100','010','001']
227    pzone = [[1,2],[0,2],[0,1]]
228    izone = zones.index(Data['Zone'])
229    Plot.set_title(self.PatternTree.GetItemText(self.Sngl)[5:])
230    HKL = []
231    HKLF = []
232    for H,Fosq,sig,Fcsq,x,x,x in HKLref:
233        HKL.append(H)
234        HKLF.append([Fosq,sig,Fcsq])
235        if H[izone] == Data['Layer']:
236            B = 0
237            if Type == 'Fosq':
238                A = scale*Fosq/FosqMax
239                B = scale*Fcsq/FosqMax
240                C = abs(A-B)
241            elif Type == 'Fo':
242                A = scale*math.sqrt(max(0,Fosq))/FoMax
243                B = scale*math.sqrt(max(0,Fcsq))/FoMax
244                C = abs(A-B)
245            elif Type == '|DFsq|/sig':
246                A = abs(Fosq-Fcsq)/(scale*sig)
247            elif Type == '|DFsq|>sig':
248                A = abs(Fosq-Fcsq)/(scale*sig)
249                if A < 1.0: A = 0                   
250            elif Type == '|DFsq|>3sig':
251                A = abs(Fosq-Fcsq)/(scale*sig)
252                if A < 3.0: A = 0                   
253            xy = (H[pzone[izone][0]],H[pzone[izone][1]])
254            if A > 0.0:
255                Plot.add_artist(Circle(xy,radius=A,ec='g',fc='w',picker=3))
256            if B:
257                Plot.add_artist(Circle(xy,radius=B,ec='b',fc='w'))
258                radius = C
259                if radius > 0:
260                    if A > B:
261                        Plot.add_artist(Circle(xy,radius=radius,ec='g',fc='g'))
262                    else:                   
263                        Plot.add_artist(Circle(xy,radius=radius,ec='r',fc='r'))
264    HKL = np.array(HKL,dtype=np.int)
265    HKLF = np.array(HKLF)
266    Plot.set_xlabel(xlabel[izone]+str(Data['Layer']),fontsize=12)
267    Plot.set_ylabel(ylabel[izone],fontsize=12)
268    Plot.set_xlim((HKLmin[pzone[izone][0]],HKLmax[pzone[izone][0]]))
269    Plot.set_ylim((HKLmin[pzone[izone][1]],HKLmax[pzone[izone][1]]))
270    if not newPlot:
271        Page.toolbar.push_current()
272        Plot.set_xlim(xylim[0])
273        Plot.set_ylim(xylim[1])
274        xylim = []
275        Page.toolbar.push_current()
276        Page.toolbar.draw()
277    else:
278        Page.canvas.draw()
279       
280def PlotPatterns(self,newPlot=False):
281    global HKL
282   
283    def OnPick(event):
284        if self.itemPicked is not None: return
285        PatternId = self.PatternId
286        try:
287            Values,Names = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,self.PatternId, 'Instrument Parameters'))[1::2]
288        except TypeError:
289            return
290        Parms = dict(zip(Names,Values))
291        try:
292            wave = Parms['Lam']
293        except KeyError:
294            wave = Parms['Lam1']
295        PickId = self.PickId
296        pick = event.artist
297        mouse = event.mouseevent       
298        xpos = pick.get_xdata()
299        ypos = pick.get_ydata()
300        ind = event.ind
301        xy = list(zip(np.take(xpos,ind),np.take(ypos,ind))[0])
302        if self.PatternTree.GetItemText(PickId) == 'Peak List':
303            if ind.all() != [0]:                                    #picked a data point
304                ins = [Parms[x] for x in ['U','V','W','X','Y','SH/L']]
305                if self.qPlot:                              #qplot - convert back to 2-theta
306                    xy[0] = 2.0*asind(xy[0]*wave/(4*math.pi))
307                sig = ins[0]*tand(xy[0]/2.0)**2+ins[1]*tand(xy[0]/2.0)+ins[2]
308                gam = ins[3]/cosd(xy[0]/2.0)+ins[4]*tand(xy[0]/2.0)           
309                data = self.PatternTree.GetItemPyData(self.PickId)
310                XY = [xy[0],0, xy[1],1, sig,0, gam,0]       #default refine intensity 1st
311                data.append(XY)
312                G2pdG.UpdatePeakGrid(self,data)
313                PlotPatterns(self)
314            else:                                                   #picked a peak list line
315                self.itemPicked = pick
316        elif self.PatternTree.GetItemText(PickId) == 'Limits':
317            if ind.all() != [0]:                                    #picked a data point
318                LimitId = G2gd.GetPatternTreeItemId(self,PatternId, 'Limits')
319                data = self.PatternTree.GetItemPyData(LimitId)
320                if self.qPlot:                              #qplot - convert back to 2-theta
321                    xy[0] = 2.0*asind(xy[0]*wave/(4*math.pi))
322                if mouse.button==1:
323                    data[1][0] = min(xy[0],data[1][1])
324                if mouse.button==3:
325                    data[1][1] = max(xy[0],data[1][0])
326                self.PatternTree.SetItemPyData(LimitId,data)
327                G2pdG.UpdateLimitsGrid(self,data)
328                PlotPatterns(self)
329            else:                                                   #picked a limit line
330                self.itemPicked = pick
331       
332    def OnPlotKeyPress(event):
333        newPlot = False
334        if event.key == 'w':
335            if self.Weight:
336                self.Weight = False
337            else:
338                self.Weight = True
339            print 'plot weighting:',self.Weight
340        elif event.key == 'n':
341            if self.Contour:
342                pass
343            else:
344                if self.logPlot:
345                    self.logPlot = False
346                else:
347                    self.Offset[0] = 0
348                    self.logPlot = True
349        elif event.key == 'u':
350            if self.Contour:
351                self.Cmax = min(1.0,self.Cmax*1.2)
352            elif self.logPlot:
353                pass
354            elif self.Offset[0] < 100.:
355                self.Offset[0] += 1.
356        elif event.key == 'd':
357            if self.Contour:
358                self.Cmax = max(0.0,self.Cmax*0.8)
359            elif self.logPlot:
360                pass
361            elif self.Offset[0] > 0.:
362                self.Offset[0] -= 1.
363        elif event.key == 'l':
364            self.Offset[1] -= 1.
365        elif event.key == 'r':
366            self.Offset[1] += 1.
367        elif event.key == 'o':
368            self.Offset = [0,0]
369        elif event.key == 'c':
370            newPlot = True
371            if self.Contour:
372                self.Contour = False
373            else:
374                self.Contour = True
375                self.SinglePlot = False
376                self.Offset = [0.,0.]
377        elif event.key == 'q':
378            newPlot = True
379            if self.qPlot:
380                self.qPlot = False
381            else:
382                self.qPlot = True
383        elif event.key == 's':
384            if self.Contour:
385                choice = [m for m in mpl.cm.datad.keys() if not m.endswith("_r")]
386                choice.sort()
387                dlg = wx.SingleChoiceDialog(self,'Select','Color scheme',choice)
388                if dlg.ShowModal() == wx.ID_OK:
389                    sel = dlg.GetSelection()
390                    self.ContourColor = choice[sel]
391                else:
392                    self.ContourColor = 'Paired'
393                dlg.Destroy()
394            else:               
395                if self.SinglePlot:
396                    self.SinglePlot = False
397                else:
398                    self.SinglePlot = True
399        elif event.key == '+':
400            if self.PickId:
401                self.PickId = False
402        elif event.key == 'i':                  #for smoothing contour plot
403            choice = ['nearest','bilinear','bicubic','spline16','spline36','hanning',
404               'hamming','hermite','kaiser','quadric','catrom','gaussian','bessel',
405               'mitchell','sinc','lanczos']
406            dlg = wx.SingleChoiceDialog(self,'Select','Interpolation',choice)
407            if dlg.ShowModal() == wx.ID_OK:
408                sel = dlg.GetSelection()
409                self.Interpolate = choice[sel]
410            else:
411                self.Interpolate = 'nearest'
412            dlg.Destroy()
413           
414        PlotPatterns(self,newPlot=newPlot)
415       
416    def OnKeyBox(event):
417        if self.G2plotNB.nb.GetSelection() == self.G2plotNB.plotList.index('Powder Patterns'):
418            event.key = cb.GetValue()[0]
419            cb.SetValue(' key press')
420            OnPlotKeyPress(event)
421                       
422    def OnMotion(event):
423        xpos = event.xdata
424        if xpos:                                        #avoid out of frame mouse position
425            ypos = event.ydata
426            Page.canvas.SetCursor(wx.CROSS_CURSOR)
427            try:
428                Values,Names = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,self.PatternId, 'Instrument Parameters'))[1::2]
429                Parms = dict(zip(Names,Values))
430                try:
431                    wave = Parms['Lam']
432                except KeyError:
433                    wave = Parms['Lam1']
434                if self.qPlot:
435                    xpos = 2.0*asind(xpos*wave/(4*math.pi))
436                dsp = 0.0
437                if abs(xpos) > 0.:                  #avoid possible singularity at beam center
438                    dsp = wave/(2.*sind(abs(xpos)/2.0))
439                if self.Contour:
440                    self.G2plotNB.status.SetStatusText('2-theta =%9.3f d =%9.5f pattern ID =%5d'%(xpos,dsp,int(ypos)),1)
441                else:
442                    self.G2plotNB.status.SetStatusText('2-theta =%9.3f d =%9.5f Intensity =%9.1f'%(xpos,dsp,ypos),1)
443                if self.itemPicked:
444                    Page.canvas.SetToolTipString('%9.3f'%(xpos))
445                if self.PickId and self.PatternTree.GetItemText(self.PickId) in ['Index Peak List','Unit Cells List']:
446                    found = []
447                    if len(HKL):
448                        view = Page.toolbar._views.forward()[0][:2]
449                        wid = view[1]-view[0]
450                        found = HKL[np.where(np.fabs(HKL.T[5]-xpos) < 0.002*wid)]
451                    if len(found):
452                        h,k,l = found[0][:3] 
453                        Page.canvas.SetToolTipString('%d,%d,%d'%(int(h),int(k),int(l)))
454                    else:
455                        Page.canvas.SetToolTipString('')
456
457            except TypeError:
458                self.G2plotNB.status.SetStatusText('Select PWDR powder pattern first',1)
459                                                   
460    def OnRelease(event):
461        if self.itemPicked is None: return
462        Values,Names = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,self.PatternId, 'Instrument Parameters'))[1::2]
463        Parms = dict(zip(Names,Values))
464        try:
465            wave = Parms['Lam']
466        except KeyError:
467            wave = Parms['Lam1']
468        xpos = event.xdata
469        if xpos:                                        #avoid out of frame mouse position
470            lines = []
471            for line in self.Lines: lines.append(line.get_xdata()[0])
472            lineNo = lines.index(self.itemPicked.get_xdata()[0])
473            if  lineNo in [0,1]:
474                LimitId = G2gd.GetPatternTreeItemId(self,self.PatternId, 'Limits')
475                data = self.PatternTree.GetItemPyData(LimitId)
476#                print 'limits',xpos
477                if self.qPlot:
478                    data[1][lineNo] = 2.0*asind(wave*xpos/(4*math.pi))
479                else:
480                    data[1][lineNo] = xpos
481                self.PatternTree.SetItemPyData(LimitId,data)
482                if self.PatternTree.GetItemText(self.PickId) == 'Limits':
483                    G2pdG.UpdateLimitsGrid(self,data)
484            else:
485                PeakId = G2gd.GetPatternTreeItemId(self,self.PatternId, 'Peak List')
486                data = self.PatternTree.GetItemPyData(PeakId)
487#                print 'peaks',xpos
488                if event.button == 3:
489                    del data[lineNo-2]
490                else:
491                    if self.qPlot:
492                        data[lineNo-2][0] = 2.0*asind(wave*xpos/(4*math.pi))
493                    else:
494                        data[lineNo-2][0] = xpos
495                self.PatternTree.SetItemPyData(PeakId,data)
496                G2pdG.UpdatePeakGrid(self,data)
497        PlotPatterns(self)
498        self.itemPicked = None   
499
500    xylim = []
501    try:
502        plotNum = self.G2plotNB.plotList.index('Powder Patterns')
503        Page = self.G2plotNB.nb.GetPage(plotNum)
504        if not newPlot:
505            Plot = Page.figure.gca()          #get previous powder plot & get limits
506            xylim = Plot.get_xlim(),Plot.get_ylim()
507        Page.figure.clf()
508        Plot = Page.figure.gca()          #get a fresh plot after clf()
509    except ValueError:
510        newPlot = True
511        self.Cmax = 1.0
512        Plot = self.G2plotNB.addMpl('Powder Patterns').gca()
513        plotNum = self.G2plotNB.plotList.index('Powder Patterns')
514        Page = self.G2plotNB.nb.GetPage(plotNum)
515        Page.canvas.mpl_connect('key_press_event', OnPlotKeyPress)
516        Page.canvas.mpl_connect('motion_notify_event', OnMotion)
517        Page.canvas.mpl_connect('pick_event', OnPick)
518        Page.canvas.mpl_connect('button_release_event', OnRelease)
519    Page.SetFocus()
520    self.G2plotNB.status.DestroyChildren()
521    if self.Contour:
522        Choice = (' key press','d: lower contour max','u: raise contour max',
523            'i: interpolation method','s: color scheme','c: contour off')
524    else:
525        if self.logPlot:
526            Choice = (' key press','n: log(I) off','l: offset left','r: offset right',
527                'c: contour on','q: toggle q plot','s: toggle single plot','+: no selection')
528        else:
529            Choice = (' key press','l: offset left','r: offset right','d: offset down',
530                'u: offset up','0: reset offset','n: log(I) on','c: contour on',
531                'q: toggle q plot','s: toggle single plot','+: no selection')
532    cb = wx.ComboBox(self.G2plotNB.status,style=wx.CB_DROPDOWN|wx.CB_READONLY,
533        choices=Choice)
534    cb.Bind(wx.EVT_COMBOBOX, OnKeyBox)
535    cb.SetValue(' key press')
536   
537    PickId = self.PickId
538    PatternId = self.PatternId
539    colors=['b','g','r','c','m','k']
540    Lines = []
541    if self.SinglePlot:
542        Pattern = self.PatternTree.GetItemPyData(PatternId)
543        Pattern.append(self.PatternTree.GetItemText(PatternId))
544        PlotList = [Pattern,]
545        ParmList = [self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,
546            self.PatternId, 'Instrument Parameters'))[1],]
547    else:       
548        PlotList = []
549        ParmList = []
550        item, cookie = self.PatternTree.GetFirstChild(self.root)
551        while item:
552            if 'PWDR' in self.PatternTree.GetItemText(item):
553                Pattern = self.PatternTree.GetItemPyData(item)
554                if len(Pattern) < 3:                    # put name on end if needed
555                    Pattern.append(self.PatternTree.GetItemText(item))
556                PlotList.append(Pattern)
557                ParmList.append(self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,
558                    item,'Instrument Parameters'))[1])
559            item, cookie = self.PatternTree.GetNextChild(self.root, cookie)               
560    Ymax = 1.0
561    lenX = 0
562    HKL = np.array(self.HKL)
563    for Pattern in PlotList:
564        xye = Pattern[1]
565        Ymax = max(Ymax,max(xye[1]))
566    offset = self.Offset[0]*Ymax/100.0
567    Title = 'Powder Patterns: '+os.path.split(self.GSASprojectfile)[1]
568    if self.logPlot:
569        Title = 'log('+Title+')'
570    Plot.set_title(Title)
571    if self.qPlot:
572        Plot.set_xlabel(r'$q, \AA^{-1}$',fontsize=14)
573    else:       
574        Plot.set_xlabel(r'$\mathsf{2\theta}$',fontsize=14)
575    Plot.set_ylabel('Intensity',fontsize=12)
576    if self.Contour:
577        ContourZ = []
578        ContourY = []
579        Nseq = 0
580    for N,Pattern in enumerate(PlotList):
581        Parms = ParmList[N]
582        ifpicked = False
583        LimitId = 0
584        xye = np.array(Pattern[1])
585        if PickId:
586            ifpicked = Pattern[2] == self.PatternTree.GetItemText(PatternId)
587            LimitId = G2gd.GetPatternTreeItemId(self,PatternId, 'Limits')
588        if self.qPlot:
589            Id = G2gd.GetPatternTreeItemId(self,self.root, Pattern[2])
590            X = 4*np.pi*npsind(xye[0]/2.0)/Parms[1]
591        else:
592            X = xye[0]
593        if not lenX:
594            lenX = len(X)           
595        Y = xye[1]+offset*N
596        if LimitId:
597            limits = np.array(self.PatternTree.GetItemPyData(LimitId))
598            if self.qPlot:
599                limits = 4*np.pi*npsind(limits/2.0)/Parms[1]
600            Lines.append(Plot.axvline(limits[1][0],color='g',dashes=(5,5),picker=3.))   
601            Lines.append(Plot.axvline(limits[1][1],color='r',dashes=(5,5),picker=3.))                   
602        if self.Contour:
603           
604            if lenX == len(X):
605                ContourY.append(N)
606                ContourZ.append(Y)
607                ContourX = X
608                Nseq += 1
609                Plot.set_ylabel('Data sequence',fontsize=12)
610        else:
611            X += self.Offset[1]*.005*N
612            if ifpicked:
613                Z = xye[3]+offset*N
614                W = xye[4]+offset*N
615                D = xye[5]+offset*N-Ymax*.02
616                if self.Weight:
617                    W2 = np.sqrt(xye[2])
618                    D *= W2-Ymax*.02
619                if self.logPlot:
620                    Plot.semilogy(X,Y,colors[N%6]+'+',picker=3.,clip_on=False,nonposy='mask')
621                    Plot.semilogy(X,Z,colors[(N+1)%6],picker=False,nonposy='mask')
622                    Plot.semilogy(X,W,colors[(N+2)%6],picker=False,nonposy='mask')
623                else:
624                    Plot.plot(X,Y,colors[N%6]+'+',picker=3.,clip_on=False)
625                    Plot.plot(X,Z,colors[(N+1)%6],picker=False)
626                    Plot.plot(X,W,colors[(N+2)%6],picker=False)
627                    Plot.plot(X,D,colors[(N+3)%6],picker=False)
628                    Plot.axhline(0.,color=wx.BLACK)
629                Page.canvas.SetToolTipString('')
630                if self.PatternTree.GetItemText(PickId) == 'Peak List':
631                    tip = 'On data point: Pick peak - L or R MB. On line: L-move, R-delete'
632                    Page.canvas.SetToolTipString(tip)
633                    data = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PatternId, 'Peak List'))
634                    for item in data:
635                        if self.qPlot:
636                            Lines.append(Plot.axvline(4*math.pi*sind(item[0]/2.)/Parms[1],color=colors[N%6],picker=2.))
637                        else:
638                            Lines.append(Plot.axvline(item[0],color=colors[N%6],picker=2.))
639                if self.PatternTree.GetItemText(PickId) == 'Limits':
640                    tip = 'On data point: Lower limit - L MB; Upper limit - R MB. On limit: MB down to move'
641                    Page.canvas.SetToolTipString(tip)
642                    data = self.LimitsTable.GetData()
643            else:
644                if self.logPlot:
645                    Plot.semilogy(X,Y,colors[N%6],picker=False,nonposy='clip')
646                else:
647                    Plot.plot(X,Y,colors[N%6],picker=False)
648    if PickId and self.PatternTree.GetItemText(PickId) in ['Index Peak List','Unit Cells List']:
649        Values,Names = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PatternId, 'Instrument Parameters'))[1::2]
650        Parms = dict(zip(Names,Values))
651        try:
652            wave = Parms['Lam']
653        except KeyError:
654            wave = Parms['Lam1']
655        peaks = np.array((self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PatternId, 'Index Peak List'))))
656        for peak in peaks:
657            if self.qPlot:
658                Plot.axvline(4*np.pi*sind(peak[0]/2.0)/wave,color='b')
659            else:
660                Plot.axvline(peak[0],color='b')
661        for hkl in self.HKL:
662            if self.qPlot:
663                Plot.axvline(4*np.pi*sind(hkl[5]/2.0)/wave,color='r',dashes=(5,5))
664            else:
665                Plot.axvline(hkl[5],color='r',dashes=(5,5))
666    if self.Contour:
667        acolor = mpl.cm.get_cmap(self.ContourColor)
668        Img = Plot.imshow(ContourZ,cmap=acolor,vmin=0,vmax=Ymax*self.Cmax,interpolation=self.Interpolate, 
669            extent=[ContourX[0],ContourX[-1],ContourY[0],ContourY[-1]],aspect='auto',origin='lower')
670        Page.figure.colorbar(Img)
671    else:
672        self.Lines = Lines
673    if not newPlot:
674        Page.toolbar.push_current()
675        Plot.set_xlim(xylim[0])
676        Plot.set_ylim(xylim[1])
677        xylim = []
678        Page.toolbar.push_current()
679        Page.toolbar.draw()
680    else:
681        Page.canvas.draw()
682    self.Pwdr = True
683   
684def PlotISFG(self,newPlot=False,type=''):
685    if not type:
686        type = self.G2plotNB.plotList[self.G2plotNB.nb.GetSelection()]
687    if type not in ['I(Q)','S(Q)','F(Q)','G(R)']:
688        return
689    superMinusOne = unichr(0xaf)+unichr(0xb9)
690   
691    def OnPlotKeyPress(event):
692        newPlot = False
693        if event.key == 'u':
694            if self.Contour:
695                self.Cmax = min(1.0,self.Cmax*1.2)
696            elif self.Offset[0] < 100.:
697                self.Offset[0] += 1.
698        elif event.key == 'd':
699            if self.Contour:
700                self.Cmax = max(0.0,self.Cmax*0.8)
701            elif self.Offset[0] > 0.:
702                self.Offset[0] -= 1.
703        elif event.key == 'l':
704            self.Offset[1] -= 1.
705        elif event.key == 'r':
706            self.Offset[1] += 1.
707        elif event.key == 'o':
708            self.Offset = [0,0]
709        elif event.key == 'c':
710            newPlot = True
711            if self.Contour:
712                self.Contour = False
713            else:
714                self.Contour = True
715                self.SinglePlot = False
716                self.Offset = [0.,0.]
717        elif event.key == 's':
718            if self.Contour:
719                choice = [m for m in mpl.cm.datad.keys() if not m.endswith("_r")]
720                choice.sort()
721                dlg = wx.SingleChoiceDialog(self,'Select','Color scheme',choice)
722                if dlg.ShowModal() == wx.ID_OK:
723                    sel = dlg.GetSelection()
724                    self.ContourColor = choice[sel]
725                else:
726                    self.ContourColor = 'Paired'
727                dlg.Destroy()
728            else:               
729                if self.SinglePlot:
730                    self.SinglePlot = False
731                else:
732                    self.SinglePlot = True
733        elif event.key == 'i':                  #for smoothing contour plot
734            choice = ['nearest','bilinear','bicubic','spline16','spline36','hanning',
735               'hamming','hermite','kaiser','quadric','catrom','gaussian','bessel',
736               'mitchell','sinc','lanczos']
737            dlg = wx.SingleChoiceDialog(self,'Select','Interpolation',choice)
738            if dlg.ShowModal() == wx.ID_OK:
739                sel = dlg.GetSelection()
740                self.Interpolate = choice[sel]
741            else:
742                self.Interpolate = 'nearest'
743            dlg.Destroy()
744        elif event.key == 't' and not self.Contour:
745            if self.Legend:
746                self.Legend = False
747            else:
748                self.Legend = True
749           
750           
751        PlotISFG(self,newPlot=newPlot,type=type)
752       
753    def OnKeyBox(event):
754        if self.G2plotNB.nb.GetSelection() == self.G2plotNB.plotList.index(type):
755            event.key = cb.GetValue()[0]
756            cb.SetValue(' key press')
757            OnPlotKeyPress(event)
758                       
759    def OnMotion(event):
760        xpos = event.xdata
761        if xpos:                                        #avoid out of frame mouse position
762            ypos = event.ydata
763            Page.canvas.SetCursor(wx.CROSS_CURSOR)
764            try:
765                if self.Contour:
766                    self.G2plotNB.status.SetStatusText('R =%.3fA pattern ID =%5d'%(xpos,int(ypos)),1)
767                else:
768                    self.G2plotNB.status.SetStatusText('R =%.3fA %s =%.2f'%(xpos,type,ypos),1)                   
769            except TypeError:
770                self.G2plotNB.status.SetStatusText('Select '+type+' pattern first',1)
771   
772    xylim = []
773    try:
774        plotNum = self.G2plotNB.plotList.index(type)
775        Page = self.G2plotNB.nb.GetPage(plotNum)
776        if not newPlot:
777            Plot = Page.figure.gca()          #get previous plot & get limits
778            xylim = Plot.get_xlim(),Plot.get_ylim()
779        Page.figure.clf()
780        Plot = Page.figure.gca()
781    except ValueError:
782        newPlot = True
783        self.Cmax = 1.0
784        Plot = self.G2plotNB.addMpl(type).gca()
785        plotNum = self.G2plotNB.plotList.index(type)
786        Page = self.G2plotNB.nb.GetPage(plotNum)
787        Page.canvas.mpl_connect('key_press_event', OnPlotKeyPress)
788        Page.canvas.mpl_connect('motion_notify_event', OnMotion)
789   
790    Page.SetFocus()
791    self.G2plotNB.status.DestroyChildren()
792    if self.Contour:
793        Choice = (' key press','d: lower contour max','u: raise contour max',
794            'i: interpolation method','s: color scheme','c: contour off')
795    else:
796        Choice = (' key press','l: offset left','r: offset right','d: offset down','u: offset up',
797            'o: reset offset','t: toggle legend','c: contour on','s: toggle single plot')
798    cb = wx.ComboBox(self.G2plotNB.status,style=wx.CB_DROPDOWN|wx.CB_READONLY,
799        choices=Choice)
800    cb.Bind(wx.EVT_COMBOBOX, OnKeyBox)
801    cb.SetValue(' key press')
802    PatternId = self.PatternId
803    PickId = self.PickId
804    Plot.set_title(type)
805    if type == 'G(R)':
806        Plot.set_xlabel(r'$R,\AA$',fontsize=14)
807    else:
808        Plot.set_xlabel(r'$Q,\AA$'+superMinusOne,fontsize=14)
809    Plot.set_ylabel(r''+type,fontsize=14)
810    colors=['b','g','r','c','m','k']
811    name = self.PatternTree.GetItemText(PatternId)[4:]
812    Pattern = []   
813    if self.SinglePlot:
814        name = self.PatternTree.GetItemText(PatternId)
815        name = type+name[4:]
816        Id = G2gd.GetPatternTreeItemId(self,PatternId,name)
817        Pattern = self.PatternTree.GetItemPyData(Id)
818        if Pattern:
819            Pattern.append(name)
820        PlotList = [Pattern,]
821    else:
822        PlotList = []
823        item, cookie = self.PatternTree.GetFirstChild(self.root)
824        while item:
825            if 'PDF' in self.PatternTree.GetItemText(item):
826                name = type+self.PatternTree.GetItemText(item)[4:]
827                Id = G2gd.GetPatternTreeItemId(self,item,name)
828                Pattern = self.PatternTree.GetItemPyData(Id)
829                if Pattern:
830                    Pattern.append(name)
831                    PlotList.append(Pattern)
832            item, cookie = self.PatternTree.GetNextChild(self.root, cookie)
833    PDFdata = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PatternId, 'PDF Controls'))
834    numbDen = G2pwd.GetNumDensity(PDFdata['ElList'],PDFdata['Form Vol'])
835    Xb = [0.,10.]
836    Yb = [0.,-40.*np.pi*numbDen]
837    Ymax = 1.0
838    lenX = 0
839    for Pattern in PlotList:
840        xye = Pattern[1]
841        Ymax = max(Ymax,max(xye[1]))
842    offset = self.Offset[0]*Ymax/100.0
843    if self.Contour:
844        ContourZ = []
845        ContourY = []
846        Nseq = 0
847    for N,Pattern in enumerate(PlotList):
848        xye = Pattern[1]
849        if PickId:
850            ifpicked = Pattern[2] == self.PatternTree.GetItemText(PatternId)
851        X = xye[0]
852        if not lenX:
853            lenX = len(X)           
854        Y = xye[1]+offset*N
855        if self.Contour:
856            if lenX == len(X):
857                ContourY.append(N)
858                ContourZ.append(Y)
859                ContourX = X
860                Nseq += 1
861                Plot.set_ylabel('Data sequence',fontsize=12)
862        else:
863            X = xye[0]+self.Offset[1]*.005*N
864            if ifpicked:
865                Plot.plot(X,Y,colors[N%6]+'+',picker=3.,clip_on=False)
866                Page.canvas.SetToolTipString('')
867            else:
868                if self.Legend:
869                    Plot.plot(X,Y,colors[N%6],picker=False,label='Azm:'+Pattern[2].split('=')[1])
870                else:
871                    Plot.plot(X,Y,colors[N%6],picker=False)
872            if type == 'G(R)':
873                Plot.plot(Xb,Yb,color='k',dashes=(5,5))
874            elif type == 'F(Q)':
875                Plot.axhline(0.,color=wx.BLACK)
876            elif type == 'S(Q)':
877                Plot.axhline(1.,color=wx.BLACK)
878    if self.Contour:
879        acolor = mpl.cm.get_cmap(self.ContourColor)
880        Img = Plot.imshow(ContourZ,cmap=acolor,vmin=0,vmax=Ymax*self.Cmax,interpolation=self.Interpolate, 
881            extent=[ContourX[0],ContourX[-1],ContourY[0],ContourY[-1]],aspect='auto',origin='lower')
882        Page.figure.colorbar(Img)
883    elif self.Legend:
884        Plot.legend(loc='best')
885    if not newPlot:
886        Page.toolbar.push_current()
887        Plot.set_xlim(xylim[0])
888        Plot.set_ylim(xylim[1])
889        xylim = []
890        Page.toolbar.push_current()
891        Page.toolbar.draw()
892    else:
893        Page.canvas.draw()
894       
895def PlotXY(self,XY,newPlot=False,type=''):
896    #simple plot of xy data
897
898    def OnMotion(event):
899        xpos = event.xdata
900        if xpos:                                        #avoid out of frame mouse position
901            ypos = event.ydata
902            Page.canvas.SetCursor(wx.CROSS_CURSOR)
903            try:
904                self.G2plotNB.status.SetStatusText('X =%9.3f %s =%9.3f'%(xpos,type,ypos),1)                   
905            except TypeError:
906                self.G2plotNB.status.SetStatusText('Select '+type+' pattern first',1)
907
908    try:
909        plotNum = self.G2plotNB.plotList.index(type)
910        Page = self.G2plotNB.nb.GetPage(plotNum)
911        if not newPlot:
912            Plot = Page.figure.gca()
913            xylim = Plot.get_xlim(),Plot.get_ylim()
914        Page.figure.clf()
915        Plot = Page.figure.gca()
916    except ValueError:
917        newPlot = True
918        Plot = self.G2plotNB.addMpl(type).gca()
919        plotNum = self.G2plotNB.plotList.index(type)
920        Page = self.G2plotNB.nb.GetPage(plotNum)
921        Page.canvas.mpl_connect('motion_notify_event', OnMotion)
922   
923    Page.SetFocus()
924    self.G2plotNB.status.DestroyChildren()
925    Plot.set_title(type)
926    Plot.set_xlabel(r'X',fontsize=14)
927    Plot.set_ylabel(r''+type,fontsize=14)
928    colors=['b','g','r','c','m','k']
929    Ymax = 1.0
930    lenX = 0
931    X,Y = XY[:2]
932    Ymax = max(Ymax,max(Y))
933    Plot.plot(X,Y,'k',picker=False)
934    if not newPlot:
935        Page.toolbar.push_current()
936        Plot.set_xlim(xylim[0])
937        Plot.set_ylim(xylim[1])
938        xylim = []
939        Page.toolbar.push_current()
940        Page.toolbar.draw()
941    else:
942        Page.canvas.draw()
943
944def PlotPowderLines(self):
945    global HKL
946
947    def OnMotion(event):
948        xpos = event.xdata
949        if xpos:                                        #avoid out of frame mouse position
950            Page.canvas.SetCursor(wx.CROSS_CURSOR)
951            self.G2plotNB.status.SetFields(['','2-theta =%9.3f '%(xpos,)])
952            if self.PickId and self.PatternTree.GetItemText(self.PickId) in ['Index Peak List','Unit Cells List']:
953                found = []
954                if len(HKL):
955                    view = Page.toolbar._views.forward()[0][:2]
956                    wid = view[1]-view[0]
957                    found = HKL[np.where(np.fabs(HKL.T[5]-xpos) < 0.002*wid)]
958                if len(found):
959                    h,k,l = found[0][:3] 
960                    Page.canvas.SetToolTipString('%d,%d,%d'%(int(h),int(k),int(l)))
961                else:
962                    Page.canvas.SetToolTipString('')
963
964    try:
965        plotNum = self.G2plotNB.plotList.index('Powder Lines')
966        Page = self.G2plotNB.nb.GetPage(plotNum)
967        Page.figure.clf()
968        Plot = Page.figure.gca()
969    except ValueError:
970        Plot = self.G2plotNB.addMpl('Powder Lines').gca()
971        plotNum = self.G2plotNB.plotList.index('Powder Lines')
972        Page = self.G2plotNB.nb.GetPage(plotNum)
973        Page.canvas.mpl_connect('motion_notify_event', OnMotion)
974       
975    Page.SetFocus()
976    Plot.set_title('Powder Pattern Lines')
977    Plot.set_xlabel(r'$\mathsf{2\theta}$',fontsize=14)
978    PickId = self.PickId
979    PatternId = self.PatternId
980    peaks = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PatternId, 'Index Peak List'))
981    for peak in peaks:
982        Plot.axvline(peak[0],color='b')
983    HKL = np.array(self.HKL)
984    for hkl in self.HKL:
985        Plot.axvline(hkl[5],color='r',dashes=(5,5))
986    xmin = peaks[0][0]
987    xmax = peaks[-1][0]
988    delt = xmax-xmin
989    xlim = [max(0,xmin-delt/20.),min(180.,xmax+delt/20.)]
990    Plot.set_xlim(xlim)
991    Page.canvas.draw()
992    Page.toolbar.push_current()
993
994def PlotPeakWidths(self):
995    PatternId = self.PatternId
996    limitID = G2gd.GetPatternTreeItemId(self,PatternId, 'Limits')
997    if limitID:
998        limits = self.PatternTree.GetItemPyData(limitID)
999    else:
1000        return
1001    instParms = self.PatternTree.GetItemPyData( \
1002        G2gd.GetPatternTreeItemId(self,PatternId, 'Instrument Parameters'))
1003    if instParms[0][0] == 'PXC':
1004        lam = instParms[1][1]
1005        if len(instParms[1]) == 13:
1006            GU,GV,GW,LX,LY = instParms[0][6:11]
1007        else:
1008            GU,GV,GW,LX,LY = instParms[0][4:9]
1009    peakID = G2gd.GetPatternTreeItemId(self,PatternId, 'Peak List')
1010    if peakID:
1011        peaks = self.PatternTree.GetItemPyData(peakID)
1012    else:
1013        peaks = []
1014   
1015    try:
1016        plotNum = self.G2plotNB.plotList.index('Peak Widths')
1017        Page = self.G2plotNB.nb.GetPage(plotNum)
1018        Page.figure.clf()
1019        Plot = Page.figure.gca()
1020    except ValueError:
1021        Plot = self.G2plotNB.addMpl('Peak Widths').gca()
1022        plotNum = self.G2plotNB.plotList.index('Peak Widths')
1023        Page = self.G2plotNB.nb.GetPage(plotNum)
1024    Page.SetFocus()
1025   
1026    Page.canvas.SetToolTipString('')
1027    colors=['b','g','r','c','m','k']
1028    Xmin,Xmax = limits[1]
1029    Xmin = min(0.5,max(Xmin,1))
1030    Xmin /= 2
1031    Xmax /= 2
1032    nPts = 100
1033    delt = (Xmax-Xmin)/nPts
1034    thetas = []
1035    for i in range(nPts):
1036        thetas.append(Xmin+i*delt)
1037    X = []
1038    Y = []
1039    Z = []
1040    W = []
1041    V = []
1042    sig = lambda Th,U,V,W: 1.17741*math.sqrt(U*tand(Th)**2+V*tand(Th)+W)*math.pi/18000.
1043    gam = lambda Th,X,Y: (X/cosd(Th)+Y*tand(Th))*math.pi/18000.
1044    gamFW = lambda s,g: math.exp(math.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.)
1045    gamFW2 = lambda s,g: math.sqrt(s**2+(0.4654996*g)**2)+.5345004*#Ubaldo Bafile - private communication
1046    for theta in thetas:
1047        X.append(4.0*math.pi*sind(theta)/lam)              #q
1048        s = sig(theta,GU,GV,GW)
1049        g = gam(theta,LX,LY)
1050        G = gamFW(g,s)
1051        H = gamFW2(g,s)
1052        Y.append(s/tand(theta))
1053        Z.append(g/tand(theta))
1054        W.append(G/tand(theta))
1055        V.append(H/tand(theta))
1056    Plot.set_title('Instrument and sample peak widths')
1057    Plot.set_ylabel(r'$\Delta q/q, \Delta d/d$',fontsize=14)
1058    Plot.set_xlabel(r'$q, \AA^{-1}$',fontsize=14)
1059    Plot.plot(X,Y,color='r',label='Gaussian')
1060    Plot.plot(X,Z,color='g',label='Lorentzian')
1061    Plot.plot(X,W,color='b',label='G+L')
1062    Plot.plot(X,V,color='k',label='G+L2')
1063    X = []
1064    Y = []
1065    Z = []
1066    W = []
1067    V = []
1068    for peak in peaks:
1069        X.append(4.0*math.pi*sind(peak[0]/2.0)/lam)
1070        s = 1.17741*math.sqrt(peak[4])*math.pi/18000.
1071        g = peak[6]*math.pi/18000.
1072        G = gamFW(g,s)
1073        H = gamFW2(g,s)
1074        Y.append(s/tand(peak[0]/2.))
1075        Z.append(g/tand(peak[0]/2.))
1076        W.append(G/tand(peak[0]/2.))
1077        V.append(H/tand(peak[0]/2.))
1078    Plot.plot(X,Y,'+',color='r',label='G peak')
1079    Plot.plot(X,Z,'+',color='g',label='L peak')
1080    Plot.plot(X,W,'+',color='b',label='G+L peak')
1081    Plot.plot(X,V,'+',color='k',label='G+L2 peak')
1082    Plot.legend(loc='best')
1083    Page.canvas.draw()
1084   
1085def PlotStrain(self,data):
1086    # in this instance data is for a phase
1087    PatternId = self.PatternId
1088    generalData = data['General']
1089    SGData = generalData['SGData']
1090    MuStrKeys = G2spc.MustrainNames(SGData)
1091    cell = generalData['Cell'][1:]
1092    A,B = G2lat.cell2AB(cell[:6])
1093    Vol = cell[6]
1094    useList = data['Histograms']
1095    numPlots = len(useList)
1096   
1097    try:
1098        plotNum = self.G2plotNB.plotList.index('Microstrain')
1099        Page = self.G2plotNB.nb.GetPage(plotNum)
1100        Page.figure.clf()
1101        Plot = mp3d.Axes3D(Page.figure)
1102    except ValueError:
1103        Plot = mp3d.Axes3D(self.G2plotNB.add3D('Microstrain'))
1104        plotNum = self.G2plotNB.plotList.index('Microstrain')
1105        Page = self.G2plotNB.nb.GetPage(plotNum)
1106    Page.SetFocus()
1107    self.G2plotNB.status.SetStatusText('Adjust frame size to get desired aspect ratio',1)
1108   
1109    for item in useList:
1110        if useList[item]['Show']:
1111            muStrain = useList[item]['Mustrain']
1112            PHI = np.linspace(0.,360.,30,True)
1113            PSI = np.linspace(0.,180.,30,True)
1114            X = np.outer(npsind(PHI),npsind(PSI))
1115            Y = np.outer(npcosd(PHI),npsind(PSI))
1116            Z = np.outer(np.ones(np.size(PHI)),npcosd(PSI))
1117            if muStrain[0] == 'isotropic':
1118                muiso = muStrain[1][0]*math.pi/0.018      #centidegrees to radians!
1119                X *= muiso
1120                Y *= muiso
1121                Z *= muiso               
1122               
1123            elif muStrain[0] == 'uniaxial':
1124                def uniaxMustrain(xyz,muiso,muaniso,axes):
1125                    cp = abs(np.dot(xyz,axes))
1126                    S = muiso+muaniso*cp
1127                    return S*xyz*math.pi/0.018      #centidegrees to radians!
1128                muiso,muaniso = muStrain[1][:2]
1129                axes = np.inner(A,np.array(muStrain[3]))
1130                axes /= nl.norm(axes)
1131                Shkl = np.array(muStrain[1])
1132                Shape = X.shape[0]
1133                XYZ = np.dstack((X,Y,Z))
1134                XYZ = np.nan_to_num(np.apply_along_axis(uniaxMustrain,2,XYZ,muiso,muaniso,axes))
1135                X,Y,Z = np.dsplit(XYZ,3)
1136                X = X[:,:,0]
1137                Y = Y[:,:,0]
1138                Z = Z[:,:,0]
1139               
1140            elif muStrain[0] == 'generalized':
1141                def genMustrain(xyz,SGData,A,Shkl):
1142                    uvw = np.inner(A.T,xyz)
1143                    Strm = np.array(G2spc.MustrainCoeff(uvw,SGData))
1144                    sum = np.sqrt(np.sum(np.multiply(Shkl,Strm)))*math.pi/0.018      #centidegrees to radians!
1145                    return sum*xyz
1146                Shkl = np.array(muStrain[4])
1147                if np.any(Shkl):
1148                    Shape = X.shape[0]
1149                    XYZ = np.dstack((X,Y,Z))
1150                    XYZ = np.nan_to_num(np.apply_along_axis(genMustrain,2,XYZ,SGData,A,Shkl))
1151                    X,Y,Z = np.dsplit(XYZ,3)
1152                    X = X[:,:,0]
1153                    Y = Y[:,:,0]
1154                    Z = Z[:,:,0]
1155                   
1156            if np.any(X) and np.any(Y) and np.any(Z):
1157                Plot.plot_surface(X,Y,Z,rstride=1,cstride=1,color='g')
1158               
1159            Plot.set_xlabel('X')
1160            Plot.set_ylabel('Y')
1161            Plot.set_zlabel('Z')
1162    Page.canvas.draw()
1163           
1164def PlotExposedImage(self,newPlot=False,event=None):
1165    plotNo = self.G2plotNB.nb.GetSelection()
1166    if self.G2plotNB.nb.GetPageText(plotNo) == '2D Powder Image':
1167        PlotImage(self,newPlot,event,newImage=True)
1168    elif self.G2plotNB.nb.GetPageText(plotNo) == '2D Integration':
1169        PlotIntegration(self,newPlot,event)
1170
1171def PlotImage(self,newPlot=False,event=None,newImage=True):
1172    from matplotlib.patches import Ellipse,Arc,Circle,Polygon
1173    import numpy.ma as ma
1174    Dsp = lambda tth,wave: wave/(2.*sind(tth/2.))
1175    global Data,Masks
1176    colors=['b','g','r','c','m','k']
1177    Data = self.PatternTree.GetItemPyData(
1178        G2gd.GetPatternTreeItemId(self,self.Image, 'Image Controls'))
1179    Masks = self.PatternTree.GetItemPyData(
1180        G2gd.GetPatternTreeItemId(self,self.Image, 'Masks'))
1181
1182    def OnImMotion(event):
1183        Page.canvas.SetToolTipString('')
1184        sizexy = Data['size']
1185        if event.xdata and event.ydata:                 #avoid out of frame errors
1186            Page.canvas.SetCursor(wx.CROSS_CURSOR)
1187            item = self.itemPicked
1188            pixelSize = Data['pixelSize']
1189            scalex = 1000./pixelSize[0]
1190            scaley = 1000./pixelSize[1]
1191            if item and self.PatternTree.GetItemText(self.PickId) == 'Image Controls':
1192                if 'Text' in str(item):
1193                    Page.canvas.SetToolTipString('%8.3f %8.3fmm'%(event.xdata,event.ydata))
1194                else:
1195                    xcent,ycent = Data['center']
1196                    xpos = event.xdata-xcent
1197                    ypos = event.ydata-ycent
1198                    tth,azm = G2img.GetTthAzm(event.xdata,event.ydata,Data)
1199                    if 'line3' in  str(item) or 'line4' in str(item) and not Data['fullIntegrate']:
1200                        Page.canvas.SetToolTipString('%6d deg'%(azm))
1201                    elif 'line1' in  str(item) or 'line2' in str(item):
1202                        Page.canvas.SetToolTipString('%8.3fdeg'%(tth))                           
1203            else:
1204                xpos = event.xdata
1205                ypos = event.ydata
1206                xpix = xpos*scalex
1207                ypix = ypos*scaley
1208                Int = 0
1209                if (0 <= xpix <= sizexy[0]) and (0 <= ypix <= sizexy[1]):
1210                    Int = self.ImageZ[ypix][xpix]
1211                tth,azm,dsp = G2img.GetTthAzmDsp(xpos,ypos,Data)
1212                Q = 2.*math.pi/dsp
1213                if self.setPoly:
1214                    self.G2plotNB.status.SetFields(['','Polygon mask pick - LB next point, RB close polygon'])
1215                else:
1216                    self.G2plotNB.status.SetFields(\
1217                        ['','Detector 2-th =%9.3fdeg, dsp =%9.3fA, Q = %6.5fA-1, azm = %7.2fdeg, I = %6d'%(tth,dsp,Q,azm,Int)])
1218
1219    def OnImPlotKeyPress(event):
1220        try:
1221            PickName = self.PatternTree.GetItemText(self.PickId)
1222        except TypeError:
1223            return
1224        if PickName == 'Masks':
1225            Xpos = event.xdata
1226            if not Xpos:            #got point out of frame
1227                return
1228            Ypos = event.ydata
1229            if event.key == 's':
1230                Masks['Points'].append([Xpos,Ypos,1.])
1231            elif event.key == 'r':
1232                tth = G2img.GetTth(Xpos,Ypos,Data)
1233                Masks['Rings'].append([tth,0.1])
1234            elif event.key == 'a':
1235                tth,azm = G2img.GetTthAzm(Xpos,Ypos,Data)
1236                azm = int(azm)               
1237                Masks['Arcs'].append([tth,[azm-5,azm+5],0.1])
1238            elif event.key == 'p':
1239                self.setPoly = True
1240                Masks['Polygons'].append([])
1241                self.G2plotNB.status.SetFields(['','Polygon mask active - LB pick next point, RB close polygon'])
1242            G2imG.UpdateMasks(self,Masks)
1243        elif PickName == 'Image Controls':
1244            if event.key == 'c':
1245                Xpos = event.xdata
1246                if not Xpos:            #got point out of frame
1247                    return
1248                Ypos = event.ydata
1249                dlg = wx.MessageDialog(self,'Are you sure you want to change the center?',
1250                    'Center change',style=wx.OK|wx.CANCEL)
1251                try:
1252                    if dlg.ShowModal() == wx.ID_OK:
1253                        print 'move center to: ',Xpos,Ypos
1254                        Data['center'] = [Xpos,Ypos]
1255                        G2imG.UpdateImageControls(self,Data,Masks)
1256                finally:
1257                    dlg.Destroy()
1258            elif event.key == 'l':
1259                if self.logPlot:
1260                    self.logPlot = False
1261                else:
1262                    self.logPlot = True
1263        PlotImage(self,newImage=True)
1264           
1265    def OnKeyBox(event):
1266        if self.G2plotNB.nb.GetSelection() == self.G2plotNB.plotList.index('2D Powder Image'):
1267            event.key = cb.GetValue()[0]
1268            cb.SetValue(' key press')
1269            if event.key in 'l':
1270                OnImPlotKeyPress(event)
1271                       
1272    def OnImPick(event):
1273        if self.PatternTree.GetItemText(self.PickId) not in ['Image Controls','Masks']:
1274            return
1275        if self.setPoly:
1276            polygon = Masks['Polygons'][-1]
1277            xpos,ypos = event.mouseevent.xdata,event.mouseevent.ydata
1278            if xpos and ypos:                       #point inside image
1279                if len(polygon) > 2 and event.mouseevent.button == 3:
1280                    x0,y0 = polygon[0]
1281                    polygon.append([x0,y0])
1282                    self.setPoly = False
1283                    self.G2plotNB.status.SetFields(['','Polygon closed - RB drag a vertex to change shape'])
1284                else:
1285                    self.G2plotNB.status.SetFields(['','New polygon point: %.1f,%.1f'%(xpos,ypos)])
1286                    polygon.append([xpos,ypos])
1287                G2imG.UpdateMasks(self,Masks)
1288        else:
1289            if self.itemPicked is not None: return
1290            self.itemPicked = event.artist
1291            self.mousePicked = event.mouseevent
1292       
1293    def OnImRelease(event):
1294        try:
1295            PickName = self.PatternTree.GetItemText(self.PickId)
1296        except TypeError:
1297            return
1298        if PickName not in ['Image Controls','Masks']:
1299            return
1300        pixelSize = Data['pixelSize']
1301        scalex = 1000./pixelSize[0]
1302        scaley = 1000./pixelSize[1]
1303        pixLimit = Data['pixLimit']
1304        if self.itemPicked is None and PickName == 'Image Controls':
1305#            sizexy = Data['size']
1306            Xpos = event.xdata
1307            if not (Xpos and self.ifGetRing):                   #got point out of frame
1308                return
1309            Ypos = event.ydata
1310            if Ypos and not Page.toolbar._active:         #make sure zoom/pan not selected
1311                if event.button == 1:
1312                    Xpix = Xpos*scalex
1313                    Ypix = Ypos*scaley
1314                    xpos,ypos,I,J = G2img.ImageLocalMax(self.ImageZ,pixLimit,Xpix,Ypix)
1315                    if I and J:
1316                        xpos += .5                              #shift to pixel center
1317                        ypos += .5
1318                        xpos /= scalex                          #convert to mm
1319                        ypos /= scaley
1320                        Data['ring'].append([xpos,ypos])
1321                elif event.button == 3:
1322                    self.dataFrame.GetStatusBar().SetStatusText('Calibrating...')
1323                    if G2img.ImageCalibrate(self,Data):
1324                        self.dataFrame.GetStatusBar().SetStatusText('Calibration successful - Show ring picks to check')
1325                        print 'Calibration successful'
1326                    else:
1327                        self.dataFrame.GetStatusBar().SetStatusText('Calibration failed - Show ring picks to diagnose')
1328                        print 'Calibration failed'
1329                    self.ifGetRing = False
1330                    G2imG.UpdateImageControls(self,Data,Masks)
1331                    return
1332                PlotImage(self,newImage=False)
1333            return
1334        else:
1335            xpos = event.xdata
1336            if xpos:                                        #avoid out of frame mouse position
1337                ypos = event.ydata
1338                if self.ifGetRing:                          #delete a calibration ring pick
1339                    xypos = [xpos,ypos]
1340                    rings = Data['ring']
1341                    for ring in rings:
1342                        if np.allclose(ring,xypos,.01,0):
1343                            rings.remove(ring)                                                                       
1344                else:
1345                    tth,azm,dsp = G2img.GetTthAzmDsp(xpos,ypos,Data)
1346                    itemPicked = str(self.itemPicked)
1347                    if 'Line2D' in itemPicked and PickName == 'Image Controls':
1348                        if 'line1' in itemPicked:
1349                            Data['IOtth'][0] = max(tth,0.001)
1350                        elif 'line2' in itemPicked:
1351                            Data['IOtth'][1] = tth
1352                        elif 'line3' in itemPicked:
1353                            Data['LRazimuth'][0] = int(azm)
1354                            if Data['fullIntegrate']:
1355                                Data['LRazimuth'][1] = Data['LRazimuth'][0]+360
1356                        elif 'line4' in itemPicked and not Data['fullIntegrate']:
1357                            Data['LRazimuth'][1] = int(azm)
1358                           
1359                        if Data['LRazimuth'][0] > Data['LRazimuth'][1]:
1360                            Data['LRazimuth'][0] -= 360
1361                           
1362                        azLim = np.array(Data['LRazimuth'])   
1363                        if np.any(azLim>360):
1364                            azLim -= 360
1365                            Data['LRazimuth'] = list(azLim)
1366                           
1367                        if  Data['IOtth'][0] > Data['IOtth'][1]:
1368                            Data['IOtth'][0],Data['IOtth'][1] = Data['IOtth'][1],Data['IOtth'][0]
1369                           
1370                        self.InnerTth.SetValue("%8.2f" % (Data['IOtth'][0]))
1371                        self.OuterTth.SetValue("%8.2f" % (Data['IOtth'][1]))
1372                        self.Lazim.SetValue("%6d" % (Data['LRazimuth'][0]))
1373                        self.Razim.SetValue("%6d" % (Data['LRazimuth'][1]))
1374                    elif 'Circle' in itemPicked and PickName == 'Masks':
1375                        spots = Masks['Points']
1376                        newPos = itemPicked.split(')')[0].split('(')[2].split(',')
1377                        newPos = np.array([float(newPos[0]),float(newPos[1])])
1378                        for spot in spots:
1379                            if np.allclose(np.array([spot[:2]]),newPos):
1380                                spot[:2] = xpos,ypos
1381                        G2imG.UpdateMasks(self,Masks)
1382                    elif 'Line2D' in itemPicked and PickName == 'Masks':
1383                        Obj = self.itemPicked.findobj()
1384                        rings = Masks['Rings']
1385                        arcs = Masks['Arcs']
1386                        polygons = Masks['Polygons']
1387                        for ring in self.ringList:
1388                            if Obj == ring[0]:
1389                                rN = ring[1]
1390                                if ring[2] == 'o':
1391                                    rings[rN][0] = G2img.GetTth(xpos,ypos,Data)-rings[rN][1]/2.
1392                                else:
1393                                    rings[rN][0] = G2img.GetTth(xpos,ypos,Data)+rings[rN][1]/2.
1394                        for arc in self.arcList:
1395                            if Obj == arc[0]:
1396                                aN = arc[1]
1397                                if arc[2] == 'o':
1398                                    arcs[aN][0] = G2img.GetTth(xpos,ypos,Data)-arcs[aN][2]/2
1399                                elif arc[2] == 'i':
1400                                    arcs[aN][0] = G2img.GetTth(xpos,ypos,Data)+arcs[aN][2]/2
1401                                elif arc[2] == 'l':
1402                                    arcs[aN][1][0] = int(G2img.GetAzm(xpos,ypos,Data))
1403                                else:
1404                                    arcs[aN][1][1] = int(G2img.GetAzm(xpos,ypos,Data))
1405                        for poly in self.polyList:
1406                            if Obj == poly[0]:
1407                                ind = self.itemPicked.contains(self.mousePicked)[1]['ind'][0]
1408                                oldPos = np.array([self.mousePicked.xdata,self.mousePicked.ydata])
1409                                pN = poly[1]
1410                                for i,xy in enumerate(polygons[pN]):
1411                                    if np.allclose(np.array([xy]),oldPos,atol=1.0):
1412                                        polygons[pN][i] = xpos,ypos
1413                        G2imG.UpdateMasks(self,Masks)
1414#                    else:                  #keep for future debugging
1415#                        print str(self.itemPicked),event.xdata,event.ydata,event.button
1416                PlotImage(self,newImage=True)
1417            self.itemPicked = None
1418           
1419    try:
1420        plotNum = self.G2plotNB.plotList.index('2D Powder Image')
1421        Page = self.G2plotNB.nb.GetPage(plotNum)
1422        if not newPlot:
1423            Plot = Page.figure.gca()          #get previous powder plot & get limits
1424            xylim = Plot.get_xlim(),Plot.get_ylim()
1425        if newImage:
1426            Page.figure.clf()
1427            Plot = Page.figure.gca()          #get a fresh plot after clf()
1428       
1429    except ValueError:
1430        Plot = self.G2plotNB.addMpl('2D Powder Image').gca()
1431        plotNum = self.G2plotNB.plotList.index('2D Powder Image')
1432        Page = self.G2plotNB.nb.GetPage(plotNum)
1433        Page.canvas.mpl_connect('key_press_event', OnImPlotKeyPress)
1434        Page.canvas.mpl_connect('motion_notify_event', OnImMotion)
1435        Page.canvas.mpl_connect('pick_event', OnImPick)
1436        Page.canvas.mpl_connect('button_release_event', OnImRelease)
1437        xylim = []
1438    if not event:                       #event from GUI TextCtrl - don't want focus to change to plot!!!
1439        Page.SetFocus()
1440    Title = self.PatternTree.GetItemText(self.Image)[4:]
1441    self.G2plotNB.status.DestroyChildren()
1442    if self.logPlot:
1443        Title = 'log('+Title+')'
1444    Plot.set_title(Title)
1445    try:
1446        if self.PatternTree.GetItemText(self.PickId) in ['Image Controls',]:
1447            if self.logPlot:
1448                Choice = (' key press','l: log(I) off')
1449            else:
1450                Choice = (' key press','l: log(I) on')
1451            cb = wx.ComboBox(self.G2plotNB.status,style=wx.CB_DROPDOWN|wx.CB_READONLY,
1452                choices=Choice)
1453            cb.Bind(wx.EVT_COMBOBOX, OnKeyBox)
1454            cb.SetValue(' key press')
1455    except TypeError:
1456        pass
1457    size,imagefile = self.PatternTree.GetItemPyData(self.Image)
1458    if imagefile != self.oldImagefile:
1459        imagefile = G2IO.CheckImageFile(self,imagefile)
1460        if not imagefile:
1461            self.G2plotNB.Delete('2D Powder Image')
1462            return
1463        self.PatternTree.SetItemPyData(self.Image,[size,imagefile])
1464        self.ImageZ = G2IO.GetImageData(self,imagefile,imageOnly=True)
1465#        print self.ImageZ.shape,self.ImageZ.size,Data['size'] #might be useful debugging line
1466        self.oldImagefile = imagefile
1467
1468    imScale = 1
1469    if len(self.ImageZ) > 1024:
1470        imScale = len(self.ImageZ)/1024
1471    sizexy = Data['size']
1472    pixelSize = Data['pixelSize']
1473    scalex = 1000./pixelSize[0]
1474    scaley = 1000./pixelSize[1]
1475    Xmax = sizexy[0]*pixelSize[0]/1000.
1476    Ymax = sizexy[1]*pixelSize[1]/1000.
1477    xlim = (0,Xmax)
1478    ylim = (Ymax,0)
1479    Imin,Imax = Data['range'][1]
1480    acolor = mpl.cm.get_cmap(Data['color'])
1481    xcent,ycent = Data['center']
1482    Plot.set_xlabel('Image x-axis, mm',fontsize=12)
1483    Plot.set_ylabel('Image y-axis, mm',fontsize=12)
1484    #do threshold mask - "real" mask - others are just bondaries
1485    Zlim = Masks['Thresholds'][1]
1486    wx.BeginBusyCursor()
1487    try:
1488           
1489        if newImage:                   
1490            MA = ma.masked_greater(ma.masked_less(self.ImageZ,Zlim[0]),Zlim[1])
1491            MaskA = ma.getmaskarray(MA)
1492            A = G2img.ImageCompress(MA,imScale)
1493            AM = G2img.ImageCompress(MaskA,imScale)
1494            if self.logPlot:
1495                A = np.log(A)
1496                AM = np.log(AM)
1497                Imin,Imax = [np.amin(A),np.amax(A)]
1498            ImgM = Plot.imshow(AM,aspect='equal',cmap='Reds',
1499                interpolation='nearest',vmin=0,vmax=2,extent=[0,Xmax,Xmax,0])
1500            Img = Plot.imshow(A,aspect='equal',cmap=acolor,
1501                interpolation='nearest',vmin=Imin,vmax=Imax,extent=[0,Xmax,Ymax,0])
1502            if self.setPoly:
1503                Img.set_picker(True)
1504   
1505        Plot.plot(xcent,ycent,'x')
1506        if Data['showLines']:
1507            LRAzim = Data['LRazimuth']                  #NB: integers
1508            Nazm = Data['outAzimuths']
1509            delAzm = float(LRAzim[1]-LRAzim[0])/Nazm
1510            AzmthOff = Data['azmthOff']
1511            IOtth = Data['IOtth']
1512            wave = Data['wavelength']
1513            dspI = wave/(2.0*sind(IOtth[0]/2.0))
1514            ellI = G2img.GetEllipse(dspI,Data)           #=False if dsp didn't yield an ellipse (ugh! a parabola or a hyperbola)
1515            dspO = wave/(2.0*sind(IOtth[1]/2.0))
1516            ellO = G2img.GetEllipse(dspO,Data)           #Ditto & more likely for outer ellipse
1517            Azm = np.array(range(LRAzim[0],LRAzim[1]+1))-AzmthOff
1518            if ellI:
1519                xyI = []
1520                for azm in Azm:
1521                    xyI.append(G2img.GetDetectorXY(dspI,azm-90.,Data))
1522                xyI = np.array(xyI)
1523                arcxI,arcyI = xyI.T
1524                Plot.plot(arcxI,arcyI,picker=3)
1525            if ellO:
1526                xyO = []
1527                for azm in Azm:
1528                    xyO.append(G2img.GetDetectorXY(dspO,azm-90.,Data))
1529                xyO = np.array(xyO)
1530                arcxO,arcyO = xyO.T
1531                Plot.plot(arcxO,arcyO,picker=3)
1532            if ellO and ellI:
1533                Plot.plot([arcxI[0],arcxO[0]],[arcyI[0],arcyO[0]],picker=3)
1534                Plot.plot([arcxI[-1],arcxO[-1]],[arcyI[-1],arcyO[-1]],picker=3)
1535            for i in range(Nazm):
1536                cake = LRAzim[0]+i*delAzm
1537                ind = np.searchsorted(Azm,cake)
1538                Plot.plot([arcxI[ind],arcxO[ind]],[arcyI[ind],arcyO[ind]],color='k',dashes=(5,5))
1539                   
1540        for xring,yring in Data['ring']:
1541            Plot.plot(xring,yring,'r+',picker=3)
1542        if Data['setRings']:
1543#            rings = np.concatenate((Data['rings']),axis=0)
1544            N = 0
1545            for ring in Data['rings']:
1546                xring,yring = np.array(ring).T[:2]
1547                Plot.plot(xring,yring,'+',color=colors[N%6])
1548                N += 1           
1549        for ellipse in Data['ellipses']:
1550            cent,phi,[width,height],col = ellipse
1551            Plot.add_artist(Ellipse([cent[0],cent[1]],2*width,2*height,phi,ec=col,fc='none'))
1552            Plot.text(cent[0],cent[1],'+',color=col,ha='center',va='center')
1553        #masks - mask lines numbered after integration limit lines
1554        spots = Masks['Points']
1555        rings = Masks['Rings']
1556        arcs = Masks['Arcs']
1557        polygons = Masks['Polygons']
1558        for x,y,d in spots:
1559            Plot.add_artist(Circle((x,y),radius=d/2,fc='none',ec='r',picker=3))
1560        self.ringList = []
1561        for iring,(tth,thick) in enumerate(rings):
1562            wave = Data['wavelength']
1563            x1,y1 = np.hsplit(np.array(G2img.makeIdealRing(G2img.GetEllipse(Dsp(tth+thick/2.,wave),Data))),2)
1564            x2,y2 = np.hsplit(np.array(G2img.makeIdealRing(G2img.GetEllipse(Dsp(tth-thick/2.,wave),Data))),2)
1565            self.ringList.append([Plot.plot(x1,y1,'r',picker=3),iring,'o'])           
1566            self.ringList.append([Plot.plot(x2,y2,'r',picker=3),iring,'i'])
1567        self.arcList = []
1568        for iarc,(tth,azm,thick) in enumerate(arcs):           
1569            wave = Data['wavelength']
1570            x1,y1 = np.hsplit(np.array(G2img.makeIdealRing(G2img.GetEllipse(Dsp(tth+thick/2.,wave),Data),azm)),2)
1571            x2,y2 = np.hsplit(np.array(G2img.makeIdealRing(G2img.GetEllipse(Dsp(max(0.01,tth-thick/2.),wave),Data),azm)),2)
1572            self.arcList.append([Plot.plot(x1,y1,'r',picker=3),iarc,'o'])           
1573            self.arcList.append([Plot.plot(x2,y2,'r',picker=3),iarc,'i'])
1574            self.arcList.append([Plot.plot([x1[0],x2[0]],[y1[0],y2[0]],'r',picker=3),iarc,'l'])
1575            self.arcList.append([Plot.plot([x1[-1],x2[-1]],[y1[-1],y2[-1]],'r',picker=3),iarc,'u'])
1576        self.polyList = []
1577        for ipoly,polygon in enumerate(polygons):
1578            x,y = np.hsplit(np.array(polygon),2)
1579            self.polyList.append([Plot.plot(x,y,'r+',picker=10),ipoly])
1580            Plot.plot(x,y,'r')           
1581        if newImage:
1582            colorBar = Page.figure.colorbar(Img)
1583        Plot.set_xlim(xlim)
1584        Plot.set_ylim(ylim)
1585        if not newPlot and xylim:
1586            Page.toolbar.push_current()
1587            Plot.set_xlim(xylim[0])
1588            Plot.set_ylim(xylim[1])
1589            xylim = []
1590            Page.toolbar.push_current()
1591            Page.toolbar.draw()
1592        else:
1593            Page.canvas.draw()
1594    finally:
1595        wx.EndBusyCursor()
1596       
1597def PlotIntegration(self,newPlot=False,event=None):
1598           
1599    def OnMotion(event):
1600        Page.canvas.SetToolTipString('')
1601        Page.canvas.SetCursor(wx.CROSS_CURSOR)
1602        azm = event.ydata
1603        tth = event.xdata
1604        if azm and tth:
1605            self.G2plotNB.status.SetFields(\
1606                ['','Detector 2-th =%9.3fdeg, azm = %7.2fdeg'%(tth,azm)])
1607                               
1608    try:
1609        plotNum = self.G2plotNB.plotList.index('2D Integration')
1610        Page = self.G2plotNB.nb.GetPage(plotNum)
1611        if not newPlot:
1612            Plot = Page.figure.gca()          #get previous plot & get limits
1613            xylim = Plot.get_xlim(),Plot.get_ylim()
1614        Page.figure.clf()
1615        Plot = Page.figure.gca()          #get a fresh plot after clf()
1616       
1617    except ValueError:
1618        Plot = self.G2plotNB.addMpl('2D Integration').gca()
1619        plotNum = self.G2plotNB.plotList.index('2D Integration')
1620        Page = self.G2plotNB.nb.GetPage(plotNum)
1621        Page.canvas.mpl_connect('motion_notify_event', OnMotion)
1622        Page.views = False
1623        view = False
1624    if not event:
1625        Page.SetFocus()
1626       
1627    Data = self.PatternTree.GetItemPyData(
1628        G2gd.GetPatternTreeItemId(self,self.Image, 'Image Controls'))
1629    image = self.Integrate[0]
1630    xsc = self.Integrate[1]
1631    ysc = self.Integrate[2]
1632    Imin,Imax = Data['range'][1]
1633    acolor = mpl.cm.get_cmap(Data['color'])
1634    Plot.set_title(self.PatternTree.GetItemText(self.Image)[4:])
1635    Plot.set_ylabel('azimuth',fontsize=12)
1636    Plot.set_xlabel('2-theta',fontsize=12)
1637    Img = Plot.imshow(image,cmap=acolor,vmin=Imin,vmax=Imax,interpolation='nearest', \
1638        extent=[ysc[0],ysc[-1],xsc[-1],xsc[0]],aspect='auto')
1639    colorBar = Page.figure.colorbar(Img)
1640    if Data['setRings'] and Data['rings']:
1641        rings = np.concatenate((Data['rings']),axis=0)
1642        for xring,yring,dsp in rings:
1643            x,y = G2img.GetTthAzm(xring,yring,Data)
1644            Plot.plot(x,y,'r+')
1645    if Data['ellipses']:           
1646        for ellipse in Data['ellipses']:
1647            ring = np.array(G2img.makeIdealRing(ellipse[:3])) #skip color
1648            x,y = np.hsplit(ring,2)
1649            tth,azm = G2img.GetTthAzm(x,y,Data)
1650            azm = np.where(azm < 0.,azm+360,azm)
1651            Plot.plot(tth,azm,'b,')
1652    if not newPlot:
1653        Page.toolbar.push_current()
1654        Plot.set_xlim(xylim[0])
1655        Plot.set_ylim(xylim[1])
1656        xylim = []
1657        Page.toolbar.push_current()
1658        Page.toolbar.draw()
1659    else:
1660        Page.canvas.draw()
1661               
1662def PlotTRImage(self,tax,tay,taz,newPlot=False):
1663    #a test plot routine - not normally used
1664           
1665    def OnMotion(event):
1666        Page.canvas.SetToolTipString('')
1667        Page.canvas.SetCursor(wx.CROSS_CURSOR)
1668        azm = event.xdata
1669        tth = event.ydata
1670        if azm and tth:
1671            self.G2plotNB.status.SetFields(\
1672                ['','Detector 2-th =%9.3fdeg, azm = %7.2fdeg'%(tth,azm)])
1673                               
1674    try:
1675        plotNum = self.G2plotNB.plotList.index('2D Transformed Powder Image')
1676        Page = self.G2plotNB.nb.GetPage(plotNum)
1677        if not newPlot:
1678            Plot = Page.figure.gca()          #get previous plot & get limits
1679            xylim = Plot.get_xlim(),Plot.get_ylim()
1680        Page.figure.clf()
1681        Plot = Page.figure.gca()          #get a fresh plot after clf()
1682       
1683    except ValueError:
1684        Plot = self.G2plotNB.addMpl('2D Transformed Powder Image').gca()
1685        plotNum = self.G2plotNB.plotList.index('2D Transformed Powder Image')
1686        Page = self.G2plotNB.nb.GetPage(plotNum)
1687        Page.canvas.mpl_connect('motion_notify_event', OnMotion)
1688        Page.views = False
1689        view = False
1690    Page.SetFocus()
1691       
1692    Data = self.PatternTree.GetItemPyData(
1693        G2gd.GetPatternTreeItemId(self,self.Image, 'Image Controls'))
1694    Imin,Imax = Data['range'][1]
1695    step = (Imax-Imin)/5.
1696    V = np.arange(Imin,Imax,step)
1697    acolor = mpl.cm.get_cmap(Data['color'])
1698    Plot.set_title(self.PatternTree.GetItemText(self.Image)[4:])
1699    Plot.set_xlabel('azimuth',fontsize=12)
1700    Plot.set_ylabel('2-theta',fontsize=12)
1701    Plot.contour(tax,tay,taz,V,cmap=acolor)
1702    if Data['showLines']:
1703        IOtth = Data['IOtth']
1704        if Data['fullIntegrate']:
1705            LRAzim = [-180,180]
1706        else:
1707            LRAzim = Data['LRazimuth']                  #NB: integers
1708        Plot.plot([LRAzim[0],LRAzim[1]],[IOtth[0],IOtth[0]],picker=True)
1709        Plot.plot([LRAzim[0],LRAzim[1]],[IOtth[1],IOtth[1]],picker=True)
1710        if not Data['fullIntegrate']:
1711            Plot.plot([LRAzim[0],LRAzim[0]],[IOtth[0],IOtth[1]],picker=True)
1712            Plot.plot([LRAzim[1],LRAzim[1]],[IOtth[0],IOtth[1]],picker=True)
1713    if Data['setRings']:
1714        rings = np.concatenate((Data['rings']),axis=0)
1715        for xring,yring,dsp in rings:
1716            x,y = G2img.GetTthAzm(xring,yring,Data)
1717            Plot.plot(y,x,'r+')           
1718    if Data['ellipses']:           
1719        for ellipse in Data['ellipses']:
1720            ring = np.array(G2img.makeIdealRing(ellipse[:3])) #skip color
1721            x,y = np.hsplit(ring,2)
1722            tth,azm = G2img.GetTthAzm(x,y,Data)
1723            Plot.plot(azm,tth,'b,')
1724    if not newPlot:
1725        Page.toolbar.push_current()
1726        Plot.set_xlim(xylim[0])
1727        Plot.set_ylim(xylim[1])
1728        xylim = []
1729        Page.toolbar.push_current()
1730        Page.toolbar.draw()
1731    else:
1732        Page.canvas.draw()
1733       
1734def PlotStructure(self,data):
1735    generalData = data['General']
1736    cell = generalData['Cell'][1:7]
1737    Amat,Bmat = G2lat.cell2AB(cell)         #Amat - crystal to cartesian, Bmat - inverse
1738    A4mat = np.concatenate((np.concatenate((Amat,[[0],[0],[0]]),axis=1),[[0,0,0,1],]),axis=0)
1739    B4mat = np.concatenate((np.concatenate((Bmat,[[0],[0],[0]]),axis=1),[[0,0,0,1],]),axis=0)
1740    Mydir = generalData['Mydir']
1741    atomData = data['Atoms']
1742    drawingData = data['Drawing']
1743    drawAtoms = drawingData['Atoms']
1744    cx,ct,cs = drawingData['atomPtrs']
1745    Wt = [255,255,255]
1746    Rd = [255,0,0]
1747    Gr = [0,255,0]
1748    Bl = [0,0,255]
1749    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]])
1750    uEdges = np.array([
1751        [uBox[0],uBox[1]],[uBox[0],uBox[3]],[uBox[0],uBox[4]],[uBox[1],uBox[2]], 
1752        [uBox[2],uBox[3]],[uBox[1],uBox[5]],[uBox[2],uBox[6]],[uBox[3],uBox[7]], 
1753        [uBox[4],uBox[5]],[uBox[5],uBox[6]],[uBox[6],uBox[7]],[uBox[7],uBox[4]]])
1754    uColors = [Rd,Gr,Bl,Wt, Wt,Wt,Wt,Wt, Wt,Wt,Wt,Wt]
1755    altDown = False
1756    shiftDown = False
1757    ctrlDown = False
1758   
1759    def OnKeyBox(event):
1760        import Image
1761        Draw()                          #make sure plot is fresh!!
1762        mode = cb.GetValue()
1763        Fname = Mydir+'\\'+generalData['Name']+'.'+mode
1764        size = Page.canvas.GetSize()
1765        glPixelStorei(GL_UNPACK_ALIGNMENT, 1)
1766        if mode in ['jpeg',]:
1767            Pix = glReadPixels(0,0,size[0],size[1],GL_RGBA, GL_UNSIGNED_BYTE)
1768            im = Image.new("RGBA", (size[0],size[1]))
1769        else:
1770            Pix = glReadPixels(0,0,size[0],size[1],GL_RGB, GL_UNSIGNED_BYTE)
1771            im = Image.new("RGB", (size[0],size[1]))
1772        im.fromstring(Pix)
1773        im.save(Fname,mode)
1774        cb.SetValue(' Save as:')
1775        self.G2plotNB.status.SetStatusText('Drawing saved to: '+Fname,1)
1776   
1777    def GetTruePosition(xy):
1778        View = glGetIntegerv(GL_VIEWPORT)
1779        Proj = glGetDoublev(GL_PROJECTION_MATRIX)
1780        Model = glGetDoublev(GL_MODELVIEW_MATRIX)
1781        Zmax = 1.
1782        for i,atom in enumerate(drawAtoms):
1783            x,y,z = atom[cx:cx+3]
1784            X,Y,Z = gluProject(x,y,z,Model,Proj,View)
1785            XY = [int(X),int(View[3]-Y)]
1786            if np.allclose(xy,XY,atol=10) and Z < Zmax:
1787                Zmax = Z
1788                SetSelectedAtoms(i)
1789                   
1790    def OnMouseDown(event):
1791        xy = event.GetPosition()
1792        if event.ShiftDown():
1793            GetTruePosition(xy)
1794        else:
1795            drawingData['Rotation'][3] = xy
1796        Draw()
1797       
1798    def OnMouseMove(event):
1799        newxy = event.GetPosition()
1800        page = getSelection()
1801        if event.ControlDown() and drawingData['showABC']:
1802            if event.LeftIsDown():
1803                SetTestRot(newxy)
1804            elif event.RightIsDown():
1805                SetTestPos(newxy)
1806            elif event.MiddleIsDown():
1807                SetTestRotZ(newxy)
1808            x,y,z = drawingData['testPos'][0]
1809            self.G2plotNB.status.SetStatusText('moving test point %.4f,%.4f,%.4f'%(x,y,z),1)
1810               
1811               
1812        if event.Dragging() and not event.ControlDown():
1813            if event.LeftIsDown():
1814                SetRotation(newxy)
1815                angX,angY,angZ = drawingData['Rotation'][:3]
1816                self.G2plotNB.status.SetStatusText('New rotation: %.2f, %.2f ,%.2f'%(angX,angY,angZ),1)
1817            elif event.RightIsDown():
1818                SetTranslation(newxy)
1819                Tx,Ty,Tz = drawingData['viewPoint'][0]
1820                self.G2plotNB.status.SetStatusText('New view point: %.4f, %.4f, %.4f'%(Tx,Ty,Tz),1)
1821            elif event.MiddleIsDown():
1822                SetRotationZ(newxy)
1823                angX,angY,angZ = drawingData['Rotation'][:3]
1824                self.G2plotNB.status.SetStatusText('New rotation: %.2f, %.2f, %.2f'%(angX,angY,angZ),1)
1825        Draw()
1826       
1827    def OnMouseWheel(event):
1828        drawingData['cameraPos'] += event.GetWheelRotation()/24
1829        drawingData['cameraPos'] = max(10,min(500,drawingData['cameraPos']))
1830        self.G2plotNB.status.SetStatusText('New camera distance: %.2f'%(drawingData['cameraPos']),1)
1831        page = getSelection()
1832        if page:
1833            if self.dataDisplay.GetPageText(page) == 'Draw Options':
1834                panel = self.dataDisplay.GetPage(page).GetChildren()[0].GetChildren()
1835                names = [child.GetName() for child in panel]
1836                panel[names.index('cameraPos')].SetLabel('Camera Position: '+'%.2f'%(drawingData['cameraPos']))
1837                panel[names.index('cameraSlider')].SetValue(drawingData['cameraPos'])
1838        Draw()
1839       
1840    def getSelection():
1841        try:
1842            return self.dataDisplay.GetSelection()
1843        except AttributeError:
1844            print self.dataDisplay.GetLabel()
1845            self.G2plotNB.status.SetStatusText('Select this from Phase data window!')
1846            return 0
1847           
1848    def SetViewPointText(VP):
1849        page = getSelection()
1850        if page:
1851            if self.dataDisplay.GetPageText(page) == 'Draw Options':
1852                panel = self.dataDisplay.GetPage(page).GetChildren()[0].GetChildren()
1853                names = [child.GetName() for child in panel]
1854                panel[names.index('viewPoint')].SetValue('%.3f, %.3f, %.3f'%(VP[0],VP[1],VP[2]))
1855           
1856    def ClearSelectedAtoms():
1857        page = getSelection()
1858        if page:
1859            if self.dataDisplay.GetPageText(page) == 'Draw Atoms':
1860                self.dataDisplay.GetPage(page).ClearSelection()      #this is the Atoms grid in Draw Atoms
1861            elif self.dataDisplay.GetPageText(page) == 'Atoms':
1862                self.dataDisplay.GetPage(page).ClearSelection()      #this is the Atoms grid in Atoms
1863                   
1864    def SetSelectedAtoms(ind):
1865        page = getSelection()
1866        if page:
1867            if self.dataDisplay.GetPageText(page) == 'Draw Atoms':
1868                self.dataDisplay.GetPage(page).SelectRow(ind)      #this is the Atoms grid in Draw Atoms
1869            elif self.dataDisplay.GetPageText(page) == 'Atoms':
1870                Id = drawAtoms[ind][-2]
1871                for i,atom in enumerate(atomData):
1872                    if atom[-1] == Id:
1873                        self.dataDisplay.GetPage(page).SelectRow(i)      #this is the Atoms grid in Atoms
1874                 
1875    def GetSelectedAtoms():
1876        page = getSelection()
1877        Ind = []
1878        if page:
1879            if self.dataDisplay.GetPageText(page) == 'Draw Atoms':
1880                Ind = self.dataDisplay.GetPage(page).GetSelectedRows()      #this is the Atoms grid in Draw Atoms
1881            elif self.dataDisplay.GetPageText(page) == 'Atoms':
1882                Ind = self.dataDisplay.GetPage(page).GetSelectedRows()      #this is the Atoms grid in Atoms
1883        return Ind
1884                                       
1885    def OnKey(event):           #on key UP!!
1886        keyCode = event.GetKeyCode()
1887        if keyCode > 255:
1888            keyCode = 0
1889        key,xyz = chr(keyCode),event.GetPosition()
1890        indx = drawingData['selectedAtoms']
1891        if key in ['c','C']:
1892            drawingData['viewPoint'] = [[.5,.5,.5],[0,0]]
1893            drawingData['testPos'] = [[-.1,-.1,-.1],[0.0,0.0,0.0],[0,0]]
1894            drawingData['Rotation'] = [0.0,0.0,0.0,[]]
1895            SetViewPointText(drawingData['viewPoint'][0])
1896        elif key in ['n','N']:
1897            drawAtoms = drawingData['Atoms']
1898            pI = drawingData['viewPoint'][1]
1899            if indx:
1900                pI[0] = indx[pI[1]]
1901                Tx,Ty,Tz = drawAtoms[pI[0]][cx:cx+3]
1902                pI[1] += 1
1903                if pI[1] >= len(indx):
1904                    pI[1] = 0
1905            else:
1906                Tx,Ty,Tz = drawAtoms[pI[0]][cx:cx+3]               
1907                pI[0] += 1
1908                if pI[0] >= len(drawAtoms):
1909                    pI[0] = 0
1910            drawingData['viewPoint'] = [[Tx,Ty,Tz],pI]
1911            SetViewPointText(drawingData['viewPoint'][0])
1912               
1913        elif key in ['p','P']:
1914            drawAtoms = drawingData['Atoms']
1915            pI = drawingData['viewPoint'][1]
1916            if indx:
1917                pI[0] = indx[pI[1]]
1918                Tx,Ty,Tz = drawAtoms[pI[0]][cx:cx+3]
1919                pI[1] -= 1
1920                if pI[1] < 0:
1921                    pI[1] = len(indx)-1
1922            else:
1923                Tx,Ty,Tz = drawAtoms[pI[0]][cx:cx+3]               
1924                pI[0] -= 1
1925                if pI[0] < 0:
1926                    pI[0] = len(drawAtoms)-1
1927            drawingData['viewPoint'] = [[Tx,Ty,Tz],pI]
1928            SetViewPointText(drawingData['viewPoint'][0])           
1929        Draw()
1930           
1931    def SetBackground():
1932        R,G,B,A = Page.camera['backColor']
1933        glClearColor(R,G,B,A)
1934        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
1935       
1936    def SetLights():
1937        glEnable(GL_DEPTH_TEST)
1938        glShadeModel(GL_SMOOTH)
1939        glEnable(GL_LIGHTING)
1940        glEnable(GL_LIGHT0)
1941        glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,0)
1942        glLightfv(GL_LIGHT0,GL_AMBIENT,[1,1,1,.8])
1943        glLightfv(GL_LIGHT0,GL_DIFFUSE,[1,1,1,1])
1944       
1945    def SetTranslation(newxy):
1946        Tx,Ty,Tz = drawingData['viewPoint'][0]
1947        anglex,angley,anglez,oldxy = drawingData['Rotation']
1948        Rx = G2lat.rotdMat(anglex,0)
1949        Ry = G2lat.rotdMat(angley,1)
1950        Rz = G2lat.rotdMat(anglez,2)
1951        dxy = list(newxy-oldxy)+[0,]
1952        dxy = np.inner(Bmat,np.inner(Rz,np.inner(Ry,np.inner(Rx,dxy))))
1953        Tx -= dxy[0]*0.01
1954        Ty += dxy[1]*0.01
1955        Tz -= dxy[2]*0.01
1956        drawingData['Rotation'][3] = newxy
1957        drawingData['viewPoint'][0] =  Tx,Ty,Tz
1958        SetViewPointText([Tx,Ty,Tz])
1959       
1960    def SetTestPos(newxy):
1961        Tx,Ty,Tz = drawingData['testPos'][0]
1962        anglex,angley,anglez,oldxy = drawingData['Rotation']
1963        Rx = G2lat.rotdMat(anglex,0)
1964        Ry = G2lat.rotdMat(angley,1)
1965        Rz = G2lat.rotdMat(anglez,2)
1966        dxy = list(newxy-oldxy)+[0,]
1967        dxy = np.inner(Rz,np.inner(Ry,np.inner(Rx,dxy)))
1968        Tx += dxy[0]*0.001
1969        Ty -= dxy[1]*0.001
1970        Tz += dxy[2]*0.001
1971        drawingData['Rotation'][3] = newxy
1972        drawingData['testPos'][0] =  Tx,Ty,Tz
1973       
1974    def SetTestRot(newxy):
1975        Txyz = np.array(drawingData['testPos'][0])
1976        oldxy = drawingData['testPos'][2]
1977        Ax,Ay,Az = drawingData['testPos'][1]
1978        Vxyz = np.array(drawingData['viewPoint'][0])
1979        Dxyz = np.inner(Amat,Txyz-Vxyz)
1980        dxy = list(newxy-oldxy)+[0,]
1981        Ax += dxy[1]*0.01
1982        Ay += dxy[0]*0.01
1983        Rx = G2lat.rotdMat(Ax,0)
1984        Ry = G2lat.rotdMat(Ay,1)
1985        Dxyz = np.inner(Ry,np.inner(Rx,Dxyz))       
1986        Dxyz = np.inner(Bmat,Dxyz)+Vxyz
1987        drawingData['testPos'][1] = [Ax,Ay,Az]
1988        drawingData['testPos'][2] = newxy
1989        drawingData['testPos'][0] = Dxyz
1990       
1991    def SetTestRotZ(newxy):
1992        Txyz = np.array(drawingData['testPos'][0])
1993        oldxy = drawingData['testPos'][2]
1994        Ax,Ay,Az = drawingData['testPos'][1]
1995        Vxyz = np.array(drawingData['viewPoint'][0])
1996        Dxyz = np.inner(Amat,Txyz-Vxyz)       
1997        dxy = list(newxy-oldxy)+[0,]
1998        Az += (dxy[0]+dxy[1])*.01
1999        Rz = G2lat.rotdMat(Az,2)
2000        Dxyz = np.inner(Rz,Dxyz)       
2001        Dxyz = np.inner(Bmat,Dxyz)+Vxyz
2002        drawingData['testPos'][1] = [Ax,Ay,Az]
2003        drawingData['testPos'][2] = newxy
2004        drawingData['testPos'][0] = Dxyz
2005                             
2006    def SetRotation(newxy):       
2007        anglex,angley,anglez,oldxy = drawingData['Rotation']
2008        dxy = newxy-oldxy
2009        anglex += dxy[1]*.25
2010        angley += dxy[0]*.25
2011        oldxy = newxy
2012        drawingData['Rotation'] = [anglex,angley,anglez,oldxy]
2013       
2014    def SetRotationZ(newxy):                       
2015        anglex,angley,anglez,oldxy = drawingData['Rotation']
2016        dxy = newxy-oldxy
2017        anglez += (dxy[0]+dxy[1])*.25
2018        oldxy = newxy
2019        drawingData['Rotation'] = [anglex,angley,anglez,oldxy]
2020       
2021    def RenderBox():
2022        glEnable(GL_COLOR_MATERIAL)
2023        glLineWidth(2)
2024        glEnable(GL_BLEND)
2025        glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA)
2026        glEnable(GL_LINE_SMOOTH)
2027        glBegin(GL_LINES)
2028        for line,color in zip(uEdges,uColors):
2029            glColor3ubv(color)
2030            glVertex3fv(line[0])
2031            glVertex3fv(line[1])
2032        glEnd()
2033        glColor4ubv([0,0,0,0])
2034        glDisable(GL_LINE_SMOOTH)
2035        glDisable(GL_BLEND)
2036        glDisable(GL_COLOR_MATERIAL)
2037       
2038    def RenderUnitVectors(x,y,z):
2039        xyz = np.array([x,y,z])
2040        glEnable(GL_COLOR_MATERIAL)
2041        glLineWidth(1)
2042        glPushMatrix()
2043        glTranslate(x,y,z)
2044        glScalef(1/cell[0],1/cell[1],1/cell[2])
2045        glBegin(GL_LINES)
2046        for line,color in zip(uEdges,uColors)[:3]:
2047            glColor3ubv(color)
2048            glVertex3fv(line[0])
2049            glVertex3fv(line[1])
2050        glEnd()
2051        glPopMatrix()
2052        glColor4ubv([0,0,0,0])
2053        glDisable(GL_COLOR_MATERIAL)
2054               
2055    def RenderSphere(x,y,z,radius,color):
2056        glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,color)
2057        glPushMatrix()
2058        glTranslate(x,y,z)
2059        glMultMatrixf(B4mat.T)
2060        q = gluNewQuadric()
2061        gluSphere(q,radius,20,10)
2062        glPopMatrix()
2063       
2064    def RenderEllipsoid(x,y,z,ellipseProb,E,R4,color):
2065        s1,s2,s3 = E
2066        glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,color)
2067        glPushMatrix()
2068        glTranslate(x,y,z)
2069        glMultMatrixf(B4mat.T)
2070        glMultMatrixf(R4.T)
2071        glEnable(GL_NORMALIZE)
2072        glScale(s1,s2,s3)
2073        q = gluNewQuadric()
2074        gluSphere(q,ellipseProb,20,10)
2075        glDisable(GL_NORMALIZE)
2076        glPopMatrix()
2077       
2078    def RenderBonds(x,y,z,Bonds,radius,color,slice=20):
2079        glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,color)
2080        glPushMatrix()
2081        glTranslate(x,y,z)
2082        glMultMatrixf(B4mat.T)
2083        for bond in Bonds:
2084            glPushMatrix()
2085            Dx = np.inner(Amat,bond)
2086            Z = np.sqrt(np.sum(Dx**2))
2087            azm = atan2d(-Dx[1],-Dx[0])
2088            phi = acosd(Dx[2]/Z)
2089            glRotate(-azm,0,0,1)
2090            glRotate(phi,1,0,0)
2091            q = gluNewQuadric()
2092            gluCylinder(q,radius,radius,Z,slice,2)
2093            glPopMatrix()           
2094        glPopMatrix()
2095               
2096    def RenderLines(x,y,z,Bonds,color):
2097        xyz = np.array([x,y,z])
2098        glEnable(GL_COLOR_MATERIAL)
2099        glLineWidth(1)
2100        glColor3fv(color)
2101        glPushMatrix()
2102        glBegin(GL_LINES)
2103        for bond in Bonds:
2104            glVertex3fv(xyz)
2105            glVertex3fv(xyz+bond)
2106        glEnd()
2107        glColor4ubv([0,0,0,0])
2108        glPopMatrix()
2109        glDisable(GL_COLOR_MATERIAL)
2110       
2111    def RenderPolyhedra(x,y,z,Faces,color):
2112        glPushMatrix()
2113        glTranslate(x,y,z)
2114        glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,color)
2115        glShadeModel(GL_SMOOTH)
2116        glMultMatrixf(B4mat.T)
2117        for face,norm in Faces:
2118            glPolygonMode(GL_FRONT_AND_BACK,GL_FILL)
2119            glFrontFace(GL_CW)
2120            glNormal3fv(norm)
2121            glBegin(GL_TRIANGLES)
2122            for vert in face:
2123                glVertex3fv(vert)
2124            glEnd()
2125        glPopMatrix()
2126       
2127    def RenderBackbone(Backbone,BackboneColor,radius):
2128        glPushMatrix()
2129        glMultMatrixf(B4mat.T)
2130        glEnable(GL_COLOR_MATERIAL)
2131        glShadeModel(GL_SMOOTH)
2132        gleSetJoinStyle(TUBE_NORM_EDGE | TUBE_JN_ANGLE | TUBE_JN_CAP)
2133        glePolyCylinder(Backbone,BackboneColor,radius)
2134        glPopMatrix()       
2135        glDisable(GL_COLOR_MATERIAL)
2136       
2137    def RenderLabel(x,y,z,label,r):       
2138        glPushMatrix()
2139        glTranslate(x,y,z)
2140        glMultMatrixf(B4mat.T)
2141        glDisable(GL_LIGHTING)
2142        glColor3f(0,1.,0)
2143        glRasterPos3f(r,r,r)
2144        for c in list(label):
2145            glutBitmapCharacter(GLUT_BITMAP_8_BY_13,ord(c))
2146        glEnable(GL_LIGHTING)
2147        glPopMatrix()
2148                           
2149    def Draw():
2150        import numpy.linalg as nl
2151        Ind = GetSelectedAtoms()
2152        VS = np.array(Page.canvas.GetSize())
2153        aspect = float(VS[0])/float(VS[1])
2154        cPos = drawingData['cameraPos']
2155        Zclip = drawingData['Zclip']*cPos/200.
2156        anglex,angley,anglez = drawingData['Rotation'][:3]
2157        Tx,Ty,Tz = drawingData['viewPoint'][0]
2158        cx,ct,cs = drawingData['atomPtrs']
2159        bondR = drawingData['bondRadius']
2160        G,g = G2lat.cell2Gmat(cell)
2161        GS = G
2162        GS[0][1] = GS[1][0] = math.sqrt(GS[0][0]*GS[1][1])
2163        GS[0][2] = GS[2][0] = math.sqrt(GS[0][0]*GS[2][2])
2164        GS[1][2] = GS[2][1] = math.sqrt(GS[1][1]*GS[2][2])
2165        ellipseProb = G2lat.criticalEllipse(drawingData['ellipseProb']/100.)
2166       
2167        SetBackground()
2168        glInitNames()
2169        glPushName(0)
2170       
2171        glMatrixMode(GL_PROJECTION)
2172        glLoadIdentity()
2173        glViewport(0,0,VS[0],VS[1])
2174        gluPerspective(20.,aspect,cPos-Zclip,cPos+Zclip)
2175        gluLookAt(0,0,cPos,0,0,0,0,1,0)
2176        SetLights()           
2177           
2178        glMatrixMode(GL_MODELVIEW)
2179        glLoadIdentity()
2180        glRotate(anglez,0,0,1)
2181        glRotate(anglex,cosd(anglez),-sind(anglez),0)
2182        glRotate(angley,sind(anglez),cosd(anglez),0)
2183        glMultMatrixf(A4mat.T)
2184        glTranslate(-Tx,-Ty,-Tz)
2185        if drawingData['unitCellBox']:
2186            RenderBox()
2187        if drawingData['showABC']:
2188            x,y,z = drawingData['testPos'][0]
2189#            if altDown:
2190#                self.G2plotNB.status.SetStatusText('moving test point %.4f,%.4f,%.4f'%(x,y,z),1)
2191#            else:
2192#                self.G2plotNB.status.SetStatusText('test point %.4f,%.4f,%.4f'%(x,y,z),1)           
2193            RenderUnitVectors(x,y,z)
2194        Backbone = []
2195        BackboneColor = []
2196        time0 = time.time()
2197        for iat,atom in enumerate(drawingData['Atoms']):
2198            x,y,z = atom[cx:cx+3]
2199            Bonds = atom[-2]
2200            Faces = atom[-1]
2201            try:
2202                atNum = generalData['AtomTypes'].index(atom[ct])
2203            except ValueError:
2204                atNum = -1
2205            CL = atom[cs+2]
2206            color = np.array(CL)/255.
2207            if iat in Ind:
2208                color = np.array(Gr)/255.
2209            radius = 0.5
2210            if atom[cs] != '':
2211                glLoadName(atom[-3])                   
2212            if 'balls' in atom[cs]:
2213                vdwScale = drawingData['vdwScale']
2214                ballScale = drawingData['ballScale']
2215                if atNum < 0:
2216                    radius = 0.2
2217                elif 'H' == atom[ct]:
2218                    if drawingData['showHydrogen']:
2219                        if 'vdW' in atom[cs] and atNum >= 0:
2220                            radius = vdwScale*generalData['vdWRadii'][atNum]
2221                        else:
2222                            radius = ballScale*drawingData['sizeH']
2223                    else:
2224                        radius = 0.0
2225                else:
2226                    if 'vdW' in atom[cs]:
2227                        radius = vdwScale*generalData['vdWRadii'][atNum]
2228                    else:
2229                        radius = ballScale*generalData['BondRadii'][atNum]
2230                RenderSphere(x,y,z,radius,color)
2231                if 'sticks' in atom[cs]:
2232                    RenderBonds(x,y,z,Bonds,bondR,color)
2233            elif 'ellipsoids' in atom[cs]:
2234                RenderBonds(x,y,z,Bonds,bondR,color)
2235                if atom[cs+3] == 'A':                   
2236                    Uij = atom[cs+5:cs+11]
2237                    U = np.multiply(G2spc.Uij2U(Uij),GS)
2238                    U = np.inner(Amat,np.inner(U,Amat).T)
2239                    E,R = nl.eigh(U)
2240                    R4 = np.concatenate((np.concatenate((R,[[0],[0],[0]]),axis=1),[[0,0,0,1],]),axis=0)
2241                    E = np.sqrt(E)
2242                    if atom[ct] == 'H' and not drawingData['showHydrogen']:
2243                        pass
2244                    else:
2245                        RenderEllipsoid(x,y,z,ellipseProb,E,R4,color)                   
2246                else:
2247                    if atom[ct] == 'H' and not drawingData['showHydrogen']:
2248                        pass
2249                    else:
2250                        radius = ellipseProb*math.sqrt(abs(atom[cs+4]))
2251                        RenderSphere(x,y,z,radius,color)
2252            elif 'lines' in atom[cs]:
2253                radius = 0.1
2254                RenderLines(x,y,z,Bonds,color)
2255#                RenderBonds(x,y,z,Bonds,0.05,color,6)
2256            elif atom[cs] == 'sticks':
2257                radius = 0.1
2258                RenderBonds(x,y,z,Bonds,bondR,color)
2259            elif atom[cs] == 'polyhedra':
2260                RenderPolyhedra(x,y,z,Faces,color)
2261            elif atom[cs] == 'backbone':
2262                if atom[ct-1].split()[0] in ['C','N']:
2263                    Backbone.append(list(np.inner(Amat,np.array([x,y,z]))))
2264                    BackboneColor.append(list(color))
2265                   
2266            if atom[cs+1] == 'type':
2267                RenderLabel(x,y,z,atom[ct],radius)
2268            elif atom[cs+1] == 'name':
2269                RenderLabel(x,y,z,atom[ct-1],radius)
2270            elif atom[cs+1] == 'number':
2271                RenderLabel(x,y,z,str(iat+1),radius)
2272            elif atom[cs+1] == 'residue' and atom[ct-1] == 'CA':
2273                RenderLabel(x,y,z,atom[ct-4],radius)
2274            elif atom[cs+1] == '1-letter' and atom[ct-1] == 'CA':
2275                RenderLabel(x,y,z,atom[ct-3],radius)
2276            elif atom[cs+1] == 'chain' and atom[ct-1] == 'CA':
2277                RenderLabel(x,y,z,atom[ct-2],radius)
2278        if Backbone:
2279            RenderBackbone(Backbone,BackboneColor,bondR)
2280#        print time.time()-time0
2281        Page.canvas.SwapBuffers()
2282       
2283    def OnSize(event):
2284        Draw()
2285       
2286    def OnFocus(event):
2287        Draw()
2288       
2289    try:
2290        plotNum = self.G2plotNB.plotList.index(generalData['Name'])
2291        Page = self.G2plotNB.nb.GetPage(plotNum)       
2292    except ValueError:
2293        Plot = self.G2plotNB.addOgl(generalData['Name'])
2294        plotNum = self.G2plotNB.plotList.index(generalData['Name'])
2295        Page = self.G2plotNB.nb.GetPage(plotNum)
2296        Page.views = False
2297        view = False
2298        altDown = False
2299    Page.SetFocus()
2300    cb = wx.ComboBox(self.G2plotNB.status,style=wx.CB_DROPDOWN|wx.CB_READONLY,
2301        choices=(' save as:','jpeg','tiff','bmp'))
2302    cb.Bind(wx.EVT_COMBOBOX, OnKeyBox)
2303    cb.SetValue(' save as:')
2304    Page.canvas.Bind(wx.EVT_MOUSEWHEEL, OnMouseWheel)
2305    Page.canvas.Bind(wx.EVT_LEFT_DOWN, OnMouseDown)
2306    Page.canvas.Bind(wx.EVT_RIGHT_DOWN, OnMouseDown)
2307    Page.canvas.Bind(wx.EVT_MIDDLE_DOWN, OnMouseDown)
2308    Page.canvas.Bind(wx.EVT_KEY_UP, OnKey)
2309    Page.canvas.Bind(wx.EVT_MOTION, OnMouseMove)
2310    Page.canvas.Bind(wx.EVT_SIZE, OnSize)
2311    Page.canvas.Bind(wx.EVT_SET_FOCUS, OnFocus)
2312    Page.camera['position'] = drawingData['cameraPos']
2313    Page.camera['viewPoint'] = np.inner(Amat,drawingData['viewPoint'][0])
2314    Page.camera['backColor'] = np.array(list(drawingData['backColor'])+[0,])/255.
2315    Page.canvas.SetCurrent()
2316    Draw()
2317       
Note: See TracBrowser for help on using the repository browser.