source: MPbranch/GSASIIplot.py @ 496

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

making 1st multiprocess version of GSAS-II

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