source: trunk/GSASIIplot.py @ 515

Last change on this file since 515 was 515, checked in by vondreele, 11 years ago

add num variables to ViewLSparams
final fixup of error analysis plots
add to help file

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