source: trunk/GSASIIplot.py @ 267

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

removed azm rotation - didn't work
fix azimuthal polarization

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