source: trunk/GSASIIplot.py @ 399

Last change on this file since 399 was 399, checked in by vondreele, 10 years ago

Implement sequential refinement
remove print "load" & "save" for each item in Tree
revise application of azimuth offset - azimuths are now all "true" with correction

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