source: trunk/GSASIIplot.py @ 271

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

make g77 versions of fortran for binwin2.7 - faster than gfortran!
fix to histogram2d.for
GSASII.py - allow 2D offset in multiplots, fix for large file lists
GSASIIimgGUI.py - more stuff in save/load controls
GSASIIplot.py - 2D offset in multiplots, fix bad behavior in structure drawings
GSASIIpwd.py - more mods to PDF calcs

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