source: trunk/GSASIIplot.py @ 390

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

Add tooltip to covariance plot
clean up LS output formats
Add Fobs extraction & R-value calculations

  • Property svn:keywords set to Date Author Revision URL Id
File size: 109.0 KB
Line 
1#GSASII plotting routines
2########### SVN repository information ###################
3# $Date: 2011-10-10 21:32:58 +0000 (Mon, 10 Oct 2011) $
4# $Author: vondreele $
5# $Revision: 390 $
6# $URL: trunk/GSASIIplot.py $
7# $Id: GSASIIplot.py 390 2011-10-10 21:32:58Z 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    covArray = Data['covariance']
1375
1376    def OnPlotKeyPress(event):
1377        newPlot = False
1378        if event.key == 's':
1379            choice = [m for m in mpl.cm.datad.keys() if not m.endswith("_r")]
1380            choice.sort()
1381            dlg = wx.SingleChoiceDialog(self,'Select','Color scheme',choice)
1382            if dlg.ShowModal() == wx.ID_OK:
1383                sel = dlg.GetSelection()
1384                self.ContourColor = choice[sel]
1385            else:
1386                self.ContourColor = 'Spectral'
1387            dlg.Destroy()
1388        PlotCovariance(self)
1389
1390    def OnMotion(event):
1391        if event.xdata and event.ydata:                 #avoid out of frame errors
1392            xpos = int(event.xdata+.5)
1393            ypos = int(event.ydata+.5)
1394            if -1 < xpos < len(varyList) and -1 < ypos < len(varyList):
1395                msg = '%s - %s: %5.3f'%(varyList[xpos],varyList[ypos],covArray[xpos][ypos])
1396                Page.canvas.SetToolTipString(msg)
1397                self.G2plotNB.status.SetFields(['Key: s to change colors',msg])
1398    try:
1399        plotNum = self.G2plotNB.plotList.index('Covariance')
1400        Page = self.G2plotNB.nb.GetPage(plotNum)
1401        Page.figure.clf()
1402        Plot = Page.figure.gca()
1403        if not Page.IsShown():
1404            Page.Show()
1405    except ValueError:
1406        Plot = self.G2plotNB.addMpl('Covariance').gca()
1407        plotNum = self.G2plotNB.plotList.index('Covariance')
1408        Page = self.G2plotNB.nb.GetPage(plotNum)
1409        Page.canvas.mpl_connect('motion_notify_event', OnMotion)
1410        Page.canvas.mpl_connect('key_press_event', OnPlotKeyPress)
1411
1412    Page.SetFocus()
1413    self.G2plotNB.status.SetFields(['',''])   
1414    acolor = mpl.cm.get_cmap(self.ContourColor)
1415    Img = Plot.imshow(covArray,aspect='equal',cmap=acolor,interpolation='nearest',origin='lower')
1416    colorBar = Page.figure.colorbar(Img)
1417    Plot.set_title('Variance-Covariance matrix from LS refinement')
1418    Plot.set_xlabel('Variable number')
1419    Plot.set_ylabel('Variable number')
1420    Page.canvas.draw()
1421
1422           
1423def PlotExposedImage(self,newPlot=False,event=None):
1424    '''General access module for 2D image plotting
1425    '''
1426    plotNo = self.G2plotNB.nb.GetSelection()
1427    if self.G2plotNB.nb.GetPageText(plotNo) == '2D Powder Image':
1428        PlotImage(self,newPlot,event,newImage=True)
1429    elif self.G2plotNB.nb.GetPageText(plotNo) == '2D Integration':
1430        PlotIntegration(self,newPlot,event)
1431
1432def PlotImage(self,newPlot=False,event=None,newImage=True):
1433    '''Plot of 2D detector images as contoured plot. Also plot calibration ellipses,
1434    masks, etc.
1435    '''
1436    from matplotlib.patches import Ellipse,Arc,Circle,Polygon
1437    import numpy.ma as ma
1438    Dsp = lambda tth,wave: wave/(2.*sind(tth/2.))
1439    global Data,Masks
1440    colors=['b','g','r','c','m','k']
1441    Data = self.PatternTree.GetItemPyData(
1442        G2gd.GetPatternTreeItemId(self,self.Image, 'Image Controls'))
1443    Masks = self.PatternTree.GetItemPyData(
1444        G2gd.GetPatternTreeItemId(self,self.Image, 'Masks'))
1445
1446    def OnImMotion(event):
1447        Page.canvas.SetToolTipString('')
1448        sizexy = Data['size']
1449        if event.xdata and event.ydata:                 #avoid out of frame errors
1450            Page.canvas.SetCursor(wx.CROSS_CURSOR)
1451            item = self.itemPicked
1452            pixelSize = Data['pixelSize']
1453            scalex = 1000./pixelSize[0]
1454            scaley = 1000./pixelSize[1]
1455            if item and self.PatternTree.GetItemText(self.PickId) == 'Image Controls':
1456                if 'Text' in str(item):
1457                    Page.canvas.SetToolTipString('%8.3f %8.3fmm'%(event.xdata,event.ydata))
1458                else:
1459                    xcent,ycent = Data['center']
1460                    xpos = event.xdata-xcent
1461                    ypos = event.ydata-ycent
1462                    tth,azm = G2img.GetTthAzm(event.xdata,event.ydata,Data)
1463                    if 'line3' in  str(item) or 'line4' in str(item) and not Data['fullIntegrate']:
1464                        Page.canvas.SetToolTipString('%6d deg'%(azm))
1465                    elif 'line1' in  str(item) or 'line2' in str(item):
1466                        Page.canvas.SetToolTipString('%8.3fdeg'%(tth))                           
1467            else:
1468                xpos = event.xdata
1469                ypos = event.ydata
1470                xpix = xpos*scalex
1471                ypix = ypos*scaley
1472                Int = 0
1473                if (0 <= xpix <= sizexy[0]) and (0 <= ypix <= sizexy[1]):
1474                    Int = self.ImageZ[ypix][xpix]
1475                tth,azm,dsp = G2img.GetTthAzmDsp(xpos,ypos,Data)
1476                Q = 2.*math.pi/dsp
1477                if self.setPoly:
1478                    self.G2plotNB.status.SetFields(['','Polygon mask pick - LB next point, RB close polygon'])
1479                else:
1480                    self.G2plotNB.status.SetFields(\
1481                        ['','Detector 2-th =%9.3fdeg, dsp =%9.3fA, Q = %6.5fA-1, azm = %7.2fdeg, I = %6d'%(tth,dsp,Q,azm,Int)])
1482
1483    def OnImPlotKeyPress(event):
1484        try:
1485            PickName = self.PatternTree.GetItemText(self.PickId)
1486        except TypeError:
1487            return
1488        if PickName == 'Masks':
1489            Xpos = event.xdata
1490            if not Xpos:            #got point out of frame
1491                return
1492            Ypos = event.ydata
1493            if event.key == 's':
1494                Masks['Points'].append([Xpos,Ypos,1.])
1495            elif event.key == 'r':
1496                tth = G2img.GetTth(Xpos,Ypos,Data)
1497                Masks['Rings'].append([tth,0.1])
1498            elif event.key == 'a':
1499                tth,azm = G2img.GetTthAzm(Xpos,Ypos,Data)
1500                azm = int(azm)               
1501                Masks['Arcs'].append([tth,[azm-5,azm+5],0.1])
1502            elif event.key == 'p':
1503                self.setPoly = True
1504                Masks['Polygons'].append([])
1505                self.G2plotNB.status.SetFields(['','Polygon mask active - LB pick next point, RB close polygon'])
1506            G2imG.UpdateMasks(self,Masks)
1507        elif PickName == 'Image Controls':
1508            if event.key == 'c':
1509                Xpos = event.xdata
1510                if not Xpos:            #got point out of frame
1511                    return
1512                Ypos = event.ydata
1513                dlg = wx.MessageDialog(self,'Are you sure you want to change the center?',
1514                    'Center change',style=wx.OK|wx.CANCEL)
1515                try:
1516                    if dlg.ShowModal() == wx.ID_OK:
1517                        print 'move center to: ',Xpos,Ypos
1518                        Data['center'] = [Xpos,Ypos]
1519                        G2imG.UpdateImageControls(self,Data,Masks)
1520                finally:
1521                    dlg.Destroy()
1522            elif event.key == 'l':
1523                if self.logPlot:
1524                    self.logPlot = False
1525                else:
1526                    self.logPlot = True
1527        PlotImage(self,newImage=True)
1528           
1529    def OnKeyBox(event):
1530        if self.G2plotNB.nb.GetSelection() == self.G2plotNB.plotList.index('2D Powder Image'):
1531            event.key = cb.GetValue()[0]
1532            cb.SetValue(' key press')
1533            if event.key in 'l':
1534                OnImPlotKeyPress(event)
1535                       
1536    def OnImPick(event):
1537        if self.PatternTree.GetItemText(self.PickId) not in ['Image Controls','Masks']:
1538            return
1539        if self.setPoly:
1540            polygon = Masks['Polygons'][-1]
1541            xpos,ypos = event.mouseevent.xdata,event.mouseevent.ydata
1542            if xpos and ypos:                       #point inside image
1543                if len(polygon) > 2 and event.mouseevent.button == 3:
1544                    x0,y0 = polygon[0]
1545                    polygon.append([x0,y0])
1546                    self.setPoly = False
1547                    self.G2plotNB.status.SetFields(['','Polygon closed - RB drag a vertex to change shape'])
1548                else:
1549                    self.G2plotNB.status.SetFields(['','New polygon point: %.1f,%.1f'%(xpos,ypos)])
1550                    polygon.append([xpos,ypos])
1551                G2imG.UpdateMasks(self,Masks)
1552        else:
1553            if self.itemPicked is not None: return
1554            self.itemPicked = event.artist
1555            self.mousePicked = event.mouseevent
1556       
1557    def OnImRelease(event):
1558        try:
1559            PickName = self.PatternTree.GetItemText(self.PickId)
1560        except TypeError:
1561            return
1562        if PickName not in ['Image Controls','Masks']:
1563            return
1564        pixelSize = Data['pixelSize']
1565        scalex = 1000./pixelSize[0]
1566        scaley = 1000./pixelSize[1]
1567        pixLimit = Data['pixLimit']
1568        if self.itemPicked is None and PickName == 'Image Controls':
1569#            sizexy = Data['size']
1570            Xpos = event.xdata
1571            if not (Xpos and self.ifGetRing):                   #got point out of frame
1572                return
1573            Ypos = event.ydata
1574            if Ypos and not Page.toolbar._active:         #make sure zoom/pan not selected
1575                if event.button == 1:
1576                    Xpix = Xpos*scalex
1577                    Ypix = Ypos*scaley
1578                    xpos,ypos,I,J = G2img.ImageLocalMax(self.ImageZ,pixLimit,Xpix,Ypix)
1579                    if I and J:
1580                        xpos += .5                              #shift to pixel center
1581                        ypos += .5
1582                        xpos /= scalex                          #convert to mm
1583                        ypos /= scaley
1584                        Data['ring'].append([xpos,ypos])
1585                elif event.button == 3:
1586                    self.dataFrame.GetStatusBar().SetStatusText('Calibrating...')
1587                    if G2img.ImageCalibrate(self,Data):
1588                        self.dataFrame.GetStatusBar().SetStatusText('Calibration successful - Show ring picks to check')
1589                        print 'Calibration successful'
1590                    else:
1591                        self.dataFrame.GetStatusBar().SetStatusText('Calibration failed - Show ring picks to diagnose')
1592                        print 'Calibration failed'
1593                    self.ifGetRing = False
1594                    G2imG.UpdateImageControls(self,Data,Masks)
1595                    return
1596                PlotImage(self,newImage=False)
1597            return
1598        else:
1599            xpos = event.xdata
1600            if xpos:                                        #avoid out of frame mouse position
1601                ypos = event.ydata
1602                if self.ifGetRing:                          #delete a calibration ring pick
1603                    xypos = [xpos,ypos]
1604                    rings = Data['ring']
1605                    for ring in rings:
1606                        if np.allclose(ring,xypos,.01,0):
1607                            rings.remove(ring)                                                                       
1608                else:
1609                    tth,azm,dsp = G2img.GetTthAzmDsp(xpos,ypos,Data)
1610                    itemPicked = str(self.itemPicked)
1611                    if 'Line2D' in itemPicked and PickName == 'Image Controls':
1612                        if 'line1' in itemPicked:
1613                            Data['IOtth'][0] = max(tth,0.001)
1614                        elif 'line2' in itemPicked:
1615                            Data['IOtth'][1] = tth
1616                        elif 'line3' in itemPicked:
1617                            Data['LRazimuth'][0] = int(azm)
1618                            if Data['fullIntegrate']:
1619                                Data['LRazimuth'][1] = Data['LRazimuth'][0]+360
1620                        elif 'line4' in itemPicked and not Data['fullIntegrate']:
1621                            Data['LRazimuth'][1] = int(azm)
1622                           
1623                        if Data['LRazimuth'][0] > Data['LRazimuth'][1]:
1624                            Data['LRazimuth'][0] -= 360
1625                           
1626                        azLim = np.array(Data['LRazimuth'])   
1627                        if np.any(azLim>360):
1628                            azLim -= 360
1629                            Data['LRazimuth'] = list(azLim)
1630                           
1631                        if  Data['IOtth'][0] > Data['IOtth'][1]:
1632                            Data['IOtth'][0],Data['IOtth'][1] = Data['IOtth'][1],Data['IOtth'][0]
1633                           
1634                        self.InnerTth.SetValue("%8.2f" % (Data['IOtth'][0]))
1635                        self.OuterTth.SetValue("%8.2f" % (Data['IOtth'][1]))
1636                        self.Lazim.SetValue("%6d" % (Data['LRazimuth'][0]))
1637                        self.Razim.SetValue("%6d" % (Data['LRazimuth'][1]))
1638                    elif 'Circle' in itemPicked and PickName == 'Masks':
1639                        spots = Masks['Points']
1640                        newPos = itemPicked.split(')')[0].split('(')[2].split(',')
1641                        newPos = np.array([float(newPos[0]),float(newPos[1])])
1642                        for spot in spots:
1643                            if np.allclose(np.array([spot[:2]]),newPos):
1644                                spot[:2] = xpos,ypos
1645                        G2imG.UpdateMasks(self,Masks)
1646                    elif 'Line2D' in itemPicked and PickName == 'Masks':
1647                        Obj = self.itemPicked.findobj()
1648                        rings = Masks['Rings']
1649                        arcs = Masks['Arcs']
1650                        polygons = Masks['Polygons']
1651                        for ring in self.ringList:
1652                            if Obj == ring[0]:
1653                                rN = ring[1]
1654                                if ring[2] == 'o':
1655                                    rings[rN][0] = G2img.GetTth(xpos,ypos,Data)-rings[rN][1]/2.
1656                                else:
1657                                    rings[rN][0] = G2img.GetTth(xpos,ypos,Data)+rings[rN][1]/2.
1658                        for arc in self.arcList:
1659                            if Obj == arc[0]:
1660                                aN = arc[1]
1661                                if arc[2] == 'o':
1662                                    arcs[aN][0] = G2img.GetTth(xpos,ypos,Data)-arcs[aN][2]/2
1663                                elif arc[2] == 'i':
1664                                    arcs[aN][0] = G2img.GetTth(xpos,ypos,Data)+arcs[aN][2]/2
1665                                elif arc[2] == 'l':
1666                                    arcs[aN][1][0] = int(G2img.GetAzm(xpos,ypos,Data))
1667                                else:
1668                                    arcs[aN][1][1] = int(G2img.GetAzm(xpos,ypos,Data))
1669                        for poly in self.polyList:
1670                            if Obj == poly[0]:
1671                                ind = self.itemPicked.contains(self.mousePicked)[1]['ind'][0]
1672                                oldPos = np.array([self.mousePicked.xdata,self.mousePicked.ydata])
1673                                pN = poly[1]
1674                                for i,xy in enumerate(polygons[pN]):
1675                                    if np.allclose(np.array([xy]),oldPos,atol=1.0):
1676                                        polygons[pN][i] = xpos,ypos
1677                        G2imG.UpdateMasks(self,Masks)
1678#                    else:                  #keep for future debugging
1679#                        print str(self.itemPicked),event.xdata,event.ydata,event.button
1680                PlotImage(self,newImage=True)
1681            self.itemPicked = None
1682           
1683    try:
1684        plotNum = self.G2plotNB.plotList.index('2D Powder Image')
1685        Page = self.G2plotNB.nb.GetPage(plotNum)
1686        if not newPlot:
1687            Plot = Page.figure.gca()          #get previous powder plot & get limits
1688            xylim = Plot.get_xlim(),Plot.get_ylim()
1689        if newImage:
1690            Page.figure.clf()
1691            Plot = Page.figure.gca()          #get a fresh plot after clf()
1692       
1693    except ValueError:
1694        Plot = self.G2plotNB.addMpl('2D Powder Image').gca()
1695        plotNum = self.G2plotNB.plotList.index('2D Powder Image')
1696        Page = self.G2plotNB.nb.GetPage(plotNum)
1697        Page.canvas.mpl_connect('key_press_event', OnImPlotKeyPress)
1698        Page.canvas.mpl_connect('motion_notify_event', OnImMotion)
1699        Page.canvas.mpl_connect('pick_event', OnImPick)
1700        Page.canvas.mpl_connect('button_release_event', OnImRelease)
1701        xylim = []
1702    if not event:                       #event from GUI TextCtrl - don't want focus to change to plot!!!
1703        Page.SetFocus()
1704    Title = self.PatternTree.GetItemText(self.Image)[4:]
1705    self.G2plotNB.status.DestroyChildren()
1706    if self.logPlot:
1707        Title = 'log('+Title+')'
1708    Plot.set_title(Title)
1709    try:
1710        if self.PatternTree.GetItemText(self.PickId) in ['Image Controls',]:
1711            Choice = (' key press','l: log(I) on',)
1712            if self.logPlot:
1713                Choice[1] = 'l: log(I) off'
1714            cb = wx.ComboBox(self.G2plotNB.status,style=wx.CB_DROPDOWN|wx.CB_READONLY,
1715                choices=Choice)
1716            cb.Bind(wx.EVT_COMBOBOX, OnKeyBox)
1717            cb.SetValue(' key press')
1718    except TypeError:
1719        pass
1720    size,imagefile = self.PatternTree.GetItemPyData(self.Image)
1721    if imagefile != self.oldImagefile:
1722        imagefile = G2IO.CheckImageFile(self,imagefile)
1723        if not imagefile:
1724            self.G2plotNB.Delete('2D Powder Image')
1725            return
1726        self.PatternTree.SetItemPyData(self.Image,[size,imagefile])
1727        self.ImageZ = G2IO.GetImageData(self,imagefile,imageOnly=True)
1728#        print self.ImageZ.shape,self.ImageZ.size,Data['size'] #might be useful debugging line
1729        self.oldImagefile = imagefile
1730
1731    imScale = 1
1732    if len(self.ImageZ) > 1024:
1733        imScale = len(self.ImageZ)/1024
1734    sizexy = Data['size']
1735    pixelSize = Data['pixelSize']
1736    scalex = 1000./pixelSize[0]
1737    scaley = 1000./pixelSize[1]
1738    Xmax = sizexy[0]*pixelSize[0]/1000.
1739    Ymax = sizexy[1]*pixelSize[1]/1000.
1740    xlim = (0,Xmax)
1741    ylim = (Ymax,0)
1742    Imin,Imax = Data['range'][1]
1743    acolor = mpl.cm.get_cmap(Data['color'])
1744    xcent,ycent = Data['center']
1745    Plot.set_xlabel('Image x-axis, mm',fontsize=12)
1746    Plot.set_ylabel('Image y-axis, mm',fontsize=12)
1747    #do threshold mask - "real" mask - others are just bondaries
1748    Zlim = Masks['Thresholds'][1]
1749    wx.BeginBusyCursor()
1750    try:
1751           
1752        if newImage:                   
1753            MA = ma.masked_greater(ma.masked_less(self.ImageZ,Zlim[0]),Zlim[1])
1754            MaskA = ma.getmaskarray(MA)
1755            A = G2img.ImageCompress(MA,imScale)
1756            AM = G2img.ImageCompress(MaskA,imScale)
1757            if self.logPlot:
1758                A = np.where(A>0,np.log(A),0)
1759                AM = np.where(AM>0,np.log(AM),0)
1760                Imin,Imax = [np.amin(A),np.amax(A)]
1761            ImgM = Plot.imshow(AM,aspect='equal',cmap='Reds',
1762                interpolation='nearest',vmin=0,vmax=2,extent=[0,Xmax,Xmax,0])
1763            Img = Plot.imshow(A,aspect='equal',cmap=acolor,
1764                interpolation='nearest',vmin=Imin,vmax=Imax,extent=[0,Xmax,Ymax,0])
1765            if self.setPoly:
1766                Img.set_picker(True)
1767   
1768        Plot.plot(xcent,ycent,'x')
1769        if Data['showLines']:
1770            LRAzim = Data['LRazimuth']                  #NB: integers
1771            Nazm = Data['outAzimuths']
1772            delAzm = float(LRAzim[1]-LRAzim[0])/Nazm
1773            AzmthOff = Data['azmthOff']
1774            IOtth = Data['IOtth']
1775            wave = Data['wavelength']
1776            dspI = wave/(2.0*sind(IOtth[0]/2.0))
1777            ellI = G2img.GetEllipse(dspI,Data)           #=False if dsp didn't yield an ellipse (ugh! a parabola or a hyperbola)
1778            dspO = wave/(2.0*sind(IOtth[1]/2.0))
1779            ellO = G2img.GetEllipse(dspO,Data)           #Ditto & more likely for outer ellipse
1780            Azm = np.array(range(LRAzim[0],LRAzim[1]+1))-AzmthOff
1781            if ellI:
1782                xyI = []
1783                for azm in Azm:
1784                    xyI.append(G2img.GetDetectorXY(dspI,azm-90.,Data))
1785                xyI = np.array(xyI)
1786                arcxI,arcyI = xyI.T
1787                Plot.plot(arcxI,arcyI,picker=3)
1788            if ellO:
1789                xyO = []
1790                for azm in Azm:
1791                    xyO.append(G2img.GetDetectorXY(dspO,azm-90.,Data))
1792                xyO = np.array(xyO)
1793                arcxO,arcyO = xyO.T
1794                Plot.plot(arcxO,arcyO,picker=3)
1795            if ellO and ellI:
1796                Plot.plot([arcxI[0],arcxO[0]],[arcyI[0],arcyO[0]],picker=3)
1797                Plot.plot([arcxI[-1],arcxO[-1]],[arcyI[-1],arcyO[-1]],picker=3)
1798            for i in range(Nazm):
1799                cake = LRAzim[0]+i*delAzm
1800                ind = np.searchsorted(Azm,cake)
1801                Plot.plot([arcxI[ind],arcxO[ind]],[arcyI[ind],arcyO[ind]],color='k',dashes=(5,5))
1802                   
1803        for xring,yring in Data['ring']:
1804            Plot.plot(xring,yring,'r+',picker=3)
1805        if Data['setRings']:
1806#            rings = np.concatenate((Data['rings']),axis=0)
1807            N = 0
1808            for ring in Data['rings']:
1809                xring,yring = np.array(ring).T[:2]
1810                Plot.plot(xring,yring,'+',color=colors[N%6])
1811                N += 1           
1812        for ellipse in Data['ellipses']:
1813            cent,phi,[width,height],col = ellipse
1814            Plot.add_artist(Ellipse([cent[0],cent[1]],2*width,2*height,phi,ec=col,fc='none'))
1815            Plot.text(cent[0],cent[1],'+',color=col,ha='center',va='center')
1816        #masks - mask lines numbered after integration limit lines
1817        spots = Masks['Points']
1818        rings = Masks['Rings']
1819        arcs = Masks['Arcs']
1820        polygons = Masks['Polygons']
1821        for x,y,d in spots:
1822            Plot.add_artist(Circle((x,y),radius=d/2,fc='none',ec='r',picker=3))
1823        self.ringList = []
1824        for iring,(tth,thick) in enumerate(rings):
1825            wave = Data['wavelength']
1826            x1,y1 = np.hsplit(np.array(G2img.makeIdealRing(G2img.GetEllipse(Dsp(tth+thick/2.,wave),Data))),2)
1827            x2,y2 = np.hsplit(np.array(G2img.makeIdealRing(G2img.GetEllipse(Dsp(tth-thick/2.,wave),Data))),2)
1828            self.ringList.append([Plot.plot(x1,y1,'r',picker=3),iring,'o'])           
1829            self.ringList.append([Plot.plot(x2,y2,'r',picker=3),iring,'i'])
1830        self.arcList = []
1831        for iarc,(tth,azm,thick) in enumerate(arcs):           
1832            wave = Data['wavelength']
1833            x1,y1 = np.hsplit(np.array(G2img.makeIdealRing(G2img.GetEllipse(Dsp(tth+thick/2.,wave),Data),azm)),2)
1834            x2,y2 = np.hsplit(np.array(G2img.makeIdealRing(G2img.GetEllipse(Dsp(max(0.01,tth-thick/2.),wave),Data),azm)),2)
1835            self.arcList.append([Plot.plot(x1,y1,'r',picker=3),iarc,'o'])           
1836            self.arcList.append([Plot.plot(x2,y2,'r',picker=3),iarc,'i'])
1837            self.arcList.append([Plot.plot([x1[0],x2[0]],[y1[0],y2[0]],'r',picker=3),iarc,'l'])
1838            self.arcList.append([Plot.plot([x1[-1],x2[-1]],[y1[-1],y2[-1]],'r',picker=3),iarc,'u'])
1839        self.polyList = []
1840        for ipoly,polygon in enumerate(polygons):
1841            x,y = np.hsplit(np.array(polygon),2)
1842            self.polyList.append([Plot.plot(x,y,'r+',picker=10),ipoly])
1843            Plot.plot(x,y,'r')           
1844        if newImage:
1845            colorBar = Page.figure.colorbar(Img)
1846        Plot.set_xlim(xlim)
1847        Plot.set_ylim(ylim)
1848        if not newPlot and xylim:
1849            Page.toolbar.push_current()
1850            Plot.set_xlim(xylim[0])
1851            Plot.set_ylim(xylim[1])
1852            xylim = []
1853            Page.toolbar.push_current()
1854            Page.toolbar.draw()
1855        else:
1856            Page.canvas.draw()
1857    finally:
1858        wx.EndBusyCursor()
1859       
1860def PlotIntegration(self,newPlot=False,event=None):
1861    '''Plot of 2D image after image integration with 2-theta and azimuth as coordinates
1862    '''
1863           
1864    def OnMotion(event):
1865        Page.canvas.SetToolTipString('')
1866        Page.canvas.SetCursor(wx.CROSS_CURSOR)
1867        azm = event.ydata
1868        tth = event.xdata
1869        if azm and tth:
1870            self.G2plotNB.status.SetFields(\
1871                ['','Detector 2-th =%9.3fdeg, azm = %7.2fdeg'%(tth,azm)])
1872                               
1873    try:
1874        plotNum = self.G2plotNB.plotList.index('2D Integration')
1875        Page = self.G2plotNB.nb.GetPage(plotNum)
1876        if not newPlot:
1877            Plot = Page.figure.gca()          #get previous plot & get limits
1878            xylim = Plot.get_xlim(),Plot.get_ylim()
1879        Page.figure.clf()
1880        Plot = Page.figure.gca()          #get a fresh plot after clf()
1881       
1882    except ValueError:
1883        Plot = self.G2plotNB.addMpl('2D Integration').gca()
1884        plotNum = self.G2plotNB.plotList.index('2D Integration')
1885        Page = self.G2plotNB.nb.GetPage(plotNum)
1886        Page.canvas.mpl_connect('motion_notify_event', OnMotion)
1887        Page.views = False
1888        view = False
1889    if not event:
1890        Page.SetFocus()
1891       
1892    Data = self.PatternTree.GetItemPyData(
1893        G2gd.GetPatternTreeItemId(self,self.Image, 'Image Controls'))
1894    image = self.Integrate[0]
1895    xsc = self.Integrate[1]
1896    ysc = self.Integrate[2]
1897    Imin,Imax = Data['range'][1]
1898    acolor = mpl.cm.get_cmap(Data['color'])
1899    Plot.set_title(self.PatternTree.GetItemText(self.Image)[4:])
1900    Plot.set_ylabel('azimuth',fontsize=12)
1901    Plot.set_xlabel('2-theta',fontsize=12)
1902    Img = Plot.imshow(image,cmap=acolor,vmin=Imin,vmax=Imax,interpolation='nearest', \
1903        extent=[ysc[0],ysc[-1],xsc[-1],xsc[0]],aspect='auto')
1904    colorBar = Page.figure.colorbar(Img)
1905    if Data['setRings'] and Data['rings']:
1906        rings = np.concatenate((Data['rings']),axis=0)
1907        for xring,yring,dsp in rings:
1908            x,y = G2img.GetTthAzm(xring,yring,Data)
1909            Plot.plot(x,y,'r+')
1910    if Data['ellipses']:           
1911        for ellipse in Data['ellipses']:
1912            ring = np.array(G2img.makeIdealRing(ellipse[:3])) #skip color
1913            x,y = np.hsplit(ring,2)
1914            tth,azm = G2img.GetTthAzm(x,y,Data)
1915            azm = np.where(azm < 0.,azm+360,azm)
1916            Plot.plot(tth,azm,'b,')
1917    if not newPlot:
1918        Page.toolbar.push_current()
1919        Plot.set_xlim(xylim[0])
1920        Plot.set_ylim(xylim[1])
1921        xylim = []
1922        Page.toolbar.push_current()
1923        Page.toolbar.draw()
1924    else:
1925        Page.canvas.draw()
1926               
1927def PlotTRImage(self,tax,tay,taz,newPlot=False):
1928    '''a test plot routine - not normally used
1929    ''' 
1930           
1931    def OnMotion(event):
1932        Page.canvas.SetToolTipString('')
1933        Page.canvas.SetCursor(wx.CROSS_CURSOR)
1934        azm = event.xdata
1935        tth = event.ydata
1936        if azm and tth:
1937            self.G2plotNB.status.SetFields(\
1938                ['','Detector 2-th =%9.3fdeg, azm = %7.2fdeg'%(tth,azm)])
1939                               
1940    try:
1941        plotNum = self.G2plotNB.plotList.index('2D Transformed Powder Image')
1942        Page = self.G2plotNB.nb.GetPage(plotNum)
1943        if not newPlot:
1944            Plot = Page.figure.gca()          #get previous plot & get limits
1945            xylim = Plot.get_xlim(),Plot.get_ylim()
1946        Page.figure.clf()
1947        Plot = Page.figure.gca()          #get a fresh plot after clf()
1948       
1949    except ValueError:
1950        Plot = self.G2plotNB.addMpl('2D Transformed Powder Image').gca()
1951        plotNum = self.G2plotNB.plotList.index('2D Transformed Powder Image')
1952        Page = self.G2plotNB.nb.GetPage(plotNum)
1953        Page.canvas.mpl_connect('motion_notify_event', OnMotion)
1954        Page.views = False
1955        view = False
1956    Page.SetFocus()
1957       
1958    Data = self.PatternTree.GetItemPyData(
1959        G2gd.GetPatternTreeItemId(self,self.Image, 'Image Controls'))
1960    Imin,Imax = Data['range'][1]
1961    step = (Imax-Imin)/5.
1962    V = np.arange(Imin,Imax,step)
1963    acolor = mpl.cm.get_cmap(Data['color'])
1964    Plot.set_title(self.PatternTree.GetItemText(self.Image)[4:])
1965    Plot.set_xlabel('azimuth',fontsize=12)
1966    Plot.set_ylabel('2-theta',fontsize=12)
1967    Plot.contour(tax,tay,taz,V,cmap=acolor)
1968    if Data['showLines']:
1969        IOtth = Data['IOtth']
1970        if Data['fullIntegrate']:
1971            LRAzim = [-180,180]
1972        else:
1973            LRAzim = Data['LRazimuth']                  #NB: integers
1974        Plot.plot([LRAzim[0],LRAzim[1]],[IOtth[0],IOtth[0]],picker=True)
1975        Plot.plot([LRAzim[0],LRAzim[1]],[IOtth[1],IOtth[1]],picker=True)
1976        if not Data['fullIntegrate']:
1977            Plot.plot([LRAzim[0],LRAzim[0]],[IOtth[0],IOtth[1]],picker=True)
1978            Plot.plot([LRAzim[1],LRAzim[1]],[IOtth[0],IOtth[1]],picker=True)
1979    if Data['setRings']:
1980        rings = np.concatenate((Data['rings']),axis=0)
1981        for xring,yring,dsp in rings:
1982            x,y = G2img.GetTthAzm(xring,yring,Data)
1983            Plot.plot(y,x,'r+')           
1984    if Data['ellipses']:           
1985        for ellipse in Data['ellipses']:
1986            ring = np.array(G2img.makeIdealRing(ellipse[:3])) #skip color
1987            x,y = np.hsplit(ring,2)
1988            tth,azm = G2img.GetTthAzm(x,y,Data)
1989            Plot.plot(azm,tth,'b,')
1990    if not newPlot:
1991        Page.toolbar.push_current()
1992        Plot.set_xlim(xylim[0])
1993        Plot.set_ylim(xylim[1])
1994        xylim = []
1995        Page.toolbar.push_current()
1996        Page.toolbar.draw()
1997    else:
1998        Page.canvas.draw()
1999       
2000def PlotStructure(self,data):
2001    '''Crystal structure plotting package. Can show structures as balls, sticks, lines,
2002    thermal motion ellipsoids and polyhedra
2003    '''
2004    generalData = data['General']
2005    cell = generalData['Cell'][1:7]
2006    Amat,Bmat = G2lat.cell2AB(cell)         #Amat - crystal to cartesian, Bmat - inverse
2007    A4mat = np.concatenate((np.concatenate((Amat,[[0],[0],[0]]),axis=1),[[0,0,0,1],]),axis=0)
2008    B4mat = np.concatenate((np.concatenate((Bmat,[[0],[0],[0]]),axis=1),[[0,0,0,1],]),axis=0)
2009    Mydir = generalData['Mydir']
2010    atomData = data['Atoms']
2011    drawingData = data['Drawing']
2012    drawAtoms = drawingData['Atoms']
2013    cx,ct,cs = drawingData['atomPtrs']
2014    Wt = [255,255,255]
2015    Rd = [255,0,0]
2016    Gr = [0,255,0]
2017    Bl = [0,0,255]
2018    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]])
2019    uEdges = np.array([
2020        [uBox[0],uBox[1]],[uBox[0],uBox[3]],[uBox[0],uBox[4]],[uBox[1],uBox[2]], 
2021        [uBox[2],uBox[3]],[uBox[1],uBox[5]],[uBox[2],uBox[6]],[uBox[3],uBox[7]], 
2022        [uBox[4],uBox[5]],[uBox[5],uBox[6]],[uBox[6],uBox[7]],[uBox[7],uBox[4]]])
2023    uColors = [Rd,Gr,Bl,Wt, Wt,Wt,Wt,Wt, Wt,Wt,Wt,Wt]
2024    altDown = False
2025    shiftDown = False
2026    ctrlDown = False
2027   
2028    def OnKeyBox(event):
2029        import Image
2030        Draw()                          #make sure plot is fresh!!
2031        mode = cb.GetValue()
2032        Fname = Mydir+'\\'+generalData['Name']+'.'+mode
2033        size = Page.canvas.GetSize()
2034        glPixelStorei(GL_UNPACK_ALIGNMENT, 1)
2035        if mode in ['jpeg',]:
2036            Pix = glReadPixels(0,0,size[0],size[1],GL_RGBA, GL_UNSIGNED_BYTE)
2037            im = Image.new("RGBA", (size[0],size[1]))
2038        else:
2039            Pix = glReadPixels(0,0,size[0],size[1],GL_RGB, GL_UNSIGNED_BYTE)
2040            im = Image.new("RGB", (size[0],size[1]))
2041        im.fromstring(Pix)
2042        im.save(Fname,mode)
2043        cb.SetValue(' Save as:')
2044        self.G2plotNB.status.SetStatusText('Drawing saved to: '+Fname,1)
2045   
2046    def GetTruePosition(xy):
2047        View = glGetIntegerv(GL_VIEWPORT)
2048        Proj = glGetDoublev(GL_PROJECTION_MATRIX)
2049        Model = glGetDoublev(GL_MODELVIEW_MATRIX)
2050        Zmax = 1.
2051        for i,atom in enumerate(drawAtoms):
2052            x,y,z = atom[cx:cx+3]
2053            X,Y,Z = gluProject(x,y,z,Model,Proj,View)
2054            XY = [int(X),int(View[3]-Y)]
2055            if np.allclose(xy,XY,atol=10) and Z < Zmax:
2056                Zmax = Z
2057                SetSelectedAtoms(i)
2058                   
2059    def OnMouseDown(event):
2060        xy = event.GetPosition()
2061        if event.ShiftDown():
2062            GetTruePosition(xy)
2063        else:
2064            drawingData['Rotation'][3] = xy
2065        Draw()
2066       
2067    def OnMouseMove(event):
2068        newxy = event.GetPosition()
2069        page = getSelection()
2070        if event.ControlDown() and drawingData['showABC']:
2071            if event.LeftIsDown():
2072                SetTestRot(newxy)
2073            elif event.RightIsDown():
2074                SetTestPos(newxy)
2075            elif event.MiddleIsDown():
2076                SetTestRotZ(newxy)
2077            x,y,z = drawingData['testPos'][0]
2078            self.G2plotNB.status.SetStatusText('moving test point %.4f,%.4f,%.4f'%(x,y,z),1)
2079               
2080               
2081        if event.Dragging() and not event.ControlDown():
2082            if event.LeftIsDown():
2083                SetRotation(newxy)
2084                angX,angY,angZ = drawingData['Rotation'][:3]
2085                self.G2plotNB.status.SetStatusText('New rotation: %.2f, %.2f ,%.2f'%(angX,angY,angZ),1)
2086            elif event.RightIsDown():
2087                SetTranslation(newxy)
2088                Tx,Ty,Tz = drawingData['viewPoint'][0]
2089                self.G2plotNB.status.SetStatusText('New view point: %.4f, %.4f, %.4f'%(Tx,Ty,Tz),1)
2090            elif event.MiddleIsDown():
2091                SetRotationZ(newxy)
2092                angX,angY,angZ = drawingData['Rotation'][:3]
2093                self.G2plotNB.status.SetStatusText('New rotation: %.2f, %.2f, %.2f'%(angX,angY,angZ),1)
2094        Draw()
2095       
2096    def OnMouseWheel(event):
2097        drawingData['cameraPos'] += event.GetWheelRotation()/24
2098        drawingData['cameraPos'] = max(10,min(500,drawingData['cameraPos']))
2099        self.G2plotNB.status.SetStatusText('New camera distance: %.2f'%(drawingData['cameraPos']),1)
2100        page = getSelection()
2101        if page:
2102            if self.dataDisplay.GetPageText(page) == 'Draw Options':
2103                panel = self.dataDisplay.GetPage(page).GetChildren()[0].GetChildren()
2104                names = [child.GetName() for child in panel]
2105                panel[names.index('cameraPos')].SetLabel('Camera Position: '+'%.2f'%(drawingData['cameraPos']))
2106                panel[names.index('cameraSlider')].SetValue(drawingData['cameraPos'])
2107        Draw()
2108       
2109    def getSelection():
2110        try:
2111            return self.dataDisplay.GetSelection()
2112        except AttributeError:
2113            print self.dataDisplay.GetLabel()
2114            self.G2plotNB.status.SetStatusText('Select this from Phase data window!')
2115            return 0
2116           
2117    def SetViewPointText(VP):
2118        page = getSelection()
2119        if page:
2120            if self.dataDisplay.GetPageText(page) == 'Draw Options':
2121                panel = self.dataDisplay.GetPage(page).GetChildren()[0].GetChildren()
2122                names = [child.GetName() for child in panel]
2123                panel[names.index('viewPoint')].SetValue('%.3f, %.3f, %.3f'%(VP[0],VP[1],VP[2]))
2124           
2125    def ClearSelectedAtoms():
2126        page = getSelection()
2127        if page:
2128            if self.dataDisplay.GetPageText(page) == 'Draw Atoms':
2129                self.dataDisplay.GetPage(page).ClearSelection()      #this is the Atoms grid in Draw Atoms
2130            elif self.dataDisplay.GetPageText(page) == 'Atoms':
2131                self.dataDisplay.GetPage(page).ClearSelection()      #this is the Atoms grid in Atoms
2132                   
2133    def SetSelectedAtoms(ind):
2134        page = getSelection()
2135        if page:
2136            if self.dataDisplay.GetPageText(page) == 'Draw Atoms':
2137                self.dataDisplay.GetPage(page).SelectRow(ind)      #this is the Atoms grid in Draw Atoms
2138            elif self.dataDisplay.GetPageText(page) == 'Atoms':
2139                Id = drawAtoms[ind][-2]
2140                for i,atom in enumerate(atomData):
2141                    if atom[-1] == Id:
2142                        self.dataDisplay.GetPage(page).SelectRow(i)      #this is the Atoms grid in Atoms
2143                 
2144    def GetSelectedAtoms():
2145        page = getSelection()
2146        Ind = []
2147        if page:
2148            if self.dataDisplay.GetPageText(page) == 'Draw Atoms':
2149                Ind = self.dataDisplay.GetPage(page).GetSelectedRows()      #this is the Atoms grid in Draw Atoms
2150            elif self.dataDisplay.GetPageText(page) == 'Atoms':
2151                Ind = self.dataDisplay.GetPage(page).GetSelectedRows()      #this is the Atoms grid in Atoms
2152        return Ind
2153                                       
2154    def OnKey(event):           #on key UP!!
2155        keyCode = event.GetKeyCode()
2156        if keyCode > 255:
2157            keyCode = 0
2158        key,xyz = chr(keyCode),event.GetPosition()
2159        indx = drawingData['selectedAtoms']
2160        if key in ['c','C']:
2161            drawingData['viewPoint'] = [[.5,.5,.5],[0,0]]
2162            drawingData['testPos'] = [[-.1,-.1,-.1],[0.0,0.0,0.0],[0,0]]
2163            drawingData['Rotation'] = [0.0,0.0,0.0,[]]
2164            SetViewPointText(drawingData['viewPoint'][0])
2165        elif key in ['n','N']:
2166            drawAtoms = drawingData['Atoms']
2167            pI = drawingData['viewPoint'][1]
2168            if indx:
2169                pI[0] = indx[pI[1]]
2170                Tx,Ty,Tz = drawAtoms[pI[0]][cx:cx+3]
2171                pI[1] += 1
2172                if pI[1] >= len(indx):
2173                    pI[1] = 0
2174            else:
2175                Tx,Ty,Tz = drawAtoms[pI[0]][cx:cx+3]               
2176                pI[0] += 1
2177                if pI[0] >= len(drawAtoms):
2178                    pI[0] = 0
2179            drawingData['viewPoint'] = [[Tx,Ty,Tz],pI]
2180            SetViewPointText(drawingData['viewPoint'][0])
2181               
2182        elif key in ['p','P']:
2183            drawAtoms = drawingData['Atoms']
2184            pI = drawingData['viewPoint'][1]
2185            if indx:
2186                pI[0] = indx[pI[1]]
2187                Tx,Ty,Tz = drawAtoms[pI[0]][cx:cx+3]
2188                pI[1] -= 1
2189                if pI[1] < 0:
2190                    pI[1] = len(indx)-1
2191            else:
2192                Tx,Ty,Tz = drawAtoms[pI[0]][cx:cx+3]               
2193                pI[0] -= 1
2194                if pI[0] < 0:
2195                    pI[0] = len(drawAtoms)-1
2196            drawingData['viewPoint'] = [[Tx,Ty,Tz],pI]
2197            SetViewPointText(drawingData['viewPoint'][0])           
2198        Draw()
2199           
2200    def SetBackground():
2201        R,G,B,A = Page.camera['backColor']
2202        glClearColor(R,G,B,A)
2203        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
2204       
2205    def SetLights():
2206        glEnable(GL_DEPTH_TEST)
2207        glShadeModel(GL_SMOOTH)
2208        glEnable(GL_LIGHTING)
2209        glEnable(GL_LIGHT0)
2210        glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,0)
2211        glLightfv(GL_LIGHT0,GL_AMBIENT,[1,1,1,.8])
2212        glLightfv(GL_LIGHT0,GL_DIFFUSE,[1,1,1,1])
2213       
2214    def SetTranslation(newxy):
2215        Tx,Ty,Tz = drawingData['viewPoint'][0]
2216        anglex,angley,anglez,oldxy = drawingData['Rotation']
2217        Rx = G2lat.rotdMat(anglex,0)
2218        Ry = G2lat.rotdMat(angley,1)
2219        Rz = G2lat.rotdMat(anglez,2)
2220        dxy = list(newxy-oldxy)+[0,]
2221        dxy = np.inner(Bmat,np.inner(Rz,np.inner(Ry,np.inner(Rx,dxy))))
2222        Tx -= dxy[0]*0.01
2223        Ty += dxy[1]*0.01
2224        Tz -= dxy[2]*0.01
2225        drawingData['Rotation'][3] = newxy
2226        drawingData['viewPoint'][0] =  Tx,Ty,Tz
2227        SetViewPointText([Tx,Ty,Tz])
2228       
2229    def SetTestPos(newxy):
2230        Tx,Ty,Tz = drawingData['testPos'][0]
2231        anglex,angley,anglez,oldxy = drawingData['Rotation']
2232        Rx = G2lat.rotdMat(anglex,0)
2233        Ry = G2lat.rotdMat(angley,1)
2234        Rz = G2lat.rotdMat(anglez,2)
2235        dxy = list(newxy-oldxy)+[0,]
2236        dxy = np.inner(Rz,np.inner(Ry,np.inner(Rx,dxy)))
2237        Tx += dxy[0]*0.001
2238        Ty -= dxy[1]*0.001
2239        Tz += dxy[2]*0.001
2240        drawingData['Rotation'][3] = newxy
2241        drawingData['testPos'][0] =  Tx,Ty,Tz
2242       
2243    def SetTestRot(newxy):
2244        Txyz = np.array(drawingData['testPos'][0])
2245        oldxy = drawingData['testPos'][2]
2246        Ax,Ay,Az = drawingData['testPos'][1]
2247        Vxyz = np.array(drawingData['viewPoint'][0])
2248        Dxyz = np.inner(Amat,Txyz-Vxyz)
2249        dxy = list(newxy-oldxy)+[0,]
2250        Ax += dxy[1]*0.01
2251        Ay += dxy[0]*0.01
2252        Rx = G2lat.rotdMat(Ax,0)
2253        Ry = G2lat.rotdMat(Ay,1)
2254        Dxyz = np.inner(Ry,np.inner(Rx,Dxyz))       
2255        Dxyz = np.inner(Bmat,Dxyz)+Vxyz
2256        drawingData['testPos'][1] = [Ax,Ay,Az]
2257        drawingData['testPos'][2] = newxy
2258        drawingData['testPos'][0] = Dxyz
2259       
2260    def SetTestRotZ(newxy):
2261        Txyz = np.array(drawingData['testPos'][0])
2262        oldxy = drawingData['testPos'][2]
2263        Ax,Ay,Az = drawingData['testPos'][1]
2264        Vxyz = np.array(drawingData['viewPoint'][0])
2265        Dxyz = np.inner(Amat,Txyz-Vxyz)       
2266        dxy = list(newxy-oldxy)+[0,]
2267        Az += (dxy[0]+dxy[1])*.01
2268        Rz = G2lat.rotdMat(Az,2)
2269        Dxyz = np.inner(Rz,Dxyz)       
2270        Dxyz = np.inner(Bmat,Dxyz)+Vxyz
2271        drawingData['testPos'][1] = [Ax,Ay,Az]
2272        drawingData['testPos'][2] = newxy
2273        drawingData['testPos'][0] = Dxyz
2274                             
2275    def SetRotation(newxy):       
2276        anglex,angley,anglez,oldxy = drawingData['Rotation']
2277        dxy = newxy-oldxy
2278        anglex += dxy[1]*.25
2279        angley += dxy[0]*.25
2280        oldxy = newxy
2281        drawingData['Rotation'] = [anglex,angley,anglez,oldxy]
2282       
2283    def SetRotationZ(newxy):                       
2284        anglex,angley,anglez,oldxy = drawingData['Rotation']
2285        dxy = newxy-oldxy
2286        anglez += (dxy[0]+dxy[1])*.25
2287        oldxy = newxy
2288        drawingData['Rotation'] = [anglex,angley,anglez,oldxy]
2289       
2290    def RenderBox():
2291        glEnable(GL_COLOR_MATERIAL)
2292        glLineWidth(2)
2293        glEnable(GL_BLEND)
2294        glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA)
2295        glEnable(GL_LINE_SMOOTH)
2296        glBegin(GL_LINES)
2297        for line,color in zip(uEdges,uColors):
2298            glColor3ubv(color)
2299            glVertex3fv(line[0])
2300            glVertex3fv(line[1])
2301        glEnd()
2302        glColor4ubv([0,0,0,0])
2303        glDisable(GL_LINE_SMOOTH)
2304        glDisable(GL_BLEND)
2305        glDisable(GL_COLOR_MATERIAL)
2306       
2307    def RenderUnitVectors(x,y,z):
2308        xyz = np.array([x,y,z])
2309        glEnable(GL_COLOR_MATERIAL)
2310        glLineWidth(1)
2311        glPushMatrix()
2312        glTranslate(x,y,z)
2313        glScalef(1/cell[0],1/cell[1],1/cell[2])
2314        glBegin(GL_LINES)
2315        for line,color in zip(uEdges,uColors)[:3]:
2316            glColor3ubv(color)
2317            glVertex3fv(line[0])
2318            glVertex3fv(line[1])
2319        glEnd()
2320        glPopMatrix()
2321        glColor4ubv([0,0,0,0])
2322        glDisable(GL_COLOR_MATERIAL)
2323               
2324    def RenderSphere(x,y,z,radius,color):
2325        glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,color)
2326        glPushMatrix()
2327        glTranslate(x,y,z)
2328        glMultMatrixf(B4mat.T)
2329        q = gluNewQuadric()
2330        gluSphere(q,radius,20,10)
2331        glPopMatrix()
2332       
2333    def RenderEllipsoid(x,y,z,ellipseProb,E,R4,color):
2334        s1,s2,s3 = E
2335        glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,color)
2336        glPushMatrix()
2337        glTranslate(x,y,z)
2338        glMultMatrixf(B4mat.T)
2339        glMultMatrixf(R4.T)
2340        glEnable(GL_NORMALIZE)
2341        glScale(s1,s2,s3)
2342        q = gluNewQuadric()
2343        gluSphere(q,ellipseProb,20,10)
2344        glDisable(GL_NORMALIZE)
2345        glPopMatrix()
2346       
2347    def RenderBonds(x,y,z,Bonds,radius,color,slice=20):
2348        glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,color)
2349        glPushMatrix()
2350        glTranslate(x,y,z)
2351        glMultMatrixf(B4mat.T)
2352        for bond in Bonds:
2353            glPushMatrix()
2354            Dx = np.inner(Amat,bond)
2355            Z = np.sqrt(np.sum(Dx**2))
2356            azm = atan2d(-Dx[1],-Dx[0])
2357            phi = acosd(Dx[2]/Z)
2358            glRotate(-azm,0,0,1)
2359            glRotate(phi,1,0,0)
2360            q = gluNewQuadric()
2361            gluCylinder(q,radius,radius,Z,slice,2)
2362            glPopMatrix()           
2363        glPopMatrix()
2364               
2365    def RenderLines(x,y,z,Bonds,color):
2366        xyz = np.array([x,y,z])
2367        glEnable(GL_COLOR_MATERIAL)
2368        glLineWidth(1)
2369        glColor3fv(color)
2370        glPushMatrix()
2371        glBegin(GL_LINES)
2372        for bond in Bonds:
2373            glVertex3fv(xyz)
2374            glVertex3fv(xyz+bond)
2375        glEnd()
2376        glColor4ubv([0,0,0,0])
2377        glPopMatrix()
2378        glDisable(GL_COLOR_MATERIAL)
2379       
2380    def RenderPolyhedra(x,y,z,Faces,color):
2381        glPushMatrix()
2382        glTranslate(x,y,z)
2383        glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,color)
2384        glShadeModel(GL_SMOOTH)
2385        glMultMatrixf(B4mat.T)
2386        for face,norm in Faces:
2387            glPolygonMode(GL_FRONT_AND_BACK,GL_FILL)
2388            glFrontFace(GL_CW)
2389            glNormal3fv(norm)
2390            glBegin(GL_TRIANGLES)
2391            for vert in face:
2392                glVertex3fv(vert)
2393            glEnd()
2394        glPopMatrix()
2395       
2396    def RenderBackbone(Backbone,BackboneColor,radius):
2397        glPushMatrix()
2398        glMultMatrixf(B4mat.T)
2399        glEnable(GL_COLOR_MATERIAL)
2400        glShadeModel(GL_SMOOTH)
2401        gleSetJoinStyle(TUBE_NORM_EDGE | TUBE_JN_ANGLE | TUBE_JN_CAP)
2402        glePolyCylinder(Backbone,BackboneColor,radius)
2403        glPopMatrix()       
2404        glDisable(GL_COLOR_MATERIAL)
2405       
2406    def RenderLabel(x,y,z,label,r):       
2407        glPushMatrix()
2408        glTranslate(x,y,z)
2409        glMultMatrixf(B4mat.T)
2410        glDisable(GL_LIGHTING)
2411        glColor3f(0,1.,0)
2412        glRasterPos3f(r,r,r)
2413        for c in list(label):
2414            glutBitmapCharacter(GLUT_BITMAP_8_BY_13,ord(c))
2415        glEnable(GL_LIGHTING)
2416        glPopMatrix()
2417                           
2418    def Draw():
2419        import numpy.linalg as nl
2420        Ind = GetSelectedAtoms()
2421        VS = np.array(Page.canvas.GetSize())
2422        aspect = float(VS[0])/float(VS[1])
2423        cPos = drawingData['cameraPos']
2424        Zclip = drawingData['Zclip']*cPos/200.
2425        anglex,angley,anglez = drawingData['Rotation'][:3]
2426        Tx,Ty,Tz = drawingData['viewPoint'][0]
2427        cx,ct,cs = drawingData['atomPtrs']
2428        bondR = drawingData['bondRadius']
2429        G,g = G2lat.cell2Gmat(cell)
2430        GS = G
2431        GS[0][1] = GS[1][0] = math.sqrt(GS[0][0]*GS[1][1])
2432        GS[0][2] = GS[2][0] = math.sqrt(GS[0][0]*GS[2][2])
2433        GS[1][2] = GS[2][1] = math.sqrt(GS[1][1]*GS[2][2])
2434        ellipseProb = G2lat.criticalEllipse(drawingData['ellipseProb']/100.)
2435       
2436        SetBackground()
2437        glInitNames()
2438        glPushName(0)
2439       
2440        glMatrixMode(GL_PROJECTION)
2441        glLoadIdentity()
2442        glViewport(0,0,VS[0],VS[1])
2443        gluPerspective(20.,aspect,cPos-Zclip,cPos+Zclip)
2444        gluLookAt(0,0,cPos,0,0,0,0,1,0)
2445        SetLights()           
2446           
2447        glMatrixMode(GL_MODELVIEW)
2448        glLoadIdentity()
2449        glRotate(anglez,0,0,1)
2450        glRotate(anglex,cosd(anglez),-sind(anglez),0)
2451        glRotate(angley,sind(anglez),cosd(anglez),0)
2452        glMultMatrixf(A4mat.T)
2453        glTranslate(-Tx,-Ty,-Tz)
2454        if drawingData['unitCellBox']:
2455            RenderBox()
2456        if drawingData['showABC']:
2457            x,y,z = drawingData['testPos'][0]
2458#            if altDown:
2459#                self.G2plotNB.status.SetStatusText('moving test point %.4f,%.4f,%.4f'%(x,y,z),1)
2460#            else:
2461#                self.G2plotNB.status.SetStatusText('test point %.4f,%.4f,%.4f'%(x,y,z),1)           
2462            RenderUnitVectors(x,y,z)
2463        Backbone = []
2464        BackboneColor = []
2465        time0 = time.time()
2466        for iat,atom in enumerate(drawingData['Atoms']):
2467            x,y,z = atom[cx:cx+3]
2468            Bonds = atom[-2]
2469            Faces = atom[-1]
2470            try:
2471                atNum = generalData['AtomTypes'].index(atom[ct])
2472            except ValueError:
2473                atNum = -1
2474            CL = atom[cs+2]
2475            color = np.array(CL)/255.
2476            if iat in Ind:
2477                color = np.array(Gr)/255.
2478            radius = 0.5
2479            if atom[cs] != '':
2480                glLoadName(atom[-3])                   
2481            if 'balls' in atom[cs]:
2482                vdwScale = drawingData['vdwScale']
2483                ballScale = drawingData['ballScale']
2484                if atNum < 0:
2485                    radius = 0.2
2486                elif 'H' == atom[ct]:
2487                    if drawingData['showHydrogen']:
2488                        if 'vdW' in atom[cs] and atNum >= 0:
2489                            radius = vdwScale*generalData['vdWRadii'][atNum]
2490                        else:
2491                            radius = ballScale*drawingData['sizeH']
2492                    else:
2493                        radius = 0.0
2494                else:
2495                    if 'vdW' in atom[cs]:
2496                        radius = vdwScale*generalData['vdWRadii'][atNum]
2497                    else:
2498                        radius = ballScale*generalData['BondRadii'][atNum]
2499                RenderSphere(x,y,z,radius,color)
2500                if 'sticks' in atom[cs]:
2501                    RenderBonds(x,y,z,Bonds,bondR,color)
2502            elif 'ellipsoids' in atom[cs]:
2503                RenderBonds(x,y,z,Bonds,bondR,color)
2504                if atom[cs+3] == 'A':                   
2505                    Uij = atom[cs+5:cs+11]
2506                    U = np.multiply(G2spc.Uij2U(Uij),GS)
2507                    U = np.inner(Amat,np.inner(U,Amat).T)
2508                    E,R = nl.eigh(U)
2509                    R4 = np.concatenate((np.concatenate((R,[[0],[0],[0]]),axis=1),[[0,0,0,1],]),axis=0)
2510                    E = np.sqrt(E)
2511                    if atom[ct] == 'H' and not drawingData['showHydrogen']:
2512                        pass
2513                    else:
2514                        RenderEllipsoid(x,y,z,ellipseProb,E,R4,color)                   
2515                else:
2516                    if atom[ct] == 'H' and not drawingData['showHydrogen']:
2517                        pass
2518                    else:
2519                        radius = ellipseProb*math.sqrt(abs(atom[cs+4]))
2520                        RenderSphere(x,y,z,radius,color)
2521            elif 'lines' in atom[cs]:
2522                radius = 0.1
2523                RenderLines(x,y,z,Bonds,color)
2524#                RenderBonds(x,y,z,Bonds,0.05,color,6)
2525            elif atom[cs] == 'sticks':
2526                radius = 0.1
2527                RenderBonds(x,y,z,Bonds,bondR,color)
2528            elif atom[cs] == 'polyhedra':
2529                RenderPolyhedra(x,y,z,Faces,color)
2530            elif atom[cs] == 'backbone':
2531                if atom[ct-1].split()[0] in ['C','N']:
2532                    Backbone.append(list(np.inner(Amat,np.array([x,y,z]))))
2533                    BackboneColor.append(list(color))
2534                   
2535            if atom[cs+1] == 'type':
2536                RenderLabel(x,y,z,atom[ct],radius)
2537            elif atom[cs+1] == 'name':
2538                RenderLabel(x,y,z,atom[ct-1],radius)
2539            elif atom[cs+1] == 'number':
2540                RenderLabel(x,y,z,str(iat+1),radius)
2541            elif atom[cs+1] == 'residue' and atom[ct-1] == 'CA':
2542                RenderLabel(x,y,z,atom[ct-4],radius)
2543            elif atom[cs+1] == '1-letter' and atom[ct-1] == 'CA':
2544                RenderLabel(x,y,z,atom[ct-3],radius)
2545            elif atom[cs+1] == 'chain' and atom[ct-1] == 'CA':
2546                RenderLabel(x,y,z,atom[ct-2],radius)
2547        if Backbone:
2548            RenderBackbone(Backbone,BackboneColor,bondR)
2549#        print time.time()-time0
2550        Page.canvas.SwapBuffers()
2551       
2552    def OnSize(event):
2553        Draw()
2554       
2555    def OnFocus(event):
2556        Draw()
2557       
2558    try:
2559        plotNum = self.G2plotNB.plotList.index(generalData['Name'])
2560        Page = self.G2plotNB.nb.GetPage(plotNum)       
2561    except ValueError:
2562        Plot = self.G2plotNB.addOgl(generalData['Name'])
2563        plotNum = self.G2plotNB.plotList.index(generalData['Name'])
2564        Page = self.G2plotNB.nb.GetPage(plotNum)
2565        Page.views = False
2566        view = False
2567        altDown = False
2568    Page.SetFocus()
2569    cb = wx.ComboBox(self.G2plotNB.status,style=wx.CB_DROPDOWN|wx.CB_READONLY,
2570        choices=(' save as:','jpeg','tiff','bmp'))
2571    cb.Bind(wx.EVT_COMBOBOX, OnKeyBox)
2572    cb.SetValue(' save as:')
2573    Page.canvas.Bind(wx.EVT_MOUSEWHEEL, OnMouseWheel)
2574    Page.canvas.Bind(wx.EVT_LEFT_DOWN, OnMouseDown)
2575    Page.canvas.Bind(wx.EVT_RIGHT_DOWN, OnMouseDown)
2576    Page.canvas.Bind(wx.EVT_MIDDLE_DOWN, OnMouseDown)
2577    Page.canvas.Bind(wx.EVT_KEY_UP, OnKey)
2578    Page.canvas.Bind(wx.EVT_MOTION, OnMouseMove)
2579    Page.canvas.Bind(wx.EVT_SIZE, OnSize)
2580    Page.canvas.Bind(wx.EVT_SET_FOCUS, OnFocus)
2581    Page.camera['position'] = drawingData['cameraPos']
2582    Page.camera['viewPoint'] = np.inner(Amat,drawingData['viewPoint'][0])
2583    Page.camera['backColor'] = np.array(list(drawingData['backColor'])+[0,])/255.
2584    Page.canvas.SetCurrent()
2585    Draw()
2586       
Note: See TracBrowser for help on using the repository browser.