source: trunk/GSASIIplot.py @ 272

Last change on this file since 272 was 272, checked in by vondreele, 12 years ago

add slider for "Ruland" coeff.
add 'o' option for undoing offset in powder plots

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