1 | #!/usr/bin/env python |
---|
2 | |
---|
3 | """main Fprime routines |
---|
4 | Copyright: 2008, Robert B. Von Dreele (Argonne National Laboratory) |
---|
5 | """ |
---|
6 | from __future__ import division, print_function |
---|
7 | import platform |
---|
8 | import math |
---|
9 | import wx |
---|
10 | import numpy as np |
---|
11 | import sys |
---|
12 | import GSASIIpath |
---|
13 | GSASIIpath.SetVersionNumber("$Revision: 3765 $") |
---|
14 | import GSASIIElem as G2elem |
---|
15 | import GSASIIElemGUI as G2elemGUI |
---|
16 | |
---|
17 | try: |
---|
18 | wx.NewIdRef |
---|
19 | wx.NewId = wx.NewIdRef |
---|
20 | except AttributeError: |
---|
21 | pass |
---|
22 | |
---|
23 | if '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) |
---|
35 | else: |
---|
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 | |
---|
62 | class 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( ''' |
---|
75 | fprime.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 |
---|
79 | without 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 = ''' |
---|
579 | Robert B. Von Dreele, 2008(C) |
---|
580 | Argonne National Laboratory |
---|
581 | This product includes software developed |
---|
582 | by the UChicago Argonne, LLC, as |
---|
583 | Operator of Argonne National Laboratory. ''' |
---|
584 | info.Description = ''' |
---|
585 | For calculating real and resonant X-ray scattering factors to 250keV; |
---|
586 | based on Fortran program of Cromer & Liberman corrected for |
---|
587 | Kissel & Pratt energy term; Jensen term not included |
---|
588 | ''' |
---|
589 | wxadv.AboutBox(info) |
---|