source: trunk/GSASIIplot.py @ 523

Last change on this file since 523 was 523, checked in by toby, 10 years ago

fix plotting with as-inititalized values (oldxy & Fourier map); fix CIF import; fix command-line load; fix early Destroy in SumDialog?

  • Property svn:keywords set to Date Author Revision URL Id
File size: 126.5 KB
Line 
1#GSASII plotting routines
2########### SVN repository information ###################
3# $Date: 2012-03-29 20:52:03 +0000 (Thu, 29 Mar 2012) $
4# $Author: toby $
5# $Revision: 523 $
6# $URL: trunk/GSASIIplot.py $
7# $Id: GSASIIplot.py 523 2012-03-29 20:52:03Z toby $
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            handles,legends = Plot.get_legend_handles_labels()  #got double entries in the legends for some reason
756            Plot.legend(handles[::2],legends[::2],title='Phases',loc='best')    #skip every other one
757           
758    if G2frame.Contour:
759        acolor = mpl.cm.get_cmap(G2frame.ContourColor)
760        Img = Plot.imshow(ContourZ,cmap=acolor,vmin=0,vmax=Ymax*G2frame.Cmax,interpolation=G2frame.Interpolate, 
761            extent=[ContourX[0],ContourX[-1],ContourY[0],ContourY[-1]],aspect='auto',origin='lower')
762        Page.figure.colorbar(Img)
763    else:
764        G2frame.Lines = Lines
765    if not newPlot:
766        Page.toolbar.push_current()
767        Plot.set_xlim(xylim[0])
768        Plot.set_ylim(xylim[1])
769        xylim = []
770        Page.toolbar.push_current()
771        Page.toolbar.draw()
772    else:
773        Page.canvas.draw()
774    G2frame.Pwdr = True
775   
776################################################################################
777##### PlotDeltSig
778################################################################################
779           
780def PlotDeltSig(G2frame):
781    try:
782        plotNum = G2frame.G2plotNB.plotList.index('Error analysis')
783        Page = G2frame.G2plotNB.nb.GetPage(plotNum)
784        Page.figure.clf()
785        Plot = Page.figure.gca()          #get a fresh plot after clf()
786    except ValueError:
787        newPlot = True
788        G2frame.Cmax = 1.0
789        Plot = G2frame.G2plotNB.addMpl('Error analysis').gca()
790        plotNum = G2frame.G2plotNB.plotList.index('Error analysis')
791        Page = G2frame.G2plotNB.nb.GetPage(plotNum)
792    PatternId = G2frame.PatternId
793    Pattern = G2frame.PatternTree.GetItemPyData(PatternId)
794    Pattern.append(G2frame.PatternTree.GetItemText(PatternId))
795    limits = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Limits'))[1]
796    xye = np.array(Pattern[1])
797    xmin = np.searchsorted(xye[0],limits[0])
798    xmax = np.searchsorted(xye[0],limits[1])
799    X = xye[0][xmin:xmax]
800    DS = xye[5][xmin:xmax]*np.sqrt(xye[2][xmin:xmax])
801    Page.SetFocus()
802    G2frame.G2plotNB.status.DestroyChildren()
803    DS.sort()
804    EDS = np.zeros_like(DS)
805    DX = np.linspace(0.,1.,num=len(DS),endpoint=True)
806    oldErr = np.seterr(invalid='ignore')    #avoid problem at DX==0
807    T = np.sqrt(np.log(1.0/DX**2))
808    top = 2.515517+0.802853*T+0.010328*T**2
809    bot = 1.0+1.432788*T+0.189269*T**2+0.001308*T**3
810    EDS = np.where(DX>0,-(T-top/bot),(T-top/bot))
811    low1 = np.searchsorted(EDS,-1.)
812    hi1 = np.searchsorted(EDS,1.)
813    slp,intcp = np.polyfit(EDS[low1:hi1],DS[low1:hi1],deg=1)
814    frac = 100.*(hi1-low1)/len(DS)
815    G2frame.G2plotNB.status.SetStatusText(  \
816        'Over range -1. to 1. :'+' slope = %.3f, intercept = %.3f for %.2f%% of the fitted data'%(slp,intcp,frac),1)
817    Plot.set_title('Normal probability for '+Pattern[-1])
818    Plot.set_xlabel(r'expected $\mathsf{\Delta/\sigma}$',fontsize=14)
819    Plot.set_ylabel(r'observed $\mathsf{\Delta/\sigma}$',fontsize=14)
820    Plot.plot(EDS,DS,'r+',label='result')
821    Plot.plot([-2,2],[-2,2],'k',dashes=(5,5),label='ideal')
822    Plot.legend(loc='upper left')
823    np.seterr(invalid='warn')
824    Page.canvas.draw()
825       
826################################################################################
827##### PlotISFG
828################################################################################
829           
830def PlotISFG(G2frame,newPlot=False,type=''):
831    ''' PLotting package for PDF analysis; displays I(q), S(q), F(q) and G(r) as single
832    or multiple plots with waterfall and contour plots as options
833    '''
834    if not type:
835        type = G2frame.G2plotNB.plotList[G2frame.G2plotNB.nb.GetSelection()]
836    if type not in ['I(Q)','S(Q)','F(Q)','G(R)']:
837        return
838    superMinusOne = unichr(0xaf)+unichr(0xb9)
839   
840    def OnPlotKeyPress(event):
841        newPlot = False
842        if event.key == 'u':
843            if G2frame.Contour:
844                G2frame.Cmax = min(1.0,G2frame.Cmax*1.2)
845            elif G2frame.Offset[0] < 100.:
846                G2frame.Offset[0] += 1.
847        elif event.key == 'd':
848            if G2frame.Contour:
849                G2frame.Cmax = max(0.0,G2frame.Cmax*0.8)
850            elif G2frame.Offset[0] > 0.:
851                G2frame.Offset[0] -= 1.
852        elif event.key == 'l':
853            G2frame.Offset[1] -= 1.
854        elif event.key == 'r':
855            G2frame.Offset[1] += 1.
856        elif event.key == 'o':
857            G2frame.Offset = [0,0]
858        elif event.key == 'c':
859            newPlot = True
860            if G2frame.Contour:
861                G2frame.Contour = False
862            else:
863                G2frame.Contour = True
864                G2frame.SinglePlot = False
865                G2frame.Offset = [0.,0.]
866        elif event.key == 's':
867            if G2frame.Contour:
868                choice = [m for m in mpl.cm.datad.keys() if not m.endswith("_r")]
869                choice.sort()
870                dlg = wx.SingleChoiceDialog(G2frame,'Select','Color scheme',choice)
871                if dlg.ShowModal() == wx.ID_OK:
872                    sel = dlg.GetSelection()
873                    G2frame.ContourColor = choice[sel]
874                else:
875                    G2frame.ContourColor = 'Paired'
876                dlg.Destroy()
877            else:               
878                if G2frame.SinglePlot:
879                    G2frame.SinglePlot = False
880                else:
881                    G2frame.SinglePlot = True
882        elif event.key == 'i':                  #for smoothing contour plot
883            choice = ['nearest','bilinear','bicubic','spline16','spline36','hanning',
884               'hamming','hermite','kaiser','quadric','catrom','gaussian','bessel',
885               'mitchell','sinc','lanczos']
886            dlg = wx.SingleChoiceDialog(G2frame,'Select','Interpolation',choice)
887            if dlg.ShowModal() == wx.ID_OK:
888                sel = dlg.GetSelection()
889                G2frame.Interpolate = choice[sel]
890            else:
891                G2frame.Interpolate = 'nearest'
892            dlg.Destroy()
893        elif event.key == 't' and not G2frame.Contour:
894            if G2frame.Legend:
895                G2frame.Legend = False
896            else:
897                G2frame.Legend = True
898           
899           
900        PlotISFG(G2frame,newPlot=newPlot,type=type)
901       
902    def OnKeyBox(event):
903        if G2frame.G2plotNB.nb.GetSelection() == G2frame.G2plotNB.plotList.index(type):
904            event.key = cb.GetValue()[0]
905            cb.SetValue(' key press')
906            OnPlotKeyPress(event)
907                       
908    def OnMotion(event):
909        xpos = event.xdata
910        if xpos:                                        #avoid out of frame mouse position
911            ypos = event.ydata
912            Page.canvas.SetCursor(wx.CROSS_CURSOR)
913            try:
914                if G2frame.Contour:
915                    G2frame.G2plotNB.status.SetStatusText('R =%.3fA pattern ID =%5d'%(xpos,int(ypos)),1)
916                else:
917                    G2frame.G2plotNB.status.SetStatusText('R =%.3fA %s =%.2f'%(xpos,type,ypos),1)                   
918            except TypeError:
919                G2frame.G2plotNB.status.SetStatusText('Select '+type+' pattern first',1)
920   
921    xylim = []
922    try:
923        plotNum = G2frame.G2plotNB.plotList.index(type)
924        Page = G2frame.G2plotNB.nb.GetPage(plotNum)
925        if not newPlot:
926            Plot = Page.figure.gca()          #get previous plot & get limits
927            xylim = Plot.get_xlim(),Plot.get_ylim()
928        Page.figure.clf()
929        Plot = Page.figure.gca()
930    except ValueError:
931        newPlot = True
932        G2frame.Cmax = 1.0
933        Plot = G2frame.G2plotNB.addMpl(type).gca()
934        plotNum = G2frame.G2plotNB.plotList.index(type)
935        Page = G2frame.G2plotNB.nb.GetPage(plotNum)
936        Page.canvas.mpl_connect('key_press_event', OnPlotKeyPress)
937        Page.canvas.mpl_connect('motion_notify_event', OnMotion)
938   
939    Page.SetFocus()
940    G2frame.G2plotNB.status.DestroyChildren()
941    if G2frame.Contour:
942        Choice = (' key press','d: lower contour max','u: raise contour max',
943            'i: interpolation method','s: color scheme','c: contour off')
944    else:
945        Choice = (' key press','l: offset left','r: offset right','d: offset down','u: offset up',
946            'o: reset offset','t: toggle legend','c: contour on','s: toggle single plot')
947    cb = wx.ComboBox(G2frame.G2plotNB.status,style=wx.CB_DROPDOWN|wx.CB_READONLY,
948        choices=Choice)
949    cb.Bind(wx.EVT_COMBOBOX, OnKeyBox)
950    cb.SetValue(' key press')
951    PatternId = G2frame.PatternId
952    PickId = G2frame.PickId
953    Plot.set_title(type)
954    if type == 'G(R)':
955        Plot.set_xlabel(r'$R,\AA$',fontsize=14)
956    else:
957        Plot.set_xlabel(r'$Q,\AA$'+superMinusOne,fontsize=14)
958    Plot.set_ylabel(r''+type,fontsize=14)
959    colors=['b','g','r','c','m','k']
960    name = G2frame.PatternTree.GetItemText(PatternId)[4:]
961    Pattern = []   
962    if G2frame.SinglePlot:
963        name = G2frame.PatternTree.GetItemText(PatternId)
964        name = type+name[4:]
965        Id = G2gd.GetPatternTreeItemId(G2frame,PatternId,name)
966        Pattern = G2frame.PatternTree.GetItemPyData(Id)
967        if Pattern:
968            Pattern.append(name)
969        PlotList = [Pattern,]
970    else:
971        PlotList = []
972        item, cookie = G2frame.PatternTree.GetFirstChild(G2frame.root)
973        while item:
974            if 'PDF' in G2frame.PatternTree.GetItemText(item):
975                name = type+G2frame.PatternTree.GetItemText(item)[4:]
976                Id = G2gd.GetPatternTreeItemId(G2frame,item,name)
977                Pattern = G2frame.PatternTree.GetItemPyData(Id)
978                if Pattern:
979                    Pattern.append(name)
980                    PlotList.append(Pattern)
981            item, cookie = G2frame.PatternTree.GetNextChild(G2frame.root, cookie)
982    PDFdata = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'PDF Controls'))
983    numbDen = G2pwd.GetNumDensity(PDFdata['ElList'],PDFdata['Form Vol'])
984    Xb = [0.,10.]
985    Yb = [0.,-40.*np.pi*numbDen]
986    Ymax = 1.0
987    lenX = 0
988    for Pattern in PlotList:
989        xye = Pattern[1]
990        Ymax = max(Ymax,max(xye[1]))
991    offset = G2frame.Offset[0]*Ymax/100.0
992    if G2frame.Contour:
993        ContourZ = []
994        ContourY = []
995        Nseq = 0
996    for N,Pattern in enumerate(PlotList):
997        xye = Pattern[1]
998        if PickId:
999            ifpicked = Pattern[2] == G2frame.PatternTree.GetItemText(PatternId)
1000        X = xye[0]
1001        if not lenX:
1002            lenX = len(X)           
1003        Y = xye[1]+offset*N
1004        if G2frame.Contour:
1005            if lenX == len(X):
1006                ContourY.append(N)
1007                ContourZ.append(Y)
1008                ContourX = X
1009                Nseq += 1
1010                Plot.set_ylabel('Data sequence',fontsize=12)
1011        else:
1012            X = xye[0]+G2frame.Offset[1]*.005*N
1013            if ifpicked:
1014                Plot.plot(X,Y,colors[N%6]+'+',picker=3.,clip_on=False)
1015                Page.canvas.SetToolTipString('')
1016            else:
1017                if G2frame.Legend:
1018                    Plot.plot(X,Y,colors[N%6],picker=False,label='Azm:'+Pattern[2].split('=')[1])
1019                else:
1020                    Plot.plot(X,Y,colors[N%6],picker=False)
1021            if type == 'G(R)':
1022                Plot.plot(Xb,Yb,color='k',dashes=(5,5))
1023            elif type == 'F(Q)':
1024                Plot.axhline(0.,color=wx.BLACK)
1025            elif type == 'S(Q)':
1026                Plot.axhline(1.,color=wx.BLACK)
1027    if G2frame.Contour:
1028        acolor = mpl.cm.get_cmap(G2frame.ContourColor)
1029        Img = Plot.imshow(ContourZ,cmap=acolor,vmin=0,vmax=Ymax*G2frame.Cmax,interpolation=G2frame.Interpolate, 
1030            extent=[ContourX[0],ContourX[-1],ContourY[0],ContourY[-1]],aspect='auto',origin='lower')
1031        Page.figure.colorbar(Img)
1032    elif G2frame.Legend:
1033        Plot.legend(loc='best')
1034    if not newPlot:
1035        Page.toolbar.push_current()
1036        Plot.set_xlim(xylim[0])
1037        Plot.set_ylim(xylim[1])
1038        xylim = []
1039        Page.toolbar.push_current()
1040        Page.toolbar.draw()
1041    else:
1042        Page.canvas.draw()
1043       
1044################################################################################
1045##### PlotXY
1046################################################################################
1047           
1048def PlotXY(G2frame,XY,newPlot=False,type=''):
1049    '''simple plot of xy data, used for diagnostic purposes
1050    '''
1051    def OnMotion(event):
1052        xpos = event.xdata
1053        if xpos:                                        #avoid out of frame mouse position
1054            ypos = event.ydata
1055            Page.canvas.SetCursor(wx.CROSS_CURSOR)
1056            try:
1057                G2frame.G2plotNB.status.SetStatusText('X =%9.3f %s =%9.3f'%(xpos,type,ypos),1)                   
1058            except TypeError:
1059                G2frame.G2plotNB.status.SetStatusText('Select '+type+' pattern first',1)
1060
1061    try:
1062        plotNum = G2frame.G2plotNB.plotList.index(type)
1063        Page = G2frame.G2plotNB.nb.GetPage(plotNum)
1064        if not newPlot:
1065            Plot = Page.figure.gca()
1066            xylim = Plot.get_xlim(),Plot.get_ylim()
1067        Page.figure.clf()
1068        Plot = Page.figure.gca()
1069    except ValueError:
1070        newPlot = True
1071        Plot = G2frame.G2plotNB.addMpl(type).gca()
1072        plotNum = G2frame.G2plotNB.plotList.index(type)
1073        Page = G2frame.G2plotNB.nb.GetPage(plotNum)
1074        Page.canvas.mpl_connect('motion_notify_event', OnMotion)
1075   
1076    Page.SetFocus()
1077    G2frame.G2plotNB.status.DestroyChildren()
1078    Plot.set_title(type)
1079    Plot.set_xlabel(r'X',fontsize=14)
1080    Plot.set_ylabel(r''+type,fontsize=14)
1081    colors=['b','g','r','c','m','k']
1082    Ymax = 1.0
1083    lenX = 0
1084    X,Y = XY[:2]
1085    Ymax = max(Ymax,max(Y))
1086    Plot.plot(X,Y,'k',picker=False)
1087    if not newPlot:
1088        Page.toolbar.push_current()
1089        Plot.set_xlim(xylim[0])
1090        Plot.set_ylim(xylim[1])
1091        xylim = []
1092        Page.toolbar.push_current()
1093        Page.toolbar.draw()
1094    else:
1095        Page.canvas.draw()
1096
1097################################################################################
1098##### PlotPowderLines
1099################################################################################
1100           
1101def PlotPowderLines(G2frame):
1102    ''' plotting of powder lines (i.e. no powder pattern) as sticks
1103    '''
1104    global HKL
1105
1106    def OnMotion(event):
1107        xpos = event.xdata
1108        if xpos:                                        #avoid out of frame mouse position
1109            Page.canvas.SetCursor(wx.CROSS_CURSOR)
1110            G2frame.G2plotNB.status.SetFields(['','2-theta =%9.3f '%(xpos,)])
1111            if G2frame.PickId and G2frame.PatternTree.GetItemText(G2frame.PickId) in ['Index Peak List','Unit Cells List']:
1112                found = []
1113                if len(HKL):
1114                    view = Page.toolbar._views.forward()[0][:2]
1115                    wid = view[1]-view[0]
1116                    found = HKL[np.where(np.fabs(HKL.T[5]-xpos) < 0.002*wid)]
1117                if len(found):
1118                    h,k,l = found[0][:3] 
1119                    Page.canvas.SetToolTipString('%d,%d,%d'%(int(h),int(k),int(l)))
1120                else:
1121                    Page.canvas.SetToolTipString('')
1122
1123    try:
1124        plotNum = G2frame.G2plotNB.plotList.index('Powder Lines')
1125        Page = G2frame.G2plotNB.nb.GetPage(plotNum)
1126        Page.figure.clf()
1127        Plot = Page.figure.gca()
1128    except ValueError:
1129        Plot = G2frame.G2plotNB.addMpl('Powder Lines').gca()
1130        plotNum = G2frame.G2plotNB.plotList.index('Powder Lines')
1131        Page = G2frame.G2plotNB.nb.GetPage(plotNum)
1132        Page.canvas.mpl_connect('motion_notify_event', OnMotion)
1133       
1134    Page.SetFocus()
1135    Plot.set_title('Powder Pattern Lines')
1136    Plot.set_xlabel(r'$\mathsf{2\theta}$',fontsize=14)
1137    PickId = G2frame.PickId
1138    PatternId = G2frame.PatternId
1139    peaks = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Index Peak List'))
1140    for peak in peaks:
1141        Plot.axvline(peak[0],color='b')
1142    HKL = np.array(G2frame.HKL)
1143    for hkl in G2frame.HKL:
1144        Plot.axvline(hkl[5],color='r',dashes=(5,5))
1145    xmin = peaks[0][0]
1146    xmax = peaks[-1][0]
1147    delt = xmax-xmin
1148    xlim = [max(0,xmin-delt/20.),min(180.,xmax+delt/20.)]
1149    Plot.set_xlim(xlim)
1150    Page.canvas.draw()
1151    Page.toolbar.push_current()
1152
1153################################################################################
1154##### PlotPeakWidths
1155################################################################################
1156           
1157def PlotPeakWidths(G2frame):
1158    ''' Plotting of instrument broadening terms as function of 2-theta (future TOF)
1159    Seen when "Instrument Parameters" chosen from powder pattern data tree
1160    '''
1161    PatternId = G2frame.PatternId
1162    limitID = G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Limits')
1163    if limitID:
1164        limits = G2frame.PatternTree.GetItemPyData(limitID)
1165    else:
1166        return
1167    instParms = G2frame.PatternTree.GetItemPyData( \
1168        G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Instrument Parameters'))
1169    if instParms[0][0] in ['PXC','PNC']:
1170        lam = instParms[1][1]
1171        if len(instParms[1]) == 13:
1172            GU,GV,GW,LX,LY = instParms[0][6:11]
1173        else:
1174            GU,GV,GW,LX,LY = instParms[0][4:9]
1175    peakID = G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Peak List')
1176    if peakID:
1177        peaks = G2frame.PatternTree.GetItemPyData(peakID)
1178    else:
1179        peaks = []
1180   
1181    try:
1182        plotNum = G2frame.G2plotNB.plotList.index('Peak Widths')
1183        Page = G2frame.G2plotNB.nb.GetPage(plotNum)
1184        Page.figure.clf()
1185        Plot = Page.figure.gca()
1186    except ValueError:
1187        Plot = G2frame.G2plotNB.addMpl('Peak Widths').gca()
1188        plotNum = G2frame.G2plotNB.plotList.index('Peak Widths')
1189        Page = G2frame.G2plotNB.nb.GetPage(plotNum)
1190    Page.SetFocus()
1191   
1192    Page.canvas.SetToolTipString('')
1193    colors=['b','g','r','c','m','k']
1194    Xmin,Xmax = limits[1]
1195    Xmin = min(0.5,max(Xmin,1))
1196    Xmin /= 2
1197    Xmax /= 2
1198    nPts = 100
1199    delt = (Xmax-Xmin)/nPts
1200    thetas = []
1201    for i in range(nPts):
1202        thetas.append(Xmin+i*delt)
1203    X = []
1204    Y = []
1205    Z = []
1206    W = []
1207    sig = lambda Th,U,V,W: 1.17741*math.sqrt(U*tand(Th)**2+V*tand(Th)+W)*math.pi/18000.
1208    gam = lambda Th,X,Y: (X/cosd(Th)+Y*tand(Th))*math.pi/18000.
1209    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.)
1210#    gamFW2 = lambda s,g: math.sqrt(s**2+(0.4654996*g)**2)+.5345004*g  #Ubaldo Bafile - private communication
1211    for theta in thetas:
1212        X.append(4.0*math.pi*sind(theta)/lam)              #q
1213        s = sig(theta,GU,GV,GW)
1214        g = gam(theta,LX,LY)
1215        G = gamFW(g,s)
1216        Y.append(s/tand(theta))
1217        Z.append(g/tand(theta))
1218        W.append(G/tand(theta))
1219    Plot.set_title('Instrument and sample peak widths')
1220    Plot.set_ylabel(r'$\Delta q/q, \Delta d/d$',fontsize=14)
1221    Plot.set_xlabel(r'$q, \AA^{-1}$',fontsize=14)
1222    Plot.plot(X,Y,color='r',label='Gaussian')
1223    Plot.plot(X,Z,color='g',label='Lorentzian')
1224    Plot.plot(X,W,color='b',label='G+L')
1225    X = []
1226    Y = []
1227    Z = []
1228    W = []
1229    V = []
1230    for peak in peaks:
1231        X.append(4.0*math.pi*sind(peak[0]/2.0)/lam)
1232        try:
1233            s = 1.17741*math.sqrt(peak[4])*math.pi/18000.
1234        except ValueError:
1235            s = 0.01
1236        g = peak[6]*math.pi/18000.
1237        G = gamFW(g,s)
1238        Y.append(s/tand(peak[0]/2.))
1239        Z.append(g/tand(peak[0]/2.))
1240        W.append(G/tand(peak[0]/2.))
1241    Plot.plot(X,Y,'+',color='r',label='G peak')
1242    Plot.plot(X,Z,'+',color='g',label='L peak')
1243    Plot.plot(X,W,'+',color='b',label='G+L peak')
1244    Plot.legend(loc='best')
1245    Page.canvas.draw()
1246   
1247################################################################################
1248##### PlotSizeStrainPO
1249################################################################################
1250           
1251def PlotSizeStrainPO(G2frame,data,Start=False):
1252    '''Plot 3D mustrain/size/preferred orientation figure. In this instance data is for a phase
1253    '''
1254   
1255    PatternId = G2frame.PatternId
1256    generalData = data['General']
1257    SGData = generalData['SGData']
1258    SGLaue = SGData['SGLaue']
1259    if Start:                   #initialize the spherical harmonics qlmn arrays
1260        ptx.pyqlmninit()
1261        Start = False
1262#    MuStrKeys = G2spc.MustrainNames(SGData)
1263    cell = generalData['Cell'][1:]
1264    A,B = G2lat.cell2AB(cell[:6])
1265    Vol = cell[6]
1266    useList = data['Histograms']
1267    phase = generalData['Name']
1268    plotType = generalData['Data plot type']
1269    plotDict = {'Mustrain':'Mustrain','Size':'Size','Preferred orientation':'Pref.Ori.'}
1270    for ptype in plotDict:
1271        G2frame.G2plotNB.Delete(ptype)       
1272
1273    for item in useList:
1274        if useList[item]['Show']:
1275            break
1276    else:
1277        return            #nothing to show!!
1278   
1279    numPlots = len(useList)
1280
1281    if plotType in ['Mustrain','Size']:
1282        Plot = mp3d.Axes3D(G2frame.G2plotNB.add3D(plotType))
1283    else:
1284        Plot = G2frame.G2plotNB.addMpl(plotType).gca()       
1285    plotNum = G2frame.G2plotNB.plotList.index(plotType)
1286    Page = G2frame.G2plotNB.nb.GetPage(plotNum)
1287    Page.SetFocus()
1288    G2frame.G2plotNB.status.SetStatusText('',1)
1289    if not Page.IsShown():
1290        Page.Show()
1291   
1292    for item in useList:
1293        if useList[item]['Show']:
1294            PHI = np.linspace(0.,360.,30,True)
1295            PSI = np.linspace(0.,180.,30,True)
1296            X = np.outer(npsind(PHI),npsind(PSI))
1297            Y = np.outer(npcosd(PHI),npsind(PSI))
1298            Z = np.outer(np.ones(np.size(PHI)),npcosd(PSI))
1299            try:        #temp patch instead of 'mustrain' for old files with 'microstrain'
1300                coeff = useList[item][plotDict[plotType]]
1301            except KeyError:
1302                break
1303            if plotType in ['Mustrain','Size']:
1304                if coeff[0] == 'isotropic':
1305                    X *= coeff[1][0]
1306                    Y *= coeff[1][0]
1307                    Z *= coeff[1][0]                               
1308                elif coeff[0] == 'uniaxial':
1309                   
1310                    def uniaxCalc(xyz,iso,aniso,axes):
1311                        Z = np.array(axes)
1312                        cp = abs(np.dot(xyz,Z))
1313                        sp = np.sqrt(1.-cp**2)
1314                        R = iso*aniso/np.sqrt((iso*cp)**2+(aniso*sp)**2)
1315                        return R*xyz
1316                       
1317                    iso,aniso = coeff[1][:2]
1318                    axes = np.inner(A,np.array(coeff[3]))
1319                    axes /= nl.norm(axes)
1320                    Shkl = np.array(coeff[1])
1321                    XYZ = np.dstack((X,Y,Z))
1322                    XYZ = np.nan_to_num(np.apply_along_axis(uniaxCalc,2,XYZ,iso,aniso,axes))
1323                    X,Y,Z = np.dsplit(XYZ,3)
1324                    X = X[:,:,0]
1325                    Y = Y[:,:,0]
1326                    Z = Z[:,:,0]
1327               
1328                elif coeff[0] == 'ellipsoidal':
1329                   
1330                    def ellipseCalc(xyz,E,R):
1331                        XYZ = xyz*E.T
1332                        return np.inner(XYZ.T,R)
1333                       
1334                    S6 = coeff[4]
1335                    Sij = G2lat.U6toUij(S6)
1336                    E,R = nl.eigh(Sij)
1337                    XYZ = np.dstack((X,Y,Z))
1338                    XYZ = np.nan_to_num(np.apply_along_axis(ellipseCalc,2,XYZ,E,R))
1339                    X,Y,Z = np.dsplit(XYZ,3)
1340                    X = X[:,:,0]
1341                    Y = Y[:,:,0]
1342                    Z = Z[:,:,0]
1343                   
1344                elif coeff[0] == 'generalized':
1345                   
1346                    def genMustrain(xyz,SGData,A,Shkl):
1347                        uvw = np.inner(A.T,xyz)
1348                        Strm = np.array(G2spc.MustrainCoeff(uvw,SGData))
1349                        sum = np.sum(np.multiply(Shkl,Strm))
1350                        sum = np.where(sum > 0.01,sum,0.01)
1351                        sum = np.sqrt(sum)*math.pi/0.018      #centidegrees to radians!
1352                        return sum*xyz
1353                       
1354                    Shkl = np.array(coeff[4])
1355                    if np.any(Shkl):
1356                        XYZ = np.dstack((X,Y,Z))
1357                        XYZ = np.nan_to_num(np.apply_along_axis(genMustrain,2,XYZ,SGData,A,Shkl))
1358                        X,Y,Z = np.dsplit(XYZ,3)
1359                        X = X[:,:,0]
1360                        Y = Y[:,:,0]
1361                        Z = Z[:,:,0]
1362                           
1363                if np.any(X) and np.any(Y) and np.any(Z):
1364                    errFlags = np.seterr(all='ignore')
1365                    Plot.plot_surface(X,Y,Z,rstride=1,cstride=1,color='g',linewidth=1)
1366                    np.seterr(all='ignore')
1367                    xyzlim = np.array([Plot.get_xlim3d(),Plot.get_ylim3d(),Plot.get_zlim3d()]).T
1368                    XYZlim = [min(xyzlim[0]),max(xyzlim[1])]
1369                    Plot.set_xlim3d(XYZlim)
1370                    Plot.set_ylim3d(XYZlim)
1371                    Plot.set_zlim3d(XYZlim)
1372                    Plot.set_aspect('equal')
1373                if plotType == 'Size':
1374                    Plot.set_title('Crystallite size for '+phase+'\n'+coeff[0]+' model')
1375                    Plot.set_xlabel(r'X, $\mu$m')
1376                    Plot.set_ylabel(r'Y, $\mu$m')
1377                    Plot.set_zlabel(r'Z, $\mu$m')
1378                else:   
1379                    Plot.set_title(r'$\mu$strain for '+phase+'\n'+coeff[0]+' model')
1380                    Plot.set_xlabel(r'X, $\mu$strain')
1381                    Plot.set_ylabel(r'Y, $\mu$strain')
1382                    Plot.set_zlabel(r'Z, $\mu$strain')
1383            else:
1384                h,k,l = generalData['POhkl']
1385                if coeff[0] == 'MD':
1386                    print 'March-Dollase preferred orientation plot'
1387               
1388                else:
1389                    PH = np.array(generalData['POhkl'])
1390                    phi,beta = G2lat.CrsAng(PH,cell[:6],SGData)
1391                    SHCoef = {}
1392                    for item in coeff[5]:
1393                        L,N = eval(item.strip('C'))
1394                        SHCoef['C%d,0,%d'%(L,N)] = coeff[5][item]                       
1395                    ODFln = G2lat.Flnh(Start,SHCoef,phi,beta,SGData)
1396                    X = np.linspace(0,90.0,26)
1397                    Y = G2lat.polfcal(ODFln,'0',X,0.0)
1398                    Plot.plot(X,Y,color='k',label=str(PH))
1399                    Plot.legend(loc='best')
1400                    Plot.set_title('Axial distribution for HKL='+str(PH)+' in '+phase)
1401                    Plot.set_xlabel(r'$\psi$',fontsize=16)
1402                    Plot.set_ylabel('MRD',fontsize=14)
1403    Page.canvas.draw()
1404   
1405################################################################################
1406##### PlotTexture
1407################################################################################
1408           
1409def PlotTexture(G2frame,data,newPlot=False,Start=False):
1410    '''Pole figure, inverse pole figure, 3D pole distribution and 3D inverse pole distribution
1411    plotting.
1412    dict generalData contains all phase info needed which is in data
1413    '''
1414
1415    shModels = ['cylindrical','none','shear - 2/m','rolling - mmm']
1416    SamSym = dict(zip(shModels,['0','-1','2/m','mmm']))
1417    PatternId = G2frame.PatternId
1418    generalData = data['General']
1419    SGData = generalData['SGData']
1420    textureData = generalData['SH Texture']
1421    G2frame.G2plotNB.Delete('Texture')
1422    if not textureData['Order']:
1423        return                  #no plot!!
1424    SHData = generalData['SH Texture']
1425    SHCoef = SHData['SH Coeff'][1]
1426    cell = generalData['Cell'][1:7]
1427    Amat,Bmat = G2lat.cell2AB(cell)
1428    sq2 = 1.0/math.sqrt(2.0)
1429   
1430    def rp2xyz(r,p):
1431        z = npcosd(r)
1432        xy = np.sqrt(1.-z**2)
1433        return xy*npsind(p),xy*npcosd(p),z
1434           
1435    def OnMotion(event):
1436        SHData = data['General']['SH Texture']
1437        if event.xdata and event.ydata:                 #avoid out of frame errors
1438            xpos = event.xdata
1439            ypos = event.ydata
1440            if 'Inverse' in SHData['PlotType']:
1441                r = xpos**2+ypos**2
1442                if r <= 1.0:
1443                    if 'equal' in G2frame.Projection: 
1444                        r,p = 2.*npasind(np.sqrt(r)*sq2),npatan2d(ypos,xpos)
1445                    else:
1446                        r,p = 2.*npatand(np.sqrt(r)),npatan2d(ypos,xpos)
1447                    ipf = G2lat.invpolfcal(IODFln,SGData,np.array([r,]),np.array([p,]))
1448                    xyz = np.inner(Amat.T,np.array([rp2xyz(r,p)]))
1449                    y,x,z = list(xyz/np.max(np.abs(xyz)))
1450                   
1451                    G2frame.G2plotNB.status.SetFields(['',
1452                        'psi =%9.3f, beta =%9.3f, MRD =%9.3f hkl=%5.2f,%5.2f,%5.2f'%(r,p,ipf,x,y,z)])
1453                                   
1454            elif 'Axial' in SHData['PlotType']:
1455                pass
1456               
1457            else:                       #ordinary pole figure
1458                z = xpos**2+ypos**2
1459                if z <= 1.0:
1460                    z = np.sqrt(z)
1461                    if 'equal' in G2frame.Projection: 
1462                        r,p = 2.*npasind(z*sq2),npatan2d(ypos,xpos)
1463                    else:
1464                        r,p = 2.*npatand(z),npatan2d(ypos,xpos)
1465                    pf = G2lat.polfcal(ODFln,SamSym[textureData['Model']],np.array([r,]),np.array([p,]))
1466                    G2frame.G2plotNB.status.SetFields(['','phi =%9.3f, gam =%9.3f, MRD =%9.3f'%(r,p,pf)])
1467   
1468    if G2frame.Projection == '3D display' and 'Axial'  not in SHData['PlotType']:               
1469        Plot = mp3d.Axes3D(G2frame.G2plotNB.add3D('Texture'))
1470    else:
1471        Plot = G2frame.G2plotNB.addMpl('Texture').gca()
1472    plotNum = G2frame.G2plotNB.plotList.index('Texture')
1473    Page = G2frame.G2plotNB.nb.GetPage(plotNum)
1474    if G2frame.Projection == '3D display':
1475        pass
1476    else:
1477        Page.canvas.mpl_connect('motion_notify_event', OnMotion)
1478
1479    Page.SetFocus()
1480    G2frame.G2plotNB.status.SetFields(['',''])   
1481    PH = np.array(SHData['PFhkl'])
1482    phi,beta = G2lat.CrsAng(PH,cell,SGData)
1483    ODFln = G2lat.Flnh(Start,SHCoef,phi,beta,SGData)
1484    PX = np.array(SHData['PFxyz'])
1485    gam = atan2d(PX[0],PX[1])
1486    xy = math.sqrt(PX[0]**2+PX[1]**2)
1487    xyz = math.sqrt(PX[0]**2+PX[1]**2+PX[2]**2)
1488    psi = asind(xy/xyz)
1489    IODFln = G2lat.Glnh(Start,SHCoef,psi,gam,SamSym[textureData['Model']])
1490    if 'Axial' in SHData['PlotType']:
1491        X = np.linspace(0,90.0,26)
1492        Y = G2lat.polfcal(ODFln,SamSym[textureData['Model']],X,0.0)
1493        Plot.plot(X,Y,color='k',label=str(SHData['PFhkl']))
1494        Plot.legend(loc='best')
1495        Plot.set_title('Axial distribution for HKL='+str(SHData['PFhkl']))
1496        Plot.set_xlabel(r'$\psi$',fontsize=16)
1497        Plot.set_ylabel('MRD',fontsize=14)
1498       
1499    else:       
1500        npts = 201
1501        if 'Inverse' in SHData['PlotType']:
1502            X,Y = np.meshgrid(np.linspace(1.,-1.,npts),np.linspace(-1.,1.,npts))
1503            R,P = np.sqrt(X**2+Y**2).flatten(),npatan2d(X,Y).flatten()
1504            if 'equal' in G2frame.Projection:
1505                R = np.where(R <= 1.,2.*npasind(R*sq2),0.0)
1506            else:
1507                R = np.where(R <= 1.,2.*npatand(R),0.0)
1508            Z = np.zeros_like(R)
1509            Z = G2lat.invpolfcal(IODFln,SGData,R,P)
1510            Z = np.reshape(Z,(npts,npts))
1511            CS = Plot.contour(Y,X,Z,aspect='equal')
1512            Plot.clabel(CS,fontsize=9,inline=1)
1513            try:
1514                Img = Plot.imshow(Z.T,aspect='equal',cmap=G2frame.ContourColor,extent=[-1,1,-1,1])
1515            except ValueError:
1516                pass
1517            if newPlot:
1518#                Page.figure.colorbar(Img)    #colorbar fails - crashes gsasii
1519                newPlot = False
1520            Plot.set_title('Inverse pole figure for XYZ='+str(SHData['PFxyz']))
1521            Plot.set_xlabel(G2frame.Projection.capitalize()+' projection')
1522                       
1523        else:
1524            X,Y = np.meshgrid(np.linspace(1.,-1.,npts),np.linspace(-1.,1.,npts))
1525            R,P = np.sqrt(X**2+Y**2).flatten(),npatan2d(X,Y).flatten()
1526            if 'equal' in G2frame.Projection:
1527                R = np.where(R <= 1.,2.*npasind(R*sq2),0.0)
1528            else:
1529                R = np.where(R <= 1.,2.*npatand(R),0.0)
1530            Z = np.zeros_like(R)
1531            Z = G2lat.polfcal(ODFln,SamSym[textureData['Model']],R,P)
1532            Z = np.reshape(Z,(npts,npts))
1533            try:
1534                CS = Plot.contour(Y,X,Z,aspect='equal')
1535                Plot.clabel(CS,fontsize=9,inline=1)
1536            except ValueError:
1537                pass
1538            Img = Plot.imshow(Z.T,aspect='equal',cmap=G2frame.ContourColor,extent=[-1,1,-1,1])
1539            if newPlot:
1540#                Page.figure.colorbar(Img)    #colorbar fails - crashes gsasii
1541                newPlot = False
1542            Plot.set_title('Pole figure for HKL='+str(SHData['PFhkl']))
1543            Plot.set_xlabel(G2frame.Projection.capitalize()+' projection')
1544    Page.canvas.draw()
1545
1546################################################################################
1547##### PlotCovariance
1548################################################################################
1549           
1550def PlotCovariance(G2frame,Data={}):
1551    if not Data:
1552        Data = G2frame.PatternTree.GetItemPyData(
1553            G2gd.GetPatternTreeItemId(G2frame,G2frame.root, 'Covariance'))
1554    if not Data:
1555        print 'No covariance matrix available'
1556        return
1557    varyList = Data['varyList']
1558    values = Data['variables']
1559    Xmax = len(varyList)
1560    covMatrix = Data['covMatrix']
1561    sig = np.sqrt(np.diag(covMatrix))
1562    xvar = np.outer(sig,np.ones_like(sig))
1563    covArray = np.divide(np.divide(covMatrix,xvar),xvar.T)
1564    title = ' for\n'+Data['title']
1565    newAtomDict = Data['newAtomDict']
1566
1567    def OnPlotKeyPress(event):
1568        newPlot = False
1569        if event.key == 's':
1570            choice = [m for m in mpl.cm.datad.keys() if not m.endswith("_r")]
1571            choice.sort()
1572            dlg = wx.SingleChoiceDialog(G2frame,'Select','Color scheme',choice)
1573            if dlg.ShowModal() == wx.ID_OK:
1574                sel = dlg.GetSelection()
1575                G2frame.VcovColor = choice[sel]
1576            else:
1577                G2frame.VcovColor = 'RdYlGn'
1578            dlg.Destroy()
1579        PlotCovariance(G2frame)
1580
1581    def OnMotion(event):
1582        if event.button:
1583            ytics = imgAx.get_yticks()
1584            ytics = np.where(ytics<len(varyList),ytics,-1)
1585            ylabs = [np.where(0<=i ,varyList[int(i)],' ') for i in ytics]
1586            imgAx.set_yticklabels(ylabs)
1587           
1588        if event.xdata and event.ydata:                 #avoid out of frame errors
1589            xpos = int(event.xdata+.5)
1590            ypos = int(event.ydata+.5)
1591            if -1 < xpos < len(varyList) and -1 < ypos < len(varyList):
1592                if xpos == ypos:
1593                    value = values[xpos]
1594                    name = varyList[xpos]
1595                    if varyList[xpos] in newAtomDict:
1596                        name,value = newAtomDict[name]                       
1597                    msg = '%s value = %.4g, esd = %.4g'%(name,value,sig[xpos])
1598                else:
1599                    msg = '%s - %s: %5.3f'%(varyList[xpos],varyList[ypos],covArray[xpos][ypos])
1600                Page.canvas.SetToolTipString(msg)
1601                G2frame.G2plotNB.status.SetFields(['Key: s to change colors',msg])
1602    try:
1603        plotNum = G2frame.G2plotNB.plotList.index('Covariance')
1604        Page = G2frame.G2plotNB.nb.GetPage(plotNum)
1605        Page.figure.clf()
1606        Plot = Page.figure.gca()
1607        if not Page.IsShown():
1608            Page.Show()
1609    except ValueError:
1610        Plot = G2frame.G2plotNB.addMpl('Covariance').gca()
1611        plotNum = G2frame.G2plotNB.plotList.index('Covariance')
1612        Page = G2frame.G2plotNB.nb.GetPage(plotNum)
1613        Page.canvas.mpl_connect('motion_notify_event', OnMotion)
1614        Page.canvas.mpl_connect('key_press_event', OnPlotKeyPress)
1615
1616    Page.SetFocus()
1617    G2frame.G2plotNB.status.SetFields(['',''])   
1618    acolor = mpl.cm.get_cmap(G2frame.VcovColor)
1619    Img = Plot.imshow(covArray,aspect='equal',cmap=acolor,interpolation='nearest',origin='lower')
1620    imgAx = Img.get_axes()
1621    ytics = imgAx.get_yticks()
1622    ylabs = [varyList[int(i)] for i in ytics[:-1]]
1623    imgAx.set_yticklabels(ylabs)
1624    colorBar = Page.figure.colorbar(Img)
1625    Plot.set_title('V-Cov matrix'+title)
1626    Plot.set_xlabel('Variable number')
1627    Plot.set_ylabel('Variable name')
1628    Page.canvas.draw()
1629   
1630################################################################################
1631##### PlotSeq
1632################################################################################
1633           
1634def PlotSeq(G2frame,SeqData,SeqSig,SeqNames,sampleParm):
1635   
1636    def OnKeyPress(event):
1637        if event.key == 's' and sampleParm:
1638            if G2frame.xAxis:
1639                G2frame.xAxis = False
1640            else:
1641                G2frame.xAxis = True
1642            Draw(False)
1643    try:
1644        plotNum = G2frame.G2plotNB.plotList.index('Sequential refinement')
1645        Page = G2frame.G2plotNB.nb.GetPage(plotNum)
1646        Page.figure.clf()
1647        Plot = Page.figure.gca()
1648        if not Page.IsShown():
1649            Page.Show()
1650    except ValueError:
1651        Plot = G2frame.G2plotNB.addMpl('Sequential refinement').gca()
1652        plotNum = G2frame.G2plotNB.plotList.index('Sequential refinement')
1653        Page = G2frame.G2plotNB.nb.GetPage(plotNum)
1654        Page.canvas.mpl_connect('key_press_event', OnKeyPress)
1655        G2frame.xAxis = False
1656       
1657    def Draw(newPlot):
1658        Page.SetFocus()
1659        G2frame.G2plotNB.status.SetFields(['','press s to toggle x-axis = sample environment parameter'])
1660        if len(SeqData):
1661            Plot.clear()
1662            if G2frame.xAxis:   
1663                xName = sampleParm.keys()[0]
1664                X = sampleParm[xName]
1665            else:
1666                X = np.arange(0,len(SeqData[0]),1)
1667                xName = 'Data sequence number'
1668            for Y,sig,name in zip(SeqData,SeqSig,SeqNames):
1669                Plot.errorbar(X,Y,yerr=sig,label=name)       
1670            Plot.legend(loc='best')
1671            Plot.set_ylabel('Parameter values')
1672            Plot.set_xlabel(xName)
1673            Page.canvas.draw()           
1674    Draw(True)
1675           
1676################################################################################
1677##### PlotExposedImage & PlotImage
1678################################################################################
1679           
1680def PlotExposedImage(G2frame,newPlot=False,event=None):
1681    '''General access module for 2D image plotting
1682    '''
1683    plotNo = G2frame.G2plotNB.nb.GetSelection()
1684    if G2frame.G2plotNB.nb.GetPageText(plotNo) == '2D Powder Image':
1685        PlotImage(G2frame,newPlot,event,newImage=True)
1686    elif G2frame.G2plotNB.nb.GetPageText(plotNo) == '2D Integration':
1687        PlotIntegration(G2frame,newPlot,event)
1688
1689def PlotImage(G2frame,newPlot=False,event=None,newImage=True):
1690    '''Plot of 2D detector images as contoured plot. Also plot calibration ellipses,
1691    masks, etc.
1692    '''
1693    from matplotlib.patches import Ellipse,Arc,Circle,Polygon
1694    import numpy.ma as ma
1695    Dsp = lambda tth,wave: wave/(2.*sind(tth/2.))
1696    global Data,Masks
1697    colors=['b','g','r','c','m','k']
1698    Data = G2frame.PatternTree.GetItemPyData(
1699        G2gd.GetPatternTreeItemId(G2frame,G2frame.Image, 'Image Controls'))
1700    Masks = G2frame.PatternTree.GetItemPyData(
1701        G2gd.GetPatternTreeItemId(G2frame,G2frame.Image, 'Masks'))
1702
1703    def OnImMotion(event):
1704        Page.canvas.SetToolTipString('')
1705        sizexy = Data['size']
1706        if event.xdata and event.ydata:                 #avoid out of frame errors
1707            Page.canvas.SetCursor(wx.CROSS_CURSOR)
1708            item = G2frame.itemPicked
1709            pixelSize = Data['pixelSize']
1710            scalex = 1000./pixelSize[0]
1711            scaley = 1000./pixelSize[1]
1712            if item and G2frame.PatternTree.GetItemText(G2frame.PickId) == 'Image Controls':
1713                if 'Text' in str(item):
1714                    Page.canvas.SetToolTipString('%8.3f %8.3fmm'%(event.xdata,event.ydata))
1715                else:
1716                    xcent,ycent = Data['center']
1717                    xpos = event.xdata-xcent
1718                    ypos = event.ydata-ycent
1719                    tth,azm = G2img.GetTthAzm(event.xdata,event.ydata,Data)
1720                    if 'line3' in  str(item) or 'line4' in str(item) and not Data['fullIntegrate']:
1721                        Page.canvas.SetToolTipString('%6d deg'%(azm))
1722                    elif 'line1' in  str(item) or 'line2' in str(item):
1723                        Page.canvas.SetToolTipString('%8.3fdeg'%(tth))                           
1724            else:
1725                xpos = event.xdata
1726                ypos = event.ydata
1727                xpix = xpos*scalex
1728                ypix = ypos*scaley
1729                Int = 0
1730                if (0 <= xpix <= sizexy[0]) and (0 <= ypix <= sizexy[1]):
1731                    Int = G2frame.ImageZ[ypix][xpix]
1732                tth,azm,dsp = G2img.GetTthAzmDsp(xpos,ypos,Data)
1733                Q = 2.*math.pi/dsp
1734                if G2frame.setPoly:
1735                    G2frame.G2plotNB.status.SetFields(['','Polygon mask pick - LB next point, RB close polygon'])
1736                else:
1737                    G2frame.G2plotNB.status.SetFields(\
1738                        ['','Detector 2-th =%9.3fdeg, dsp =%9.3fA, Q = %6.5fA-1, azm = %7.2fdeg, I = %6d'%(tth,dsp,Q,azm,Int)])
1739
1740    def OnImPlotKeyPress(event):
1741        try:
1742            PickName = G2frame.PatternTree.GetItemText(G2frame.PickId)
1743        except TypeError:
1744            return
1745        if PickName == 'Masks':
1746            Xpos = event.xdata
1747            if not Xpos:            #got point out of frame
1748                return
1749            Ypos = event.ydata
1750            if event.key == 's':
1751                Masks['Points'].append([Xpos,Ypos,1.])
1752            elif event.key == 'r':
1753                tth = G2img.GetTth(Xpos,Ypos,Data)
1754                Masks['Rings'].append([tth,0.1])
1755            elif event.key == 'a':
1756                tth,azm = G2img.GetTthAzm(Xpos,Ypos,Data)
1757                azm = int(azm)               
1758                Masks['Arcs'].append([tth,[azm-5,azm+5],0.1])
1759            elif event.key == 'p':
1760                G2frame.setPoly = True
1761                Masks['Polygons'].append([])
1762                G2frame.G2plotNB.status.SetFields(['','Polygon mask active - LB pick next point, RB close polygon'])
1763            G2imG.UpdateMasks(G2frame,Masks)
1764        elif PickName == 'Image Controls':
1765            if event.key == 'c':
1766                Xpos = event.xdata
1767                if not Xpos:            #got point out of frame
1768                    return
1769                Ypos = event.ydata
1770                dlg = wx.MessageDialog(G2frame,'Are you sure you want to change the center?',
1771                    'Center change',style=wx.OK|wx.CANCEL)
1772                try:
1773                    if dlg.ShowModal() == wx.ID_OK:
1774                        print 'move center to: ',Xpos,Ypos
1775                        Data['center'] = [Xpos,Ypos]
1776                        G2imG.UpdateImageControls(G2frame,Data,Masks)
1777                finally:
1778                    dlg.Destroy()
1779            elif event.key == 'l':
1780                if G2frame.logPlot:
1781                    G2frame.logPlot = False
1782                else:
1783                    G2frame.logPlot = True
1784        PlotImage(G2frame,newImage=True)
1785           
1786    def OnKeyBox(event):
1787        if G2frame.G2plotNB.nb.GetSelection() == G2frame.G2plotNB.plotList.index('2D Powder Image'):
1788            event.key = cb.GetValue()[0]
1789            cb.SetValue(' key press')
1790            if event.key in 'l':
1791                OnImPlotKeyPress(event)
1792                       
1793    def OnImPick(event):
1794        if G2frame.PatternTree.GetItemText(G2frame.PickId) not in ['Image Controls','Masks']:
1795            return
1796        if G2frame.setPoly:
1797            polygon = Masks['Polygons'][-1]
1798            xpos,ypos = event.mouseevent.xdata,event.mouseevent.ydata
1799            if xpos and ypos:                       #point inside image
1800                if len(polygon) > 2 and event.mouseevent.button == 3:
1801                    x0,y0 = polygon[0]
1802                    polygon.append([x0,y0])
1803                    G2frame.setPoly = False
1804                    G2frame.G2plotNB.status.SetFields(['','Polygon closed - RB drag a vertex to change shape'])
1805                else:
1806                    G2frame.G2plotNB.status.SetFields(['','New polygon point: %.1f,%.1f'%(xpos,ypos)])
1807                    polygon.append([xpos,ypos])
1808                G2imG.UpdateMasks(G2frame,Masks)
1809        else:
1810            if G2frame.itemPicked is not None: return
1811            G2frame.itemPicked = event.artist
1812            G2frame.mousePicked = event.mouseevent
1813       
1814    def OnImRelease(event):
1815        try:
1816            PickName = G2frame.PatternTree.GetItemText(G2frame.PickId)
1817        except TypeError:
1818            return
1819        if PickName not in ['Image Controls','Masks']:
1820            return
1821        pixelSize = Data['pixelSize']
1822        scalex = 1000./pixelSize[0]
1823        scaley = 1000./pixelSize[1]
1824        pixLimit = Data['pixLimit']
1825        if G2frame.itemPicked is None and PickName == 'Image Controls':
1826#            sizexy = Data['size']
1827            Xpos = event.xdata
1828            if not (Xpos and G2frame.ifGetRing):                   #got point out of frame
1829                return
1830            Ypos = event.ydata
1831            if Ypos and not Page.toolbar._active:         #make sure zoom/pan not selected
1832                if event.button == 1:
1833                    Xpix = Xpos*scalex
1834                    Ypix = Ypos*scaley
1835                    xpos,ypos,I,J = G2img.ImageLocalMax(G2frame.ImageZ,pixLimit,Xpix,Ypix)
1836                    if I and J:
1837                        xpos += .5                              #shift to pixel center
1838                        ypos += .5
1839                        xpos /= scalex                          #convert to mm
1840                        ypos /= scaley
1841                        Data['ring'].append([xpos,ypos])
1842                elif event.button == 3:
1843                    G2frame.dataFrame.GetStatusBar().SetStatusText('Calibrating...')
1844                    if G2img.ImageCalibrate(G2frame,Data):
1845                        G2frame.dataFrame.GetStatusBar().SetStatusText('Calibration successful - Show ring picks to check')
1846                        print 'Calibration successful'
1847                    else:
1848                        G2frame.dataFrame.GetStatusBar().SetStatusText('Calibration failed - Show ring picks to diagnose')
1849                        print 'Calibration failed'
1850                    G2frame.ifGetRing = False
1851                    G2imG.UpdateImageControls(G2frame,Data,Masks)
1852                    return
1853                PlotImage(G2frame,newImage=False)
1854            return
1855        else:
1856            xpos = event.xdata
1857            if xpos:                                        #avoid out of frame mouse position
1858                ypos = event.ydata
1859                if G2frame.ifGetRing:                          #delete a calibration ring pick
1860                    xypos = [xpos,ypos]
1861                    rings = Data['ring']
1862                    for ring in rings:
1863                        if np.allclose(ring,xypos,.01,0):
1864                            rings.remove(ring)                                                                       
1865                else:
1866                    tth,azm,dsp = G2img.GetTthAzmDsp(xpos,ypos,Data)
1867                    itemPicked = str(G2frame.itemPicked)
1868                    if 'Line2D' in itemPicked and PickName == 'Image Controls':
1869                        if 'line1' in itemPicked:
1870                            Data['IOtth'][0] = max(tth,0.001)
1871                        elif 'line2' in itemPicked:
1872                            Data['IOtth'][1] = tth
1873                        elif 'line3' in itemPicked:
1874                            Data['LRazimuth'][0] = int(azm)
1875                            if Data['fullIntegrate']:
1876                                Data['LRazimuth'][1] = Data['LRazimuth'][0]+360
1877                        elif 'line4' in itemPicked and not Data['fullIntegrate']:
1878                            Data['LRazimuth'][1] = int(azm)
1879                           
1880                        if Data['LRazimuth'][0] > Data['LRazimuth'][1]:
1881                            Data['LRazimuth'][0] -= 360
1882                           
1883                        azLim = np.array(Data['LRazimuth'])   
1884                        if np.any(azLim>360):
1885                            azLim -= 360
1886                            Data['LRazimuth'] = list(azLim)
1887                           
1888                        if  Data['IOtth'][0] > Data['IOtth'][1]:
1889                            Data['IOtth'][0],Data['IOtth'][1] = Data['IOtth'][1],Data['IOtth'][0]
1890                           
1891                        G2frame.InnerTth.SetValue("%8.2f" % (Data['IOtth'][0]))
1892                        G2frame.OuterTth.SetValue("%8.2f" % (Data['IOtth'][1]))
1893                        G2frame.Lazim.SetValue("%6d" % (Data['LRazimuth'][0]))
1894                        G2frame.Razim.SetValue("%6d" % (Data['LRazimuth'][1]))
1895                    elif 'Circle' in itemPicked and PickName == 'Masks':
1896                        spots = Masks['Points']
1897                        newPos = itemPicked.split(')')[0].split('(')[2].split(',')
1898                        newPos = np.array([float(newPos[0]),float(newPos[1])])
1899                        for spot in spots:
1900                            if np.allclose(np.array([spot[:2]]),newPos):
1901                                spot[:2] = xpos,ypos
1902                        G2imG.UpdateMasks(G2frame,Masks)
1903                    elif 'Line2D' in itemPicked and PickName == 'Masks':
1904                        Obj = G2frame.itemPicked.findobj()
1905                        rings = Masks['Rings']
1906                        arcs = Masks['Arcs']
1907                        polygons = Masks['Polygons']
1908                        for ring in G2frame.ringList:
1909                            if Obj == ring[0]:
1910                                rN = ring[1]
1911                                if ring[2] == 'o':
1912                                    rings[rN][0] = G2img.GetTth(xpos,ypos,Data)-rings[rN][1]/2.
1913                                else:
1914                                    rings[rN][0] = G2img.GetTth(xpos,ypos,Data)+rings[rN][1]/2.
1915                        for arc in G2frame.arcList:
1916                            if Obj == arc[0]:
1917                                aN = arc[1]
1918                                if arc[2] == 'o':
1919                                    arcs[aN][0] = G2img.GetTth(xpos,ypos,Data)-arcs[aN][2]/2
1920                                elif arc[2] == 'i':
1921                                    arcs[aN][0] = G2img.GetTth(xpos,ypos,Data)+arcs[aN][2]/2
1922                                elif arc[2] == 'l':
1923                                    arcs[aN][1][0] = int(G2img.GetAzm(xpos,ypos,Data))
1924                                else:
1925                                    arcs[aN][1][1] = int(G2img.GetAzm(xpos,ypos,Data))
1926                        for poly in G2frame.polyList:
1927                            if Obj == poly[0]:
1928                                ind = G2frame.itemPicked.contains(G2frame.mousePicked)[1]['ind'][0]
1929                                oldPos = np.array([G2frame.mousePicked.xdata,G2frame.mousePicked.ydata])
1930                                pN = poly[1]
1931                                for i,xy in enumerate(polygons[pN]):
1932                                    if np.allclose(np.array([xy]),oldPos,atol=1.0):
1933                                        polygons[pN][i] = xpos,ypos
1934                        G2imG.UpdateMasks(G2frame,Masks)
1935#                    else:                  #keep for future debugging
1936#                        print str(G2frame.itemPicked),event.xdata,event.ydata,event.button
1937                PlotImage(G2frame,newImage=True)
1938            G2frame.itemPicked = None
1939           
1940    try:
1941        plotNum = G2frame.G2plotNB.plotList.index('2D Powder Image')
1942        Page = G2frame.G2plotNB.nb.GetPage(plotNum)
1943        if not newPlot:
1944            Plot = Page.figure.gca()          #get previous powder plot & get limits
1945            xylim = Plot.get_xlim(),Plot.get_ylim()
1946        if newImage:
1947            Page.figure.clf()
1948            Plot = Page.figure.gca()          #get a fresh plot after clf()
1949       
1950    except ValueError:
1951        Plot = G2frame.G2plotNB.addMpl('2D Powder Image').gca()
1952        plotNum = G2frame.G2plotNB.plotList.index('2D Powder Image')
1953        Page = G2frame.G2plotNB.nb.GetPage(plotNum)
1954        Page.canvas.mpl_connect('key_press_event', OnImPlotKeyPress)
1955        Page.canvas.mpl_connect('motion_notify_event', OnImMotion)
1956        Page.canvas.mpl_connect('pick_event', OnImPick)
1957        Page.canvas.mpl_connect('button_release_event', OnImRelease)
1958        xylim = []
1959    if not event:                       #event from GUI TextCtrl - don't want focus to change to plot!!!
1960        Page.SetFocus()
1961    Title = G2frame.PatternTree.GetItemText(G2frame.Image)[4:]
1962    G2frame.G2plotNB.status.DestroyChildren()
1963    if G2frame.logPlot:
1964        Title = 'log('+Title+')'
1965    Plot.set_title(Title)
1966    try:
1967        if G2frame.PatternTree.GetItemText(G2frame.PickId) in ['Image Controls',]:
1968            Choice = (' key press','l: log(I) on',)
1969            if G2frame.logPlot:
1970                Choice[1] = 'l: log(I) off'
1971            cb = wx.ComboBox(G2frame.G2plotNB.status,style=wx.CB_DROPDOWN|wx.CB_READONLY,
1972                choices=Choice)
1973            cb.Bind(wx.EVT_COMBOBOX, OnKeyBox)
1974            cb.SetValue(' key press')
1975    except TypeError:
1976        pass
1977    size,imagefile = G2frame.PatternTree.GetItemPyData(G2frame.Image)
1978    if imagefile != G2frame.oldImagefile:
1979        imagefile = G2IO.CheckImageFile(G2frame,imagefile)
1980        if not imagefile:
1981            G2frame.G2plotNB.Delete('2D Powder Image')
1982            return
1983        G2frame.PatternTree.SetItemPyData(G2frame.Image,[size,imagefile])
1984        G2frame.ImageZ = G2IO.GetImageData(G2frame,imagefile,imageOnly=True)
1985#        print G2frame.ImageZ.shape,G2frame.ImageZ.size,Data['size'] #might be useful debugging line
1986        G2frame.oldImagefile = imagefile
1987
1988    imScale = 1
1989    if len(G2frame.ImageZ) > 1024:
1990        imScale = len(G2frame.ImageZ)/1024
1991    sizexy = Data['size']
1992    pixelSize = Data['pixelSize']
1993    scalex = 1000./pixelSize[0]
1994    scaley = 1000./pixelSize[1]
1995    Xmax = sizexy[0]*pixelSize[0]/1000.
1996    Ymax = sizexy[1]*pixelSize[1]/1000.
1997    xlim = (0,Xmax)
1998    ylim = (Ymax,0)
1999    Imin,Imax = Data['range'][1]
2000    acolor = mpl.cm.get_cmap(Data['color'])
2001    xcent,ycent = Data['center']
2002    Plot.set_xlabel('Image x-axis, mm',fontsize=12)
2003    Plot.set_ylabel('Image y-axis, mm',fontsize=12)
2004    #do threshold mask - "real" mask - others are just bondaries
2005    Zlim = Masks['Thresholds'][1]
2006    wx.BeginBusyCursor()
2007    try:
2008           
2009        if newImage:                   
2010            MA = ma.masked_greater(ma.masked_less(G2frame.ImageZ,Zlim[0]),Zlim[1])
2011            MaskA = ma.getmaskarray(MA)
2012            A = G2img.ImageCompress(MA,imScale)
2013            AM = G2img.ImageCompress(MaskA,imScale)
2014            if G2frame.logPlot:
2015                A = np.where(A>0,np.log(A),0)
2016                AM = np.where(AM>0,np.log(AM),0)
2017                Imin,Imax = [np.amin(A),np.amax(A)]
2018            ImgM = Plot.imshow(AM,aspect='equal',cmap='Reds',
2019                interpolation='nearest',vmin=0,vmax=2,extent=[0,Xmax,Ymax,0])
2020            Img = Plot.imshow(A,aspect='equal',cmap=acolor,
2021                interpolation='nearest',vmin=Imin,vmax=Imax,extent=[0,Xmax,Ymax,0])
2022            if G2frame.setPoly:
2023                Img.set_picker(True)
2024   
2025        Plot.plot(xcent,ycent,'x')
2026        if Data['showLines']:
2027            LRAzim = Data['LRazimuth']                  #NB: integers
2028            Nazm = Data['outAzimuths']
2029            delAzm = float(LRAzim[1]-LRAzim[0])/Nazm
2030            AzmthOff = Data['azmthOff']
2031            IOtth = Data['IOtth']
2032            wave = Data['wavelength']
2033            dspI = wave/(2.0*sind(IOtth[0]/2.0))
2034            ellI = G2img.GetEllipse(dspI,Data)           #=False if dsp didn't yield an ellipse (ugh! a parabola or a hyperbola)
2035            dspO = wave/(2.0*sind(IOtth[1]/2.0))
2036            ellO = G2img.GetEllipse(dspO,Data)           #Ditto & more likely for outer ellipse
2037            Azm = np.array(range(LRAzim[0],LRAzim[1]+1))-AzmthOff
2038            if ellI:
2039                xyI = []
2040                for azm in Azm:
2041                    xyI.append(G2img.GetDetectorXY(dspI,azm-90.,Data))
2042                xyI = np.array(xyI)
2043                arcxI,arcyI = xyI.T
2044                Plot.plot(arcxI,arcyI,picker=3)
2045            if ellO:
2046                xyO = []
2047                for azm in Azm:
2048                    xyO.append(G2img.GetDetectorXY(dspO,azm-90.,Data))
2049                xyO = np.array(xyO)
2050                arcxO,arcyO = xyO.T
2051                Plot.plot(arcxO,arcyO,picker=3)
2052            if ellO and ellI:
2053                Plot.plot([arcxI[0],arcxO[0]],[arcyI[0],arcyO[0]],picker=3)
2054                Plot.plot([arcxI[-1],arcxO[-1]],[arcyI[-1],arcyO[-1]],picker=3)
2055            for i in range(Nazm):
2056                cake = LRAzim[0]+i*delAzm-AzmthOff
2057                ind = np.searchsorted(Azm,cake)
2058                Plot.plot([arcxI[ind],arcxO[ind]],[arcyI[ind],arcyO[ind]],color='k',dashes=(5,5))
2059                   
2060        for xring,yring in Data['ring']:
2061            Plot.plot(xring,yring,'r+',picker=3)
2062        if Data['setRings']:
2063#            rings = np.concatenate((Data['rings']),axis=0)
2064            N = 0
2065            for ring in Data['rings']:
2066                xring,yring = np.array(ring).T[:2]
2067                Plot.plot(xring,yring,'+',color=colors[N%6])
2068                N += 1           
2069        for ellipse in Data['ellipses']:
2070            cent,phi,[width,height],col = ellipse
2071            Plot.add_artist(Ellipse([cent[0],cent[1]],2*width,2*height,phi,ec=col,fc='none'))
2072            Plot.text(cent[0],cent[1],'+',color=col,ha='center',va='center')
2073        #masks - mask lines numbered after integration limit lines
2074        spots = Masks['Points']
2075        rings = Masks['Rings']
2076        arcs = Masks['Arcs']
2077        polygons = Masks['Polygons']
2078        for x,y,d in spots:
2079            Plot.add_artist(Circle((x,y),radius=d/2,fc='none',ec='r',picker=3))
2080        G2frame.ringList = []
2081        for iring,(tth,thick) in enumerate(rings):
2082            wave = Data['wavelength']
2083            x1,y1 = np.hsplit(np.array(G2img.makeIdealRing(G2img.GetEllipse(Dsp(tth+thick/2.,wave),Data))),2)
2084            x2,y2 = np.hsplit(np.array(G2img.makeIdealRing(G2img.GetEllipse(Dsp(tth-thick/2.,wave),Data))),2)
2085            G2frame.ringList.append([Plot.plot(x1,y1,'r',picker=3),iring,'o'])           
2086            G2frame.ringList.append([Plot.plot(x2,y2,'r',picker=3),iring,'i'])
2087        G2frame.arcList = []
2088        for iarc,(tth,azm,thick) in enumerate(arcs):           
2089            wave = Data['wavelength']
2090            x1,y1 = np.hsplit(np.array(G2img.makeIdealRing(G2img.GetEllipse(Dsp(tth+thick/2.,wave),Data),azm)),2)
2091            x2,y2 = np.hsplit(np.array(G2img.makeIdealRing(G2img.GetEllipse(Dsp(max(0.01,tth-thick/2.),wave),Data),azm)),2)
2092            G2frame.arcList.append([Plot.plot(x1,y1,'r',picker=3),iarc,'o'])           
2093            G2frame.arcList.append([Plot.plot(x2,y2,'r',picker=3),iarc,'i'])
2094            G2frame.arcList.append([Plot.plot([x1[0],x2[0]],[y1[0],y2[0]],'r',picker=3),iarc,'l'])
2095            G2frame.arcList.append([Plot.plot([x1[-1],x2[-1]],[y1[-1],y2[-1]],'r',picker=3),iarc,'u'])
2096        G2frame.polyList = []
2097        for ipoly,polygon in enumerate(polygons):
2098            x,y = np.hsplit(np.array(polygon),2)
2099            G2frame.polyList.append([Plot.plot(x,y,'r+',picker=10),ipoly])
2100            Plot.plot(x,y,'r')           
2101        if newImage:
2102            colorBar = Page.figure.colorbar(Img)
2103        Plot.set_xlim(xlim)
2104        Plot.set_ylim(ylim)
2105        Plot.invert_yaxis()
2106        if not newPlot and xylim:
2107            Page.toolbar.push_current()
2108            Plot.set_xlim(xylim[0])
2109            Plot.set_ylim(xylim[1])
2110            xylim = []
2111            Page.toolbar.push_current()
2112            Page.toolbar.draw()
2113        else:
2114            Page.canvas.draw()
2115    finally:
2116        wx.EndBusyCursor()
2117       
2118################################################################################
2119##### PlotIntegration
2120################################################################################
2121           
2122def PlotIntegration(G2frame,newPlot=False,event=None):
2123    '''Plot of 2D image after image integration with 2-theta and azimuth as coordinates
2124    '''
2125           
2126    def OnMotion(event):
2127        Page.canvas.SetToolTipString('')
2128        Page.canvas.SetCursor(wx.CROSS_CURSOR)
2129        azm = event.ydata
2130        tth = event.xdata
2131        if azm and tth:
2132            G2frame.G2plotNB.status.SetFields(\
2133                ['','Detector 2-th =%9.3fdeg, azm = %7.2fdeg'%(tth,azm)])
2134                               
2135    try:
2136        plotNum = G2frame.G2plotNB.plotList.index('2D Integration')
2137        Page = G2frame.G2plotNB.nb.GetPage(plotNum)
2138        if not newPlot:
2139            Plot = Page.figure.gca()          #get previous plot & get limits
2140            xylim = Plot.get_xlim(),Plot.get_ylim()
2141        Page.figure.clf()
2142        Plot = Page.figure.gca()          #get a fresh plot after clf()
2143       
2144    except ValueError:
2145        Plot = G2frame.G2plotNB.addMpl('2D Integration').gca()
2146        plotNum = G2frame.G2plotNB.plotList.index('2D Integration')
2147        Page = G2frame.G2plotNB.nb.GetPage(plotNum)
2148        Page.canvas.mpl_connect('motion_notify_event', OnMotion)
2149        Page.views = False
2150        view = False
2151    if not event:
2152        Page.SetFocus()
2153       
2154    Data = G2frame.PatternTree.GetItemPyData(
2155        G2gd.GetPatternTreeItemId(G2frame,G2frame.Image, 'Image Controls'))
2156    image = G2frame.Integrate[0]
2157    xsc = G2frame.Integrate[1]
2158    ysc = G2frame.Integrate[2]
2159    Imin,Imax = Data['range'][1]
2160    acolor = mpl.cm.get_cmap(Data['color'])
2161    Plot.set_title(G2frame.PatternTree.GetItemText(G2frame.Image)[4:])
2162    Plot.set_ylabel('azimuth',fontsize=12)
2163    Plot.set_xlabel('2-theta',fontsize=12)
2164    Img = Plot.imshow(image,cmap=acolor,vmin=Imin,vmax=Imax,interpolation='nearest', \
2165        extent=[ysc[0],ysc[-1],xsc[-1],xsc[0]],aspect='auto')
2166    colorBar = Page.figure.colorbar(Img)
2167    if Data['ellipses']:           
2168        for ellipse in Data['ellipses']:
2169            ring = np.array(G2img.makeIdealRing(ellipse[:3])) #skip color
2170            x,y = np.hsplit(ring,2)
2171            tth,azm = G2img.GetTthAzm(x,y,Data)
2172#            azm = np.where(azm < 0.,azm+360,azm)
2173            Plot.plot(tth,azm,'b,')
2174    if not newPlot:
2175        Page.toolbar.push_current()
2176        Plot.set_xlim(xylim[0])
2177        Plot.set_ylim(xylim[1])
2178        xylim = []
2179        Page.toolbar.push_current()
2180        Page.toolbar.draw()
2181    else:
2182        Page.canvas.draw()
2183               
2184################################################################################
2185##### PlotTRImage
2186################################################################################
2187           
2188def PlotTRImage(G2frame,tax,tay,taz,newPlot=False):
2189    '''a test plot routine - not normally used
2190    ''' 
2191           
2192    def OnMotion(event):
2193        Page.canvas.SetToolTipString('')
2194        Page.canvas.SetCursor(wx.CROSS_CURSOR)
2195        azm = event.xdata
2196        tth = event.ydata
2197        if azm and tth:
2198            G2frame.G2plotNB.status.SetFields(\
2199                ['','Detector 2-th =%9.3fdeg, azm = %7.2fdeg'%(tth,azm)])
2200                               
2201    try:
2202        plotNum = G2frame.G2plotNB.plotList.index('2D Transformed Powder Image')
2203        Page = G2frame.G2plotNB.nb.GetPage(plotNum)
2204        if not newPlot:
2205            Plot = Page.figure.gca()          #get previous plot & get limits
2206            xylim = Plot.get_xlim(),Plot.get_ylim()
2207        Page.figure.clf()
2208        Plot = Page.figure.gca()          #get a fresh plot after clf()
2209       
2210    except ValueError:
2211        Plot = G2frame.G2plotNB.addMpl('2D Transformed Powder Image').gca()
2212        plotNum = G2frame.G2plotNB.plotList.index('2D Transformed Powder Image')
2213        Page = G2frame.G2plotNB.nb.GetPage(plotNum)
2214        Page.canvas.mpl_connect('motion_notify_event', OnMotion)
2215        Page.views = False
2216        view = False
2217    Page.SetFocus()
2218       
2219    Data = G2frame.PatternTree.GetItemPyData(
2220        G2gd.GetPatternTreeItemId(G2frame,G2frame.Image, 'Image Controls'))
2221    Imin,Imax = Data['range'][1]
2222    step = (Imax-Imin)/5.
2223    V = np.arange(Imin,Imax,step)
2224    acolor = mpl.cm.get_cmap(Data['color'])
2225    Plot.set_title(G2frame.PatternTree.GetItemText(G2frame.Image)[4:])
2226    Plot.set_xlabel('azimuth',fontsize=12)
2227    Plot.set_ylabel('2-theta',fontsize=12)
2228    Plot.contour(tax,tay,taz,V,cmap=acolor)
2229    if Data['showLines']:
2230        IOtth = Data['IOtth']
2231        if Data['fullIntegrate']:
2232            LRAzim = [-180,180]
2233        else:
2234            LRAzim = Data['LRazimuth']                  #NB: integers
2235        Plot.plot([LRAzim[0],LRAzim[1]],[IOtth[0],IOtth[0]],picker=True)
2236        Plot.plot([LRAzim[0],LRAzim[1]],[IOtth[1],IOtth[1]],picker=True)
2237        if not Data['fullIntegrate']:
2238            Plot.plot([LRAzim[0],LRAzim[0]],[IOtth[0],IOtth[1]],picker=True)
2239            Plot.plot([LRAzim[1],LRAzim[1]],[IOtth[0],IOtth[1]],picker=True)
2240    if Data['setRings']:
2241        rings = np.concatenate((Data['rings']),axis=0)
2242        for xring,yring,dsp in rings:
2243            x,y = G2img.GetTthAzm(xring,yring,Data)
2244            Plot.plot(y,x,'r+')           
2245    if Data['ellipses']:           
2246        for ellipse in Data['ellipses']:
2247            ring = np.array(G2img.makeIdealRing(ellipse[:3])) #skip color
2248            x,y = np.hsplit(ring,2)
2249            tth,azm = G2img.GetTthAzm(x,y,Data)
2250            Plot.plot(azm,tth,'b,')
2251    if not newPlot:
2252        Page.toolbar.push_current()
2253        Plot.set_xlim(xylim[0])
2254        Plot.set_ylim(xylim[1])
2255        xylim = []
2256        Page.toolbar.push_current()
2257        Page.toolbar.draw()
2258    else:
2259        Page.canvas.draw()
2260       
2261################################################################################
2262##### PlotStructure
2263################################################################################
2264           
2265def PlotStructure(G2frame,data):
2266    '''Crystal structure plotting package. Can show structures as balls, sticks, lines,
2267    thermal motion ellipsoids and polyhedra
2268    '''
2269    ForthirdPI = 4.0*math.pi/3.0
2270    generalData = data['General']
2271    cell = generalData['Cell'][1:7]
2272    Vol = generalData['Cell'][7:8][0]
2273    Amat,Bmat = G2lat.cell2AB(cell)         #Amat - crystal to cartesian, Bmat - inverse
2274    A4mat = np.concatenate((np.concatenate((Amat,[[0],[0],[0]]),axis=1),[[0,0,0,1],]),axis=0)
2275    B4mat = np.concatenate((np.concatenate((Bmat,[[0],[0],[0]]),axis=1),[[0,0,0,1],]),axis=0)
2276    Mydir = generalData['Mydir']
2277    atomData = data['Atoms']
2278    drawingData = data['Drawing']
2279    drawAtoms = drawingData['Atoms']
2280    mapData = {}
2281    rhoXYZ = []
2282    if 'Map' in generalData:
2283        mapData = generalData['Map']
2284    cx,ct,cs = drawingData['atomPtrs']
2285    Wt = np.array([255,255,255])
2286    Rd = np.array([255,0,0])
2287    Gr = np.array([0,255,0])
2288    Bl = np.array([0,0,255])
2289    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]])
2290    uEdges = np.array([
2291        [uBox[0],uBox[1]],[uBox[0],uBox[3]],[uBox[0],uBox[4]],[uBox[1],uBox[2]], 
2292        [uBox[2],uBox[3]],[uBox[1],uBox[5]],[uBox[2],uBox[6]],[uBox[3],uBox[7]], 
2293        [uBox[4],uBox[5]],[uBox[5],uBox[6]],[uBox[6],uBox[7]],[uBox[7],uBox[4]]])
2294    uColors = [Rd,Gr,Bl,Wt, Wt,Wt,Wt,Wt, Wt,Wt,Wt,Wt]
2295    altDown = False
2296    shiftDown = False
2297    ctrlDown = False
2298   
2299    def OnKeyBox(event):
2300        import Image
2301        Draw()                          #make sure plot is fresh!!
2302        mode = cb.GetValue()
2303        Fname = Mydir+'\\'+generalData['Name']+'.'+mode
2304        size = Page.canvas.GetSize()
2305        glPixelStorei(GL_UNPACK_ALIGNMENT, 1)
2306        if mode in ['jpeg',]:
2307            Pix = glReadPixels(0,0,size[0],size[1],GL_RGBA, GL_UNSIGNED_BYTE)
2308            im = Image.new("RGBA", (size[0],size[1]))
2309        else:
2310            Pix = glReadPixels(0,0,size[0],size[1],GL_RGB, GL_UNSIGNED_BYTE)
2311            im = Image.new("RGB", (size[0],size[1]))
2312        im.fromstring(Pix)
2313        im.save(Fname,mode)
2314        cb.SetValue(' Save as:')
2315        G2frame.G2plotNB.status.SetStatusText('Drawing saved to: '+Fname,1)
2316   
2317    def GetTruePosition(xy,Add=False):
2318        View = glGetIntegerv(GL_VIEWPORT)
2319        Proj = glGetDoublev(GL_PROJECTION_MATRIX)
2320        Model = glGetDoublev(GL_MODELVIEW_MATRIX)
2321        Zmax = 1.
2322        if Add:
2323            Indx = GetSelectedAtoms()
2324        for i,atom in enumerate(drawAtoms):
2325            x,y,z = atom[cx:cx+3]
2326            X,Y,Z = gluProject(x,y,z,Model,Proj,View)
2327            XY = [int(X),int(View[3]-Y)]
2328            if np.allclose(xy,XY,atol=10) and Z < Zmax:
2329                Zmax = Z
2330                try:
2331                    Indx.remove(i)
2332                    ClearSelectedAtoms()
2333                    for id in Indx:
2334                        SetSelectedAtoms(id,Add)
2335                except:
2336                    SetSelectedAtoms(i,Add)
2337                   
2338    def OnMouseDown(event):
2339        xy = event.GetPosition()
2340        if event.ShiftDown():
2341            if event.LeftIsDown():
2342                GetTruePosition(xy)
2343            elif event.RightIsDown():
2344                GetTruePosition(xy,True)
2345        else:
2346            drawingData['Rotation'][3] = list(xy)
2347        Draw()
2348       
2349    def OnMouseMove(event):
2350        if event.ShiftDown():
2351            return       
2352        newxy = event.GetPosition()
2353        page = getSelection()
2354        if event.ControlDown() and drawingData['showABC']:
2355            if event.LeftIsDown():
2356                SetTestRot(newxy)
2357            elif event.RightIsDown():
2358                SetTestPos(newxy)
2359            elif event.MiddleIsDown():
2360                SetTestRotZ(newxy)
2361            x,y,z = drawingData['testPos'][0]
2362            G2frame.G2plotNB.status.SetStatusText('moving test point %.4f,%.4f,%.4f'%(x,y,z),1)
2363            Draw()
2364                               
2365        if event.Dragging() and not event.ControlDown():
2366            if event.LeftIsDown():
2367                SetRotation(newxy)
2368                angX,angY,angZ = drawingData['Rotation'][:3]
2369                G2frame.G2plotNB.status.SetStatusText('New rotation: %.2f, %.2f ,%.2f'%(angX,angY,angZ),1)
2370            elif event.RightIsDown():
2371                SetTranslation(newxy)
2372                Tx,Ty,Tz = drawingData['viewPoint'][0]
2373                G2frame.G2plotNB.status.SetStatusText('New view point: %.4f, %.4f, %.4f'%(Tx,Ty,Tz),1)
2374            elif event.MiddleIsDown():
2375                SetRotationZ(newxy)
2376                angX,angY,angZ = drawingData['Rotation'][:3]
2377                G2frame.G2plotNB.status.SetStatusText('New rotation: %.2f, %.2f, %.2f'%(angX,angY,angZ),1)
2378            Draw()
2379       
2380    def OnMouseWheel(event):
2381        if event.ShiftDown():
2382            return
2383        drawingData['cameraPos'] += event.GetWheelRotation()/24
2384        drawingData['cameraPos'] = max(10,min(500,drawingData['cameraPos']))
2385        G2frame.G2plotNB.status.SetStatusText('New camera distance: %.2f'%(drawingData['cameraPos']),1)
2386        page = getSelection()
2387        if page:
2388            if G2frame.dataDisplay.GetPageText(page) == 'Draw Options':
2389                panel = G2frame.dataDisplay.GetPage(page).GetChildren()[0].GetChildren()
2390                names = [child.GetName() for child in panel]
2391                panel[names.index('cameraPos')].SetLabel('Camera Position: '+'%.2f'%(drawingData['cameraPos']))
2392                panel[names.index('cameraSlider')].SetValue(drawingData['cameraPos'])
2393            Draw()
2394       
2395    def getSelection():
2396        try:
2397            return G2frame.dataDisplay.GetSelection()
2398        except AttributeError:
2399            G2frame.G2plotNB.status.SetStatusText('Select this from Phase data window!')
2400            return 0
2401           
2402    def SetViewPointText(VP):
2403        page = getSelection()
2404        if page:
2405            if G2frame.dataDisplay.GetPageText(page) == 'Draw Options':
2406                panel = G2frame.dataDisplay.GetPage(page).GetChildren()[0].GetChildren()
2407                names = [child.GetName() for child in panel]
2408                panel[names.index('viewPoint')].SetValue('%.3f, %.3f, %.3f'%(VP[0],VP[1],VP[2]))
2409           
2410    def ClearSelectedAtoms():
2411        page = getSelection()
2412        if page:
2413            if G2frame.dataDisplay.GetPageText(page) == 'Draw Atoms':
2414                G2frame.dataDisplay.GetPage(page).ClearSelection()      #this is the Atoms grid in Draw Atoms
2415            elif G2frame.dataDisplay.GetPageText(page) == 'Atoms':
2416                G2frame.dataDisplay.GetPage(page).ClearSelection()      #this is the Atoms grid in Atoms
2417                   
2418    def SetSelectedAtoms(ind,Add=False):
2419        page = getSelection()
2420        if page:
2421            if G2frame.dataDisplay.GetPageText(page) == 'Draw Atoms':
2422                G2frame.dataDisplay.GetPage(page).SelectRow(ind,Add)      #this is the Atoms grid in Draw Atoms
2423            elif G2frame.dataDisplay.GetPageText(page) == 'Atoms':
2424                Id = drawAtoms[ind][-2]
2425                for i,atom in enumerate(atomData):
2426                    if atom[-1] == Id:
2427                        G2frame.dataDisplay.GetPage(page).SelectRow(i)      #this is the Atoms grid in Atoms
2428                 
2429    def GetSelectedAtoms():
2430        page = getSelection()
2431        Ind = []
2432        if page:
2433            if G2frame.dataDisplay.GetPageText(page) == 'Draw Atoms':
2434                Ind = G2frame.dataDisplay.GetPage(page).GetSelectedRows()      #this is the Atoms grid in Draw Atoms
2435            elif G2frame.dataDisplay.GetPageText(page) == 'Atoms':
2436                Ind = G2frame.dataDisplay.GetPage(page).GetSelectedRows()      #this is the Atoms grid in Atoms
2437        return Ind
2438                                       
2439    def OnKey(event):           #on key UP!!
2440        keyCode = event.GetKeyCode()
2441        if keyCode > 255:
2442            keyCode = 0
2443        key,xyz = chr(keyCode),event.GetPosition()
2444        indx = drawingData['selectedAtoms']
2445        if key in ['c','C']:
2446            drawingData['viewPoint'] = [[.5,.5,.5],[0,0]]
2447            drawingData['testPos'] = [[-.1,-.1,-.1],[0.0,0.0,0.0],[0,0]]
2448            drawingData['Rotation'] = [0.0,0.0,0.0,[]]
2449            SetViewPointText(drawingData['viewPoint'][0])
2450        elif key in ['n','N']:
2451            drawAtoms = drawingData['Atoms']
2452            pI = drawingData['viewPoint'][1]
2453            if indx:
2454                pI[0] = indx[pI[1]]
2455                Tx,Ty,Tz = drawAtoms[pI[0]][cx:cx+3]
2456                pI[1] += 1
2457                if pI[1] >= len(indx):
2458                    pI[1] = 0
2459            else:
2460                Tx,Ty,Tz = drawAtoms[pI[0]][cx:cx+3]               
2461                pI[0] += 1
2462                if pI[0] >= len(drawAtoms):
2463                    pI[0] = 0
2464            drawingData['viewPoint'] = [[Tx,Ty,Tz],pI]
2465            SetViewPointText(drawingData['viewPoint'][0])
2466            G2frame.G2plotNB.status.SetStatusText('View point at atom '+drawAtoms[pI[0]][ct-1]+str(pI),1)
2467               
2468        elif key in ['p','P']:
2469            drawAtoms = drawingData['Atoms']
2470            pI = drawingData['viewPoint'][1]
2471            if indx:
2472                pI[0] = indx[pI[1]]
2473                Tx,Ty,Tz = drawAtoms[pI[0]][cx:cx+3]
2474                pI[1] -= 1
2475                if pI[1] < 0:
2476                    pI[1] = len(indx)-1
2477            else:
2478                Tx,Ty,Tz = drawAtoms[pI[0]][cx:cx+3]               
2479                pI[0] -= 1
2480                if pI[0] < 0:
2481                    pI[0] = len(drawAtoms)-1
2482            drawingData['viewPoint'] = [[Tx,Ty,Tz],pI]
2483            SetViewPointText(drawingData['viewPoint'][0])           
2484            G2frame.G2plotNB.status.SetStatusText('View point at atom '+drawAtoms[pI[0]][ct-1]+str(pI),1)
2485        Draw()
2486           
2487    def SetBackground():
2488        R,G,B,A = Page.camera['backColor']
2489        glClearColor(R,G,B,A)
2490        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
2491       
2492    def SetLights():
2493        glEnable(GL_DEPTH_TEST)
2494        glShadeModel(GL_SMOOTH)
2495        glEnable(GL_LIGHTING)
2496        glEnable(GL_LIGHT0)
2497        glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,0)
2498        glLightfv(GL_LIGHT0,GL_AMBIENT,[1,1,1,.8])
2499        glLightfv(GL_LIGHT0,GL_DIFFUSE,[1,1,1,1])
2500       
2501    def SetTranslation(newxy):
2502        Tx,Ty,Tz = drawingData['viewPoint'][0]
2503        anglex,angley,anglez,oldxy = drawingData['Rotation']
2504        if not len(oldxy): oldxy = list(newxy)
2505        Rx = G2lat.rotdMat(anglex,0)
2506        Ry = G2lat.rotdMat(angley,1)
2507        Rz = G2lat.rotdMat(anglez,2)
2508        dxy = list(newxy-oldxy)+[0,]
2509        dxy = np.inner(Bmat,np.inner(Rz,np.inner(Ry,np.inner(Rx,dxy))))
2510        Tx -= dxy[0]*0.01
2511        Ty += dxy[1]*0.01
2512        Tz -= dxy[2]*0.01
2513        drawingData['Rotation'][3] = list(newxy)
2514        drawingData['viewPoint'][0] =  Tx,Ty,Tz
2515        SetViewPointText([Tx,Ty,Tz])
2516       
2517    def SetTestPos(newxy):
2518        Tx,Ty,Tz = drawingData['testPos'][0]
2519        anglex,angley,anglez,oldxy = drawingData['Rotation']
2520        if not len(oldxy): oldxy = list(newxy)
2521        Rx = G2lat.rotdMat(anglex,0)
2522        Ry = G2lat.rotdMat(angley,1)
2523        Rz = G2lat.rotdMat(anglez,2)
2524        dxy = list(newxy-oldxy)+[0,]
2525        dxy = np.inner(Rz,np.inner(Ry,np.inner(Rx,dxy)))
2526        Tx += dxy[0]*0.001
2527        Ty -= dxy[1]*0.001
2528        Tz += dxy[2]*0.001
2529        drawingData['Rotation'][3] = list(newxy)
2530        drawingData['testPos'][0] =  Tx,Ty,Tz
2531       
2532    def SetTestRot(newxy):
2533        Txyz = np.array(drawingData['testPos'][0])
2534        oldxy = drawingData['testPos'][2]
2535        Ax,Ay,Az = drawingData['testPos'][1]
2536        Vxyz = np.array(drawingData['viewPoint'][0])
2537        Dxyz = np.inner(Amat,Txyz-Vxyz)
2538        dxy = list(newxy-oldxy)+[0,]
2539        Ax += dxy[1]*0.01
2540        Ay += dxy[0]*0.01
2541        Rx = G2lat.rotdMat(Ax,0)
2542        Ry = G2lat.rotdMat(Ay,1)
2543        Dxyz = np.inner(Ry,np.inner(Rx,Dxyz))       
2544        Dxyz = np.inner(Bmat,Dxyz)+Vxyz
2545        drawingData['testPos'][1] = [Ax,Ay,Az]
2546        drawingData['testPos'][2] = newxy
2547        drawingData['testPos'][0] = Dxyz
2548       
2549    def SetTestRotZ(newxy):
2550        Txyz = np.array(drawingData['testPos'][0])
2551        oldxy = drawingData['testPos'][2]
2552        Ax,Ay,Az = drawingData['testPos'][1]
2553        Vxyz = np.array(drawingData['viewPoint'][0])
2554        Dxyz = np.inner(Amat,Txyz-Vxyz)       
2555        dxy = list(newxy-oldxy)+[0,]
2556        Az += (dxy[0]+dxy[1])*.01
2557        Rz = G2lat.rotdMat(Az,2)
2558        Dxyz = np.inner(Rz,Dxyz)       
2559        Dxyz = np.inner(Bmat,Dxyz)+Vxyz
2560        drawingData['testPos'][1] = [Ax,Ay,Az]
2561        drawingData['testPos'][2] = newxy
2562        drawingData['testPos'][0] = Dxyz
2563                             
2564    def SetRotation(newxy):       
2565        anglex,angley,anglez,oldxy = drawingData['Rotation']
2566        if not len(oldxy): oldxy = list(newxy)
2567        dxy = newxy-oldxy
2568        anglex += dxy[1]*.25
2569        angley += dxy[0]*.25
2570        oldxy = newxy
2571        drawingData['Rotation'] = [anglex,angley,anglez,list(oldxy)]
2572       
2573    def SetRotationZ(newxy):                       
2574        anglex,angley,anglez,oldxy = drawingData['Rotation']
2575        if not len(oldxy): oldxy = list(newxy)
2576        dxy = newxy-oldxy
2577        anglez += (dxy[0]+dxy[1])*.25
2578        oldxy = newxy
2579        drawingData['Rotation'] = [anglex,angley,anglez,list(oldxy)]
2580       
2581    def RenderBox():
2582        glEnable(GL_COLOR_MATERIAL)
2583        glLineWidth(2)
2584        glEnable(GL_BLEND)
2585        glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA)
2586        glEnable(GL_LINE_SMOOTH)
2587        glBegin(GL_LINES)
2588        for line,color in zip(uEdges,uColors):
2589            glColor3ubv(color)
2590            glVertex3fv(line[0])
2591            glVertex3fv(line[1])
2592        glEnd()
2593        glColor4ubv([0,0,0,0])
2594        glDisable(GL_LINE_SMOOTH)
2595        glDisable(GL_BLEND)
2596        glDisable(GL_COLOR_MATERIAL)
2597       
2598    def RenderUnitVectors(x,y,z):
2599        xyz = np.array([x,y,z])
2600        glEnable(GL_COLOR_MATERIAL)
2601        glLineWidth(1)
2602        glPushMatrix()
2603        glTranslate(x,y,z)
2604        glScalef(1/cell[0],1/cell[1],1/cell[2])
2605        glBegin(GL_LINES)
2606        for line,color in zip(uEdges,uColors)[:3]:
2607            glColor3ubv(color)
2608            glVertex3fv(line[0])
2609            glVertex3fv(line[1])
2610        glEnd()
2611        glPopMatrix()
2612        glColor4ubv([0,0,0,0])
2613        glDisable(GL_COLOR_MATERIAL)
2614               
2615    def RenderSphere(x,y,z,radius,color):
2616        glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,color)
2617        glPushMatrix()
2618        glTranslate(x,y,z)
2619        glMultMatrixf(B4mat.T)
2620        q = gluNewQuadric()
2621        gluSphere(q,radius,20,10)
2622        glPopMatrix()
2623       
2624    def RenderSmallSphere(x,y,z,radius,color):
2625        glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,color)
2626        glPushMatrix()
2627        glTranslate(x,y,z)
2628        glMultMatrixf(B4mat.T)
2629        q = gluNewQuadric()
2630        gluSphere(q,radius,4,2)
2631        glPopMatrix()
2632       
2633    def RenderEllipsoid(x,y,z,ellipseProb,E,R4,color):
2634        s1,s2,s3 = E
2635        glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,color)
2636        glPushMatrix()
2637        glTranslate(x,y,z)
2638        glMultMatrixf(B4mat.T)
2639        glMultMatrixf(R4.T)
2640        glEnable(GL_NORMALIZE)
2641        glScale(s1,s2,s3)
2642        q = gluNewQuadric()
2643        gluSphere(q,ellipseProb,20,10)
2644        glDisable(GL_NORMALIZE)
2645        glPopMatrix()
2646       
2647    def RenderBonds(x,y,z,Bonds,radius,color,slice=20):
2648        glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,color)
2649        glPushMatrix()
2650        glTranslate(x,y,z)
2651        glMultMatrixf(B4mat.T)
2652        for bond in Bonds:
2653            glPushMatrix()
2654            Dx = np.inner(Amat,bond)
2655            Z = np.sqrt(np.sum(Dx**2))
2656            azm = atan2d(-Dx[1],-Dx[0])
2657            phi = acosd(Dx[2]/Z)
2658            glRotate(-azm,0,0,1)
2659            glRotate(phi,1,0,0)
2660            q = gluNewQuadric()
2661            gluCylinder(q,radius,radius,Z,slice,2)
2662            glPopMatrix()           
2663        glPopMatrix()
2664               
2665    def RenderLines(x,y,z,Bonds,color):
2666        xyz = np.array([x,y,z])
2667        glEnable(GL_COLOR_MATERIAL)
2668        glLineWidth(1)
2669        glColor3fv(color)
2670        glPushMatrix()
2671        glBegin(GL_LINES)
2672        for bond in Bonds:
2673            glVertex3fv(xyz)
2674            glVertex3fv(xyz+bond)
2675        glEnd()
2676        glColor4ubv([0,0,0,0])
2677        glPopMatrix()
2678        glDisable(GL_COLOR_MATERIAL)
2679       
2680    def RenderPolyhedra(x,y,z,Faces,color):
2681        glPushMatrix()
2682        glTranslate(x,y,z)
2683        glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,color)
2684        glShadeModel(GL_SMOOTH)
2685        glMultMatrixf(B4mat.T)
2686        for face,norm in Faces:
2687            glPolygonMode(GL_FRONT_AND_BACK,GL_FILL)
2688            glFrontFace(GL_CW)
2689            glNormal3fv(norm)
2690            glBegin(GL_TRIANGLES)
2691            for vert in face:
2692                glVertex3fv(vert)
2693            glEnd()
2694        glPopMatrix()
2695       
2696    def RenderBackbone(Backbone,BackboneColor,radius):
2697        glPushMatrix()
2698        glMultMatrixf(B4mat.T)
2699        glEnable(GL_COLOR_MATERIAL)
2700        glShadeModel(GL_SMOOTH)
2701        gleSetJoinStyle(TUBE_NORM_EDGE | TUBE_JN_ANGLE | TUBE_JN_CAP)
2702        glePolyCylinder(Backbone,BackboneColor,radius)
2703        glPopMatrix()       
2704        glDisable(GL_COLOR_MATERIAL)
2705       
2706    def RenderLabel(x,y,z,label,r):       
2707        glPushMatrix()
2708        glTranslate(x,y,z)
2709        glMultMatrixf(B4mat.T)
2710        glDisable(GL_LIGHTING)
2711        glColor3f(0,1.,0)
2712        glRasterPos3f(r,r,r)
2713        for c in list(label):
2714            glutBitmapCharacter(GLUT_BITMAP_8_BY_13,ord(c))
2715        glEnable(GL_LIGHTING)
2716        glPopMatrix()
2717       
2718    def RenderMap(rho,rhoXYZ,indx,Rok):
2719        cLevel = drawingData['contourLevel']
2720        for i,xyz in enumerate(rhoXYZ):
2721            if not Rok[i]:
2722                x,y,z = xyz
2723                I,J,K = indx[i]
2724                alpha = 1.0
2725                if cLevel < 1.:
2726                    alpha = (abs(rho[I,J,K])/mapData['rhoMax']-cLevel)/(1.-cLevel)
2727                if rho[I,J,K] < 0.:
2728                    RenderSmallSphere(x,y,z,0.1*alpha,Rd)
2729                else:
2730                    RenderSmallSphere(x,y,z,0.1*alpha,Bl)
2731                           
2732    def Draw():
2733        if 'Map' in generalData:
2734            VP = np.array(drawingData['viewPoint'][0])-np.array([.5,.5,.5])
2735            mapData = generalData['Map']
2736            contLevel = drawingData['contourLevel']*mapData['rhoMax']
2737            if 'delt-F' in mapData['MapType']:
2738                rho = ma.array(mapData['rho'],mask=(np.abs(mapData['rho'])<contLevel))
2739            else:
2740                rho = ma.array(mapData['rho'],mask=(mapData['rho']<contLevel))
2741            if rho.size > 0: 
2742                steps = 1./np.array(rho.shape)
2743                incre = np.where(VP>0,VP%steps,VP%steps-steps)
2744                Vsteps = -np.array(VP/steps,dtype='i')
2745                rho = np.roll(np.roll(np.roll(rho,Vsteps[0],axis=0),Vsteps[1],axis=1),Vsteps[2],axis=2)
2746                indx = np.array(ma.nonzero(rho)).T
2747                rhoXYZ = indx*steps+VP-incre
2748                Nc = len(rhoXYZ)
2749                rcube = 2000.*Vol/(ForthirdPI*Nc)
2750                rmax = math.exp(math.log(rcube)/3.)**2
2751                radius = min(drawingData['mapSize']**2,rmax)
2752                view = np.array(drawingData['viewPoint'][0])
2753                Rok = np.sum(np.inner(Amat,rhoXYZ-view).T**2,axis=1)>radius
2754            else:
2755                rhoXYZ = []
2756        Ind = GetSelectedAtoms()
2757        VS = np.array(Page.canvas.GetSize())
2758        aspect = float(VS[0])/float(VS[1])
2759        cPos = drawingData['cameraPos']
2760        Zclip = drawingData['Zclip']*cPos/200.
2761        anglex,angley,anglez = drawingData['Rotation'][:3]
2762        Tx,Ty,Tz = drawingData['viewPoint'][0]
2763        cx,ct,cs = drawingData['atomPtrs']
2764        bondR = drawingData['bondRadius']
2765        G,g = G2lat.cell2Gmat(cell)
2766        GS = G
2767        GS[0][1] = GS[1][0] = math.sqrt(GS[0][0]*GS[1][1])
2768        GS[0][2] = GS[2][0] = math.sqrt(GS[0][0]*GS[2][2])
2769        GS[1][2] = GS[2][1] = math.sqrt(GS[1][1]*GS[2][2])
2770        ellipseProb = G2lat.criticalEllipse(drawingData['ellipseProb']/100.)
2771       
2772        SetBackground()
2773        glInitNames()
2774        glPushName(0)
2775       
2776        glMatrixMode(GL_PROJECTION)
2777        glLoadIdentity()
2778        glViewport(0,0,VS[0],VS[1])
2779        gluPerspective(20.,aspect,cPos-Zclip,cPos+Zclip)
2780        gluLookAt(0,0,cPos,0,0,0,0,1,0)
2781        SetLights()           
2782           
2783        glMatrixMode(GL_MODELVIEW)
2784        glLoadIdentity()
2785        glRotate(anglez,0,0,1)
2786        glRotate(anglex,cosd(anglez),-sind(anglez),0)
2787        glRotate(angley,sind(anglez),cosd(anglez),0)
2788        glMultMatrixf(A4mat.T)
2789        glTranslate(-Tx,-Ty,-Tz)
2790        if drawingData['unitCellBox']:
2791            RenderBox()
2792        if drawingData['showABC']:
2793            x,y,z = drawingData['testPos'][0]
2794#            if altDown:
2795#                G2frame.G2plotNB.status.SetStatusText('moving test point %.4f,%.4f,%.4f'%(x,y,z),1)
2796#            else:
2797#                G2frame.G2plotNB.status.SetStatusText('test point %.4f,%.4f,%.4f'%(x,y,z),1)           
2798            RenderUnitVectors(x,y,z)
2799        Backbone = []
2800        BackboneColor = []
2801        time0 = time.time()
2802#        glEnable(GL_BLEND)
2803#        glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA)
2804        for iat,atom in enumerate(drawingData['Atoms']):
2805            x,y,z = atom[cx:cx+3]
2806            Bonds = atom[-2]
2807            Faces = atom[-1]
2808            try:
2809                atNum = generalData['AtomTypes'].index(atom[ct])
2810            except ValueError:
2811                atNum = -1
2812            CL = atom[cs+2]
2813            color = np.array(CL)/255.
2814            if iat in Ind:
2815                color = np.array(Gr)/255.
2816#            color += [.25,]
2817            radius = 0.5
2818            if atom[cs] != '':
2819                try:
2820                    glLoadName(atom[-3])
2821                except: #problem with old files - missing code
2822                    pass                   
2823            if 'balls' in atom[cs]:
2824                vdwScale = drawingData['vdwScale']
2825                ballScale = drawingData['ballScale']
2826                if atNum < 0:
2827                    radius = 0.2
2828                elif 'H' == atom[ct]:
2829                    if drawingData['showHydrogen']:
2830                        if 'vdW' in atom[cs] and atNum >= 0:
2831                            radius = vdwScale*generalData['vdWRadii'][atNum]
2832                        else:
2833                            radius = ballScale*drawingData['sizeH']
2834                    else:
2835                        radius = 0.0
2836                else:
2837                    if 'vdW' in atom[cs]:
2838                        radius = vdwScale*generalData['vdWRadii'][atNum]
2839                    else:
2840                        radius = ballScale*generalData['BondRadii'][atNum]
2841                RenderSphere(x,y,z,radius,color)
2842                if 'sticks' in atom[cs]:
2843                    RenderBonds(x,y,z,Bonds,bondR,color)
2844            elif 'ellipsoids' in atom[cs]:
2845                RenderBonds(x,y,z,Bonds,bondR,color)
2846                if atom[cs+3] == 'A':                   
2847                    Uij = atom[cs+5:cs+11]
2848                    U = np.multiply(G2spc.Uij2U(Uij),GS)
2849                    U = np.inner(Amat,np.inner(U,Amat).T)
2850                    E,R = nl.eigh(U)
2851                    R4 = np.concatenate((np.concatenate((R,[[0],[0],[0]]),axis=1),[[0,0,0,1],]),axis=0)
2852                    E = np.sqrt(E)
2853                    if atom[ct] == 'H' and not drawingData['showHydrogen']:
2854                        pass
2855                    else:
2856                        RenderEllipsoid(x,y,z,ellipseProb,E,R4,color)                   
2857                else:
2858                    if atom[ct] == 'H' and not drawingData['showHydrogen']:
2859                        pass
2860                    else:
2861                        radius = ellipseProb*math.sqrt(abs(atom[cs+4]))
2862                        RenderSphere(x,y,z,radius,color)
2863            elif 'lines' in atom[cs]:
2864                radius = 0.1
2865                RenderLines(x,y,z,Bonds,color)
2866#                RenderBonds(x,y,z,Bonds,0.05,color,6)
2867            elif atom[cs] == 'sticks':
2868                radius = 0.1
2869                RenderBonds(x,y,z,Bonds,bondR,color)
2870            elif atom[cs] == 'polyhedra':
2871                RenderPolyhedra(x,y,z,Faces,color)
2872            elif atom[cs] == 'backbone':
2873                if atom[ct-1].split()[0] in ['C','N']:
2874                    Backbone.append(list(np.inner(Amat,np.array([x,y,z]))))
2875                    BackboneColor.append(list(color))
2876                   
2877            if atom[cs+1] == 'type':
2878                RenderLabel(x,y,z,atom[ct],radius)
2879            elif atom[cs+1] == 'name':
2880                RenderLabel(x,y,z,atom[ct-1],radius)
2881            elif atom[cs+1] == 'number':
2882                RenderLabel(x,y,z,str(iat),radius)
2883            elif atom[cs+1] == 'residue' and atom[ct-1] == 'CA':
2884                RenderLabel(x,y,z,atom[ct-4],radius)
2885            elif atom[cs+1] == '1-letter' and atom[ct-1] == 'CA':
2886                RenderLabel(x,y,z,atom[ct-3],radius)
2887            elif atom[cs+1] == 'chain' and atom[ct-1] == 'CA':
2888                RenderLabel(x,y,z,atom[ct-2],radius)
2889#        glDisable(GL_BLEND)
2890        if len(rhoXYZ):
2891            RenderMap(rho,rhoXYZ,indx,Rok)
2892        if Backbone:
2893            RenderBackbone(Backbone,BackboneColor,bondR)
2894#        print time.time()-time0
2895        Page.canvas.SwapBuffers()
2896       
2897    def OnSize(event):
2898        Draw()
2899       
2900    def OnFocus(event):
2901        Draw()
2902       
2903    try:
2904        plotNum = G2frame.G2plotNB.plotList.index(generalData['Name'])
2905        Page = G2frame.G2plotNB.nb.GetPage(plotNum)       
2906    except ValueError:
2907        Plot = G2frame.G2plotNB.addOgl(generalData['Name'])
2908        plotNum = G2frame.G2plotNB.plotList.index(generalData['Name'])
2909        Page = G2frame.G2plotNB.nb.GetPage(plotNum)
2910        Page.views = False
2911        view = False
2912        altDown = False
2913    Page.SetFocus()
2914    cb = wx.ComboBox(G2frame.G2plotNB.status,style=wx.CB_DROPDOWN|wx.CB_READONLY,
2915        choices=(' save as:','jpeg','tiff','bmp'))
2916    cb.Bind(wx.EVT_COMBOBOX, OnKeyBox)
2917    cb.SetValue(' save as:')
2918    Page.canvas.Bind(wx.EVT_MOUSEWHEEL, OnMouseWheel)
2919    Page.canvas.Bind(wx.EVT_LEFT_DOWN, OnMouseDown)
2920    Page.canvas.Bind(wx.EVT_RIGHT_DOWN, OnMouseDown)
2921    Page.canvas.Bind(wx.EVT_MIDDLE_DOWN, OnMouseDown)
2922    Page.canvas.Bind(wx.EVT_KEY_UP, OnKey)
2923    Page.canvas.Bind(wx.EVT_MOTION, OnMouseMove)
2924    Page.canvas.Bind(wx.EVT_SIZE, OnSize)
2925    Page.canvas.Bind(wx.EVT_SET_FOCUS, OnFocus)
2926    Page.camera['position'] = drawingData['cameraPos']
2927    Page.camera['viewPoint'] = np.inner(Amat,drawingData['viewPoint'][0])
2928    Page.camera['backColor'] = np.array(list(drawingData['backColor'])+[0,])/255.
2929    Page.canvas.SetCurrent()
2930    Draw()
2931       
Note: See TracBrowser for help on using the repository browser.