source: trunk/GSASIIplot.py @ 428

Last change on this file since 428 was 428, checked in by vondreele, 11 years ago

begin something for plotting size & PO figures as well as mustrain
allow sorting of the indexing result by volume
fix weights for "STD" GSAS powder data files

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