source: trunk/GSASIIplot.py @ 749

Last change on this file since 749 was 749, checked in by vondreele, 10 years ago

fix crash on delete atoms
couple roll & peak shift on charge flip maps

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