source: trunk/fprime.py @ 3766

Last change on this file since 3766 was 3766, checked in by vondreele, 3 years ago

Add Absorb and Fprime to the main Calculate menu

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