source: trunk/fprime.py @ 3967

Last change on this file since 3967 was 3967, checked in by vondreele, 2 years ago

embed fprime & absorb plots in GSAS-II plot window as separate tabs. This removes conflict between contour plots & fprime/absorb plots

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