source: trunk/GSASIIplot.py @ 412

Last change on this file since 412 was 404, checked in by vondreele, 14 years ago

put error bars on seq refinement plots
add cubic elastic strain coeff
make sure results are saved from seq refinements

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