source: trunk/GSASIIplot.py @ 82

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

split powder GUI stuff out of G2gd & put in new GSASIIpwdGUI.py - all seems to work

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