source: trunk/GSASIIplot.py @ 612

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

complete combined x/n exercise & fix bugs uncovered in process
made version 0.2.0
moved tutorials in help menu to be 2nd
fixed problem with drawing after f-map generated
fixed some plot errors
reverse sign on macrostrain

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