source: trunk/GSASIIplot.py @ 87

Last change on this file since 87 was 87, checked in by vondreel, 12 years ago

"Spots" in Masks is really "Points"
Start of "points" for masks

File size: 39.7 KB
Line 
1import math
2import time
3import copy
4import numpy as np
5import wx
6import wx.aui
7import matplotlib as mpl
8import GSASIIpath
9import GSASIIgrid as G2gd
10import GSASIIimage as G2img
11import GSASIIIO as G2IO
12import GSASIIpwdGUI as G2pdG
13import GSASIIimgGUI as G2imG
14from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as Canvas
15from matplotlib.backends.backend_wxagg import NavigationToolbar2Wx as Toolbar
16
17# useful degree trig functions
18sind = lambda x: math.sin(x*math.pi/180.)
19cosd = lambda x: math.cos(x*math.pi/180.)
20tand = lambda x: math.tan(x*math.pi/180.)
21asind = lambda x: 180.*math.asin(x)/math.pi
22acosd = lambda x: 180.*math.acos(x)/math.pi
23atan2d = lambda x,y: 180.*math.atan2(y,x)/math.pi
24atand = lambda x: 180.*math.atan(x)/math.pi
25   
26class G2Plot(wx.Panel):
27   
28    def __init__(self,parent,id=-1,dpi=None,**kwargs):
29        wx.Panel.__init__(self,parent,id=id,**kwargs)
30        self.figure = mpl.figure.Figure(dpi=dpi,figsize=(5,7))
31        self.canvas = Canvas(self,-1,self.figure)
32        self.toolbar = Toolbar(self.canvas)
33
34        self.toolbar.Realize()
35       
36        sizer=wx.BoxSizer(wx.VERTICAL)
37        sizer.Add(self.canvas,1,wx.EXPAND)
38        sizer.Add(self.toolbar,0,wx.LEFT|wx.EXPAND)
39        self.SetSizer(sizer)
40               
41class G2PlotNoteBook(wx.Panel):
42    def __init__(self,parent,id=-1):
43        wx.Panel.__init__(self,parent,id=id)
44        #so one can't delete a plot page!!
45        self.nb = wx.aui.AuiNotebook(self, \
46            style=wx.aui.AUI_NB_DEFAULT_STYLE ^ wx.aui.AUI_NB_CLOSE_ON_ACTIVE_TAB)
47        sizer = wx.BoxSizer()
48        sizer.Add(self.nb,1,wx.EXPAND)
49        self.SetSizer(sizer)
50        self.status = parent.CreateStatusBar()
51        self.status.SetFieldsCount(2)
52        self.status.SetStatusWidths([125,-1])
53        self.Bind(wx.aui.EVT_AUINOTEBOOK_PAGE_CHANGED, self.OnPageChanged)
54       
55        self.plotList = []
56           
57    def add(self,name=""):
58        page = G2Plot(self.nb)
59        self.nb.AddPage(page,name)
60       
61        self.plotList.append(name)
62       
63        return page.figure
64       
65    def OnPageChanged(self,event):
66        self.status.DestroyChildren()                           #get rid of special stuff on status bar
67       
68def PlotSngl(self,newPlot=False):
69    from matplotlib.patches import Circle
70
71    def OnSCMotion(event):
72        xpos = event.xdata
73        if xpos:
74            xpos = round(xpos)                                        #avoid out of frame mouse position
75            ypos = round(event.ydata)
76            zpos = Data['Layer']
77            if '100' in Data['Zone']:
78                HKLtxt = '(%3d,%3d,%3d)'%(zpos,xpos,ypos)
79            elif '010' in Data['Zone']:
80                HKLtxt = '(%3d,%3d,%3d)'%(xpos,zpos,ypos)
81            elif '001' in Data['Zone']:
82                HKLtxt = '(%3d,%3d,%3d)'%(xpos,ypos,zpos)
83            Page.canvas.SetToolTipString(HKLtxt)
84            self.G2plotNB.status.SetFields(['HKL = '+HKLtxt,''])
85               
86    def OnSCPick(event):
87        zpos = Data['Layer']
88        pos = event.artist.center
89        if '100' in Data['Zone']:
90            Page.canvas.SetToolTipString('(picked:(%3d,%3d,%3d))'%(zpos,pos[0],pos[1]))
91            hkl = [zpos,pos[0],pos[1]]
92        elif '010' in Data['Zone']:
93            Page.canvas.SetToolTipString('(picked:(%3d,%3d,%3d))'%(pos[0],zpos,pos[1]))
94            hkl = [pos[0],zpos,pos[1]]
95        elif '001' in Data['Zone']:
96            Page.canvas.SetToolTipString('(picked:(%3d,%3d,%3d))'%(pos[0],pos[1],zpos))
97            hkl = [pos[0],pos[1],zpos]
98        h,k,l = hkl
99        i = HKL.all(hkl)
100        print i
101        HKLtxt = '(%3d,%3d,%3d %10.2f %6.3f %10.2f)'%(h,k,l,Fosq,sig,Fcsq)
102        self.G2plotNB.status.SetFields(['','HKL, Fosq, sig, Fcsq = '+HKLtxt])
103                         
104       
105    def OnSCKeyPress(event):
106        print event.key
107
108    try:
109        plotNum = self.G2plotNB.plotList.index('Structure Factors')
110        Page = self.G2plotNB.nb.GetPage(plotNum)
111        if not newPlot:
112            Plot = Page.figure.gca()          #get previous powder plot & get limits
113            xylim = Plot.get_xlim(),Plot.get_ylim()
114        Page.figure.clf()
115        Plot = Page.figure.gca()          #get a fresh plot after clf()
116    except ValueError,error:
117        Plot = self.G2plotNB.add('Structure Factors').gca()
118        plotNum = self.G2plotNB.plotList.index('Structure Factors')
119        Page = self.G2plotNB.nb.GetPage(plotNum)
120        Page.canvas.mpl_connect('key_press_event', OnSCKeyPress)
121        Page.canvas.mpl_connect('pick_event', OnSCPick)
122        Page.canvas.mpl_connect('motion_notify_event', OnSCMotion)
123    Page.SetFocus()
124   
125    Plot.set_aspect(aspect='equal')
126    HKLref = self.PatternTree.GetItemPyData(self.Sngl)
127    Data = self.PatternTree.GetItemPyData( \
128        G2gd.GetPatternTreeItemId(self,self.Sngl, 'HKL Plot Controls'))
129    Type = Data['Type']           
130    scale = Data['Scale']
131    HKLmax = Data['HKLmax']
132    HKLmin = Data['HKLmin']
133    FosqMax = Data['FoMax']
134    FoMax = math.sqrt(FosqMax)
135    ifFc = Data['ifFc']
136    xlabel = ['k, h=','h, k=','h, l=']
137    ylabel = ['l','l','k']
138    zones = ['100','010','001']
139    pzone = [[1,2],[0,2],[0,1]]
140    izone = zones.index(Data['Zone'])
141    Plot.set_title(self.PatternTree.GetItemText(self.Sngl)[5:])
142    HKL = []
143    for H,Fosq,sig,Fcsq,x,x,x in HKLref:
144        HKL.append(H)
145        if H[izone] == Data['Layer']:
146            B = 0
147            if Type == 'Fosq':
148                A = scale*Fosq/FosqMax
149                B = scale*Fcsq/FosqMax
150                C = abs(A-B)
151            elif Type == 'Fo':
152                A = scale*math.sqrt(max(0,Fosq))/FoMax
153                B = scale*math.sqrt(max(0,Fcsq))/FoMax
154                C = abs(A-B)
155            elif Type == '|DFsq|/sig':
156                A = abs(Fosq-Fcsq)/(scale*sig)
157            elif Type == '|DFsq|>sig':
158                A = abs(Fosq-Fcsq)/(scale*sig)
159                if A < 1.0: A = 0                   
160            elif Type == '|DFsq|>3sig':
161                A = abs(Fosq-Fcsq)/(scale*sig)
162                if A < 3.0: A = 0                   
163            xy = (H[pzone[izone][0]],H[pzone[izone][1]])
164            if A > 0.0:
165                Plot.add_artist(Circle(xy,radius=A,ec='g',fc='w',picker=3))
166            if B:
167                Plot.add_artist(Circle(xy,radius=B,ec='b',fc='w'))
168                radius = C
169                if radius > 0:
170                    if A > B:
171                        Plot.add_artist(Circle(xy,radius=radius,ec='r',fc='r'))
172                    else:                   
173                        Plot.add_artist(Circle(xy,radius=radius,ec='g',fc='g'))
174    HKL = np.array(HKL)
175    Plot.set_xlabel(xlabel[izone]+str(Data['Layer']),fontsize=12)
176    Plot.set_ylabel(ylabel[izone],fontsize=12)
177    Plot.set_xlim((HKLmin[pzone[izone][0]],HKLmax[pzone[izone][0]]))
178    Plot.set_ylim((HKLmin[pzone[izone][1]],HKLmax[pzone[izone][1]]))
179    if not newPlot:
180        Page.toolbar.push_current()
181        Plot.set_xlim(xylim[0])
182        Plot.set_ylim(xylim[1])
183        xylim = []
184        Page.toolbar.push_current()
185        Page.toolbar.draw()
186    else:
187        Page.canvas.draw()
188       
189def PlotPatterns(self,newPlot=False):
190   
191    def OnPick(event):
192        if self.itemPicked is not None: return
193        PatternId = self.PatternId
194        PickId = self.PickId
195        pick = event.artist
196        mouse = event.mouseevent
197        xpos = pick.get_xdata()
198        ypos = pick.get_ydata()
199        ind = event.ind
200        view = Page.toolbar._views.forward()
201        if view and 'line2' in str(pick):           #apply offset only for picked powder pattern points
202            ind += np.searchsorted(xye[0],view[0][0])
203        xy = zip(xpos[ind],ypos[ind])[0]
204        if self.PatternTree.GetItemText(PickId) == 'Peak List':
205            if ind.all() != [0]:                                    #picked a data point
206                inst = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PatternId, 'Instrument Parameters'))
207                if len(inst[1]) == 11:
208                    ins = inst[1][4:10]
209                else:
210                    ins = inst[1][6:12]   
211                sig = ins[0]*tand(xy[0]/2.0)**2+ins[1]*tand(xy[0]/2.0)+ins[2]
212                gam = ins[3]/cosd(xy[0]/2.0)+ins[4]*tand(xy[0]/2.0)           
213                data = self.PatternTree.GetItemPyData(self.PickId)
214                XY = [xy[0],0, xy[1],1, sig,0, gam,0]       #default refine intensity 1st   
215                data.append(XY)
216                G2pdG.UpdatePeakGrid(self,data)
217                PlotPatterns(self)
218            else:                                                   #picked a peak list line
219                self.itemPicked = pick
220        elif self.PatternTree.GetItemText(PickId) == 'Limits':
221            if ind.all() != [0]:                                    #picked a data point
222                LimitId = G2gd.GetPatternTreeItemId(self,PatternId, 'Limits')
223                data = self.PatternTree.GetItemPyData(LimitId)
224                if mouse.button==1:
225                    data[1][0] = min(xy[0],data[1][1])
226                if mouse.button==3:
227                    data[1][1] = max(xy[0],data[1][0])
228                self.PatternTree.SetItemPyData(LimitId,data)
229                G2pdG.UpdateLimitsGrid(self,data)
230                PlotPatterns(self)
231            else:                                                   #picked a limit line
232                self.itemPicked = pick               
233       
234    def OnPlotKeyPress(event):
235        if event.key == 'w':
236            if self.Weight:
237                self.Weight = False
238            else:
239                self.Weight = True
240            print 'plot weighting:',self.Weight
241        elif event.key == 'u' and self.Offset < 100.:
242            self.Offset += 1.
243        elif event.key == 'd' and self.Offset > 0.:
244            self.Offset -= 1.
245        elif event.key == 'c':
246            if self.Contour:
247                self.Contour = False
248            else:
249                self.Contour = True
250        elif event.key == 's':
251            if self.SinglePlot:
252                self.SinglePlot = False
253            else:
254                self.SinglePlot = True
255           
256        PlotPatterns(self)
257       
258    def OnKeyBox(event):
259        if self.G2plotNB.nb.GetSelection() == self.G2plotNB.plotList.index('Powder Patterns'):
260            event.key = cb.GetValue()[0]
261            cb.SetValue(' key press')
262            OnPlotKeyPress(event)
263                       
264    def OnMotion(event):
265        xpos = event.xdata
266        if xpos:                                        #avoid out of frame mouse position
267            ypos = event.ydata
268            Page.canvas.SetCursor(wx.CROSS_CURSOR)
269            try:
270                wave = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self, \
271                    self.PatternId, 'Instrument Parameters'))[0][1]
272                dsp = 0.0
273                if abs(xpos) > 0.:                  #avoid possible singularity at beam center
274                    dsp = wave/(2.*sind(abs(xpos)/2.0))
275                self.G2plotNB.status.SetStatusText('2-theta =%9.3f d =%9.5f Intensity =%9.1f'%(xpos,dsp,ypos),1)
276                if self.itemPicked:
277                    Page.canvas.SetToolTipString('%9.3f'%(xpos))
278            except TypeError:
279                self.G2plotNB.status.SetStatusText('Select PWDR powder pattern first',1)
280                                   
281    def OnRelease(event):
282        if self.itemPicked is None: return
283        xpos = event.xdata
284        if xpos:                                        #avoid out of frame mouse position
285            lines = []
286            for line in self.Lines: lines.append(line.get_xdata()[0])
287            lineNo = lines.index(self.itemPicked.get_xdata()[0])
288            if  lineNo in [0,1]:
289                LimitId = G2gd.GetPatternTreeItemId(self,self.PatternId, 'Limits')
290                data = self.PatternTree.GetItemPyData(LimitId)
291#                print 'limits',xpos
292                data[1][lineNo] = xpos
293                self.PatternTree.SetItemPyData(LimitId,data)
294                if self.PatternTree.GetItemText(self.PickId) == 'Limits':
295                    G2pdG.UpdateLimitsGrid(self,data)
296            else:
297                PeakId = G2gd.GetPatternTreeItemId(self,self.PatternId, 'Peak List')
298                data = self.PatternTree.GetItemPyData(PeakId)
299#                print 'peaks',xpos
300                data[lineNo-2][0] = xpos
301                self.PatternTree.SetItemPyData(PeakId,data)
302                G2pdG.UpdatePeakGrid(self,data)
303        PlotPatterns(self)
304        self.itemPicked = None   
305
306    xylim = []
307    try:
308        plotNum = self.G2plotNB.plotList.index('Powder Patterns')
309        Page = self.G2plotNB.nb.GetPage(plotNum)
310        if not newPlot:
311            Plot = Page.figure.gca()          #get previous powder plot & get limits
312            xylim = Plot.get_xlim(),Plot.get_ylim()
313        Page.figure.clf()
314        Plot = Page.figure.gca()          #get a fresh plot after clf()
315    except ValueError,error:
316        newPlot = True
317        Plot = self.G2plotNB.add('Powder Patterns').gca()
318        plotNum = self.G2plotNB.plotList.index('Powder Patterns')
319        Page = self.G2plotNB.nb.GetPage(plotNum)
320        Page.canvas.mpl_connect('key_press_event', OnPlotKeyPress)
321        Page.canvas.mpl_connect('motion_notify_event', OnMotion)
322        Page.canvas.mpl_connect('pick_event', OnPick)
323        Page.canvas.mpl_connect('button_release_event', OnRelease)
324    Page.SetFocus()
325    cb = wx.ComboBox(self.G2plotNB.status,style=wx.CB_DROPDOWN|wx.CB_READONLY,
326        choices=(' key press','d: offset down','u: offset up','c: toggle contour','s: toggle single plot'))
327    cb.Bind(wx.EVT_COMBOBOX, OnKeyBox)
328    cb.SetValue(' key press')
329   
330    PickId = self.PickId
331    PatternId = self.PatternId
332    colors=['b','g','r','c','m','k']
333    Lines = []
334    if self.SinglePlot:
335        Pattern = self.PatternTree.GetItemPyData(self.PatternId)
336        Pattern.append(self.PatternTree.GetItemText(self.PatternId))
337        PlotList = [Pattern,]
338    else:       
339        PlotList = []
340        item, cookie = self.PatternTree.GetFirstChild(self.root)
341        while item:
342            if 'PWDR' in self.PatternTree.GetItemText(item):
343                Pattern = self.PatternTree.GetItemPyData(item)
344                Pattern.append(self.PatternTree.GetItemText(item))
345                PlotList.append(Pattern)
346            item, cookie = self.PatternTree.GetNextChild(self.root, cookie)               
347    Ymax = 1.0
348    for Pattern in PlotList:
349        xye = Pattern[1]
350        Ymax = max(Ymax,max(xye[1]))
351    offset = self.Offset*Ymax/100.0
352    Plot.set_title('Powder Patterns')
353    Plot.set_xlabel(r'$\mathsf{2\theta}$',fontsize=14)
354    Plot.set_ylabel('Intensity',fontsize=12)
355    if self.Contour:
356        ContourZ = []
357        ContourY = []
358        Nseq = 0
359    for N,Pattern in enumerate(PlotList):
360        ifpicked = False
361        LimitId = 0
362        xye = Pattern[1]
363        if PickId:
364            ifpicked = Pattern[2] == self.PatternTree.GetItemText(PatternId)
365            LimitId = G2gd.GetPatternTreeItemId(self,PatternId, 'Limits')
366        X = xye[0]
367        Y = xye[1]+offset*N
368        if LimitId:
369            limits = self.PatternTree.GetItemPyData(LimitId)
370            Lines.append(Plot.axvline(limits[1][0],color='g',dashes=(5,5),picker=3.))   
371            Lines.append(Plot.axvline(limits[1][1],color='r',dashes=(5,5),picker=3.))                   
372        if self.Contour:
373            ContourY.append(N)
374            ContourZ.append(Y)
375            ContourX = X
376            Nseq += 1
377            Plot.set_ylabel('Data sequence',fontsize=12)
378        else:
379            if ifpicked:
380                Z = xye[3]+offset*N
381                W = xye[4]+offset*N
382                D = xye[5]+offset*N-Ymax*.02
383                if self.Weight:
384                    W2 = np.sqrt(xye[2])
385                    D *= W2-Ymax*.02
386                Plot.plot(X,Y,colors[N%6]+'+',picker=3.,clip_on=False)
387                Plot.plot(X,Z,colors[(N+1)%6],picker=False)
388                Plot.plot(X,W,colors[(N+2)%6],picker=False)
389                Plot.plot(X,D,colors[(N+3)%6],picker=False)
390                Plot.axhline(0.,color=wx.BLACK)
391                Page.canvas.SetToolTipString('')
392                if self.PatternTree.GetItemText(PickId) == 'Peak List':
393                    tip = 'On data point: Pick peak - L or R MB.On line: MB down to move'
394                    Page.canvas.SetToolTipString(tip)
395                    data = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PatternId, 'Peak List'))
396                    for item in data:
397                        Lines.append(Plot.axvline(item[0],color=colors[N%6],picker=2.))
398                if self.PatternTree.GetItemText(PickId) == 'Limits':
399                    tip = 'On data point: Lower limit - L MB; Upper limit - R MB. On limit: MB down to move'
400                    Page.canvas.SetToolTipString(tip)
401                    data = self.LimitsTable.GetData()
402            else:
403                Plot.plot(X,Y,colors[N%6],picker=False)
404    if PickId and self.PatternTree.GetItemText(PickId) in ['Index Peak List','Unit Cells List']:
405        peaks = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PatternId, 'Index Peak List'))
406        for peak in peaks:
407            Plot.axvline(peak[0],color='b')
408        for hkl in self.HKL:
409            Plot.axvline(hkl[5],color='r',dashes=(5,5))
410    if self.Contour:
411        acolor = mpl.cm.get_cmap('Paired')
412        Plot.imshow(ContourZ,cmap=acolor,vmin=0,vmax=Ymax,interpolation='nearest', 
413            extent=[ContourX[0],ContourX[-1],ContourY[0],ContourY[-1]],aspect='auto')
414        newPlot = True
415    else:
416        self.Lines = Lines
417    if not newPlot:
418        Page.toolbar.push_current()
419        Plot.set_xlim(xylim[0])
420        Plot.set_ylim(xylim[1])
421        xylim = []
422        Page.toolbar.push_current()
423        Page.toolbar.draw()
424    else:
425        Page.canvas.draw()
426    self.Pwdr = True
427
428def PlotPowderLines(self):
429
430    def OnMotion(event):
431        xpos = event.xdata
432        if xpos:                                        #avoid out of frame mouse position
433            Page.canvas.SetCursor(wx.CROSS_CURSOR)
434            self.G2plotNB.status.SetFields(['','2-theta =%9.3f '%(xpos,)])
435
436    try:
437        plotNum = self.G2plotNB.plotList.index('Powder Lines')
438        Page = self.G2plotNB.nb.GetPage(plotNum)
439        Page.figure.clf()
440        Plot = Page.figure.gca()
441    except ValueError,error:
442        Plot = self.G2plotNB.add('Powder Lines').gca()
443        plotNum = self.G2plotNB.plotList.index('Powder Lines')
444        Page = self.G2plotNB.nb.GetPage(plotNum)
445        Page.canvas.mpl_connect('motion_notify_event', OnMotion)
446       
447    Page.SetFocus()
448    Plot.set_title('Powder Pattern Lines')
449    Plot.set_xlabel(r'$\mathsf{2\theta}$',fontsize=14)
450    PickId = self.PickId
451    PatternId = self.PatternId
452    peaks = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PatternId, 'Index Peak List'))
453    for peak in peaks:
454        Plot.axvline(peak[0],color='b')
455    for hkl in self.HKL:
456        Plot.axvline(hkl[5],color='r',dashes=(5,5))
457    xmin = peaks[0][0]
458    xmax = peaks[-1][0]
459    delt = xmax-xmin
460    xlim = [max(0,xmin-delt/20.),min(180.,xmax+delt/20.)]
461    Plot.set_xlim(xlim)
462    Page.canvas.draw()
463
464def PlotPeakWidths(self):
465    PatternId = self.PatternId
466    limitID = G2gd.GetPatternTreeItemId(self,PatternId, 'Limits')
467    if limitID:
468        limits = self.PatternTree.GetItemPyData(limitID)
469    else:
470        return
471    instParms = self.PatternTree.GetItemPyData( \
472        G2gd.GetPatternTreeItemId(self,PatternId, 'Instrument Parameters'))
473    if instParms[0][0] == 'PXC':
474        lam = instParms[1][1]
475        if len(instParms[1]) == 13:
476            GU,GV,GW,LX,LY = instParms[0][6:11]
477        else:
478            GU,GV,GW,LX,LY = instParms[0][4:9]
479    peakID = G2gd.GetPatternTreeItemId(self,PatternId, 'Peak List')
480    if peakID:
481        peaks = self.PatternTree.GetItemPyData(peakID)
482    else:
483        peaks = []
484   
485    try:
486        plotNum = self.G2plotNB.plotList.index('Peak Widths')
487        Page = self.G2plotNB.nb.GetPage(plotNum)
488        Page.figure.clf()
489        Plot = Page.figure.gca()
490    except ValueError,error:
491        Plot = self.G2plotNB.add('Peak Widths').gca()
492        plotNum = self.G2plotNB.plotList.index('Peak Widths')
493        Page = self.G2plotNB.nb.GetPage(plotNum)
494    Page.SetFocus()
495   
496    Page.canvas.SetToolTipString('')
497    colors=['b','g','r','c','m','k']
498    Xmin,Xmax = limits[1]
499    Xmin = min(0.5,max(Xmin,1))
500    Xmin /= 2
501    Xmax /= 2
502    nPts = 100
503    delt = (Xmax-Xmin)/nPts
504    thetas = []
505    for i in range(nPts):
506        thetas.append(Xmin+i*delt)
507    X = []
508    Y = []
509    Z = []
510    W = []
511    V = []
512    sig = lambda Th,U,V,W: 1.17741*math.sqrt(U*tand(Th)**2+V*tand(Th)+W)*math.pi/18000.
513    gam = lambda Th,X,Y: (X/cosd(Th)+Y*tand(Th))*math.pi/18000.
514    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.)
515    gamFW2 = lambda s,g: math.sqrt(s**2+(0.4654996*g)**2)+.5345004*#Ubaldo Bafile - private communication
516    for theta in thetas:
517        X.append(4.0*math.pi*sind(theta)/lam)              #q
518        s = sig(theta,GU,GV,GW)
519        g = gam(theta,LX,LY)
520        G = gamFW(g,s)
521        H = gamFW2(g,s)
522        Y.append(s/tand(theta))
523        Z.append(g/tand(theta))
524        W.append(G/tand(theta))
525        V.append(H/tand(theta))
526    Plot.set_title('Instrument and sample peak widths')
527    Plot.set_ylabel(r'$\Delta q/q, \Delta d/d$',fontsize=14)
528    Plot.set_xlabel(r'$q, \AA^{-1}$',fontsize=14)
529    Plot.plot(X,Y,color='r',label='Gaussian')
530    Plot.plot(X,Z,color='g',label='Lorentzian')
531    Plot.plot(X,W,color='b',label='G+L')
532    Plot.plot(X,V,color='k',label='G+L2')
533    X = []
534    Y = []
535    Z = []
536    W = []
537    V = []
538    for peak in peaks:
539        X.append(4.0*math.pi*sind(peak[0]/2.0)/lam)
540        s = 1.17741*math.sqrt(peak[4])*math.pi/18000.
541        g = peak[6]*math.pi/18000.
542        G = gamFW(g,s)
543        H = gamFW2(g,s)
544        Y.append(s/tand(peak[0]/2.))
545        Z.append(g/tand(peak[0]/2.))
546        W.append(G/tand(peak[0]/2.))
547        V.append(H/tand(peak[0]/2.))
548    Plot.plot(X,Y,'+',color='r',label='G peak')
549    Plot.plot(X,Z,'+',color='g',label='L peak')
550    Plot.plot(X,W,'+',color='b',label='G+L peak')
551    Plot.plot(X,V,'+',color='k',label='G+L2 peak')
552    Plot.legend(loc='best')
553    Page.canvas.draw()
554           
555def PlotExposedImage(self,newPlot=False):
556    plotNo = self.G2plotNB.nb.GetSelection()
557    if self.G2plotNB.nb.GetPageText(plotNo) == '2D Powder Image':
558        PlotImage(self,newPlot)
559    elif self.G2plotNB.nb.GetPageText(plotNo) == '2D Integration':
560        PlotIntegration(self,newPlot)
561
562def PlotImage(self,newPlot=False):
563    from matplotlib.patches import Ellipse,Arc,Circle
564    import numpy.ma as ma
565
566    def OnImMotion(event):
567        Page.canvas.SetToolTipString('')
568        size = len(self.ImageZ)
569        if event.xdata and event.ydata:                 #avoid out of frame errors
570            Page.canvas.SetCursor(wx.CROSS_CURSOR)
571            item = self.itemPicked
572            pixelSize = Data['pixelSize']
573            scalex = 1000./pixelSize[0]
574            scaley = 1000./pixelSize[1]                   
575            if item and self.PatternTree.GetItemText(self.PickId) == 'Image Controls':
576                if 'Text' in str(item):
577                    Page.canvas.SetToolTipString('%8.3f %8.3fmm'%(event.xdata,event.ydata))
578                else:
579                    xcent,ycent = Data['center']
580                    xpos = event.xdata-xcent
581                    ypos = event.ydata-ycent
582                    if 'line3' in  str(item) or 'line4' in str(item) and not Data['fullIntegrate']:
583                        ang = int(atan2d(xpos,ypos))
584                        Page.canvas.SetToolTipString('%6d deg'%(ang))
585                    elif 'line1' in  str(item) or 'line2' in str(item):
586                        tth = G2img.GetTth(event.xdata,event.ydata,Data)
587                        Page.canvas.SetToolTipString('%8.3fdeg'%(tth))                           
588            else:
589                xpos = event.xdata
590                ypos = event.ydata
591                xpix = xpos*scalex
592                ypix = ypos*scaley
593                Int = 0
594                if (0 <= xpix <= size) and (0 <= ypix <= size):
595                    Int = self.ImageZ[ypix][xpix]
596                tth,azm,dsp = G2img.GetTthAzmDsp(xpos,ypos,Data)
597                Q = 2.*math.pi/dsp
598                self.G2plotNB.status.SetFields(\
599                    ['','Detector 2-th =%9.2fdeg, dsp =%9.3fA, Q = %6.3fA-1, azm = %7.2fdeg, I = %6d'%(tth,dsp,Q,azm,Int)])
600
601    def OnImPlotKeyPress(event):
602        if self.PatternTree.GetItemText(self.PickId) == 'Masks':
603            Mask = self.PatternTree.GetItemPyData(self.PickId)
604            Xpos = event.xdata
605            if not Xpos:            #got point out of frame
606                return
607            Ypos = event.ydata
608            if event.key == 's':
609                print 'spot mask @ ',Xpos,Ypos
610                Mask['Points'].append([Xpos,Ypos,1])
611            elif event.key == 'r':
612                print 'ring mask @ ',Xpos,Ypos
613            elif event.key == 'a':
614                print 'arc mask @ ', Xpos,Ypos
615            G2imG.UpdateMasks(self,Mask)
616        PlotImage(self)
617           
618    def OnImPick(event):
619        if self.PatternTree.GetItemText(self.PickId) not in ['Image Controls','Masks']:
620            return
621        if self.itemPicked is not None: return
622        pick = event.artist
623        self.itemPicked = pick
624       
625    def OnImRelease(event):
626        PickName = self.PatternTree.GetItemText(self.PickId)
627        if PickName not in ['Image Controls','Masks']:
628            return
629        pixelSize = Data['pixelSize']
630        scalex = 1000./pixelSize[0]
631        scaley = 1000./pixelSize[1]
632        if self.itemPicked is None and PickName == 'Image Controls':
633            size = len(self.ImageZ)
634            Xpos = event.xdata
635            if not (Xpos and self.ifGetRing):                   #got point out of frame
636                return
637            Ypos = event.ydata
638            if Ypos and not Page.toolbar._active:         #make sure zoom/pan not selected
639                if event.button == 1:
640                    Xpix = Xpos*scalex
641                    Ypix = Ypos*scaley
642                    xpos,ypos,I,J = G2img.ImageLocalMax(self.ImageZ,20,Xpix,Ypix)
643                    if I and J:
644                        xpos += .5                              #shift to pixel center
645                        ypos += .5
646                        xpos /= scalex                          #convert to mm
647                        ypos /= scaley
648                        Data['ring'].append([xpos,ypos])
649                PlotImage(self)
650            return
651        else:
652            xpos = event.xdata
653            if xpos:                                        #avoid out of frame mouse position
654                ypos = event.ydata
655                if self.ifGetRing:
656                    xypos = [xpos,ypos]
657                    rings = Data['ring']
658                    for ring in rings:
659                        if np.allclose(ring,xypos,.01,0):
660                            rings.remove(ring)                                                                       
661                else:
662                    tth,azm,dsp = G2img.GetTthAzmDsp(xpos,ypos,Data)
663                    itemPicked = str(self.itemPicked)
664                    if 'Line2D' in itemPicked and PickName == 'Image Controls':
665                        if 'line1' in str(self.itemPicked):
666                            Data['IOtth'][0] = tth
667                        elif 'line2' in str(self.itemPicked):
668                            Data['IOtth'][1] = tth
669                        elif 'line3' in str(self.itemPicked) and not Data['fullIntegrate']:
670                            Data['LRazimuth'][0] = int(azm)
671                        elif 'line4' in str(self.itemPicked) and not Data['fullIntegrate']:
672                            Data['LRazimuth'][1] = int(azm)
673                           
674                        if Data['LRazimuth'][1] < Data['LRazimuth'][0]:
675                            Data['LRazimuth'][1] += 360
676                        if  Data['IOtth'][0] > Data['IOtth'][1]:
677                            Data['IOtth'][0],Data['IOtth'][1] = Data['IOtth'][1],Data['IOtth'][0]
678                           
679                        self.InnerTth.SetValue("%8.2f" % (Data['IOtth'][0]))
680                        self.OuterTth.SetValue("%8.2f" % (Data['IOtth'][1]))
681                        self.Lazim.SetValue("%6d" % (Data['LRazimuth'][0]))
682                        self.Razim.SetValue("%6d" % (Data['LRazimuth'][1]))
683                    elif 'Circle' in itemPicked and PickName == 'Masks':
684                        spots = Masks['Points']
685                        newPos = itemPicked.split(')')[0].split('(')[2].split(',')
686                        newPos = np.array([float(newPos[0]),float(newPos[1])])
687                        for spot in spots:
688                            if np.allclose(np.array([spot[:2]]),newPos):
689                                spot[:2] = xpos,ypos
690                        G2imG.UpdateMasks(self,Masks)
691                    else:
692                        print str(self.itemPicked),event.xdata,event.ydata,event.button
693                PlotImage(self)
694            self.itemPicked = None
695           
696    try:
697        plotNum = self.G2plotNB.plotList.index('2D Powder Image')
698        Page = self.G2plotNB.nb.GetPage(plotNum)
699        if not newPlot:
700            Plot = Page.figure.gca()          #get previous powder plot & get limits
701            xylim = Plot.get_xlim(),Plot.get_ylim()
702        Page.figure.clf()
703        Plot = Page.figure.gca()          #get a fresh plot after clf()
704       
705    except ValueError,error:
706        Plot = self.G2plotNB.add('2D Powder Image').gca()
707        plotNum = self.G2plotNB.plotList.index('2D Powder Image')
708        Page = self.G2plotNB.nb.GetPage(plotNum)
709        Page.canvas.mpl_connect('key_press_event', OnImPlotKeyPress)
710        Page.canvas.mpl_connect('motion_notify_event', OnImMotion)
711        Page.canvas.mpl_connect('pick_event', OnImPick)
712        Page.canvas.mpl_connect('button_release_event', OnImRelease)
713    Page.SetFocus()
714    Plot.set_title(self.PatternTree.GetItemText(self.Image)[4:])
715    size,imagefile = self.PatternTree.GetItemPyData(self.Image)
716    if imagefile != self.oldImagefile:
717        self.ImageZ = G2IO.GetImageData(imagefile,imageOnly=True)
718        self.oldImagefile = imagefile
719    Data = self.PatternTree.GetItemPyData(
720        G2gd.GetPatternTreeItemId(self,self.Image, 'Image Controls'))
721    Masks = self.PatternTree.GetItemPyData(
722        G2gd.GetPatternTreeItemId(self,self.Image, 'Masks'))
723
724    imScale = 1
725    if len(self.ImageZ) > 1024:
726        imScale = len(self.ImageZ)/1024
727    pixelSize = Data['pixelSize']
728    scalex = 1000./pixelSize[0]
729    scaley = 1000./pixelSize[1]
730    xmax = len(self.ImageZ)
731    Xmax = len(self.ImageZ)*pixelSize[0]/1000.
732    xlim = (-0.5,Xmax-.5)
733    ylim = (Xmax-.5,-0.5,)
734    Imin,Imax = Data['range'][1]
735    acolor = mpl.cm.get_cmap(Data['color'])
736    xcent,ycent = Data['center']
737    Plot.set_xlabel('Image x-axis, mm',fontsize=12)
738    Plot.set_ylabel('Image y-axis, mm',fontsize=12)
739    #need "applyMask" routine here
740    Zlim = Masks['Thresholds'][1]
741    spots = Masks['Points']
742    MA = ma.masked_greater(ma.masked_less(self.ImageZ,Zlim[0]),Zlim[1])
743    MaskA = ma.getmaskarray(MA)
744    A = G2img.ImageCompress(MA,imScale)
745    AM = G2img.ImageCompress(MaskA,imScale)
746   
747    ImgM = Plot.imshow(AM,aspect='equal',cmap='Reds',
748        interpolation='nearest',vmin=0,vmax=2,extent=[0,Xmax,Xmax,0])
749    Img = Plot.imshow(A,aspect='equal',cmap=acolor,
750        interpolation='nearest',vmin=Imin,vmax=Imax,extent=[0,Xmax,Xmax,0])
751    for x,y,d in spots:
752        Plot.add_artist(Circle((x,y),radius=d/2,fc='r',ec='r',picker=3))
753
754    Plot.plot(xcent,ycent,'x')
755    if Data['showLines']:
756        LRAzim = Data['LRazimuth']                  #NB: integers
757        IOtth = Data['IOtth']
758        wave = Data['wavelength']
759        dspI = wave/(2.0*sind(IOtth[0]/2.0))
760        ellI = G2img.GetEllipse(dspI,Data)           #=False if dsp didn't yield an ellipse (ugh! a parabola or a hyperbola)
761        dspO = wave/(2.0*sind(IOtth[1]/2.0))
762        ellO = G2img.GetEllipse(dspO,Data)           #Ditto & more likely for outer ellipse
763        if Data['fullIntegrate']:
764            Azm = np.array(range(0,361))
765        else:
766            Azm = np.array(range(LRAzim[0],LRAzim[1]+1))
767        if ellI:
768            xyI = []
769            for azm in Azm:
770                xyI.append(G2img.GetDetectorXY(dspI,azm,Data))
771            xyI = np.array(xyI)
772            arcxI,arcyI = xyI.T
773            Plot.plot(arcxI,arcyI,picker=3)
774        if ellO:
775            xyO = []
776            for azm in Azm:
777                xyO.append(G2img.GetDetectorXY(dspO,azm,Data))
778            xyO = np.array(xyO)
779            arcxO,arcyO = xyO.T
780            Plot.plot(arcxO,arcyO,picker=3)
781        if ellO and ellI and not Data['fullIntegrate']:
782            Plot.plot([arcxI[0],arcxO[0]],[arcyI[0],arcyO[0]],picker=3)
783            Plot.plot([arcxI[-1],arcxO[-1]],[arcyI[-1],arcyO[-1]],picker=3)
784    for xring,yring in Data['ring']:
785        Plot.plot(xring,yring,'r+',picker=3)
786    if Data['setRings']:
787        rings = np.concatenate((Data['rings']),axis=0)
788        for xring,yring,dsp in rings:
789            Plot.plot(xring,yring,'r+')           
790    for ellipse in Data['ellipses']:
791        cent,phi,[width,height],col = ellipse
792        Plot.add_artist(Ellipse([cent[0],cent[1]],2*width,2*height,phi,ec=col,fc='none'))
793        Plot.text(cent[0],cent[1],'+',color=col,ha='center',va='center')
794    colorBar = Page.figure.colorbar(Img)
795    Plot.set_xlim(xlim)
796    Plot.set_ylim(ylim)
797    if not newPlot:
798        Page.toolbar.push_current()
799        Plot.set_xlim(xylim[0])
800        Plot.set_ylim(xylim[1])
801        xylim = []
802        Page.toolbar.push_current()
803        Page.toolbar.draw()
804    else:
805        Page.canvas.draw()
806       
807def PlotIntegration(self,newPlot=False):
808           
809    def OnMotion(event):
810        Page.canvas.SetToolTipString('')
811        Page.canvas.SetCursor(wx.CROSS_CURSOR)
812        azm = event.ydata
813        tth = event.xdata
814        if azm and tth:
815            self.G2plotNB.status.SetFields(\
816                ['','Detector 2-th =%9.3fdeg, azm = %7.2fdeg'%(tth,azm)])
817                               
818    try:
819        plotNum = self.G2plotNB.plotList.index('2D Integration')
820        Page = self.G2plotNB.nb.GetPage(plotNum)
821        if not newPlot:
822            Plot = Page.figure.gca()          #get previous plot & get limits
823            xylim = Plot.get_xlim(),Plot.get_ylim()
824        Page.figure.clf()
825        Plot = Page.figure.gca()          #get a fresh plot after clf()
826       
827    except ValueError,error:
828        Plot = self.G2plotNB.add('2D Integration').gca()
829        plotNum = self.G2plotNB.plotList.index('2D Integration')
830        Page = self.G2plotNB.nb.GetPage(plotNum)
831        Page.canvas.mpl_connect('motion_notify_event', OnMotion)
832        Page.views = False
833        view = False
834    Page.SetFocus()
835       
836    Data = self.PatternTree.GetItemPyData(
837        G2gd.GetPatternTreeItemId(self,self.Image, 'Image Controls'))
838    image = self.Integrate[0]
839    xsc = self.Integrate[1]
840    ysc = self.Integrate[2]
841    Imin,Imax = Data['range'][1]
842    acolor = mpl.cm.get_cmap(Data['color'])
843    Plot.set_title(self.PatternTree.GetItemText(self.Image)[4:])
844    Plot.set_ylabel('azimuth',fontsize=12)
845    Plot.set_xlabel('2-theta',fontsize=12)
846    Img = Plot.imshow(image,cmap=acolor,vmin=Imin,vmax=Imax,interpolation='nearest', \
847        extent=[ysc[0],ysc[-1],xsc[-1],xsc[0]],aspect='auto')
848    colorBar = Page.figure.colorbar(Img)
849    if Data['setRings']:
850        rings = np.concatenate((Data['rings']),axis=0)
851        for xring,yring,dsp in rings:
852            x,y = G2img.GetTthAzm(xring,yring,Data)
853            Plot.plot(x,y,'r+')
854    if Data['ellipses']:           
855        for ellipse in Data['ellipses']:
856            ring = np.array(G2img.makeIdealRing(ellipse[:3])) #skip color
857            x,y = np.hsplit(ring,2)
858            tth,azm = G2img.GetTthAzm(x,y,Data)
859            Plot.plot(tth,azm,'b,')
860    if not newPlot:
861        Page.toolbar.push_current()
862        Plot.set_xlim(xylim[0])
863        Plot.set_ylim(xylim[1])
864        xylim = []
865        Page.toolbar.push_current()
866        Page.toolbar.draw()
867    else:
868        Page.canvas.draw()
869       
870       
871def PlotTRImage(self,tax,tay,taz,newPlot=False):
872    #a test plot routine - not normally used
873           
874    def OnMotion(event):
875        Page.canvas.SetToolTipString('')
876        Page.canvas.SetCursor(wx.CROSS_CURSOR)
877        azm = event.xdata
878        tth = event.ydata
879        if azm and tth:
880            self.G2plotNB.status.SetFields(\
881                ['','Detector 2-th =%9.3fdeg, azm = %7.2fdeg'%(tth,azm)])
882                               
883    try:
884        plotNum = self.G2plotNB.plotList.index('2D Transformed Powder Image')
885        Page = self.G2plotNB.nb.GetPage(plotNum)
886        if not newPlot:
887            Plot = Page.figure.gca()          #get previous plot & get limits
888            xylim = Plot.get_xlim(),Plot.get_ylim()
889        Page.figure.clf()
890        Plot = Page.figure.gca()          #get a fresh plot after clf()
891       
892    except ValueError,error:
893        Plot = self.G2plotNB.add('2D Transformed Powder Image').gca()
894        plotNum = self.G2plotNB.plotList.index('2D Transformed Powder Image')
895        Page = self.G2plotNB.nb.GetPage(plotNum)
896        Page.canvas.mpl_connect('motion_notify_event', OnMotion)
897        Page.views = False
898        view = False
899    Page.SetFocus()
900       
901    Data = self.PatternTree.GetItemPyData(
902        G2gd.GetPatternTreeItemId(self,self.Image, 'Image Controls'))
903    Imin,Imax = Data['range'][1]
904    step = (Imax-Imin)/5.
905    V = np.arange(Imin,Imax,step)
906    acolor = mpl.cm.get_cmap(Data['color'])
907    Plot.set_title(self.PatternTree.GetItemText(self.Image)[4:])
908    Plot.set_xlabel('azimuth',fontsize=12)
909    Plot.set_ylabel('2-theta',fontsize=12)
910    Plot.contour(tax,tay,taz,V,cmap=acolor)
911    if Data['showLines']:
912        IOtth = Data['IOtth']
913        if Data['fullIntegrate']:
914            LRAzim = [-180,180]
915        else:
916            LRAzim = Data['LRazimuth']                  #NB: integers
917        Plot.plot([LRAzim[0],LRAzim[1]],[IOtth[0],IOtth[0]],picker=True)
918        Plot.plot([LRAzim[0],LRAzim[1]],[IOtth[1],IOtth[1]],picker=True)
919        if not Data['fullIntegrate']:
920            Plot.plot([LRAzim[0],LRAzim[0]],[IOtth[0],IOtth[1]],picker=True)
921            Plot.plot([LRAzim[1],LRAzim[1]],[IOtth[0],IOtth[1]],picker=True)
922    if Data['setRings']:
923        rings = np.concatenate((Data['rings']),axis=0)
924        for xring,yring,dsp in rings:
925            x,y = G2img.GetTthAzm(xring,yring,Data)
926            Plot.plot(y,x,'r+')           
927    if Data['ellipses']:           
928        for ellipse in Data['ellipses']:
929            ring = np.array(G2img.makeIdealRing(ellipse[:3])) #skip color
930            x,y = np.hsplit(ring,2)
931            tth,azm = G2img.GetTthAzm(x,y,Data)
932            Plot.plot(azm,tth,'b,')
933    if not newPlot:
934        Page.toolbar.push_current()
935        Plot.set_xlim(xylim[0])
936        Plot.set_ylim(xylim[1])
937        xylim = []
938        Page.toolbar.push_current()
939        Page.toolbar.draw()
940    else:
941        Page.canvas.draw()
942       
943       
Note: See TracBrowser for help on using the repository browser.