source: trunk/fprime.py

Last change on this file was 5623, checked in by vondreele, 3 months ago

Add Ga & In Ka to known x-ray wavelengths
Update of orbital form factors to Tc
fix error in B x-ray form factor (wrong sign for c term!)
change LeBail? message
apply random distribution to starting LeBail? structure factors

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Author Revision URL Id
File size: 24.4 KB
Line 
1#!/usr/bin/env python
2
3"""main Fprime routines
4   Copyright: 2008, Robert B. Von Dreele (Argonne National Laboratory)
5"""
6from __future__ import division, print_function
7import platform
8import math
9import wx
10import numpy as np
11import sys
12import matplotlib as mpl
13import GSASIIpath
14GSASIIpath.SetVersionNumber("$Revision: 5623 $")
15import GSASIIElem as G2elem
16import GSASIIElemGUI as G2elemGUI
17
18try:
19    wx.NewIdRef
20    wx.NewId = wx.NewIdRef
21except AttributeError:
22    pass
23
24if '2' in platform.python_version_tuple()[0]:
25    Gkmu = unichr(0x3bc)
26    Gktheta = unichr(0x3b8)
27    Gklambda = unichr(0x3bb)
28    GkDelta = unichr(0x0394)
29    Pwr10 = unichr(0x0b9)+unichr(0x2070)
30    Pwr20 = unichr(0x0b2)+unichr(0x2070)
31    Pwrm1 = unichr(0x207b)+unichr(0x0b9)
32    Pwrm2 = unichr(0x207b)+unichr(0x0b2)
33    Pwrm6 = unichr(0x207b)+unichr(0x2076)
34    Pwrm4 = unichr(0x207b)+unichr(0x2074)
35    Angstr = unichr(0x00c5)
36else:
37    Gkmu = chr(0x3bc)
38    Gktheta = chr(0x3b8)
39    Gklambda = chr(0x3bb)
40    GkDelta = chr(0x0394)
41    Pwr10 = chr(0x0b9)+chr(0x2070)
42    Pwr20 = chr(0x0b2)+chr(0x2070)
43    Pwrm1 = chr(0x207b)+chr(0x0b9)
44    Pwrm2 = chr(0x207b)+chr(0x0b2)
45    Pwrm6 = chr(0x207b)+chr(0x2076)
46    Pwrm4 = chr(0x207b)+chr(0x2074)
47    Angstr = chr(0x00c5)   
48
49[wxID_FPRIMECHOICE1, wxID_FPRIMECHOICE2, wxID_SPINTEXT1, wxID_SPINTEXT2,
50 wxID_FPRIMERESULTS,wxID_FPRIMESLIDER1, wxID_SPINBUTTON,
51] = [wx.NewId() for _init_ctrls in range(7)]
52
53[wxID_FPRIMEEXIT, wxID_FPRIMEDELETE, wxID_FPRIMENEW, 
54] = [wx.NewId() for _init_coll_FPRIME_Items in range(3)]
55
56[wxID_FPRIMEKALPHAAGKA, wxID_FPRIMEKALPHACOKA, wxID_FPRIMEKALPHACRKA, 
57 wxID_FPRIMEKALPHACUKA, wxID_FPRIMEKALPHAFEKA, wxID_FPRIMEKALPHAMNKA, 
58 wxID_FPRIMEKALPHAMOKA, wxID_FPRIMEKALPHANIKA, wxID_FPRIMEKALPHAZNKA, 
59wxID_FPRIMEKALPHAGAKA,wxID_FPRIMEKALPHAINKA, 
60] = [wx.NewId() for _init_coll_KALPHA_Items in range(11)]
61
62[wxID_FPRIMEABOUT] = [wx.NewId() for _init_coll_ABOUT_Items in range(1)]
63
64class Fprime(wx.Frame):
65    '''Creates a frame where input for absorption calculation is supplied
66    '''
67    Elems = []
68    Wave = 1.5405      #CuKa default
69    Kev = 12.397639    #keV for 1A x-rays
70    for arg in sys.argv:
71        if '-w' in arg:
72            Wave = float(arg.split('-w')[1])
73        elif '-e' in arg:
74            E = float(arg.split('-e')[1])
75            Wave = Kev/E
76        elif '-h' in arg:
77            print( '''
78fprime.py can take the following arguments:
79-h   -  this help listing
80-wv  -  set default wavelength to v, e.g. -w1.54 sets wavelength to 1.54A
81-ev  -  set default energy to v, e.g. -e27 sets energy to 27keV
82without arguments fprime uses CuKa as default (Wave=1.54052A, E=8.0478keV)
83''')
84            sys.exit()
85    Wmin = 0.05        #wavelength range
86    Wmax = 3.0
87    Wres = 0.004094    #plot resolution step size as const delta-lam/lam - gives 1000 steps for Wmin to Wmax
88    Eres = 1.5e-4      #typical energy resolution for synchrotron x-ray sources
89    ffpfignum = 1
90    fppfignum = 2
91    Energy = Kev/Wave
92    ifWave = True
93    FFxaxis = 'S'      #default form factor plot is vs sin(theta)/lambda
94    def _init_coll_ABOUT_Items(self, parent):
95
96        parent.Append(wxID_FPRIMEABOUT, 'About')
97        self.Bind(wx.EVT_MENU, self.OnABOUTItems0Menu, id=wxID_FPRIMEABOUT)
98
99    def _init_coll_menuBar1_Menus(self, parent):
100
101        parent.Append(menu=self.FPRIME, title='Fprime')
102        parent.Append(menu=self.KALPHA, title='Kalpha')
103        parent.Append(menu=self.ABOUT, title='About')
104
105    def _init_coll_KALPHA_Items(self, parent):
106        "Set of characteristic radiation from sealed tube sources"
107
108        parent.Append(wxID_FPRIMEKALPHACRKA,'CrKa')
109        parent.Append(wxID_FPRIMEKALPHAMNKA,'MnKa')
110        parent.Append(wxID_FPRIMEKALPHAFEKA,'FeKa')
111        parent.Append(wxID_FPRIMEKALPHACOKA,'CoKa')
112        parent.Append(wxID_FPRIMEKALPHANIKA,'NiKa')
113        parent.Append(wxID_FPRIMEKALPHACUKA,'CuKa')
114        parent.Append(wxID_FPRIMEKALPHAZNKA,'ZnKa')
115        parent.Append(wxID_FPRIMEKALPHAGAKA,'GaKa')
116        parent.Append(wxID_FPRIMEKALPHAMOKA,'MoKa')
117        parent.Append(wxID_FPRIMEKALPHAAGKA,'AgKa')
118        parent.Append(wxID_FPRIMEKALPHAINKA,'InKa')
119        self.Bind(wx.EVT_MENU, self.OnKALPHACrkaMenu, id=wxID_FPRIMEKALPHACRKA)
120        self.Bind(wx.EVT_MENU, self.OnKALPHAMnkaMenu, id=wxID_FPRIMEKALPHAMNKA)
121        self.Bind(wx.EVT_MENU, self.OnKALPHAFekaMenu, id=wxID_FPRIMEKALPHAFEKA)
122        self.Bind(wx.EVT_MENU, self.OnKALPHACokaMenu, id=wxID_FPRIMEKALPHACOKA)
123        self.Bind(wx.EVT_MENU, self.OnKALPHANikaMenu, id=wxID_FPRIMEKALPHANIKA)
124        self.Bind(wx.EVT_MENU, self.OnKALPHACukaMenu, id=wxID_FPRIMEKALPHACUKA)
125        self.Bind(wx.EVT_MENU, self.OnKALPHAZnkaMenu, id=wxID_FPRIMEKALPHAZNKA)
126        self.Bind(wx.EVT_MENU, self.OnKALPHAGakaMenu, id=wxID_FPRIMEKALPHAGAKA)
127        self.Bind(wx.EVT_MENU, self.OnKALPHAMokaMenu, id=wxID_FPRIMEKALPHAMOKA)
128        self.Bind(wx.EVT_MENU, self.OnKALPHAAgkaMenu, id=wxID_FPRIMEKALPHAAGKA)
129        self.Bind(wx.EVT_MENU, self.OnKALPHAInkaMenu, id=wxID_FPRIMEKALPHAINKA)
130
131    def _init_coll_FPRIME_Items(self, parent):
132        parent.Append(wxID_FPRIMENEW,'&New Element','Add new element')
133        self.Delete = parent.Append(wxID_FPRIMEDELETE,'&Delete Element','Delete an element')
134        self.Delete.Enable(False)
135        parent.Append(wxID_FPRIMEEXIT,'&Exit','Exit Fprime')
136        self.Bind(wx.EVT_MENU, self.OnFPRIMEExitMenu, id=wxID_FPRIMEEXIT)
137        self.Bind(wx.EVT_MENU, self.OnFPRIMENewMenu, id=wxID_FPRIMENEW)
138        self.Bind(wx.EVT_MENU, self.OnFPRIMEDeleteMenu, id=wxID_FPRIMEDELETE)
139
140    def _init_utils(self):
141        self.FPRIME = wx.Menu(title='')
142
143        self.KALPHA = wx.Menu(title='')
144        self.KALPHA.SetEvtHandlerEnabled(True)
145
146        self.ABOUT = wx.Menu(title='')
147
148        self.menuBar1 = wx.MenuBar()
149
150        self._init_coll_FPRIME_Items(self.FPRIME)
151        self._init_coll_KALPHA_Items(self.KALPHA)
152        self._init_coll_ABOUT_Items(self.ABOUT)
153        self._init_coll_menuBar1_Menus(self.menuBar1)
154
155    def _init_ctrls(self, parent):
156
157        wx.Frame.__init__(self, parent=parent,
158              size=wx.Size(500, 300),style=wx.DEFAULT_FRAME_STYLE ^ wx.CLOSE_BOX, title='Fprime')             
159        self._init_utils()
160        self.SetMenuBar(self.menuBar1)
161        panel = wx.Panel(self)
162
163        mainSizer = wx.BoxSizer(wx.VERTICAL)
164        self.Results = wx.TextCtrl( parent=panel,style=wx.TE_MULTILINE|wx.TE_DONTWRAP )
165        self.Results.SetEditable(False)
166        mainSizer.Add(self.Results,1,wx.EXPAND)
167        mainSizer.Add((10,15),0)
168
169        selSizer = wx.BoxSizer(wx.HORIZONTAL)
170        selSizer.Add((5,10),0)
171        selSizer.Add(wx.StaticText(parent=panel, label='Wavelength:'),0,wx.EXPAND)
172        selSizer.Add((5,10),0)
173        self.SpinText1 = wx.TextCtrl(id=wxID_SPINTEXT1, parent=panel, 
174              size=wx.Size(100,20), value = "%6.4f" % (self.Wave),style=wx.TE_PROCESS_ENTER )
175        selSizer.Add(self.SpinText1,0)
176        selSizer.Add((5,10),0)
177        self.SpinText1.Bind(wx.EVT_TEXT_ENTER, self.OnSpinText1, id=wxID_SPINTEXT1)
178       
179        selSizer.Add(wx.StaticText(parent=panel, label='Energy:'),0,wx.EXPAND)
180        selSizer.Add((5,10),0)
181        self.SpinText2 = wx.TextCtrl(id=wxID_SPINTEXT2, parent=panel, 
182              size=wx.Size(100,20), value = "%7.4f" % (self.Energy),style=wx.TE_PROCESS_ENTER) 
183        selSizer.Add(self.SpinText2,0)
184        self.SpinText2.Bind(wx.EVT_TEXT_ENTER, self.OnSpinText2, id=wxID_SPINTEXT2)
185        mainSizer.Add(selSizer,0)
186        mainSizer.Add((10,10),0)
187       
188        slideSizer = wx.BoxSizer(wx.HORIZONTAL)
189        self.SpinButton = wx.SpinButton(id=wxID_SPINBUTTON, parent=panel, 
190              size=wx.Size(25,24), style=wx.SP_VERTICAL | wx.SP_ARROW_KEYS)
191        slideSizer.Add(self.SpinButton)
192        self.SpinButton.SetRange(-1,1)
193        self.SpinButton.SetValue(0)
194        self.SpinButton.Bind(wx.EVT_SPIN, self.OnSpinButton, id=wxID_SPINBUTTON)
195
196        self.slider1 = wx.Slider(id=wxID_FPRIMESLIDER1, maxValue=int(1000.*self.Wmax),
197            minValue=int(1000.*self.Wmin), parent=panel,style=wx.SL_HORIZONTAL,
198            value=int(self.Wave*1000.), )
199        slideSizer.Add(self.slider1,1,wx.EXPAND)
200        self.slider1.Bind(wx.EVT_SLIDER, self.OnSlider1, id=wxID_FPRIMESLIDER1)
201        mainSizer.Add(slideSizer,0,wx.EXPAND)
202        mainSizer.Add((10,10),0)
203       
204        choiceSizer = wx.BoxSizer(wx.HORIZONTAL)
205        choiceSizer.Add((5,10),0)
206        choiceSizer.Add(wx.StaticText(parent=panel, label='Plot scales:'),0,wx.EXPAND)
207        choiceSizer.Add((5,10),0)
208
209        self.choice1 = wx.ComboBox(id=wxID_FPRIMECHOICE1, parent=panel, value='Wavelength',
210             choices=['Wavelength','Energy'],style=wx.CB_READONLY|wx.CB_DROPDOWN)
211        choiceSizer.Add(self.choice1,0)
212        choiceSizer.Add((10,10),0)
213        self.choice1.Bind(wx.EVT_COMBOBOX, self.OnChoice1, id=wxID_FPRIMECHOICE1)
214
215        def OnChoice2(event):
216            if event.GetString() == ' sin('+Gktheta+')/'+Gklambda:
217                self.FFxaxis = 'S'
218            elif event.GetString() == ' Q':
219                self.FFxaxis = 'Q'
220            else:
221                self.FFxaxis = 'T'
222            self.UpDateFPlot(self.Wave,rePlot=False)
223           
224        self.choice2 = wx.ComboBox(id=wxID_FPRIMECHOICE2, value=' sin('+Gktheta+')/'+Gklambda,
225            choices=[' sin('+Gktheta+')/'+Gklambda,' 2'+Gktheta,' Q'],
226            parent=panel, style=wx.CB_READONLY|wx.CB_DROPDOWN)
227        choiceSizer.Add(self.choice2,0)
228        self.choice2.Bind(wx.EVT_COMBOBOX, OnChoice2, id=wxID_FPRIMECHOICE2)
229        mainSizer.Add(choiceSizer,0)
230        mainSizer.Add((10,10),0)
231        panel.SetSizer(mainSizer)
232
233    def __init__(self, parent):
234        self._init_ctrls(parent)
235        self.parent = parent
236        self.Lines = []
237        self.Elems = []
238        self.linePicked = None
239       
240    def OnFPRIMEExitMenu(self, event):
241        self.parent.G2plotNB.Delete('Fprime')
242        self.Close()
243        self.Destroy()
244
245    def OnFPRIMENewMenu(self, event):
246        ElList = []
247        for Elem in self.Elems: ElList.append(Elem[0])
248        PE = G2elemGUI.PickElements(self,ElList)
249        if PE.ShowModal() == wx.ID_OK:
250            Elems = PE.Elem
251        else:
252            return
253#        PE.Destroy()
254        if Elems:
255            for El in Elems:
256                ElemSym = El.strip().upper()
257                if ElemSym not in ElList:
258                    FormFactors = G2elem.GetFormFactorCoeff(ElemSym)
259                    for FormFac in FormFactors:
260                        FormSym = FormFac['Symbol'].strip()
261                        if FormSym == ElemSym:
262                            Z = FormFac['Z']                #At. No.
263                            Orbs = G2elem.GetXsectionCoeff(ElemSym)
264                            Elem = (ElemSym,Z,FormFac,Orbs)
265                    self.Elems.append(Elem)
266            self.Delete.Enable(True)
267            self.CalcFPPS()
268            self.SetWaveEnergy(self.Wave)
269           
270    def OnFPRIMEDeleteMenu(self, event):
271        if len(self.Elems):
272            ElList = []
273            for Elem in self.Elems: ElList.append(Elem[0])
274            S = []
275            DE = G2elemGUI.DeleteElement(self,ElList)
276            if DE.ShowModal() == wx.ID_OK:
277                El = DE.GetDeleteElement().strip().upper()
278                for Elem in self.Elems:
279                    if Elem[0] != El:
280                        S.append(Elem)
281                self.Elems = S
282                self.CalcFPPS()
283                if not self.Elems:
284                    self.Delete.Enable(False)
285                self.SetWaveEnergy(self.Wave)
286       
287    def OnKALPHACrkaMenu(self, event):
288        self.SetWaveEnergy(2.28962)
289
290    def OnKALPHAMnkaMenu(self, event):
291        self.SetWaveEnergy(2.10174)
292
293    def OnKALPHAFekaMenu(self, event):
294        self.SetWaveEnergy(1.93597)
295
296    def OnKALPHACokaMenu(self, event):
297        self.SetWaveEnergy(1.78896)
298
299    def OnKALPHANikaMenu(self, event):
300        self.SetWaveEnergy(1.65784)
301
302    def OnKALPHACukaMenu(self, event):
303        self.SetWaveEnergy(1.54052)
304
305    def OnKALPHAZnkaMenu(self, event):
306        self.SetWaveEnergy(1.43510)
307
308    def OnKALPHAGakaMenu(self, event):
309        self.SetWaveEnergy(1.34134)
310   
311    def OnKALPHAMokaMenu(self, event):
312        self.SetWaveEnergy(0.70926)
313
314    def OnKALPHAAgkaMenu(self, event):
315        self.SetWaveEnergy(0.55936)
316       
317    def OnKALPHAInkaMenu(self, event):
318        self.SetWaveEnergy(0.51357)
319       
320    def OnSpinText1(self, event):
321        self.SetWaveEnergy(float(self.SpinText1.GetValue()))
322       
323    def OnSpinText2(self, event):
324        self.SetWaveEnergy(self.Kev/(float(self.SpinText2.GetValue())))
325       
326    def OnSpinButton(self, event):
327        move = self.SpinButton.GetValue()/10000.
328        self.Wave = min(max(self.Wave+move,self.Wmin),self.Wmax)
329        self.SpinButton.SetValue(0)
330        self.SetWaveEnergy(self.Wave)
331
332    def OnSlider1(self, event):
333        if self.ifWave:
334            Wave = float(self.slider1.GetValue())/1000.
335        else:
336            Wave = self.Kev/(float(self.slider1.GetValue())/1000.)
337        self.SetWaveEnergy(Wave)
338       
339    def OnKeyPress(self,event):
340        if event.key == 'g':
341            mpl.rcParams['axes.grid'] = not mpl.rcParams['axes.grid']
342            self.SetWaveEnergy(self.Wave)           
343
344    def UpDateFPlot(self,Wave,rePlot=True):
345        """Plot f' & f" vs wavelength 0.05-3.0A"""
346        "generate a set of form factor curves & plot them vs sin-theta/lambda or q or 2-theta"
347        self.axylim = []
348        self.bxylim = []
349        try:
350            if rePlot:
351                self.axylim = self.ax.get_xlim(),self.ax.get_ylim()
352                self.bxylim = self.bx.get_xlim(),self.bx.get_ylim()
353            newPlot = False
354        except:
355            new,plotNum,self.Page,self.fplot,lim = self.parent.G2plotNB.FindPlotTab('Fprime','mpl')
356            self.Page.canvas.mpl_connect('pick_event', self.OnPick)
357            self.Page.canvas.mpl_connect('button_release_event', self.OnRelease)
358            self.Page.canvas.mpl_connect('motion_notify_event', self.OnMotion)
359            self.Page.canvas.mpl_connect('key_press_event', self.OnKeyPress)
360            newPlot = True
361            self.ax,self.bx = self.Page.figure.subplots(1,2)
362        self.Page.Choice = (' key press','g: toggle grid',)
363        self.Page.keyPress = self.OnKeyPress
364        self.fplot.set_visible(False)
365        self.ax.cla()
366        self.bx.cla()
367        self.ax.set_title('Resonant Scattering Factors',x=0,ha='left')
368        self.ax.set_ylabel("f ',"+' f ", e-',fontsize=14)
369        Ymin = 0.0
370        Ymax = 0.0
371        colors=['r','b','g','c','m','k']
372        if self.FPPS: 
373            for i,Fpps in enumerate(self.FPPS):
374                Color = colors[i%6]
375                Ymin = min(Ymin,min(Fpps[2]),min(Fpps[3]))
376                Ymax = max(Ymax,max(Fpps[2]),max(Fpps[3]))
377                fppsP1 = np.array(Fpps[1])
378                fppsP2 = np.array(Fpps[2])
379                fppsP3 = np.array(Fpps[3])
380                self.ax.plot(fppsP1,fppsP2,Color,label=Fpps[0]+" f '")
381                self.ax.plot(fppsP1,fppsP3,Color,linestyle='dashed',label=Fpps[0]+' f "')
382        if self.ifWave: 
383            self.ax.set_xlabel(r'$\mathsf{\lambda, \AA}$',fontsize=14)
384            self.ax.axvline(x=Wave,picker=3,color='black')
385        else:
386            self.ax.set_xlabel(r'$\mathsf{E, keV}$',fontsize=14)
387            self.ax.set_xscale('log')
388            self.ax.axvline(x=self.Kev/Wave,picker=3,color='black')
389        self.ax.set_ylim(Ymin,Ymax)
390        if self.FPPS:
391            self.ax.legend(loc='best')
392        self.Page.figure.subplots_adjust(hspace=0.25)
393        if self.ifWave:
394            self.bx.set_title('%s%s%6.4f%s'%('Form factors (',r'$\lambda=$',self.Wave,r'$\AA)$'),x=0,ha='left')
395        else:
396            self.bx.set_title('%s%6.2f%s'%('Form factors  (E =',self.Energy,'keV)'),x=0,ha='left')
397        if self.FFxaxis == 'S':
398            self.bxlabel = 'sin('+Gktheta+')/'+Gklambda
399            self.bx.set_xlabel(r'$\mathsf{sin(\theta)/\lambda}$',fontsize=14)
400        elif self.FFxaxis == 'T':
401            self.bxlabel = '2'+Gktheta
402            self.bx.set_xlabel(r'$\mathsf{2\theta}$',fontsize=14)
403        else:
404            self.bxlabel = 'Q, '+Angstr+Pwrm1
405            self.bx.set_xlabel(r'$Q, \AA$',fontsize=14)
406        self.bx.set_ylabel("f+f ', e-",fontsize=14)
407        E = self.Energy
408        DE = E*self.Eres                         #smear by defined source resolution
409        StlMax = min(2.0,math.sin(80.0*math.pi/180.)/Wave)
410        Stl = np.arange(0.,StlMax,.01)
411        Ymax = 0.0
412        for i,Elem in enumerate(self.Elems):
413            Els = Elem[0]
414            Els = Els = Els.ljust(2).lower().capitalize()
415            Ymax = max(Ymax,Elem[1])
416            res1 = G2elem.FPcalc(Elem[3],E+DE)
417            res2 = G2elem.FPcalc(Elem[3],E-DE)
418            res = (res1[0]+res2[0])/2.0
419            if Elem[1] > 78 and self.Energy > self.Kev/0.16: res = 0.0
420            if Elem[1] > 94 and self.Energy < self.Kev/2.67: res = 0.0
421            Els = Elem[0]
422            Els = Els.ljust(2).lower().capitalize()
423            X = []
424            ff = []
425            ffo = []
426            for S in Stl: 
427                ff.append(G2elem.ScatFac(Elem[2],S*S)+res)
428                ffo.append(G2elem.ScatFac(Elem[2],S*S))
429                if self.FFxaxis == 'S':
430                    X.append(S)
431                elif self.FFxaxis == 'T':
432                    X.append(360.0*math.asin(S*self.Wave)/math.pi)
433                else:
434                    X.append(4.0*S*math.pi)
435            Color = colors[i%6]
436            Xp = np.array(X)
437            ffop = np.array(ffo)
438            ffp = np.array(ff)
439            self.bx.plot(Xp,ffop,Color,linestyle='dashed',label=Els+" f")
440            self.bx.plot(Xp,ffp,Color,label=Els+" f+f'")
441        if self.Elems:
442            self.bx.legend(loc='best')
443        self.bx.set_ylim(0.0,Ymax+1.0)
444       
445        if newPlot:
446            newPlot = False
447            self.Page.canvas.draw()
448        else:
449            if rePlot:
450                tb = self.Page.canvas.toolbar
451                tb.push_current()
452                self.ax.set_xlim(self.axylim[0])
453                self.ax.set_ylim(self.axylim[1])
454                self.axylim = []
455                tb.push_current()
456                self.bx.set_xlim(self.bxylim[0])
457                self.bx.set_ylim(self.bxylim[1])
458                self.bxylim = []
459                tb.push_current()
460            self.Page.canvas.draw()
461       
462    def OnPick(self, event):
463        self.linePicked = event.artist
464       
465    def OnMotion(self,event):
466        xpos = event.xdata
467        if xpos and xpos>0.1:
468            ypos = event.ydata
469            if self.ifWave:
470                Wave = xpos
471            else:
472                Wave = self.Kev/xpos
473            Wave = min(max(Wave,self.Wmin),self.Wmax)
474            if event.inaxes == self.ax:
475                self.parent.G2plotNB.status.SetStatusText("Wavelength: %.4f, Energy: %.3f, f'%s: %.3f"%(Wave,self.Kev/Wave,'f"',ypos),1)
476            elif event.inaxes == self.bx:
477                self.parent.G2plotNB.status.SetStatusText("%s: %.4f, f,f+f': %.3f"%(self.bxlabel,xpos,ypos),1)
478        if self.linePicked:
479            self.SetWaveEnergy(Wave)
480               
481    def OnRelease(self, event):
482        if self.linePicked is None: return
483        self.linePicked = None
484        xpos = event.xdata
485        if xpos:
486            if self.ifWave:
487                Wave = xpos
488            else:
489                Wave = self.Kev/xpos               
490            self.SetWaveEnergy(Wave)
491
492    def SetWaveEnergy(self,Wave):
493        self.Wave = Wave
494        self.Energy = self.Kev/self.Wave
495        self.Energy = round(self.Energy,4)
496        E = self.Energy
497        DE = E*self.Eres                         #smear by defined source resolution
498        self.SpinText1.SetValue("%6.4f" % (self.Wave))
499        self.SpinText2.SetValue("%7.4f" % (self.Energy))
500        self.SpinText1.Update()
501        self.SpinText2.Update()
502        if self.ifWave:
503            self.slider1.SetValue(int(1000.*self.Wave))
504        else:
505            self.slider1.SetValue(int(1000.*self.Energy))
506        Text = ''
507        for Elem in self.Elems:
508            r1 = G2elem.FPcalc(Elem[3],E+DE)
509            r2 = G2elem.FPcalc(Elem[3],E-DE)
510            Els = Elem[0]
511            Els = Els.ljust(2).lower().capitalize()
512            if Elem[1] > 78 and self.Energy+DE > self.Kev/0.16:
513                Text += "%s\t%s%6s\t%s%6.3f  \t%s%10.2f %s\n" %    (
514                    'Element= '+str(Els)," f'=",'not valid',
515                    ' f"=',(r1[1]+r2[1])/2.0,' '+Gkmu+'=',(r1[2]+r2[2])/2.0,'barns/atom')
516            elif Elem[1] > 94 and self.Energy-DE < self.Kev/2.67:
517                Text += "%s\t%s%6s\t%s%6s\t%s%10s%s\n" %    (
518                    'Element= '+str(Els)," f'=",'not valid',
519                    ' f"=','not valid',' '+Gkmu+'=','not valid')
520            else:
521                Text += "%s\t%s%6.3f   \t%s%6.3f  \t%s%10.2f %s\n" %    (
522                    'Element= '+str(Els)," f'=",(r1[0]+r2[0])/2.0,
523                    ' f"=',(r1[1]+r2[1])/2.0,' '+Gkmu+'=',(r1[2]+r2[2])/2.0,'barns/atom')
524        if len(self.Elems):
525            self.Results.SetValue(Text)
526            self.Results.Update()
527            self.UpDateFPlot(Wave)
528
529    def CalcFPPS(self):
530        """generate set of f' & f" curves for selected elements
531           does constant delta-lambda/lambda steps over defined range
532        """
533        FPPS = []
534        if self.Elems:
535            wx.BeginBusyCursor()
536            try:
537                for Elem in self.Elems:
538                    Els = Elem[0]
539                    Els = Els = Els.ljust(2).lower().capitalize()
540                    Wmin = self.Wmin
541                    Wmax = self.Wmax
542                    Z = Elem[1]
543                    if Z > 78: Wmin = 0.16        #heavy element high energy failure of Cromer-Liberman
544                    if Z > 94: Wmax = 2.67        #heavy element low energy failure of Cromer-Liberman
545                    lWmin = math.log(Wmin)
546                    N = int(round(math.log(Wmax/Wmin)/self.Wres))    #number of constant delta-lam/lam steps
547                    I = range(N+1)
548                    Ws = []
549                    for i in I: Ws.append(math.exp(i*self.Wres+lWmin))
550                    fps = []
551                    fpps = []
552                    Es = []
553                    for W in Ws:
554                        E = self.Kev/W
555                        DE = E*self.Eres                         #smear by defined source resolution
556                        res1 = G2elem.FPcalc(Elem[3],E+DE)
557                        res2 = G2elem.FPcalc(Elem[3],E-DE)
558                        fps.append((res1[0]+res2[0])/2.0)
559                        fpps.append((res1[1]+res2[1])/2.0)
560                        Es.append(E)
561                    if self.ifWave:
562                        Fpps = (Els,Ws,fps,fpps)
563                    else:
564                        Fpps = (Els,Es,fps,fpps)
565                    FPPS.append(Fpps)
566            finally:
567                wx.EndBusyCursor()
568        self.FPPS = FPPS
569
570    def OnChoice1(self, event):
571        if event.GetString() == "Wavelength":
572            self.ifWave = True
573            self.NewFPPlot = True
574            self.Wave = round(self.Wave,4)
575            self.slider1.SetRange(int(1000.*self.Wmin),int(1000.*self.Wmax))
576            self.slider1.SetValue(int(1000.*self.Wave))
577            self.SpinText1.SetValue("%6.4f" % (self.Wave))
578            self.SpinText2.SetValue("%7.4f" % (self.Energy))
579        else:
580            self.ifWave = False
581            self.NewFPPlot = True
582            Emin = self.Kev/self.Wmax
583            Emax = self.Kev/self.Wmin
584            self.Energy = round(self.Energy,4)
585            self.slider1.SetRange(int(1000.*Emin),int(1000.*Emax))
586            self.slider1.SetValue(int(1000.*self.Energy))
587            self.SpinText1.SetValue("%6.4f" % (self.Wave))
588            self.SpinText2.SetValue("%7.4f" % (self.Energy))
589        self.CalcFPPS()
590        self.UpDateFPlot(self.Wave,rePlot=False)
591
592    def OnABOUTItems0Menu(self, event):
593        '''Displays the About window
594        '''
595        try:
596            import wx.adv as wxadv  # AboutBox moved here in Phoenix
597        except:
598            wxadv = wx
599        info = wxadv.AboutDialogInfo()
600        info.Name = 'pyFprime'
601        info.Copyright = '''
602Robert B. Von Dreele, 2008(C)
603Argonne National Laboratory
604This product includes software developed
605by the UChicago Argonne, LLC, as
606Operator of Argonne National Laboratory.        '''
607        info.Description = '''
608For calculating real and resonant X-ray scattering factors to 250keV;       
609based on Fortran program of Cromer & Liberman corrected for
610Kissel & Pratt energy term; Jensen term not included
611(D. T. Cromer and D. A. Liberman, Acta Cryst. (1981). A37, 267-268.)
612        '''
613        wxadv.AboutBox(info)
Note: See TracBrowser for help on using the repository browser.