source: trunk/GSASIIplot.py @ 256

Last change on this file since 256 was 256, checked in by vondreele, 11 years ago

remove popup message box for 2D image calibration
add delete line with R mouse button in powder patterns
fix image controls sizer issues

  • Property svn:keywords set to Date Author Revision URL Id
File size: 84.9 KB
Line 
1#GSASII plotting routines
2########### SVN repository information ###################
3# $Date: 2011-03-09 17:33:59 +0000 (Wed, 09 Mar 2011) $
4# $Author: vondreele $
5# $Revision: 256 $
6# $URL: trunk/GSASIIplot.py $
7# $Id: GSASIIplot.py 256 2011-03-09 17:33:59Z vondreele $
8########### SVN repository information ###################
9import math
10import time
11import copy
12import os.path
13import numpy as np
14import numpy.linalg as nl
15import wx
16import wx.aui
17import wx.glcanvas
18import matplotlib as mpl
19import mpl_toolkits.mplot3d.axes3d as mp3d
20import GSASIIpath
21import GSASIIgrid as G2gd
22import GSASIIimage as G2img
23import GSASIIIO as G2IO
24import GSASIIpwdGUI as G2pdG
25import GSASIIimgGUI as G2imG
26import GSASIIphsGUI as G2phG
27import GSASIIlattice as G2lat
28import GSASIIspc as G2spc
29from  OpenGL.GL import *
30from OpenGL.GLU import *
31from OpenGL.GLUT import *
32from OpenGL.GLE import *
33from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as Canvas
34from matplotlib.backends.backend_wxagg import NavigationToolbar2Wx as Toolbar
35
36# useful degree trig functions
37sind = lambda x: math.sin(x*math.pi/180.)
38cosd = lambda x: math.cos(x*math.pi/180.)
39tand = lambda x: math.tan(x*math.pi/180.)
40asind = lambda x: 180.*math.asin(x)/math.pi
41acosd = lambda x: 180.*math.acos(x)/math.pi
42atan2d = lambda x,y: 180.*math.atan2(y,x)/math.pi
43atand = lambda x: 180.*math.atan(x)/math.pi
44# numpy versions
45npsind = lambda x: np.sin(x*np.pi/180.)
46npcosd = lambda x: np.cos(x*np.pi/180.)
47npacosd = lambda x: 180.*np.arccos(x)/np.pi
48   
49class G2PlotMpl(wx.Panel):   
50    def __init__(self,parent,id=-1,dpi=None,**kwargs):
51        wx.Panel.__init__(self,parent,id=id,**kwargs)
52        self.figure = mpl.figure.Figure(dpi=dpi,figsize=(5,7))
53        self.canvas = Canvas(self,-1,self.figure)
54        self.toolbar = Toolbar(self.canvas)
55
56        self.toolbar.Realize()
57       
58        sizer=wx.BoxSizer(wx.VERTICAL)
59        sizer.Add(self.canvas,1,wx.EXPAND)
60        sizer.Add(self.toolbar,0,wx.LEFT|wx.EXPAND)
61        self.SetSizer(sizer)
62       
63class G2PlotOgl(wx.Panel):
64    def __init__(self,parent,id=-1,dpi=None,**kwargs):
65        self.figure = wx.Panel.__init__(self,parent,id=id,**kwargs)
66        self.canvas = wx.glcanvas.GLCanvas(self,-1,**kwargs)
67        self.camera = {}
68        sizer=wx.BoxSizer(wx.VERTICAL)
69        sizer.Add(self.canvas,1,wx.EXPAND)
70        self.SetSizer(sizer)
71       
72class G2Plot3D(wx.Panel):
73    def __init__(self,parent,id=-1,dpi=None,**kwargs):
74        wx.Panel.__init__(self,parent,id=id,**kwargs)
75        self.figure = mpl.figure.Figure(dpi=dpi,figsize=(6,6))
76        self.canvas = Canvas(self,-1,self.figure)
77        self.toolbar = Toolbar(self.canvas)
78
79        self.toolbar.Realize()
80       
81        sizer=wx.BoxSizer(wx.VERTICAL)
82        sizer.Add(self.canvas,1,wx.EXPAND)
83        sizer.Add(self.toolbar,0,wx.LEFT|wx.EXPAND)
84        self.SetSizer(sizer)
85                             
86class G2PlotNoteBook(wx.Panel):
87    def __init__(self,parent,id=-1):
88        wx.Panel.__init__(self,parent,id=id)
89        #so one can't delete a plot page!!
90        self.nb = wx.aui.AuiNotebook(self, \
91            style=wx.aui.AUI_NB_DEFAULT_STYLE ^ wx.aui.AUI_NB_CLOSE_ON_ACTIVE_TAB)
92        sizer = wx.BoxSizer()
93        sizer.Add(self.nb,1,wx.EXPAND)
94        self.SetSizer(sizer)
95        self.status = parent.CreateStatusBar()
96        self.status.SetFieldsCount(2)
97        self.status.SetStatusWidths([125,-1])
98        self.Bind(wx.aui.EVT_AUINOTEBOOK_PAGE_CHANGED, self.OnPageChanged)
99       
100        self.plotList = []
101           
102    def addMpl(self,name=""):
103        page = G2PlotMpl(self.nb)
104        self.nb.AddPage(page,name)
105       
106        self.plotList.append(name)
107       
108        return page.figure
109       
110    def add3D(self,name=""):
111        page = G2Plot3D(self.nb)
112        self.nb.AddPage(page,name)
113       
114        self.plotList.append(name)
115       
116        return page.figure
117       
118    def addOgl(self,name=""):
119        page = G2PlotOgl(self.nb)
120        self.nb.AddPage(page,name)
121       
122        self.plotList.append(name)
123       
124        return page.figure
125       
126    def Delete(self,name):
127        try:
128            item = self.plotList.index(name)
129            del self.plotList[item]
130            self.nb.DeletePage(item)
131        except ValueError:          #no plot of this name - do nothing
132            return     
133               
134    def clear(self):
135        while self.nb.GetPageCount():
136            self.nb.DeletePage(0)
137        self.plotList = []
138        self.status.DestroyChildren()
139       
140    def Rename(self,oldName,newName):
141        try:
142            item = self.plotList.index(oldName)
143            self.plotList[item] = newName
144            self.nb.SetPageText(item,newName)
145        except ValueError:          #no plot of this name - do nothing
146            return     
147       
148    def OnPageChanged(self,event):       
149        if self.plotList:
150            self.status.SetStatusText('Better to select this from GSAS-II data tree',1)
151        self.status.DestroyChildren()                           #get rid of special stuff on status bar
152       
153def PlotSngl(self,newPlot=False):
154    from matplotlib.patches import Circle
155    global HKL,HKLF
156
157    def OnSCMotion(event):
158        xpos = event.xdata
159        if xpos:
160            xpos = round(xpos)                                        #avoid out of frame mouse position
161            ypos = round(event.ydata)
162            zpos = Data['Layer']
163            if '100' in Data['Zone']:
164                HKLtxt = '(%3d,%3d,%3d)'%(zpos,xpos,ypos)
165            elif '010' in Data['Zone']:
166                HKLtxt = '(%3d,%3d,%3d)'%(xpos,zpos,ypos)
167            elif '001' in Data['Zone']:
168                HKLtxt = '(%3d,%3d,%3d)'%(xpos,ypos,zpos)
169            Page.canvas.SetToolTipString(HKLtxt)
170            self.G2plotNB.status.SetFields(['HKL = '+HKLtxt,''])
171               
172    def OnSCPick(event):
173        zpos = Data['Layer']
174        pos = event.artist.center
175        if '100' in Data['Zone']:
176            Page.canvas.SetToolTipString('(picked:(%3d,%3d,%3d))'%(zpos,pos[0],pos[1]))
177            hkl = np.array([zpos,pos[0],pos[1]])
178        elif '010' in Data['Zone']:
179            Page.canvas.SetToolTipString('(picked:(%3d,%3d,%3d))'%(pos[0],zpos,pos[1]))
180            hkl = np.array([pos[0],zpos,pos[1]])
181        elif '001' in Data['Zone']:
182            Page.canvas.SetToolTipString('(picked:(%3d,%3d,%3d))'%(pos[0],pos[1],zpos))
183            hkl = np.array([pos[0],pos[1],zpos])
184        h,k,l = hkl
185        hklf = HKLF[np.where(np.all(HKL-hkl == [0,0,0],axis=1))]
186        if len(hklf):
187            Fosq,sig,Fcsq = hklf[0]
188            HKLtxt = '(%3d,%3d,%3d %.2f %.3f %.2f %.2f)'%(h,k,l,Fosq,sig,Fcsq,(Fosq-Fcsq)/(scale*sig))
189            self.G2plotNB.status.SetFields(['','HKL, Fosq, sig, Fcsq, delFsq/sig = '+HKLtxt])
190                                 
191    def OnSCKeyPress(event):
192        print event.key
193
194    try:
195        plotNum = self.G2plotNB.plotList.index('Structure Factors')
196        Page = self.G2plotNB.nb.GetPage(plotNum)
197        if not newPlot:
198            Plot = Page.figure.gca()          #get previous powder plot & get limits
199            xylim = Plot.get_xlim(),Plot.get_ylim()
200        Page.figure.clf()
201        Plot = Page.figure.gca()          #get a fresh plot after clf()
202    except ValueError,error:
203        Plot = self.G2plotNB.addMpl('Structure Factors').gca()
204        plotNum = self.G2plotNB.plotList.index('Structure Factors')
205        Page = self.G2plotNB.nb.GetPage(plotNum)
206#        Page.canvas.mpl_connect('key_press_event', OnSCKeyPress)
207        Page.canvas.mpl_connect('pick_event', OnSCPick)
208        Page.canvas.mpl_connect('motion_notify_event', OnSCMotion)
209    Page.SetFocus()
210   
211    Plot.set_aspect(aspect='equal')
212    HKLref = self.PatternTree.GetItemPyData(self.Sngl)
213    Data = self.PatternTree.GetItemPyData( \
214        G2gd.GetPatternTreeItemId(self,self.Sngl, 'HKL Plot Controls'))
215    Type = Data['Type']           
216    scale = Data['Scale']
217    HKLmax = Data['HKLmax']
218    HKLmin = Data['HKLmin']
219    FosqMax = Data['FoMax']
220    FoMax = math.sqrt(FosqMax)
221    ifFc = Data['ifFc']
222    xlabel = ['k, h=','h, k=','h, l=']
223    ylabel = ['l','l','k']
224    zones = ['100','010','001']
225    pzone = [[1,2],[0,2],[0,1]]
226    izone = zones.index(Data['Zone'])
227    Plot.set_title(self.PatternTree.GetItemText(self.Sngl)[5:])
228    HKL = []
229    HKLF = []
230    for H,Fosq,sig,Fcsq,x,x,x in HKLref:
231        HKL.append(H)
232        HKLF.append([Fosq,sig,Fcsq])
233        if H[izone] == Data['Layer']:
234            B = 0
235            if Type == 'Fosq':
236                A = scale*Fosq/FosqMax
237                B = scale*Fcsq/FosqMax
238                C = abs(A-B)
239            elif Type == 'Fo':
240                A = scale*math.sqrt(max(0,Fosq))/FoMax
241                B = scale*math.sqrt(max(0,Fcsq))/FoMax
242                C = abs(A-B)
243            elif Type == '|DFsq|/sig':
244                A = abs(Fosq-Fcsq)/(scale*sig)
245            elif Type == '|DFsq|>sig':
246                A = abs(Fosq-Fcsq)/(scale*sig)
247                if A < 1.0: A = 0                   
248            elif Type == '|DFsq|>3sig':
249                A = abs(Fosq-Fcsq)/(scale*sig)
250                if A < 3.0: A = 0                   
251            xy = (H[pzone[izone][0]],H[pzone[izone][1]])
252            if A > 0.0:
253                Plot.add_artist(Circle(xy,radius=A,ec='g',fc='w',picker=3))
254            if B:
255                Plot.add_artist(Circle(xy,radius=B,ec='b',fc='w'))
256                radius = C
257                if radius > 0:
258                    if A > B:
259                        Plot.add_artist(Circle(xy,radius=radius,ec='g',fc='g'))
260                    else:                   
261                        Plot.add_artist(Circle(xy,radius=radius,ec='r',fc='r'))
262    HKL = np.array(HKL,dtype=np.int)
263    HKLF = np.array(HKLF)
264    Plot.set_xlabel(xlabel[izone]+str(Data['Layer']),fontsize=12)
265    Plot.set_ylabel(ylabel[izone],fontsize=12)
266    Plot.set_xlim((HKLmin[pzone[izone][0]],HKLmax[pzone[izone][0]]))
267    Plot.set_ylim((HKLmin[pzone[izone][1]],HKLmax[pzone[izone][1]]))
268    if not newPlot:
269        Page.toolbar.push_current()
270        Plot.set_xlim(xylim[0])
271        Plot.set_ylim(xylim[1])
272        xylim = []
273        Page.toolbar.push_current()
274        Page.toolbar.draw()
275    else:
276        Page.canvas.draw()
277       
278def PlotPatterns(self,newPlot=False):
279    global HKL
280   
281    def OnPick(event):
282        if self.itemPicked is not None: return
283        PatternId = self.PatternId
284        try:
285            Values,Names = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,self.PatternId, 'Instrument Parameters'))[1::2]
286        except TypeError:
287            return
288        Parms = dict(zip(Names,Values))
289        try:
290            wave = Parms['Lam']
291        except KeyError:
292            wave = Parms['Lam1']
293        PickId = self.PickId
294        pick = event.artist
295        mouse = event.mouseevent       
296        xpos = pick.get_xdata()
297        ypos = pick.get_ydata()
298        ind = event.ind
299        xy = list(zip(np.take(xpos,ind),np.take(ypos,ind))[0])
300        if self.PatternTree.GetItemText(PickId) == 'Peak List':
301            if ind.all() != [0]:                                    #picked a data point
302                ins = [Parms[x] for x in ['U','V','W','X','Y','SH/L']]
303                if self.qPlot:                              #qplot - convert back to 2-theta
304                    xy[0] = 2.0*asind(xy[0]*wave/(4*math.pi))
305                sig = ins[0]*tand(xy[0]/2.0)**2+ins[1]*tand(xy[0]/2.0)+ins[2]
306                gam = ins[3]/cosd(xy[0]/2.0)+ins[4]*tand(xy[0]/2.0)           
307                data = self.PatternTree.GetItemPyData(self.PickId)
308                XY = [xy[0],0, xy[1],1, sig,0, gam,0]       #default refine intensity 1st
309                data.append(XY)
310                G2pdG.UpdatePeakGrid(self,data)
311                PlotPatterns(self)
312            else:                                                   #picked a peak list line
313                self.itemPicked = pick
314        elif self.PatternTree.GetItemText(PickId) == 'Limits':
315            if ind.all() != [0]:                                    #picked a data point
316                LimitId = G2gd.GetPatternTreeItemId(self,PatternId, 'Limits')
317                data = self.PatternTree.GetItemPyData(LimitId)
318                if self.qPlot:                              #qplot - convert back to 2-theta
319                    xy[0] = 2.0*asind(xy[0]*wave/(4*math.pi))
320                if mouse.button==1:
321                    data[1][0] = min(xy[0],data[1][1])
322                if mouse.button==3:
323                    data[1][1] = max(xy[0],data[1][0])
324                self.PatternTree.SetItemPyData(LimitId,data)
325                G2pdG.UpdateLimitsGrid(self,data)
326                PlotPatterns(self)
327            else:                                                   #picked a limit line
328                self.itemPicked = pick
329       
330    def OnPlotKeyPress(event):
331        newPlot = False
332        if event.key == 'w':
333            if self.Weight:
334                self.Weight = False
335            else:
336                self.Weight = True
337            print 'plot weighting:',self.Weight
338        elif event.key == 'l':
339            if self.Contour:
340                pass
341            else:
342                if self.logPlot:
343                    self.logPlot = False
344                else:
345                    self.Offset = 0
346                    self.logPlot = True
347        elif event.key == 'u':
348            if self.Contour:
349                self.Cmax = min(1.0,self.Cmax*1.2)
350            elif self.logPlot:
351                pass
352            elif self.Offset < 100.:
353                self.Offset += 1.
354        elif event.key == 'd':
355            if self.Contour:
356                self.Cmax = max(0.0,self.Cmax*0.8)
357            elif self.logPlot:
358                pass
359            elif self.Offset > 0.:
360                self.Offset -= 1.
361        elif event.key == 'c':
362            newPlot = True
363            if self.Contour:
364                self.Contour = False
365            else:
366                self.Contour = True
367                self.SinglePlot = False
368                self.Offset = 0
369        elif event.key == 'q':
370            newPlot = True
371            if self.qPlot:
372                self.qPlot = False
373            else:
374                self.qPlot = True
375        elif event.key == 's':
376            if self.Contour:
377                choice = [m for m in mpl.cm.datad.keys() if not m.endswith("_r")]
378                dlg = wx.SingleChoiceDialog(self,'Select','Color scheme',choice)
379                if dlg.ShowModal() == wx.ID_OK:
380                    sel = dlg.GetSelection()
381                    self.ContourColor = choice[sel]
382                else:
383                    self.ContourColor = 'Paired'
384                dlg.Destroy()
385            else:               
386                if self.SinglePlot:
387                    self.SinglePlot = False
388                else:
389                    self.SinglePlot = True
390        elif event.key == '+':
391            if self.PickId:
392                self.PickId = False
393        elif event.key == 'i':                  #for smoothing contour plot
394            choice = ['nearest','bilinear','bicubic','spline16','spline36','hanning',
395               'hamming','hermite','kaiser','quadric','catrom','gaussian','bessel',
396               'mitchell','sinc','lanczos']
397            dlg = wx.SingleChoiceDialog(self,'Select','Interpolation',choice)
398            if dlg.ShowModal() == wx.ID_OK:
399                sel = dlg.GetSelection()
400                self.Interpolate = choice[sel]
401            else:
402                self.Interpolate = 'nearest'
403            dlg.Destroy()
404           
405        PlotPatterns(self,newPlot=newPlot)
406       
407    def OnKeyBox(event):
408        if self.G2plotNB.nb.GetSelection() == self.G2plotNB.plotList.index('Powder Patterns'):
409            event.key = cb.GetValue()[0]
410            cb.SetValue(' key press')
411            OnPlotKeyPress(event)
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 = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,self.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 self.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 self.Contour:
431                    self.G2plotNB.status.SetStatusText('2-theta =%9.3f d =%9.5f pattern ID =%5d'%(xpos,dsp,int(ypos)),1)
432                else:
433                    self.G2plotNB.status.SetStatusText('2-theta =%9.3f d =%9.5f Intensity =%9.1f'%(xpos,dsp,ypos),1)
434                if self.itemPicked:
435                    Page.canvas.SetToolTipString('%9.3f'%(xpos))
436                if self.PickId and self.PatternTree.GetItemText(self.PickId) in ['Index Peak List','Unit Cells List']:
437                    found = []
438                    if len(HKL):
439                        view = Page.toolbar._views.forward()[0][:2]
440                        wid = view[1]-view[0]
441                        found = HKL[np.where(np.fabs(HKL.T[5]-xpos) < 0.002*wid)]
442                    if len(found):
443                        h,k,l = found[0][:3] 
444                        Page.canvas.SetToolTipString('%d,%d,%d'%(int(h),int(k),int(l)))
445                    else:
446                        Page.canvas.SetToolTipString('')
447
448            except TypeError:
449                self.G2plotNB.status.SetStatusText('Select PWDR powder pattern first',1)
450                                                   
451    def OnRelease(event):
452        if self.itemPicked is None: return
453        Values,Names = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,self.PatternId, 'Instrument Parameters'))[1::2]
454        Parms = dict(zip(Names,Values))
455        try:
456            wave = Parms['Lam']
457        except KeyError:
458            wave = Parms['Lam1']
459        xpos = event.xdata
460        if xpos:                                        #avoid out of frame mouse position
461            lines = []
462            for line in self.Lines: lines.append(line.get_xdata()[0])
463            lineNo = lines.index(self.itemPicked.get_xdata()[0])
464            if  lineNo in [0,1]:
465                LimitId = G2gd.GetPatternTreeItemId(self,self.PatternId, 'Limits')
466                data = self.PatternTree.GetItemPyData(LimitId)
467#                print 'limits',xpos
468                if self.qPlot:
469                    data[1][lineNo] = 2.0*asind(wave*xpos/(4*math.pi))
470                else:
471                    data[1][lineNo] = xpos
472                self.PatternTree.SetItemPyData(LimitId,data)
473                if self.PatternTree.GetItemText(self.PickId) == 'Limits':
474                    G2pdG.UpdateLimitsGrid(self,data)
475            else:
476                PeakId = G2gd.GetPatternTreeItemId(self,self.PatternId, 'Peak List')
477                data = self.PatternTree.GetItemPyData(PeakId)
478#                print 'peaks',xpos
479                if event.button == 3:
480                    del data[lineNo-2]
481                else:
482                    if self.qPlot:
483                        data[lineNo-2][0] = 2.0*asind(wave*xpos/(4*math.pi))
484                    else:
485                        data[lineNo-2][0] = xpos
486                self.PatternTree.SetItemPyData(PeakId,data)
487                G2pdG.UpdatePeakGrid(self,data)
488        PlotPatterns(self)
489        self.itemPicked = None   
490
491    xylim = []
492    try:
493        plotNum = self.G2plotNB.plotList.index('Powder Patterns')
494        Page = self.G2plotNB.nb.GetPage(plotNum)
495        if not newPlot:
496            Plot = Page.figure.gca()          #get previous powder plot & get limits
497            xylim = Plot.get_xlim(),Plot.get_ylim()
498        Page.figure.clf()
499        Plot = Page.figure.gca()          #get a fresh plot after clf()
500    except ValueError,error:
501        newPlot = True
502        self.Cmax = 1.0
503        Plot = self.G2plotNB.addMpl('Powder Patterns').gca()
504        plotNum = self.G2plotNB.plotList.index('Powder Patterns')
505        Page = self.G2plotNB.nb.GetPage(plotNum)
506        Page.canvas.mpl_connect('key_press_event', OnPlotKeyPress)
507        Page.canvas.mpl_connect('motion_notify_event', OnMotion)
508        Page.canvas.mpl_connect('pick_event', OnPick)
509        Page.canvas.mpl_connect('button_release_event', OnRelease)
510    Page.SetFocus()
511    self.G2plotNB.status.DestroyChildren()
512    if self.Contour:
513        Choice = (' key press','d: lower contour max','u: raise contour max',
514            'i: interpolation method','s: color scheme','c: contour off')
515    else:
516        if self.logPlot:
517            Choice = (' key press','l: log(I) off',
518                'c: contour on','q: toggle q plot','s: toggle single plot','+: no selection')
519        else:
520            Choice = (' key press','d: offset down','u: offset up','l: log(I) on',
521                'c: contour on','q: toggle q plot','s: toggle single plot','+: no selection')
522    cb = wx.ComboBox(self.G2plotNB.status,style=wx.CB_DROPDOWN|wx.CB_READONLY,
523        choices=Choice)
524    cb.Bind(wx.EVT_COMBOBOX, OnKeyBox)
525    cb.SetValue(' key press')
526   
527    PickId = self.PickId
528    PatternId = self.PatternId
529    colors=['b','g','r','c','m','k']
530    Lines = []
531    if self.SinglePlot:
532        Pattern = self.PatternTree.GetItemPyData(PatternId)
533        Pattern.append(self.PatternTree.GetItemText(PatternId))
534        PlotList = [Pattern,]
535        ParmList = [self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,
536            self.PatternId, 'Instrument Parameters'))[1],]
537    else:       
538        PlotList = []
539        ParmList = []
540        item, cookie = self.PatternTree.GetFirstChild(self.root)
541        while item:
542            if 'PWDR' in self.PatternTree.GetItemText(item):
543                Pattern = self.PatternTree.GetItemPyData(item)
544                if len(Pattern) < 3:                    # put name on end if needed
545                    Pattern.append(self.PatternTree.GetItemText(item))
546                PlotList.append(Pattern)
547                ParmList.append(self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,
548                    item,'Instrument Parameters'))[1])
549            item, cookie = self.PatternTree.GetNextChild(self.root, cookie)               
550    Ymax = 1.0
551    lenX = 0
552    HKL = np.array(self.HKL)
553    for Pattern in PlotList:
554        xye = Pattern[1]
555        Ymax = max(Ymax,max(xye[1]))
556    offset = self.Offset*Ymax/100.0
557    Title = 'Powder Patterns: '+os.path.split(self.GSASprojectfile)[1]
558    if self.logPlot:
559        Title = 'log('+Title+')'
560    Plot.set_title(Title)
561    if self.qPlot:
562        Plot.set_xlabel(r'$q, \AA^{-1}$',fontsize=14)
563    else:       
564        Plot.set_xlabel(r'$\mathsf{2\theta}$',fontsize=14)
565    Plot.set_ylabel('Intensity',fontsize=12)
566    if self.Contour:
567        ContourZ = []
568        ContourY = []
569        Nseq = 0
570    for N,Pattern in enumerate(PlotList):
571        Parms = ParmList[N]
572        ifpicked = False
573        LimitId = 0
574        xye = np.array(Pattern[1])
575        if PickId:
576            ifpicked = Pattern[2] == self.PatternTree.GetItemText(PatternId)
577            LimitId = G2gd.GetPatternTreeItemId(self,PatternId, 'Limits')
578        if self.qPlot:
579            Id = G2gd.GetPatternTreeItemId(self,self.root, Pattern[2])
580            X = 4*np.pi*npsind(xye[0]/2.0)/Parms[1]
581        else:
582            X = xye[0]
583        if not lenX:
584            lenX = len(X)           
585        Y = xye[1]+offset*N
586        if LimitId:
587            limits = np.array(self.PatternTree.GetItemPyData(LimitId))
588            if self.qPlot:
589                limits = 4*np.pi*npsind(limits/2.0)/Parms[1]
590            Lines.append(Plot.axvline(limits[1][0],color='g',dashes=(5,5),picker=3.))   
591            Lines.append(Plot.axvline(limits[1][1],color='r',dashes=(5,5),picker=3.))                   
592        if self.Contour:
593           
594            if lenX == len(X):
595                ContourY.append(N)
596                ContourZ.append(Y)
597                ContourX = X
598                Nseq += 1
599                Plot.set_ylabel('Data sequence',fontsize=12)
600        else:
601            if ifpicked:
602                Z = xye[3]+offset*N
603                W = xye[4]+offset*N
604                D = xye[5]+offset*N-Ymax*.02
605                if self.Weight:
606                    W2 = np.sqrt(xye[2])
607                    D *= W2-Ymax*.02
608                if self.logPlot:
609                    Plot.semilogy(X,Y,colors[N%6]+'+',picker=3.,clip_on=False,nonposy='mask')
610                    Plot.semilogy(X,Z,colors[(N+1)%6],picker=False,nonposy='mask')
611                    Plot.semilogy(X,W,colors[(N+2)%6],picker=False,nonposy='mask')
612                else:
613                    Plot.plot(X,Y,colors[N%6]+'+',picker=3.,clip_on=False)
614                    Plot.plot(X,Z,colors[(N+1)%6],picker=False)
615                    Plot.plot(X,W,colors[(N+2)%6],picker=False)
616                    Plot.plot(X,D,colors[(N+3)%6],picker=False)
617                    Plot.axhline(0.,color=wx.BLACK)
618                Page.canvas.SetToolTipString('')
619                if self.PatternTree.GetItemText(PickId) == 'Peak List':
620                    tip = 'On data point: Pick peak - L or R MB. On line: L-move, R-delete'
621                    Page.canvas.SetToolTipString(tip)
622                    data = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PatternId, 'Peak List'))
623                    for item in data:
624                        if self.qPlot:
625                            Lines.append(Plot.axvline(4*math.pi*sind(item[0]/2.)/Parms[1],color=colors[N%6],picker=2.))
626                        else:
627                            Lines.append(Plot.axvline(item[0],color=colors[N%6],picker=2.))
628                if self.PatternTree.GetItemText(PickId) == 'Limits':
629                    tip = 'On data point: Lower limit - L MB; Upper limit - R MB. On limit: MB down to move'
630                    Page.canvas.SetToolTipString(tip)
631                    data = self.LimitsTable.GetData()
632            else:
633                if self.logPlot:
634                    Plot.semilogy(X,Y,colors[N%6],picker=False,nonposy='clip')
635                else:
636                    Plot.plot(X,Y,colors[N%6],picker=False)
637    if PickId and self.PatternTree.GetItemText(PickId) in ['Index Peak List','Unit Cells List']:
638        Values,Names = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PatternId, 'Instrument Parameters'))[1::2]
639        Parms = dict(zip(Names,Values))
640        try:
641            wave = Parms['Lam']
642        except KeyError:
643            wave = Parms['Lam1']
644        peaks = np.array((self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PatternId, 'Index Peak List'))))
645        for peak in peaks:
646            if self.qPlot:
647                Plot.axvline(4*np.pi*sind(peak[0]/2.0)/wave,color='b')
648            else:
649                Plot.axvline(peak[0],color='b')
650        for hkl in self.HKL:
651            if self.qPlot:
652                Plot.axvline(4*np.pi*sind(hkl[5]/2.0)/wave,color='r',dashes=(5,5))
653            else:
654                Plot.axvline(hkl[5],color='r',dashes=(5,5))
655    if self.Contour:
656        acolor = mpl.cm.get_cmap(self.ContourColor)
657        Img = Plot.imshow(ContourZ,cmap=acolor,vmin=0,vmax=Ymax*self.Cmax,interpolation=self.Interpolate, 
658            extent=[ContourX[0],ContourX[-1],ContourY[0],ContourY[-1]],aspect='auto',origin='lower')
659        Page.figure.colorbar(Img)
660    else:
661        self.Lines = Lines
662    if not newPlot:
663        Page.toolbar.push_current()
664        Plot.set_xlim(xylim[0])
665        Plot.set_ylim(xylim[1])
666        xylim = []
667        Page.toolbar.push_current()
668        Page.toolbar.draw()
669    else:
670        Page.canvas.draw()
671    self.Pwdr = True
672
673def PlotPowderLines(self):
674    global HKL
675
676    def OnMotion(event):
677        xpos = event.xdata
678        if xpos:                                        #avoid out of frame mouse position
679            Page.canvas.SetCursor(wx.CROSS_CURSOR)
680            self.G2plotNB.status.SetFields(['','2-theta =%9.3f '%(xpos,)])
681            if self.PickId and self.PatternTree.GetItemText(self.PickId) in ['Index Peak List','Unit Cells List']:
682                found = []
683                if len(HKL):
684                    view = Page.toolbar._views.forward()[0][:2]
685                    wid = view[1]-view[0]
686                    found = HKL[np.where(np.fabs(HKL.T[5]-xpos) < 0.002*wid)]
687                if len(found):
688                    h,k,l = found[0][:3] 
689                    Page.canvas.SetToolTipString('%d,%d,%d'%(int(h),int(k),int(l)))
690                else:
691                    Page.canvas.SetToolTipString('')
692
693    try:
694        plotNum = self.G2plotNB.plotList.index('Powder Lines')
695        Page = self.G2plotNB.nb.GetPage(plotNum)
696        Page.figure.clf()
697        Plot = Page.figure.gca()
698    except ValueError,error:
699        Plot = self.G2plotNB.addMpl('Powder Lines').gca()
700        plotNum = self.G2plotNB.plotList.index('Powder Lines')
701        Page = self.G2plotNB.nb.GetPage(plotNum)
702        Page.canvas.mpl_connect('motion_notify_event', OnMotion)
703       
704    Page.SetFocus()
705    Plot.set_title('Powder Pattern Lines')
706    Plot.set_xlabel(r'$\mathsf{2\theta}$',fontsize=14)
707    PickId = self.PickId
708    PatternId = self.PatternId
709    peaks = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PatternId, 'Index Peak List'))
710    for peak in peaks:
711        Plot.axvline(peak[0],color='b')
712    HKL = np.array(self.HKL)
713    for hkl in self.HKL:
714        Plot.axvline(hkl[5],color='r',dashes=(5,5))
715    xmin = peaks[0][0]
716    xmax = peaks[-1][0]
717    delt = xmax-xmin
718    xlim = [max(0,xmin-delt/20.),min(180.,xmax+delt/20.)]
719    Plot.set_xlim(xlim)
720    Page.canvas.draw()
721
722def PlotPeakWidths(self):
723    PatternId = self.PatternId
724    limitID = G2gd.GetPatternTreeItemId(self,PatternId, 'Limits')
725    if limitID:
726        limits = self.PatternTree.GetItemPyData(limitID)
727    else:
728        return
729    instParms = self.PatternTree.GetItemPyData( \
730        G2gd.GetPatternTreeItemId(self,PatternId, 'Instrument Parameters'))
731    if instParms[0][0] == 'PXC':
732        lam = instParms[1][1]
733        if len(instParms[1]) == 13:
734            GU,GV,GW,LX,LY = instParms[0][6:11]
735        else:
736            GU,GV,GW,LX,LY = instParms[0][4:9]
737    peakID = G2gd.GetPatternTreeItemId(self,PatternId, 'Peak List')
738    if peakID:
739        peaks = self.PatternTree.GetItemPyData(peakID)
740    else:
741        peaks = []
742   
743    try:
744        plotNum = self.G2plotNB.plotList.index('Peak Widths')
745        Page = self.G2plotNB.nb.GetPage(plotNum)
746        Page.figure.clf()
747        Plot = Page.figure.gca()
748    except ValueError,error:
749        Plot = self.G2plotNB.addMpl('Peak Widths').gca()
750        plotNum = self.G2plotNB.plotList.index('Peak Widths')
751        Page = self.G2plotNB.nb.GetPage(plotNum)
752    Page.SetFocus()
753   
754    Page.canvas.SetToolTipString('')
755    colors=['b','g','r','c','m','k']
756    Xmin,Xmax = limits[1]
757    Xmin = min(0.5,max(Xmin,1))
758    Xmin /= 2
759    Xmax /= 2
760    nPts = 100
761    delt = (Xmax-Xmin)/nPts
762    thetas = []
763    for i in range(nPts):
764        thetas.append(Xmin+i*delt)
765    X = []
766    Y = []
767    Z = []
768    W = []
769    V = []
770    sig = lambda Th,U,V,W: 1.17741*math.sqrt(U*tand(Th)**2+V*tand(Th)+W)*math.pi/18000.
771    gam = lambda Th,X,Y: (X/cosd(Th)+Y*tand(Th))*math.pi/18000.
772    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.)
773    gamFW2 = lambda s,g: math.sqrt(s**2+(0.4654996*g)**2)+.5345004*#Ubaldo Bafile - private communication
774    for theta in thetas:
775        X.append(4.0*math.pi*sind(theta)/lam)              #q
776        s = sig(theta,GU,GV,GW)
777        g = gam(theta,LX,LY)
778        G = gamFW(g,s)
779        H = gamFW2(g,s)
780        Y.append(s/tand(theta))
781        Z.append(g/tand(theta))
782        W.append(G/tand(theta))
783        V.append(H/tand(theta))
784    Plot.set_title('Instrument and sample peak widths')
785    Plot.set_ylabel(r'$\Delta q/q, \Delta d/d$',fontsize=14)
786    Plot.set_xlabel(r'$q, \AA^{-1}$',fontsize=14)
787    Plot.plot(X,Y,color='r',label='Gaussian')
788    Plot.plot(X,Z,color='g',label='Lorentzian')
789    Plot.plot(X,W,color='b',label='G+L')
790    Plot.plot(X,V,color='k',label='G+L2')
791    X = []
792    Y = []
793    Z = []
794    W = []
795    V = []
796    for peak in peaks:
797        X.append(4.0*math.pi*sind(peak[0]/2.0)/lam)
798        s = 1.17741*math.sqrt(peak[4])*math.pi/18000.
799        g = peak[6]*math.pi/18000.
800        G = gamFW(g,s)
801        H = gamFW2(g,s)
802        Y.append(s/tand(peak[0]/2.))
803        Z.append(g/tand(peak[0]/2.))
804        W.append(G/tand(peak[0]/2.))
805        V.append(H/tand(peak[0]/2.))
806    Plot.plot(X,Y,'+',color='r',label='G peak')
807    Plot.plot(X,Z,'+',color='g',label='L peak')
808    Plot.plot(X,W,'+',color='b',label='G+L peak')
809    Plot.plot(X,V,'+',color='k',label='G+L2 peak')
810    Plot.legend(loc='best')
811    Page.canvas.draw()
812   
813def PlotStrain(self,data):
814    # in this instance data is for a phase
815    PatternId = self.PatternId
816    generalData = data['General']
817    SGData = generalData['SGData']
818    MuStrKeys = G2spc.MustrainNames(SGData)
819    cell = generalData['Cell'][1:]
820    A,B = G2lat.cell2AB(cell[:6])
821    Vol = cell[6]
822    useList = data['Histograms']
823    numPlots = len(useList)
824   
825    try:
826        plotNum = self.G2plotNB.plotList.index('Microstrain')
827        Page = self.G2plotNB.nb.GetPage(plotNum)
828        Page.figure.clf()
829        Plot = mp3d.Axes3D(Page.figure)
830    except ValueError,error:
831        Plot = mp3d.Axes3D(self.G2plotNB.add3D('Microstrain'))
832        plotNum = self.G2plotNB.plotList.index('Microstrain')
833        Page = self.G2plotNB.nb.GetPage(plotNum)
834    Page.SetFocus()
835    self.G2plotNB.status.SetStatusText('Adjust frame size to get desired aspect ratio',1)
836   
837    for item in useList:
838        if useList[item]['Show']:
839            muStrain = useList[item]['Mustrain']
840            PHI = np.linspace(0.,360.,30,True)
841            PSI = np.linspace(0.,180.,30,True)
842            X = np.outer(npsind(PHI),npsind(PSI))
843            Y = np.outer(npcosd(PHI),npsind(PSI))
844            Z = np.outer(np.ones(np.size(PHI)),npcosd(PSI))
845            if muStrain[0] == 'isotropic':
846                muiso = muStrain[1][0]*math.pi/0.018
847                X *= muiso
848                Y *= muiso
849                Z *= muiso               
850               
851            elif muStrain[0] == 'uniaxial':
852                def uniaxMustrain(xyz,muiso,muaniso,axes):
853                    cp = abs(np.dot(xyz,axes))
854                    S = muiso+muaniso*cp
855                    return S*xyz*math.pi/0.018
856                muiso,muaniso = muStrain[1][:2]
857                axes = np.inner(A,np.array(muStrain[3]))
858                axes /= nl.norm(axes)
859                Shkl = np.array(muStrain[1])
860                Shape = X.shape[0]
861                XYZ = np.dstack((X,Y,Z))
862                XYZ = np.nan_to_num(np.apply_along_axis(uniaxMustrain,2,XYZ,muiso,muaniso,axes))
863                X,Y,Z = np.dsplit(XYZ,3)
864                X = X[:,:,0]
865                Y = Y[:,:,0]
866                Z = Z[:,:,0]
867               
868            elif muStrain[0] == 'generalized':
869                def genMustrain(xyz,SGData,A,Shkl):
870                    uvw = np.inner(A.T,xyz)
871                    Strm = np.array(G2spc.MustrainCoeff(uvw,SGData))
872                    sum = np.sqrt(np.sum(np.multiply(Shkl,Strm)))*math.pi/0.018
873                    return sum*xyz
874                Shkl = np.array(muStrain[4])
875                if np.any(Shkl):
876                    Shape = X.shape[0]
877                    XYZ = np.dstack((X,Y,Z))
878                    XYZ = np.nan_to_num(np.apply_along_axis(genMustrain,2,XYZ,SGData,A,Shkl))
879                    X,Y,Z = np.dsplit(XYZ,3)
880                    X = X[:,:,0]
881                    Y = Y[:,:,0]
882                    Z = Z[:,:,0]
883                   
884            if np.any(X) and np.any(Y) and np.any(Z):
885                Plot.plot_surface(X,Y,Z,rstride=1,cstride=1,color='g')
886               
887            Plot.set_xlabel('X')
888            Plot.set_ylabel('Y')
889            Plot.set_zlabel('Z')
890    Page.canvas.draw()
891           
892def PlotExposedImage(self,newPlot=False,event=None):
893    plotNo = self.G2plotNB.nb.GetSelection()
894    if self.G2plotNB.nb.GetPageText(plotNo) == '2D Powder Image':
895        PlotImage(self,newPlot,event)
896    elif self.G2plotNB.nb.GetPageText(plotNo) == '2D Integration':
897        PlotIntegration(self,newPlot,event)
898
899def PlotImage(self,newPlot=False,event=None):
900    from matplotlib.patches import Ellipse,Arc,Circle,Polygon
901    import numpy.ma as ma
902    Dsp = lambda tth,wave: wave/(2.*sind(tth/2.))
903    global Data,Masks
904    Data = self.PatternTree.GetItemPyData(
905        G2gd.GetPatternTreeItemId(self,self.Image, 'Image Controls'))
906    Masks = self.PatternTree.GetItemPyData(
907        G2gd.GetPatternTreeItemId(self,self.Image, 'Masks'))
908
909    def OnImMotion(event):
910        Page.canvas.SetToolTipString('')
911        sizexy = Data['size']
912        if event.xdata and event.ydata:                 #avoid out of frame errors
913            Page.canvas.SetCursor(wx.CROSS_CURSOR)
914            item = self.itemPicked
915            pixelSize = Data['pixelSize']
916            scalex = 1000./pixelSize[0]
917            scaley = 1000./pixelSize[1]
918            if item and self.PatternTree.GetItemText(self.PickId) == 'Image Controls':
919                if 'Text' in str(item):
920                    Page.canvas.SetToolTipString('%8.3f %8.3fmm'%(event.xdata,event.ydata))
921                else:
922                    xcent,ycent = Data['center']
923                    xpos = event.xdata-xcent
924                    ypos = event.ydata-ycent
925                    tth,azm = G2img.GetTthAzm(event.xdata,event.ydata,Data)
926                    if 'line3' in  str(item) or 'line4' in str(item) and not Data['fullIntegrate']:
927                        Page.canvas.SetToolTipString('%6d deg'%(azm))
928                    elif 'line1' in  str(item) or 'line2' in str(item):
929                        Page.canvas.SetToolTipString('%8.3fdeg'%(tth))                           
930            else:
931                xpos = event.xdata
932                ypos = event.ydata
933                xpix = xpos*scalex
934                ypix = ypos*scaley
935                Int = 0
936                if (0 <= xpix <= sizexy[0]) and (0 <= ypix <= sizexy[1]):
937                    Int = self.ImageZ[ypix][xpix]
938                tth,azm,dsp = G2img.GetTthAzmDsp(xpos,ypos,Data)
939                Q = 2.*math.pi/dsp
940                if self.setPoly:
941                    self.G2plotNB.status.SetFields(['','Polygon mask pick - LB next point, RB close polygon'])
942                else:
943                    self.G2plotNB.status.SetFields(\
944                        ['','Detector 2-th =%9.3fdeg, dsp =%9.3fA, Q = %6.5fA-1, azm = %7.2fdeg, I = %6d'%(tth,dsp,Q,azm,Int)])
945
946    def OnImPlotKeyPress(event):
947        try:
948            PickName = self.PatternTree.GetItemText(self.PickId)
949        except TypeError:
950            return
951        if PickName == 'Masks':
952            Xpos = event.xdata
953            if not Xpos:            #got point out of frame
954                return
955            Ypos = event.ydata
956            if event.key == 's':
957                print 'spot mask @ ',Xpos,Ypos
958                Masks['Points'].append([Xpos,Ypos,1.])
959            elif event.key == 'r':
960                tth = G2img.GetTth(Xpos,Ypos,Data)
961                print 'ring mask @ ',Xpos,Ypos,tth
962                Masks['Rings'].append([tth,0.1])
963            elif event.key == 'a':
964                tth,azm = G2img.GetTthAzm(Xpos,Ypos,Data)
965                azm = int(azm)               
966                print 'arc mask @ ', Xpos,Ypos
967                Masks['Arcs'].append([tth,[azm-5,azm+5],0.1])
968            elif event.key == 'p':
969                self.setPoly = True
970                Masks['Polygons'].append([])
971                self.G2plotNB.status.SetFields(['','Polygon mask active - LB pick next point, RB close polygon'])
972            G2imG.UpdateMasks(self,Masks)
973        elif PickName == 'Image Controls':
974            if event.key == 'c':
975                Xpos = event.xdata
976                if not Xpos:            #got point out of frame
977                    return
978                Ypos = event.ydata
979                dlg = wx.MessageDialog(self,'Are you sure you want to change the center?',
980                    'Center change',style=wx.OK|wx.CANCEL)
981                try:
982                    if dlg.ShowModal() == wx.ID_OK:
983                        print 'move center to: ',Xpos,Ypos
984                        Data['center'] = [Xpos,Ypos]
985                        G2imG.UpdateImageControls(self,Data,Masks)
986                finally:
987                    dlg.Destroy()
988            elif event.key == 'l':
989                if self.logPlot:
990                    self.logPlot = False
991                else:
992                    self.logPlot = True
993        PlotImage(self)
994           
995    def OnKeyBox(event):
996        if self.G2plotNB.nb.GetSelection() == self.G2plotNB.plotList.index('2D Powder Image'):
997            event.key = cb.GetValue()[0]
998            cb.SetValue(' key press')
999            if event.key in 'l':
1000                OnImPlotKeyPress(event)
1001                       
1002    def OnImPick(event):
1003        if self.PatternTree.GetItemText(self.PickId) not in ['Image Controls','Masks']:
1004            return
1005        if self.setPoly:
1006            polygon = Masks['Polygons'][-1]
1007            xpos,ypos = event.mouseevent.xdata,event.mouseevent.ydata
1008            if xpos and ypos:                       #point inside image
1009                if len(polygon) > 2 and event.mouseevent.button == 3:
1010                    x0,y0 = polygon[0]
1011                    polygon.append([x0,y0])
1012                    self.setPoly = False
1013                    self.G2plotNB.status.SetFields(['','Polygon closed - RB drag a vertex to change shape'])
1014                else:
1015                    self.G2plotNB.status.SetFields(['','New polygon point: %.1f,%.1f'%(xpos,ypos)])
1016                    polygon.append([xpos,ypos])
1017                G2imG.UpdateMasks(self,Masks)
1018        else:
1019            if self.itemPicked is not None: return
1020            self.itemPicked = event.artist
1021            self.mousePicked = event.mouseevent
1022       
1023    def OnImRelease(event):
1024        try:
1025            PickName = self.PatternTree.GetItemText(self.PickId)
1026        except TypeError:
1027            return
1028        if PickName not in ['Image Controls','Masks']:
1029            return
1030        pixelSize = Data['pixelSize']
1031        scalex = 1000./pixelSize[0]
1032        scaley = 1000./pixelSize[1]
1033        pixLimit = Data['pixLimit']
1034        if self.itemPicked is None and PickName == 'Image Controls':
1035#            sizexy = Data['size']
1036            Xpos = event.xdata
1037            if not (Xpos and self.ifGetRing):                   #got point out of frame
1038                return
1039            Ypos = event.ydata
1040            if Ypos and not Page.toolbar._active:         #make sure zoom/pan not selected
1041                if event.button == 1:
1042                    if event.key == 'shift':                #terminate picking?
1043                        print 'LB shift'
1044                        self.dataFrame.GetStatusBar().SetStatusText('Calibrating...')
1045                        if G2img.ImageCalibrate(self,Data):
1046                            self.dataFrame.GetStatusBar().SetStatusText('Calibration successful')
1047                            print 'Calibration successful'
1048                        else:
1049                            self.dataFrame.GetStatusBar().SetStatusText('Calibration failed')
1050                            print 'Calibration failed'
1051                        self.ifGetRing = False
1052                        G2imG.UpdateImageControls(self,Data,Masks)
1053                        return
1054                    Xpix = Xpos*scalex
1055                    Ypix = Ypos*scaley
1056                    xpos,ypos,I,J = G2img.ImageLocalMax(self.ImageZ,pixLimit,Xpix,Ypix)
1057                    if I and J:
1058                        xpos += .5                              #shift to pixel center
1059                        ypos += .5
1060                        xpos /= scalex                          #convert to mm
1061                        ypos /= scaley
1062                        Data['ring'].append([xpos,ypos])
1063                PlotImage(self)
1064            return
1065        else:
1066            xpos = event.xdata
1067            if xpos:                                        #avoid out of frame mouse position
1068                ypos = event.ydata
1069                if self.ifGetRing:                          #delete a calibration ring pick
1070                    xypos = [xpos,ypos]
1071                    rings = Data['ring']
1072                    for ring in rings:
1073                        if np.allclose(ring,xypos,.01,0):
1074                            rings.remove(ring)                                                                       
1075                else:
1076                    tth,azm,dsp = G2img.GetTthAzmDsp(xpos,ypos,Data)
1077                    itemPicked = str(self.itemPicked)
1078                    if 'Line2D' in itemPicked and PickName == 'Image Controls':
1079                        if 'line1' in itemPicked:
1080                            Data['IOtth'][0] = max(tth,0.001)
1081                        elif 'line2' in itemPicked:
1082                            Data['IOtth'][1] = tth
1083                        elif 'line3' in itemPicked and not Data['fullIntegrate']:
1084                            Data['LRazimuth'][0] = int(azm)
1085                        elif 'line4' in itemPicked and not Data['fullIntegrate']:
1086                            Data['LRazimuth'][1] = int(azm)
1087                           
1088                        if Data['LRazimuth'][1] < Data['LRazimuth'][0]:
1089                            Data['LRazimuth'][1] += 360
1090                        if  Data['IOtth'][0] > Data['IOtth'][1]:
1091                            Data['IOtth'][0],Data['IOtth'][1] = Data['IOtth'][1],Data['IOtth'][0]
1092                           
1093                        self.InnerTth.SetValue("%8.2f" % (Data['IOtth'][0]))
1094                        self.OuterTth.SetValue("%8.2f" % (Data['IOtth'][1]))
1095                        self.Lazim.SetValue("%6d" % (Data['LRazimuth'][0]))
1096                        self.Razim.SetValue("%6d" % (Data['LRazimuth'][1]))
1097                    elif 'Circle' in itemPicked and PickName == 'Masks':
1098                        spots = Masks['Points']
1099                        newPos = itemPicked.split(')')[0].split('(')[2].split(',')
1100                        newPos = np.array([float(newPos[0]),float(newPos[1])])
1101                        for spot in spots:
1102                            if np.allclose(np.array([spot[:2]]),newPos):
1103                                spot[:2] = xpos,ypos
1104                        G2imG.UpdateMasks(self,Masks)
1105                    elif 'Line2D' in itemPicked and PickName == 'Masks':
1106                        Obj = self.itemPicked.findobj()
1107                        rings = Masks['Rings']
1108                        arcs = Masks['Arcs']
1109                        polygons = Masks['Polygons']
1110                        for ring in self.ringList:
1111                            if Obj == ring[0]:
1112                                rN = ring[1]
1113                                if ring[2] == 'o':
1114                                    rings[rN][0] = G2img.GetTth(xpos,ypos,Data)-rings[rN][1]/2.
1115                                else:
1116                                    rings[rN][0] = G2img.GetTth(xpos,ypos,Data)+rings[rN][1]/2.
1117                        for arc in self.arcList:
1118                            if Obj == arc[0]:
1119                                aN = arc[1]
1120                                if arc[2] == 'o':
1121                                    arcs[aN][0] = G2img.GetTth(xpos,ypos,Data)-arcs[aN][2]/2
1122                                elif arc[2] == 'i':
1123                                    arcs[aN][0] = G2img.GetTth(xpos,ypos,Data)+arcs[aN][2]/2
1124                                elif arc[2] == 'l':
1125                                    arcs[aN][1][0] = int(G2img.GetAzm(xpos,ypos,Data))
1126                                else:
1127                                    arcs[aN][1][1] = int(G2img.GetAzm(xpos,ypos,Data))
1128                        for poly in self.polyList:
1129                            if Obj == poly[0]:
1130                                ind = self.itemPicked.contains(self.mousePicked)[1]['ind'][0]
1131                                oldPos = np.array([self.mousePicked.xdata,self.mousePicked.ydata])
1132                                pN = poly[1]
1133                                for i,xy in enumerate(polygons[pN]):
1134                                    if np.allclose(np.array([xy]),oldPos,atol=1.0):
1135                                        polygons[pN][i] = xpos,ypos
1136                        G2imG.UpdateMasks(self,Masks)
1137#                    else:                  #keep for future debugging
1138#                        print str(self.itemPicked),event.xdata,event.ydata,event.button
1139                PlotImage(self)
1140            self.itemPicked = None
1141           
1142    try:
1143        plotNum = self.G2plotNB.plotList.index('2D Powder Image')
1144        Page = self.G2plotNB.nb.GetPage(plotNum)
1145        if not newPlot:
1146            Plot = Page.figure.gca()          #get previous powder plot & get limits
1147            xylim = Plot.get_xlim(),Plot.get_ylim()
1148        Page.figure.clf()
1149        Plot = Page.figure.gca()          #get a fresh plot after clf()
1150       
1151    except ValueError,error:
1152        Plot = self.G2plotNB.addMpl('2D Powder Image').gca()
1153        plotNum = self.G2plotNB.plotList.index('2D Powder Image')
1154        Page = self.G2plotNB.nb.GetPage(plotNum)
1155        Page.canvas.mpl_connect('key_press_event', OnImPlotKeyPress)
1156        Page.canvas.mpl_connect('motion_notify_event', OnImMotion)
1157        Page.canvas.mpl_connect('pick_event', OnImPick)
1158        Page.canvas.mpl_connect('button_release_event', OnImRelease)
1159        xylim = []
1160    if not event:                       #event from GUI TextCtrl - don't want focus to change to plot!!!
1161        Page.SetFocus()
1162    Title = self.PatternTree.GetItemText(self.Image)[4:]
1163    self.G2plotNB.status.DestroyChildren()
1164    if self.logPlot:
1165        Title = 'log('+Title+')'
1166    Plot.set_title(Title)
1167    try:
1168        if self.PatternTree.GetItemText(self.PickId) in ['Image Controls',]:
1169            if self.logPlot:
1170                Choice = (' key press','l: log(I) off')
1171            else:
1172                Choice = (' key press','l: log(I) on')
1173            cb = wx.ComboBox(self.G2plotNB.status,style=wx.CB_DROPDOWN|wx.CB_READONLY,
1174                choices=Choice)
1175            cb.Bind(wx.EVT_COMBOBOX, OnKeyBox)
1176            cb.SetValue(' key press')
1177    except TypeError:
1178        pass
1179    size,imagefile = self.PatternTree.GetItemPyData(self.Image)
1180    if imagefile != self.oldImagefile:
1181        imagefile = G2IO.CheckImageFile(self,imagefile)
1182        if not imagefile:
1183            self.G2plotNB.Delete('2D Powder Image')
1184            return
1185        self.PatternTree.SetItemPyData(self.Image,[size,imagefile])
1186        self.ImageZ = G2IO.GetImageData(self,imagefile,imageOnly=True)
1187#        print self.ImageZ.shape,self.ImageZ.size,Data['size'] #might be useful debugging line
1188        self.oldImagefile = imagefile
1189
1190    imScale = 1
1191    if len(self.ImageZ) > 1024:
1192        imScale = len(self.ImageZ)/1024
1193    sizexy = Data['size']
1194    pixelSize = Data['pixelSize']
1195    scalex = 1000./pixelSize[0]
1196    scaley = 1000./pixelSize[1]
1197    Xmax = sizexy[0]*pixelSize[0]/1000.
1198    Ymax = sizexy[1]*pixelSize[1]/1000.
1199    xlim = (0,Xmax)
1200    ylim = (Ymax,0)
1201    Imin,Imax = Data['range'][1]
1202    acolor = mpl.cm.get_cmap(Data['color'])
1203    xcent,ycent = Data['center']
1204    Plot.set_xlabel('Image x-axis, mm',fontsize=12)
1205    Plot.set_ylabel('Image y-axis, mm',fontsize=12)
1206    #do threshold mask - "real" mask - others are just bondaries
1207    Zlim = Masks['Thresholds'][1]
1208    wx.BeginBusyCursor()
1209    try:
1210        MA = ma.masked_greater(ma.masked_less(self.ImageZ,Zlim[0]),Zlim[1])
1211        MaskA = ma.getmaskarray(MA)
1212        A = G2img.ImageCompress(MA,imScale)
1213        AM = G2img.ImageCompress(MaskA,imScale)
1214        if self.logPlot:
1215            A = np.log(A)
1216            AM = np.log(AM)
1217            Imin,Imax = [np.amin(A),np.amax(A)]
1218                   
1219        ImgM = Plot.imshow(AM,aspect='equal',cmap='Reds',
1220            interpolation='nearest',vmin=0,vmax=2,extent=[0,Xmax,Xmax,0])
1221        Img = Plot.imshow(A,aspect='equal',cmap=acolor,
1222            interpolation='nearest',vmin=Imin,vmax=Imax,extent=[0,Xmax,Ymax,0])
1223        if self.setPoly:
1224            Img.set_picker(True)
1225   
1226        Plot.plot(xcent,ycent,'x')
1227        if Data['showLines']:
1228            LRAzim = Data['LRazimuth']                  #NB: integers
1229            AzmthOff = Data['azmthOff']
1230            IOtth = Data['IOtth']
1231            wave = Data['wavelength']
1232            dspI = wave/(2.0*sind(IOtth[0]/2.0))
1233            ellI = G2img.GetEllipse(dspI,Data)           #=False if dsp didn't yield an ellipse (ugh! a parabola or a hyperbola)
1234            dspO = wave/(2.0*sind(IOtth[1]/2.0))
1235            ellO = G2img.GetEllipse(dspO,Data)           #Ditto & more likely for outer ellipse
1236            if Data['fullIntegrate']:
1237                Azm = np.array(range(0,361))
1238            else:
1239                Azm = np.array(range(LRAzim[0],LRAzim[1]+1))-AzmthOff
1240            if ellI:
1241                xyI = []
1242                for azm in Azm:
1243                    xyI.append(G2img.GetDetectorXY(dspI,azm,Data))
1244                xyI = np.array(xyI)
1245                arcxI,arcyI = xyI.T
1246                Plot.plot(arcxI,arcyI,picker=3)
1247            if ellO:
1248                xyO = []
1249                for azm in Azm:
1250                    xyO.append(G2img.GetDetectorXY(dspO,azm,Data))
1251                xyO = np.array(xyO)
1252                arcxO,arcyO = xyO.T
1253                Plot.plot(arcxO,arcyO,picker=3)
1254            if ellO and ellI and not Data['fullIntegrate']:
1255                Plot.plot([arcxI[0],arcxO[0]],[arcyI[0],arcyO[0]],picker=3)
1256                Plot.plot([arcxI[-1],arcxO[-1]],[arcyI[-1],arcyO[-1]],picker=3)
1257        for xring,yring in Data['ring']:
1258            Plot.plot(xring,yring,'r+',picker=3)
1259        if Data['setRings']:
1260            rings = np.concatenate((Data['rings']),axis=0)
1261            for xring,yring,dsp in rings:
1262                Plot.plot(xring,yring,'r+')           
1263        for ellipse in Data['ellipses']:
1264            cent,phi,[width,height],col = ellipse
1265            Plot.add_artist(Ellipse([cent[0],cent[1]],2*width,2*height,phi,ec=col,fc='none'))
1266            Plot.text(cent[0],cent[1],'+',color=col,ha='center',va='center')
1267        #masks - mask lines numbered after integration limit lines
1268        spots = Masks['Points']
1269        rings = Masks['Rings']
1270        arcs = Masks['Arcs']
1271        polygons = Masks['Polygons']
1272        for x,y,d in spots:
1273            Plot.add_artist(Circle((x,y),radius=d/2,fc='none',ec='r',picker=3))
1274        self.ringList = []
1275        for iring,(tth,thick) in enumerate(rings):
1276            wave = Data['wavelength']
1277            x1,y1 = np.hsplit(np.array(G2img.makeIdealRing(G2img.GetEllipse(Dsp(tth+thick/2.,wave),Data))),2)
1278            x2,y2 = np.hsplit(np.array(G2img.makeIdealRing(G2img.GetEllipse(Dsp(tth-thick/2.,wave),Data))),2)
1279            self.ringList.append([Plot.plot(x1,y1,'r',picker=3),iring,'o'])           
1280            self.ringList.append([Plot.plot(x2,y2,'r',picker=3),iring,'i'])
1281        self.arcList = []
1282        for iarc,(tth,azm,thick) in enumerate(arcs):           
1283            wave = Data['wavelength']
1284            x1,y1 = np.hsplit(np.array(G2img.makeIdealRing(G2img.GetEllipse(Dsp(tth+thick/2.,wave),Data),azm)),2)
1285            x2,y2 = np.hsplit(np.array(G2img.makeIdealRing(G2img.GetEllipse(Dsp(max(0.01,tth-thick/2.),wave),Data),azm)),2)
1286            self.arcList.append([Plot.plot(x1,y1,'r',picker=3),iarc,'o'])           
1287            self.arcList.append([Plot.plot(x2,y2,'r',picker=3),iarc,'i'])
1288            self.arcList.append([Plot.plot([x1[0],x2[0]],[y1[0],y2[0]],'r',picker=3),iarc,'l'])
1289            self.arcList.append([Plot.plot([x1[-1],x2[-1]],[y1[-1],y2[-1]],'r',picker=3),iarc,'u'])
1290        self.polyList = []
1291        for ipoly,polygon in enumerate(polygons):
1292            x,y = np.hsplit(np.array(polygon),2)
1293            self.polyList.append([Plot.plot(x,y,'r+',picker=10),ipoly])
1294            Plot.plot(x,y,'r')           
1295        colorBar = Page.figure.colorbar(Img)
1296        Plot.set_xlim(xlim)
1297        Plot.set_ylim(ylim)
1298        if not newPlot and xylim:
1299            Page.toolbar.push_current()
1300            Plot.set_xlim(xylim[0])
1301            Plot.set_ylim(xylim[1])
1302            xylim = []
1303            Page.toolbar.push_current()
1304            Page.toolbar.draw()
1305        else:
1306            Page.canvas.draw()
1307    finally:
1308        wx.EndBusyCursor()
1309       
1310def PlotIntegration(self,newPlot=False,event=None):
1311           
1312    def OnMotion(event):
1313        Page.canvas.SetToolTipString('')
1314        Page.canvas.SetCursor(wx.CROSS_CURSOR)
1315        azm = event.ydata
1316        tth = event.xdata
1317        if azm and tth:
1318            self.G2plotNB.status.SetFields(\
1319                ['','Detector 2-th =%9.3fdeg, azm = %7.2fdeg'%(tth,azm)])
1320                               
1321    try:
1322        plotNum = self.G2plotNB.plotList.index('2D Integration')
1323        Page = self.G2plotNB.nb.GetPage(plotNum)
1324        if not newPlot:
1325            Plot = Page.figure.gca()          #get previous plot & get limits
1326            xylim = Plot.get_xlim(),Plot.get_ylim()
1327        Page.figure.clf()
1328        Plot = Page.figure.gca()          #get a fresh plot after clf()
1329       
1330    except ValueError,error:
1331        Plot = self.G2plotNB.addMpl('2D Integration').gca()
1332        plotNum = self.G2plotNB.plotList.index('2D Integration')
1333        Page = self.G2plotNB.nb.GetPage(plotNum)
1334        Page.canvas.mpl_connect('motion_notify_event', OnMotion)
1335        Page.views = False
1336        view = False
1337    if not event:
1338        Page.SetFocus()
1339       
1340    Data = self.PatternTree.GetItemPyData(
1341        G2gd.GetPatternTreeItemId(self,self.Image, 'Image Controls'))
1342    image = self.Integrate[0]
1343    xsc = self.Integrate[1]
1344    ysc = self.Integrate[2]
1345    Imin,Imax = Data['range'][1]
1346    acolor = mpl.cm.get_cmap(Data['color'])
1347    Plot.set_title(self.PatternTree.GetItemText(self.Image)[4:])
1348    Plot.set_ylabel('azimuth',fontsize=12)
1349    Plot.set_xlabel('2-theta',fontsize=12)
1350    Img = Plot.imshow(image,cmap=acolor,vmin=Imin,vmax=Imax,interpolation='nearest', \
1351        extent=[ysc[0],ysc[-1],xsc[-1],xsc[0]],aspect='auto')
1352    colorBar = Page.figure.colorbar(Img)
1353    if Data['setRings']:
1354        rings = np.concatenate((Data['rings']),axis=0)
1355        for xring,yring,dsp in rings:
1356            x,y = G2img.GetTthAzm(xring,yring,Data)
1357            Plot.plot(x,y,'r+')
1358    if Data['ellipses']:           
1359        for ellipse in Data['ellipses']:
1360            ring = np.array(G2img.makeIdealRing(ellipse[:3])) #skip color
1361            x,y = np.hsplit(ring,2)
1362            tth,azm = G2img.GetTthAzm(x,y,Data)
1363            Plot.plot(tth,azm,'b,')
1364    if not newPlot:
1365        Page.toolbar.push_current()
1366        Plot.set_xlim(xylim[0])
1367        Plot.set_ylim(xylim[1])
1368        xylim = []
1369        Page.toolbar.push_current()
1370        Page.toolbar.draw()
1371    else:
1372        Page.canvas.draw()
1373               
1374def PlotTRImage(self,tax,tay,taz,newPlot=False):
1375    #a test plot routine - not normally used
1376           
1377    def OnMotion(event):
1378        Page.canvas.SetToolTipString('')
1379        Page.canvas.SetCursor(wx.CROSS_CURSOR)
1380        azm = event.xdata
1381        tth = event.ydata
1382        if azm and tth:
1383            self.G2plotNB.status.SetFields(\
1384                ['','Detector 2-th =%9.3fdeg, azm = %7.2fdeg'%(tth,azm)])
1385                               
1386    try:
1387        plotNum = self.G2plotNB.plotList.index('2D Transformed Powder Image')
1388        Page = self.G2plotNB.nb.GetPage(plotNum)
1389        if not newPlot:
1390            Plot = Page.figure.gca()          #get previous plot & get limits
1391            xylim = Plot.get_xlim(),Plot.get_ylim()
1392        Page.figure.clf()
1393        Plot = Page.figure.gca()          #get a fresh plot after clf()
1394       
1395    except ValueError,error:
1396        Plot = self.G2plotNB.addMpl('2D Transformed Powder Image').gca()
1397        plotNum = self.G2plotNB.plotList.index('2D Transformed Powder Image')
1398        Page = self.G2plotNB.nb.GetPage(plotNum)
1399        Page.canvas.mpl_connect('motion_notify_event', OnMotion)
1400        Page.views = False
1401        view = False
1402    Page.SetFocus()
1403       
1404    Data = self.PatternTree.GetItemPyData(
1405        G2gd.GetPatternTreeItemId(self,self.Image, 'Image Controls'))
1406    Imin,Imax = Data['range'][1]
1407    step = (Imax-Imin)/5.
1408    V = np.arange(Imin,Imax,step)
1409    acolor = mpl.cm.get_cmap(Data['color'])
1410    Plot.set_title(self.PatternTree.GetItemText(self.Image)[4:])
1411    Plot.set_xlabel('azimuth',fontsize=12)
1412    Plot.set_ylabel('2-theta',fontsize=12)
1413    Plot.contour(tax,tay,taz,V,cmap=acolor)
1414    if Data['showLines']:
1415        IOtth = Data['IOtth']
1416        if Data['fullIntegrate']:
1417            LRAzim = [-180,180]
1418        else:
1419            LRAzim = Data['LRazimuth']                  #NB: integers
1420        Plot.plot([LRAzim[0],LRAzim[1]],[IOtth[0],IOtth[0]],picker=True)
1421        Plot.plot([LRAzim[0],LRAzim[1]],[IOtth[1],IOtth[1]],picker=True)
1422        if not Data['fullIntegrate']:
1423            Plot.plot([LRAzim[0],LRAzim[0]],[IOtth[0],IOtth[1]],picker=True)
1424            Plot.plot([LRAzim[1],LRAzim[1]],[IOtth[0],IOtth[1]],picker=True)
1425    if Data['setRings']:
1426        rings = np.concatenate((Data['rings']),axis=0)
1427        for xring,yring,dsp in rings:
1428            x,y = G2img.GetTthAzm(xring,yring,Data)
1429            Plot.plot(y,x,'r+')           
1430    if Data['ellipses']:           
1431        for ellipse in Data['ellipses']:
1432            ring = np.array(G2img.makeIdealRing(ellipse[:3])) #skip color
1433            x,y = np.hsplit(ring,2)
1434            tth,azm = G2img.GetTthAzm(x,y,Data)
1435            Plot.plot(azm,tth,'b,')
1436    if not newPlot:
1437        Page.toolbar.push_current()
1438        Plot.set_xlim(xylim[0])
1439        Plot.set_ylim(xylim[1])
1440        xylim = []
1441        Page.toolbar.push_current()
1442        Page.toolbar.draw()
1443    else:
1444        Page.canvas.draw()
1445       
1446def PlotStructure(self,data):
1447    generalData = data['General']
1448    cell = generalData['Cell'][1:7]
1449    Amat,Bmat = G2lat.cell2AB(cell)         #Amat - crystal to cartesian, Bmat - inverse
1450    A4mat = np.concatenate((np.concatenate((Amat,[[0],[0],[0]]),axis=1),[[0,0,0,1],]),axis=0)
1451    B4mat = np.concatenate((np.concatenate((Bmat,[[0],[0],[0]]),axis=1),[[0,0,0,1],]),axis=0)
1452    Mydir = generalData['Mydir']
1453    atomData = data['Atoms']
1454    drawingData = data['Drawing']
1455    drawAtoms = drawingData['Atoms']
1456    cx,ct,cs = drawingData['atomPtrs']
1457    Wt = [255,255,255]
1458    Rd = [255,0,0]
1459    Gr = [0,255,0]
1460    Bl = [0,0,255]
1461    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]])
1462    uEdges = np.array([
1463        [uBox[0],uBox[1]],[uBox[0],uBox[3]],[uBox[0],uBox[4]],[uBox[1],uBox[2]], 
1464        [uBox[2],uBox[3]],[uBox[1],uBox[5]],[uBox[2],uBox[6]],[uBox[3],uBox[7]], 
1465        [uBox[4],uBox[5]],[uBox[5],uBox[6]],[uBox[6],uBox[7]],[uBox[7],uBox[4]]])
1466    uColors = [Rd,Gr,Bl,Wt, Wt,Wt,Wt,Wt, Wt,Wt,Wt,Wt]
1467    altDown = False
1468    shiftDown = False
1469    ctrlDown = False
1470   
1471    def OnKeyBox(event):
1472        import Image
1473        Draw()                          #make sure plot is fresh!!
1474        mode = cb.GetValue()
1475        Fname = Mydir+'\\'+generalData['Name']+'.'+mode
1476        size = Page.canvas.GetSize()
1477        glPixelStorei(GL_UNPACK_ALIGNMENT, 1)
1478        if mode in ['jpeg',]:
1479            Pix = glReadPixels(0,0,size[0],size[1],GL_RGBA, GL_UNSIGNED_BYTE)
1480            im = Image.new("RGBA", (size[0],size[1]))
1481        else:
1482            Pix = glReadPixels(0,0,size[0],size[1],GL_RGB, GL_UNSIGNED_BYTE)
1483            im = Image.new("RGB", (size[0],size[1]))
1484        im.fromstring(Pix)
1485        im.save(Fname,mode)
1486        cb.SetValue(' Save as:')
1487        self.G2plotNB.status.SetStatusText('Drawing saved to: '+Fname,1)
1488   
1489    def GetTruePosition(xy):
1490        View = glGetIntegerv(GL_VIEWPORT)
1491        Proj = glGetDoublev(GL_PROJECTION_MATRIX)
1492        Model = glGetDoublev(GL_MODELVIEW_MATRIX)
1493        Zmax = 1.
1494        for i,atom in enumerate(drawAtoms):
1495            x,y,z = atom[cx:cx+3]
1496            X,Y,Z = gluProject(x,y,z,Model,Proj,View)
1497            XY = [int(X),int(View[3]-Y)]
1498            if np.allclose(xy,XY,atol=10) and Z < Zmax:
1499                Zmax = Z
1500                SetSelectedAtoms(i)
1501                   
1502    def OnMouseDown(event):
1503        xy = event.GetPosition()
1504        if event.ShiftDown():
1505            GetTruePosition(xy)
1506        else:
1507            drawingData['Rotation'][3] = xy
1508        Draw()
1509       
1510    def OnMouseMove(event):
1511        newxy = event.GetPosition()
1512        if event.ControlDown() and drawingData['showABC']:
1513            if event.LeftIsDown():
1514                ctrlDown = True
1515                SetTestRot(newxy)
1516            elif event.RightIsDown():
1517                SetTestPos(newxy)
1518            elif event.MiddleIsDown():
1519                SetTestRotZ(newxy)
1520               
1521               
1522        if event.Dragging() and not event.ControlDown():
1523            if event.LeftIsDown():
1524                SetRotation(newxy)
1525            elif event.RightIsDown():
1526                SetTranslation(newxy)
1527            elif event.MiddleIsDown():
1528                SetRotationZ(newxy)
1529        Draw()
1530       
1531    def OnMouseWheel(event):
1532        drawingData['cameraPos'] += event.GetWheelRotation()/24
1533        drawingData['cameraPos'] = max(10,min(500,drawingData['cameraPos']))
1534        page = self.dataDisplay.GetSelection()
1535        if page:
1536            if self.dataDisplay.GetPageText(page) == 'Draw Options':
1537                panel = self.dataDisplay.GetPage(page).GetChildren()[0].GetChildren()
1538                names = [child.GetName() for child in panel]
1539                panel[names.index('cameraPos')].SetLabel('Camera Position: '+'%.2f'%(drawingData['cameraPos']))
1540                panel[names.index('cameraSlider')].SetValue(drawingData['cameraPos'])
1541        Draw()
1542           
1543    def SetViewPointText(VP):
1544        page = self.dataDisplay.GetSelection()
1545        if page:
1546            if self.dataDisplay.GetPageText(page) == 'Draw Options':
1547                panel = self.dataDisplay.GetPage(page).GetChildren()[0].GetChildren()
1548                names = [child.GetName() for child in panel]
1549                panel[names.index('viewPoint')].SetValue('%.3f, %.3f, %.3f'%(VP[0],VP[1],VP[2]))
1550           
1551    def ClearSelectedAtoms():
1552        page = self.dataDisplay.GetSelection()
1553        if page:
1554            if self.dataDisplay.GetPageText(page) == 'Draw Atoms':
1555                self.dataDisplay.GetPage(page).ClearSelection()      #this is the Atoms grid in Draw Atoms
1556            elif self.dataDisplay.GetPageText(page) == 'Atoms':
1557                self.dataDisplay.GetPage(page).ClearSelection()      #this is the Atoms grid in Atoms
1558                   
1559    def SetSelectedAtoms(ind):
1560        page = self.dataDisplay.GetSelection()
1561        if page:
1562            if self.dataDisplay.GetPageText(page) == 'Draw Atoms':
1563                self.dataDisplay.GetPage(page).SelectRow(ind)      #this is the Atoms grid in Draw Atoms
1564            elif self.dataDisplay.GetPageText(page) == 'Atoms':
1565                Id = drawAtoms[ind][-2]
1566                for i,atom in enumerate(atomData):
1567                    if atom[-1] == Id:
1568                        self.dataDisplay.GetPage(page).SelectRow(i)      #this is the Atoms grid in Atoms
1569                 
1570    def GetSelectedAtoms():
1571        page = self.dataDisplay.GetSelection()
1572        Ind = []
1573        if page:
1574            if self.dataDisplay.GetPageText(page) == 'Draw Atoms':
1575                Ind = self.dataDisplay.GetPage(page).GetSelectedRows()      #this is the Atoms grid in Draw Atoms
1576            elif self.dataDisplay.GetPageText(page) == 'Atoms':
1577                Ind = self.dataDisplay.GetPage(page).GetSelectedRows()      #this is the Atoms grid in Atoms
1578        return Ind
1579                                       
1580    def OnKey(event):           #on key UP!!
1581        keyCode = event.GetKeyCode()
1582        if keyCode > 255:
1583            keyCode = 0
1584        key,xyz = chr(keyCode),event.GetPosition()
1585        indx = drawingData['selectedAtoms']
1586        if key in ['c','C']:
1587            drawingData['viewPoint'] = [[.5,.5,.5],[0,0]]
1588            drawingData['testPos'] = [[-.1,-.1,-.1],[0.0,0.0,0.0],[0,0]]
1589            drawingData['Rotation'] = [0.0,0.0,0.0,[]]
1590            SetViewPointText(drawingData['viewPoint'][0])
1591        elif key in ['n','N']:
1592            drawAtoms = drawingData['Atoms']
1593            pI = drawingData['viewPoint'][1]
1594            if indx:
1595                pI[0] = indx[pI[1]]
1596                Tx,Ty,Tz = drawAtoms[pI[0]][cx:cx+3]
1597                pI[1] += 1
1598                if pI[1] >= len(indx):
1599                    pI[1] = 0
1600            else:
1601                Tx,Ty,Tz = drawAtoms[pI[0]][cx:cx+3]               
1602                pI[0] += 1
1603                if pI[0] >= len(drawAtoms):
1604                    pI[0] = 0
1605            drawingData['viewPoint'] = [[Tx,Ty,Tz],pI]
1606            SetViewPointText(drawingData['viewPoint'][0])
1607               
1608        elif key in ['p','P']:
1609            drawAtoms = drawingData['Atoms']
1610            pI = drawingData['viewPoint'][1]
1611            if indx:
1612                pI[0] = indx[pI[1]]
1613                Tx,Ty,Tz = drawAtoms[pI[0]][cx:cx+3]
1614                pI[1] -= 1
1615                if pI[1] < 0:
1616                    pI[1] = len(indx)-1
1617            else:
1618                Tx,Ty,Tz = drawAtoms[pI[0]][cx:cx+3]               
1619                pI[0] -= 1
1620                if pI[0] < 0:
1621                    pI[0] = len(drawAtoms)-1
1622            drawingData['viewPoint'] = [[Tx,Ty,Tz],pI]
1623            SetViewPointText(drawingData['viewPoint'][0])           
1624        Draw()
1625           
1626    def SetBackground():
1627        R,G,B,A = Page.camera['backColor']
1628        glClearColor(R,G,B,A)
1629        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
1630       
1631    def SetLights():
1632        glEnable(GL_DEPTH_TEST)
1633        glShadeModel(GL_SMOOTH)
1634        glEnable(GL_LIGHTING)
1635        glEnable(GL_LIGHT0)
1636        glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,0)
1637        glLightfv(GL_LIGHT0,GL_AMBIENT,[1,1,1,.8])
1638        glLightfv(GL_LIGHT0,GL_DIFFUSE,[1,1,1,1])
1639       
1640    def SetTranslation(newxy):
1641        Tx,Ty,Tz = drawingData['viewPoint'][0]
1642        anglex,angley,anglez,oldxy = drawingData['Rotation']
1643        Rx = G2lat.rotdMat(anglex,0)
1644        Ry = G2lat.rotdMat(angley,1)
1645        Rz = G2lat.rotdMat(anglez,2)
1646        dxy = list(newxy-oldxy)+[0,]
1647        dxy = np.inner(Bmat,np.inner(Rz,np.inner(Ry,np.inner(Rx,dxy))))
1648        Tx -= dxy[0]*0.01
1649        Ty += dxy[1]*0.01
1650        Tz -= dxy[2]*0.01
1651        drawingData['Rotation'][3] = newxy
1652        drawingData['viewPoint'][0] =  Tx,Ty,Tz
1653        SetViewPointText([Tx,Ty,Tz])
1654       
1655    def SetTestPos(newxy):
1656        Tx,Ty,Tz = drawingData['testPos'][0]
1657        anglex,angley,anglez,oldxy = drawingData['Rotation']
1658        Rx = G2lat.rotdMat(anglex,0)
1659        Ry = G2lat.rotdMat(angley,1)
1660        Rz = G2lat.rotdMat(anglez,2)
1661        dxy = list(newxy-oldxy)+[0,]
1662        dxy = np.inner(Rz,np.inner(Ry,np.inner(Rx,dxy)))
1663        Tx += dxy[0]*0.001
1664        Ty -= dxy[1]*0.001
1665        Tz += dxy[2]*0.001
1666        drawingData['Rotation'][3] = newxy
1667        drawingData['testPos'][0] =  Tx,Ty,Tz
1668       
1669    def SetTestRot(newxy):
1670        Txyz = np.array(drawingData['testPos'][0])
1671        oldxy = drawingData['testPos'][2]
1672        Ax,Ay,Az = drawingData['testPos'][1]
1673        Vxyz = np.array(drawingData['viewPoint'][0])
1674        Dxyz = np.inner(Amat,Txyz-Vxyz)
1675        dxy = list(newxy-oldxy)+[0,]
1676        Ax += dxy[1]*0.01
1677        Ay += dxy[0]*0.01
1678        Rx = G2lat.rotdMat(Ax,0)
1679        Ry = G2lat.rotdMat(Ay,1)
1680        Dxyz = np.inner(Ry,np.inner(Rx,Dxyz))       
1681        Dxyz = np.inner(Bmat,Dxyz)+Vxyz
1682        drawingData['testPos'][1] = [Ax,Ay,Az]
1683        drawingData['testPos'][2] = newxy
1684        drawingData['testPos'][0] = Dxyz
1685       
1686    def SetTestRotZ(newxy):
1687        Txyz = np.array(drawingData['testPos'][0])
1688        oldxy = drawingData['testPos'][2]
1689        Ax,Ay,Az = drawingData['testPos'][1]
1690        Vxyz = np.array(drawingData['viewPoint'][0])
1691        Dxyz = np.inner(Amat,Txyz-Vxyz)       
1692        dxy = list(newxy-oldxy)+[0,]
1693        Az += (dxy[0]+dxy[1])*.01
1694        Rz = G2lat.rotdMat(Az,2)
1695        Dxyz = np.inner(Rz,Dxyz)       
1696        Dxyz = np.inner(Bmat,Dxyz)+Vxyz
1697        drawingData['testPos'][1] = [Ax,Ay,Az]
1698        drawingData['testPos'][2] = newxy
1699        drawingData['testPos'][0] = Dxyz
1700                             
1701    def SetRotation(newxy):       
1702        anglex,angley,anglez,oldxy = drawingData['Rotation']
1703        dxy = newxy-oldxy
1704        anglex += dxy[1]*.25
1705        angley += dxy[0]*.25
1706        oldxy = newxy
1707        drawingData['Rotation'] = [anglex,angley,anglez,oldxy]
1708       
1709    def SetRotationZ(newxy):                       
1710        anglex,angley,anglez,oldxy = drawingData['Rotation']
1711        dxy = newxy-oldxy
1712        anglez += (dxy[0]+dxy[1])*.25
1713        oldxy = newxy
1714        drawingData['Rotation'] = [anglex,angley,anglez,oldxy]
1715       
1716    def RenderBox():
1717        glEnable(GL_COLOR_MATERIAL)
1718        glLineWidth(2)
1719        glEnable(GL_BLEND)
1720        glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA)
1721        glEnable(GL_LINE_SMOOTH)
1722        glBegin(GL_LINES)
1723        for line,color in zip(uEdges,uColors):
1724            glColor3ubv(color)
1725            glVertex3fv(line[0])
1726            glVertex3fv(line[1])
1727        glEnd()
1728        glColor4ubv([0,0,0,0])
1729        glDisable(GL_LINE_SMOOTH)
1730        glDisable(GL_BLEND)
1731        glDisable(GL_COLOR_MATERIAL)
1732       
1733    def RenderUnitVectors(x,y,z):
1734        xyz = np.array([x,y,z])
1735        glEnable(GL_COLOR_MATERIAL)
1736        glLineWidth(1)
1737        glPushMatrix()
1738        glTranslate(x,y,z)
1739        glScalef(1/cell[0],1/cell[1],1/cell[2])
1740        glBegin(GL_LINES)
1741        for line,color in zip(uEdges,uColors)[:3]:
1742            glColor3ubv(color)
1743            glVertex3fv(line[0])
1744            glVertex3fv(line[1])
1745        glEnd()
1746        glPopMatrix()
1747        glColor4ubv([0,0,0,0])
1748        glDisable(GL_COLOR_MATERIAL)
1749               
1750    def RenderSphere(x,y,z,radius,color):
1751        glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,color)
1752        glPushMatrix()
1753        glTranslate(x,y,z)
1754        glMultMatrixf(B4mat.T)
1755        q = gluNewQuadric()
1756        gluSphere(q,radius,20,10)
1757        glPopMatrix()
1758       
1759    def RenderEllipsoid(x,y,z,ellipseProb,E,R4,color):
1760        s1,s2,s3 = E
1761        glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,color)
1762        glPushMatrix()
1763        glTranslate(x,y,z)
1764        glMultMatrixf(B4mat.T)
1765        glMultMatrixf(R4.T)
1766        glEnable(GL_NORMALIZE)
1767        glScale(s1,s2,s3)
1768        q = gluNewQuadric()
1769        gluSphere(q,ellipseProb,20,10)
1770        glDisable(GL_NORMALIZE)
1771        glPopMatrix()
1772       
1773    def RenderBonds(x,y,z,Bonds,radius,color,slice=20):
1774        glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,color)
1775        glPushMatrix()
1776        glTranslate(x,y,z)
1777        glMultMatrixf(B4mat.T)
1778        for bond in Bonds:
1779            glPushMatrix()
1780            Dx = np.inner(Amat,bond)
1781            Z = np.sqrt(np.sum(Dx**2))
1782            azm = atan2d(-Dx[1],-Dx[0])
1783            phi = acosd(Dx[2]/Z)
1784            glRotate(-azm,0,0,1)
1785            glRotate(phi,1,0,0)
1786            q = gluNewQuadric()
1787            gluCylinder(q,radius,radius,Z,slice,2)
1788            glPopMatrix()           
1789        glPopMatrix()
1790               
1791    def RenderLines(x,y,z,Bonds,color):
1792        xyz = np.array([x,y,z])
1793        glEnable(GL_COLOR_MATERIAL)
1794        glLineWidth(1)
1795        glColor3fv(color)
1796        glPushMatrix()
1797        glBegin(GL_LINES)
1798        for bond in Bonds:
1799            glVertex3fv(xyz)
1800            glVertex3fv(xyz+bond)
1801        glEnd()
1802        glColor4ubv([0,0,0,0])
1803        glPopMatrix()
1804        glDisable(GL_COLOR_MATERIAL)
1805       
1806    def RenderPolyhedra(x,y,z,Faces,color):
1807        glPushMatrix()
1808        glTranslate(x,y,z)
1809        glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,color)
1810        glShadeModel(GL_SMOOTH)
1811        glMultMatrixf(B4mat.T)
1812        for face,norm in Faces:
1813            glPolygonMode(GL_FRONT_AND_BACK,GL_FILL)
1814            glFrontFace(GL_CW)
1815            glNormal3fv(norm)
1816            glBegin(GL_TRIANGLES)
1817            for vert in face:
1818                glVertex3fv(vert)
1819            glEnd()
1820        glPopMatrix()
1821       
1822    def RenderBackbone(Backbone,BackboneColor,radius):
1823        glPushMatrix()
1824        glMultMatrixf(B4mat.T)
1825        glEnable(GL_COLOR_MATERIAL)
1826        glShadeModel(GL_SMOOTH)
1827        gleSetJoinStyle(TUBE_NORM_EDGE | TUBE_JN_ANGLE | TUBE_JN_CAP)
1828        glePolyCylinder(Backbone,BackboneColor,radius)
1829        glPopMatrix()       
1830        glDisable(GL_COLOR_MATERIAL)
1831       
1832    def RenderLabel(x,y,z,label,r):       
1833        glPushMatrix()
1834        glTranslate(x,y,z)
1835        glMultMatrixf(B4mat.T)
1836        glDisable(GL_LIGHTING)
1837        glColor3f(0,1.,0)
1838        glRasterPos3f(r,r,r)
1839        for c in list(label):
1840            glutBitmapCharacter(GLUT_BITMAP_8_BY_13,ord(c))
1841        glEnable(GL_LIGHTING)
1842        glPopMatrix()
1843                           
1844    def Draw():
1845        import numpy.linalg as nl
1846        Ind = GetSelectedAtoms()
1847        VS = np.array(Page.canvas.GetSize())
1848        aspect = float(VS[0])/float(VS[1])
1849        cPos = drawingData['cameraPos']
1850        Zclip = drawingData['Zclip']*cPos/200.
1851        anglex,angley,anglez = drawingData['Rotation'][:3]
1852        Tx,Ty,Tz = drawingData['viewPoint'][0]
1853        cx,ct,cs = drawingData['atomPtrs']
1854        bondR = drawingData['bondRadius']
1855        G,g = G2lat.cell2Gmat(cell)
1856        GS = G
1857        GS[0][1] = GS[1][0] = math.sqrt(GS[0][0]*GS[1][1])
1858        GS[0][2] = GS[2][0] = math.sqrt(GS[0][0]*GS[2][2])
1859        GS[1][2] = GS[2][1] = math.sqrt(GS[1][1]*GS[2][2])
1860        ellipseProb = G2lat.criticalEllipse(drawingData['ellipseProb']/100.)
1861       
1862        SetBackground()
1863        glInitNames()
1864        glPushName(0)
1865       
1866        glMatrixMode(GL_PROJECTION)
1867        glLoadIdentity()
1868        glViewport(0,0,VS[0],VS[1])
1869        gluPerspective(20.,aspect,cPos-Zclip,cPos+Zclip)
1870        gluLookAt(0,0,cPos,0,0,0,0,1,0)
1871        SetLights()           
1872           
1873        glMatrixMode(GL_MODELVIEW)
1874        glLoadIdentity()
1875        glRotate(anglez,0,0,1)
1876        glRotate(anglex,cosd(anglez),-sind(anglez),0)
1877        glRotate(angley,sind(anglez),cosd(anglez),0)
1878        glMultMatrixf(A4mat.T)
1879        glTranslate(-Tx,-Ty,-Tz)
1880        if drawingData['unitCellBox']:
1881            RenderBox()
1882        if drawingData['showABC']:
1883#            try:            #temporary fix - not needed further?
1884#                x,y,z = drawingData['testPos'][0]
1885#            except TypeError:
1886#                x,y,z = drawingData['testPos']
1887            x,y,z = drawingData['testPos'][0]
1888            if altDown:
1889                self.G2plotNB.status.SetStatusText('moving test point %.4f,%.4f,%.4f'%(x,y,z),1)
1890            else:
1891                self.G2plotNB.status.SetStatusText('test point %.4f,%.4f,%.4f'%(x,y,z),1)           
1892            RenderUnitVectors(x,y,z)
1893        Backbone = []
1894        BackboneColor = []
1895        time0 = time.time()
1896        for iat,atom in enumerate(drawingData['Atoms']):
1897            x,y,z = atom[cx:cx+3]
1898            Bonds = atom[-2]
1899            Faces = atom[-1]
1900            try:
1901                atNum = generalData['AtomTypes'].index(atom[ct])
1902            except ValueError:
1903                atNum = -1
1904            CL = atom[cs+2]
1905            color = np.array(CL)/255.
1906            if iat in Ind:
1907                color = np.array(Gr)/255.
1908            radius = 0.5
1909            if atom[cs] != '':
1910                glLoadName(atom[-3])                   
1911            if 'balls' in atom[cs]:
1912                vdwScale = drawingData['vdwScale']
1913                ballScale = drawingData['ballScale']
1914                if atNum < 0:
1915                    radius = 0.2
1916                elif 'H' == atom[ct]:
1917                    if drawingData['showHydrogen']:
1918                        if 'vdW' in atom[cs] and atNum >= 0:
1919                            radius = vdwScale*generalData['vdWRadii'][atNum]
1920                        else:
1921                            radius = ballScale*drawingData['sizeH']
1922                    else:
1923                        radius = 0.0
1924                else:
1925                    if 'vdW' in atom[cs]:
1926                        radius = vdwScale*generalData['vdWRadii'][atNum]
1927                    else:
1928                        radius = ballScale*generalData['BondRadii'][atNum]
1929                RenderSphere(x,y,z,radius,color)
1930                if 'sticks' in atom[cs]:
1931                    RenderBonds(x,y,z,Bonds,bondR,color)
1932            elif 'ellipsoids' in atom[cs]:
1933                RenderBonds(x,y,z,Bonds,bondR,color)
1934                if atom[cs+3] == 'A':                   
1935                    Uij = atom[cs+5:cs+11]
1936                    U = np.multiply(G2spc.Uij2U(Uij),GS)
1937                    U = np.inner(Amat,np.inner(U,Amat).T)
1938                    E,R = nl.eigh(U)
1939                    R4 = np.concatenate((np.concatenate((R,[[0],[0],[0]]),axis=1),[[0,0,0,1],]),axis=0)
1940                    E = np.sqrt(E)
1941                    if atom[ct] == 'H' and not drawingData['showHydrogen']:
1942                        pass
1943                    else:
1944                        RenderEllipsoid(x,y,z,ellipseProb,E,R4,color)                   
1945                else:
1946                    if atom[ct] == 'H' and not drawingData['showHydrogen']:
1947                        pass
1948                    else:
1949                        radius = ellipseProb*math.sqrt(abs(atom[cs+4]))
1950                        RenderSphere(x,y,z,radius,color)
1951            elif 'lines' in atom[cs]:
1952                radius = 0.1
1953                RenderLines(x,y,z,Bonds,color)
1954#                RenderBonds(x,y,z,Bonds,0.05,color,6)
1955            elif atom[cs] == 'sticks':
1956                radius = 0.1
1957                RenderBonds(x,y,z,Bonds,bondR,color)
1958            elif atom[cs] == 'polyhedra':
1959                RenderPolyhedra(x,y,z,Faces,color)
1960            elif atom[cs] == 'backbone':
1961                if atom[ct-1].split()[0] in ['C','N']:
1962                    Backbone.append(list(np.inner(Amat,np.array([x,y,z]))))
1963                    BackboneColor.append(list(color))
1964                   
1965            if atom[cs+1] == 'type':
1966                RenderLabel(x,y,z,atom[ct],radius)
1967            elif atom[cs+1] == 'name':
1968                RenderLabel(x,y,z,atom[ct-1],radius)
1969            elif atom[cs+1] == 'number':
1970                RenderLabel(x,y,z,str(iat+1),radius)
1971            elif atom[cs+1] == 'residue' and atom[ct-1] == 'CA':
1972                RenderLabel(x,y,z,atom[ct-4],radius)
1973            elif atom[cs+1] == '1-letter' and atom[ct-1] == 'CA':
1974                RenderLabel(x,y,z,atom[ct-3],radius)
1975            elif atom[cs+1] == 'chain' and atom[ct-1] == 'CA':
1976                RenderLabel(x,y,z,atom[ct-2],radius)
1977        if Backbone:
1978            RenderBackbone(Backbone,BackboneColor,bondR)
1979#        print time.time()-time0
1980        Page.canvas.SwapBuffers()
1981       
1982    def OnSize(event):
1983        Draw()
1984       
1985    def OnFocus(event):
1986        Draw()
1987       
1988    try:
1989        plotNum = self.G2plotNB.plotList.index(generalData['Name'])
1990        Page = self.G2plotNB.nb.GetPage(plotNum)       
1991    except (ValueError,error):
1992        Plot = self.G2plotNB.addOgl(generalData['Name'])
1993        plotNum = self.G2plotNB.plotList.index(generalData['Name'])
1994        Page = self.G2plotNB.nb.GetPage(plotNum)
1995        Page.views = False
1996        view = False
1997        altDown = False
1998    Page.SetFocus()
1999    cb = wx.ComboBox(self.G2plotNB.status,style=wx.CB_DROPDOWN|wx.CB_READONLY,
2000        choices=(' save as:','jpeg','tiff','bmp'))
2001    cb.Bind(wx.EVT_COMBOBOX, OnKeyBox)
2002    cb.SetValue(' save as:')
2003    Page.canvas.Bind(wx.EVT_MOUSEWHEEL, OnMouseWheel)
2004    Page.canvas.Bind(wx.EVT_LEFT_DOWN, OnMouseDown)
2005    Page.canvas.Bind(wx.EVT_RIGHT_DOWN, OnMouseDown)
2006    Page.canvas.Bind(wx.EVT_MIDDLE_DOWN, OnMouseDown)
2007    Page.canvas.Bind(wx.EVT_KEY_UP, OnKey)
2008    Page.canvas.Bind(wx.EVT_MOTION, OnMouseMove)
2009    Page.canvas.Bind(wx.EVT_SIZE, OnSize)
2010    Page.canvas.Bind(wx.EVT_SET_FOCUS, OnFocus)
2011    Page.camera['position'] = drawingData['cameraPos']
2012    Page.camera['viewPoint'] = np.inner(Amat,drawingData['viewPoint'][0])
2013    Page.camera['backColor'] = np.array(list(drawingData['backColor'])+[0,])/255.
2014    Page.canvas.SetCurrent()
2015    Draw()
2016       
Note: See TracBrowser for help on using the repository browser.