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 matplotlib as mpl |
---|
13 | import GSASIIpath |
---|
14 | GSASIIpath.SetVersionNumber("$Revision: 5623 $") |
---|
15 | import GSASIIElem as G2elem |
---|
16 | import GSASIIElemGUI as G2elemGUI |
---|
17 | |
---|
18 | try: |
---|
19 | wx.NewIdRef |
---|
20 | wx.NewId = wx.NewIdRef |
---|
21 | except AttributeError: |
---|
22 | pass |
---|
23 | |
---|
24 | if '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) |
---|
36 | else: |
---|
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, |
---|
59 | wxID_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 | |
---|
64 | class 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( ''' |
---|
78 | fprime.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 |
---|
82 | without 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 = ''' |
---|
602 | Robert B. Von Dreele, 2008(C) |
---|
603 | Argonne National Laboratory |
---|
604 | This product includes software developed |
---|
605 | by the UChicago Argonne, LLC, as |
---|
606 | Operator of Argonne National Laboratory. ''' |
---|
607 | info.Description = ''' |
---|
608 | For calculating real and resonant X-ray scattering factors to 250keV; |
---|
609 | based on Fortran program of Cromer & Liberman corrected for |
---|
610 | Kissel & 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) |
---|