source: trunk/GSASIIplot.py @ 391

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

set default atom frac=1 for cif files
store covMatrix not normalized by diagonal
make esds on cell parameters

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