source: trunk/GSASIIplot.py @ 526

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

make SetNewPhase? routine in GSASIIIO.py to initialize phase info
begin Fourier map search routine
fix atom plotting if no map

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