source: trunk/GSASIIplot.py @ 264

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

begin implementation of pdf generation - work in progress
modify image to have azimuth=0 as vertical "up"
add textctrls for max and min image intensity
fix to some lattice parameter defaults for some Laue groups

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