1 | #!/usr/bin/env python |
---|
2 | |
---|
3 | """main Absorb routines |
---|
4 | Copyright: 2009, 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: 4830 $") |
---|
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 | 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 | Gkmu = unichr(0x3bc) |
---|
36 | Pwr3 = unichr(0x0b3) |
---|
37 | Pwr4 = unichr(0x2074) |
---|
38 | Pwr20 = unichr(0x0b2)+unichr(0x0b0) |
---|
39 | Pwrm1 = unichr(0x207b)+unichr(0x0b9) |
---|
40 | |
---|
41 | else: |
---|
42 | Gktheta = chr(0x3b8) |
---|
43 | Gklambda = chr(0x3bb) |
---|
44 | GkDelta = chr(0x0394) |
---|
45 | Pwr10 = chr(0x0b9)+chr(0x2070) |
---|
46 | Pwr20 = chr(0x0b2)+chr(0x2070) |
---|
47 | Pwrm1 = chr(0x207b)+chr(0x0b9) |
---|
48 | Pwrm2 = chr(0x207b)+chr(0x0b2) |
---|
49 | Pwrm6 = chr(0x207b)+chr(0x2076) |
---|
50 | Pwrm4 = chr(0x207b)+chr(0x2074) |
---|
51 | Angstr = chr(0x00c5) |
---|
52 | Gkmu = chr(0x3bc) |
---|
53 | Pwr3 = chr(0x0b3) |
---|
54 | Pwr4 = chr(0x2074) |
---|
55 | Pwr20 = chr(0x0b2)+chr(0x0b0) |
---|
56 | Pwrm1 = chr(0x207b)+chr(0x0b9) |
---|
57 | |
---|
58 | [wxID_CHOICE1, wxID_SPINTEXT1, wxID_SPINTEXT2, wxID_SPINTEXT3, wxID_SPINTEXT4, |
---|
59 | wxID_RESULTS,wxID_SLIDER1, wxID_SPINBUTTON, wxID_NUMELEM, wxID_SPINTEXT5,wxID_SPINTEXT6, |
---|
60 | ] = [wx.NewId() for _init_ctrls in range(11)] |
---|
61 | |
---|
62 | [wxID_EXIT, wxID_DELETE, wxID_NEW, |
---|
63 | ] = [wx.NewId() for _init_coll_ABSORB_Items in range(3)] |
---|
64 | |
---|
65 | [wxID_KALPHAAGKA, wxID_KALPHACOKA, wxID_KALPHACRKA, |
---|
66 | wxID_KALPHACUKA, wxID_KALPHAFEKA, wxID_KALPHAMNKA, |
---|
67 | wxID_KALPHAMOKA, wxID_KALPHANIKA, wxID_KALPHAZNKA, |
---|
68 | ] = [wx.NewId() for _init_coll_KALPHA_Items in range(9)] |
---|
69 | |
---|
70 | [wxID_ABSORBABOUT] = [wx.NewId() for _init_coll_ABOUT_Items in range(1)] |
---|
71 | |
---|
72 | class Absorb(wx.Frame): |
---|
73 | ''' ''' |
---|
74 | Elems = [] |
---|
75 | Wave = 1.5405 #CuKa default |
---|
76 | Kev = 12.397639 #keV for 1A x-rays |
---|
77 | for arg in sys.argv: |
---|
78 | if '-w' in arg: |
---|
79 | Wave = float(arg.split('-w')[1]) |
---|
80 | elif '-e' in arg: |
---|
81 | E = float(arg.split('-e')[1]) |
---|
82 | Wave = Kev/E |
---|
83 | elif '-h' in arg: |
---|
84 | print (''' |
---|
85 | Absorb.py can take the following arguments: |
---|
86 | -h - this help listing |
---|
87 | -wv - set default wavelength to v, e.g. -w1.54 sets wavelength to 1.54A |
---|
88 | -ev - set default energy to v, e.g. -e27 sets energy to 27keV |
---|
89 | without arguments Absorb uses CuKa as default (Wave=1.54052A, E=8.0478keV) |
---|
90 | ''') |
---|
91 | sys.exit() |
---|
92 | Wmin = 0.05 #wavelength range |
---|
93 | Wmax = 3.0 |
---|
94 | Wres = 0.004094 #plot resolution step size as const delta-lam/lam - gives 1000 steps for Wmin to Wmax |
---|
95 | Eres = 1.5e-4 #typical energy resolution for synchrotron x-ray sources |
---|
96 | Energy = Kev/Wave |
---|
97 | ifWave = True |
---|
98 | Volume = 0 |
---|
99 | ifVol = False |
---|
100 | Zcell = 1 |
---|
101 | Pack = 0.50 |
---|
102 | Radius = 0.4 |
---|
103 | def _init_coll_ABOUT_Items(self, parent): |
---|
104 | |
---|
105 | parent.Append(wxID_ABSORBABOUT,'About') |
---|
106 | self.Bind(wx.EVT_MENU, self.OnABOUTItems0Menu, id=wxID_ABSORBABOUT) |
---|
107 | |
---|
108 | def _init_coll_menuBar1_Menus(self, parent): |
---|
109 | |
---|
110 | parent.Append(menu=self.ABSORB, title='Absorb') |
---|
111 | parent.Append(menu=self.KALPHA, title='Kalpha') |
---|
112 | parent.Append(menu=self.ABOUT, title='About') |
---|
113 | |
---|
114 | def _init_coll_KALPHA_Items(self, parent): |
---|
115 | "Set of characteristic radiation from sealed tube sources" |
---|
116 | def OnCrkaMenu(event): |
---|
117 | self.SetWaveEnergy(2.28962) |
---|
118 | |
---|
119 | def OnMnkaMenu(event): |
---|
120 | self.SetWaveEnergy(2.10174) |
---|
121 | |
---|
122 | def OnFekaMenu(event): |
---|
123 | self.SetWaveEnergy(1.93597) |
---|
124 | |
---|
125 | def OnCokaMenu(event): |
---|
126 | self.SetWaveEnergy(1.78896) |
---|
127 | |
---|
128 | def OnNikaMenu(event): |
---|
129 | self.SetWaveEnergy(1.65784) |
---|
130 | |
---|
131 | def OnCukaMenu(event): |
---|
132 | self.SetWaveEnergy(1.54052) |
---|
133 | |
---|
134 | def OnZnkaMenu(event): |
---|
135 | self.SetWaveEnergy(1.43510) |
---|
136 | |
---|
137 | def OnMokaMenu(event): |
---|
138 | self.SetWaveEnergy(0.70926) |
---|
139 | |
---|
140 | def OnAgkaMenu(event): |
---|
141 | self.SetWaveEnergy(0.55936) |
---|
142 | |
---|
143 | parent.Append(wxID_KALPHACRKA, 'CrKa') |
---|
144 | parent.Append(wxID_KALPHAMNKA, 'MnKa') |
---|
145 | parent.Append(wxID_KALPHAFEKA, 'FeKa') |
---|
146 | parent.Append(wxID_KALPHACOKA, 'CoKa') |
---|
147 | parent.Append(wxID_KALPHANIKA, 'NiKa') |
---|
148 | parent.Append(wxID_KALPHACUKA, 'CuKa') |
---|
149 | parent.Append(wxID_KALPHAZNKA, 'ZnKa') |
---|
150 | parent.Append(wxID_KALPHAMOKA, 'MoKa') |
---|
151 | parent.Append(wxID_KALPHAAGKA, 'AgKa') |
---|
152 | self.Bind(wx.EVT_MENU, OnCrkaMenu, id=wxID_KALPHACRKA) |
---|
153 | self.Bind(wx.EVT_MENU, OnMnkaMenu, id=wxID_KALPHAMNKA) |
---|
154 | self.Bind(wx.EVT_MENU, OnFekaMenu, id=wxID_KALPHAFEKA) |
---|
155 | self.Bind(wx.EVT_MENU, OnCokaMenu, id=wxID_KALPHACOKA) |
---|
156 | self.Bind(wx.EVT_MENU, OnNikaMenu, id=wxID_KALPHANIKA) |
---|
157 | self.Bind(wx.EVT_MENU, OnCukaMenu, id=wxID_KALPHACUKA) |
---|
158 | self.Bind(wx.EVT_MENU, OnZnkaMenu, id=wxID_KALPHAZNKA) |
---|
159 | self.Bind(wx.EVT_MENU, OnMokaMenu, id=wxID_KALPHAMOKA) |
---|
160 | self.Bind(wx.EVT_MENU, OnAgkaMenu, id=wxID_KALPHAAGKA) |
---|
161 | |
---|
162 | def _init_coll_ABSORB_Items(self, parent): |
---|
163 | parent.Append(wxID_NEW,'&New Element','Add new element') |
---|
164 | self.Delete = parent.Append(wxID_DELETE,'&Delete Element','Delete an element') |
---|
165 | self.Delete.Enable(False) |
---|
166 | parent.Append(wxID_EXIT,'&Exit','Exit Fprime') |
---|
167 | self.Bind(wx.EVT_MENU, self.OnExitMenu, id=wxID_EXIT) |
---|
168 | self.Bind(wx.EVT_MENU, self.OnNewMenu, id=wxID_NEW) |
---|
169 | self.Bind(wx.EVT_MENU, self.OnDeleteMenu, id=wxID_DELETE) |
---|
170 | |
---|
171 | def _init_utils(self): |
---|
172 | self.ABSORB = wx.Menu(title='') |
---|
173 | |
---|
174 | self.KALPHA = wx.Menu(title='') |
---|
175 | self.KALPHA.SetEvtHandlerEnabled(True) |
---|
176 | |
---|
177 | self.ABOUT = wx.Menu(title='') |
---|
178 | |
---|
179 | self.menuBar1 = wx.MenuBar() |
---|
180 | |
---|
181 | self._init_coll_ABSORB_Items(self.ABSORB) |
---|
182 | self._init_coll_KALPHA_Items(self.KALPHA) |
---|
183 | self._init_coll_ABOUT_Items(self.ABOUT) |
---|
184 | self._init_coll_menuBar1_Menus(self.menuBar1) |
---|
185 | |
---|
186 | def _init_ctrls(self, parent): |
---|
187 | wx.Frame.__init__(self, parent=parent, |
---|
188 | size=wx.Size(500, 400),style=wx.DEFAULT_FRAME_STYLE ^ wx.CLOSE_BOX, title='Absorb') |
---|
189 | self._init_utils() |
---|
190 | self.SetMenuBar(self.menuBar1) |
---|
191 | self.DrawPanel() |
---|
192 | |
---|
193 | def SetSize(self): |
---|
194 | w,h = self.GetClientSize() |
---|
195 | self.panel.SetSize(wx.Size(w,h)) |
---|
196 | |
---|
197 | def DrawPanel(self): |
---|
198 | self.panel = wx.Panel(self) |
---|
199 | |
---|
200 | mainSizer = wx.BoxSizer(wx.VERTICAL) |
---|
201 | self.Results = wx.TextCtrl( parent=self.panel, |
---|
202 | style=wx.TE_MULTILINE|wx.TE_DONTWRAP ) |
---|
203 | self.Results.SetEditable(False) |
---|
204 | mainSizer.Add(self.Results,1,wx.EXPAND) |
---|
205 | mainSizer.Add((10,15),0) |
---|
206 | |
---|
207 | if self.Elems: |
---|
208 | lablSizer = wx.BoxSizer(wx.HORIZONTAL) |
---|
209 | lablSizer.Add((5,10),0) |
---|
210 | lablSizer.Add(wx.StaticText(parent=self.panel,label='Chemical Formula:'),0, |
---|
211 | wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT) |
---|
212 | mainSizer.Add(lablSizer,0) |
---|
213 | mainSizer.Add((5,5),0) |
---|
214 | nRow = len(self.Elems)/5 |
---|
215 | compSizer = wx.FlexGridSizer(nRow+1,10,0,0) |
---|
216 | for Elem in self.Elems: |
---|
217 | compSizer.Add(wx.StaticText(parent=self.panel,label=" "+Elem[0].capitalize(), |
---|
218 | size=wx.Size(30,20)),0,wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_RIGHT) |
---|
219 | numElem = wx.TextCtrl(id=wxID_NUMELEM,parent=self.panel,name=Elem[0], |
---|
220 | size=wx.Size(70,20),value="%.2f" % (Elem[2]),style=wx.TE_PROCESS_ENTER) |
---|
221 | compSizer.Add(numElem,0) |
---|
222 | numElem.Bind(wx.EVT_TEXT_ENTER, self.OnNumElem, id=wxID_NUMELEM) |
---|
223 | mainSizer.Add(compSizer,0) |
---|
224 | mainSizer.Add((10,15),0) |
---|
225 | |
---|
226 | selSizer = wx.BoxSizer(wx.HORIZONTAL) |
---|
227 | selSizer.Add((5,10),0) |
---|
228 | selSizer.Add(wx.StaticText(parent=self.panel, label='Wavelength:'),0,wx.EXPAND) |
---|
229 | selSizer.Add((5,10),0) |
---|
230 | self.SpinText1 = wx.TextCtrl(id=wxID_SPINTEXT1, parent=self.panel, |
---|
231 | size=wx.Size(100,20), value = "%.4f" % (self.Wave),style=wx.TE_PROCESS_ENTER ) |
---|
232 | selSizer.Add(self.SpinText1,0) |
---|
233 | selSizer.Add((5,10),0) |
---|
234 | self.SpinText1.Bind(wx.EVT_TEXT_ENTER, self.OnSpinText1, id=wxID_SPINTEXT1) |
---|
235 | |
---|
236 | selSizer.Add(wx.StaticText(parent=self.panel, label='Energy:'),0,wx.EXPAND) |
---|
237 | selSizer.Add((5,10),0) |
---|
238 | self.SpinText2 = wx.TextCtrl(id=wxID_SPINTEXT2, parent=self.panel, |
---|
239 | size=wx.Size(100,20), value = "%.4f" % (self.Energy),style=wx.TE_PROCESS_ENTER) |
---|
240 | selSizer.Add(self.SpinText2,0) |
---|
241 | selSizer.Add((5,10),0) |
---|
242 | self.SpinText2.Bind(wx.EVT_TEXT_ENTER, self.OnSpinText2, id=wxID_SPINTEXT2) |
---|
243 | |
---|
244 | selSizer.Add(wx.StaticText(parent=self.panel, label='Plot scale:'),0,wx.EXPAND) |
---|
245 | selSizer.Add((5,10),0) |
---|
246 | self.choice1 = wx.ComboBox(id=wxID_CHOICE1, parent=self.panel, value='Wavelength', |
---|
247 | choices=['Wavelength','Energy'],style=wx.CB_READONLY|wx.CB_DROPDOWN) |
---|
248 | selSizer.Add(self.choice1,0) |
---|
249 | selSizer.Add((10,10),0) |
---|
250 | self.choice1.Bind(wx.EVT_COMBOBOX, self.OnChoice1, id=wxID_CHOICE1) |
---|
251 | mainSizer.Add(selSizer,0) |
---|
252 | mainSizer.Add((10,10),0) |
---|
253 | |
---|
254 | slideSizer = wx.BoxSizer(wx.HORIZONTAL) |
---|
255 | self.SpinButton = wx.SpinButton(id=wxID_SPINBUTTON, parent=self.panel, |
---|
256 | size=wx.Size(25,24), style=wx.SP_VERTICAL | wx.SP_ARROW_KEYS) |
---|
257 | slideSizer.Add(self.SpinButton,0,wx.ALIGN_RIGHT) |
---|
258 | self.SpinButton.SetRange(-1,1) |
---|
259 | self.SpinButton.SetValue(0) |
---|
260 | self.SpinButton.Bind(wx.EVT_SPIN, self.OnSpinButton, id=wxID_SPINBUTTON) |
---|
261 | |
---|
262 | self.slider1 = wx.Slider(id=wxID_SLIDER1, maxValue=int(1000.*self.Wmax), |
---|
263 | minValue=int(1000.*self.Wmin), parent=self.panel,style=wx.SL_HORIZONTAL, |
---|
264 | value=int(self.Wave*1000.), ) |
---|
265 | slideSizer.Add(self.slider1,1,wx.EXPAND) |
---|
266 | self.slider1.Bind(wx.EVT_SLIDER, self.OnSlider1, id=wxID_SLIDER1) |
---|
267 | mainSizer.Add(slideSizer,0,wx.EXPAND) |
---|
268 | mainSizer.Add((10,10),0) |
---|
269 | |
---|
270 | cellSizer = wx.BoxSizer(wx.HORIZONTAL) |
---|
271 | cellSizer.Add((5,10),0) |
---|
272 | cellSizer.Add(wx.StaticText(parent=self.panel, label='Volume:'),0,wx.EXPAND) |
---|
273 | cellSizer.Add((5,10),0) |
---|
274 | self.SpinText3 = wx.TextCtrl(id=wxID_SPINTEXT3, parent=self.panel, |
---|
275 | size=wx.Size(100,20), value = "%.2f" % (self.Volume),style=wx.TE_PROCESS_ENTER ) |
---|
276 | cellSizer.Add(self.SpinText3,0) |
---|
277 | cellSizer.Add((5,10),0) |
---|
278 | self.SpinText3.Bind(wx.EVT_TEXT_ENTER, self.OnSpinText3, id=wxID_SPINTEXT3) |
---|
279 | |
---|
280 | cellSizer.Add((5,10),0) |
---|
281 | cellSizer.Add(wx.StaticText(parent=self.panel, label='Z(vol):'),0,wx.EXPAND) |
---|
282 | cellSizer.Add((5,10),0) |
---|
283 | self.SpinText4 = wx.TextCtrl(id=wxID_SPINTEXT4, parent=self.panel, |
---|
284 | size=wx.Size(50,20), value = "%d" % (self.Zcell),style=wx.TE_PROCESS_ENTER ) |
---|
285 | cellSizer.Add(self.SpinText4,0) |
---|
286 | cellSizer.Add((5,10),0) |
---|
287 | self.SpinText4.Bind(wx.EVT_TEXT_ENTER, self.OnSpinText4, id=wxID_SPINTEXT4) |
---|
288 | |
---|
289 | cellSizer.Add((5,10),0) |
---|
290 | cellSizer.Add(wx.StaticText(parent=self.panel, label='Sample R:'),0,wx.EXPAND) |
---|
291 | cellSizer.Add((5,10),0) |
---|
292 | self.SpinText5 = wx.TextCtrl(id=wxID_SPINTEXT5, parent=self.panel, |
---|
293 | size=wx.Size(50,20), value = "%.2f" % (self.Radius),style=wx.TE_PROCESS_ENTER ) |
---|
294 | cellSizer.Add(self.SpinText5,0) |
---|
295 | cellSizer.Add((5,10),0) |
---|
296 | self.SpinText5.Bind(wx.EVT_TEXT_ENTER, self.OnSpinText5, id=wxID_SPINTEXT5) |
---|
297 | |
---|
298 | cellSizer.Add((5,10),0) |
---|
299 | cellSizer.Add(wx.StaticText(parent=self.panel, label='packing:'),0,wx.EXPAND) |
---|
300 | cellSizer.Add((5,10),0) |
---|
301 | self.SpinText6 = wx.TextCtrl(id=wxID_SPINTEXT6, parent=self.panel, |
---|
302 | size=wx.Size(50,20), value = "%.2f" % (self.Pack),style=wx.TE_PROCESS_ENTER ) |
---|
303 | cellSizer.Add(self.SpinText6,0) |
---|
304 | cellSizer.Add((5,10),0) |
---|
305 | self.SpinText6.Bind(wx.EVT_TEXT_ENTER, self.OnSpinText6, id=wxID_SPINTEXT6) |
---|
306 | |
---|
307 | mainSizer.Add(cellSizer,0) |
---|
308 | mainSizer.Add((10,10),0) |
---|
309 | self.panel.SetSizer(mainSizer) |
---|
310 | self.panel.Fit() |
---|
311 | self.panel.GetParent().SetSize() |
---|
312 | |
---|
313 | def __init__(self, parent): |
---|
314 | self._init_ctrls(parent) |
---|
315 | self.parent = parent |
---|
316 | self.Lines = [] |
---|
317 | self.Elems = [] |
---|
318 | self.linePicked = None |
---|
319 | |
---|
320 | def OnExitMenu(self, event): |
---|
321 | self.parent.G2plotNB.Delete('Absorb') |
---|
322 | self.Close() |
---|
323 | self.Destroy() |
---|
324 | |
---|
325 | def OnNewMenu(self, event): |
---|
326 | ElList = [] |
---|
327 | for Elem in self.Elems: ElList.append(Elem[0]) |
---|
328 | PE = G2elemGUI.PickElements(self,ElList) |
---|
329 | if PE.ShowModal() == wx.ID_OK: |
---|
330 | Elem = PE.Elem |
---|
331 | PE.Destroy() |
---|
332 | if Elem: |
---|
333 | for El in Elem: |
---|
334 | ElemSym = El.strip().upper() |
---|
335 | if ElemSym not in ElList: |
---|
336 | atomData = G2elem.GetAtomInfo(ElemSym.capitalize()) |
---|
337 | FormFactors = G2elem.GetFormFactorCoeff(ElemSym) |
---|
338 | for FormFac in FormFactors: |
---|
339 | FormSym = FormFac['Symbol'].strip() |
---|
340 | if FormSym == ElemSym: |
---|
341 | Z = FormFac['Z'] #At. No. |
---|
342 | N = 1. #no atoms / formula unit |
---|
343 | Orbs = G2elem.GetXsectionCoeff(ElemSym) |
---|
344 | Elem = [ElemSym,Z,N,FormFac,Orbs,atomData] |
---|
345 | self.Elems.append(Elem) |
---|
346 | self.Delete.Enable(True) |
---|
347 | self.panel.Destroy() |
---|
348 | self.DrawPanel() |
---|
349 | self.NewFPPlot = True |
---|
350 | self.SetWaveEnergy(self.Wave) |
---|
351 | |
---|
352 | def OnDeleteMenu(self, event): |
---|
353 | if len(self.Elems): |
---|
354 | ElList = [] |
---|
355 | for Elem in self.Elems: ElList.append(Elem[0]) |
---|
356 | S = [] |
---|
357 | DE = G2elemGUI.DeleteElement(self,ElList) |
---|
358 | if DE.ShowModal() == wx.ID_OK: |
---|
359 | El = DE.GetDeleteElement().strip().upper() |
---|
360 | for Elem in self.Elems: |
---|
361 | if Elem[0] != El: |
---|
362 | S.append(Elem) |
---|
363 | self.Elems = S |
---|
364 | self.CalcFPPS() |
---|
365 | if not self.Elems: |
---|
366 | self.Delete.Enable(False) |
---|
367 | self.panel.Destroy() |
---|
368 | self.DrawPanel() |
---|
369 | self.NewFPPlot = True |
---|
370 | self.SetWaveEnergy(self.Wave) |
---|
371 | |
---|
372 | def OnNumElem(self, event): |
---|
373 | for Elem in self.Elems: |
---|
374 | if event.GetEventObject().GetName() == Elem[0]: |
---|
375 | Elem[2] = float(event.GetEventObject().GetValue()) |
---|
376 | event.GetEventObject().SetValue("%8.2f" % (Elem[2])) |
---|
377 | self.SetWaveEnergy(self.Wave) |
---|
378 | |
---|
379 | def OnSpinText1(self, event): |
---|
380 | self.SetWaveEnergy(float(self.SpinText1.GetValue())) |
---|
381 | |
---|
382 | def OnSpinText2(self, event): |
---|
383 | self.SetWaveEnergy(self.Kev/(float(self.SpinText2.GetValue()))) |
---|
384 | |
---|
385 | def OnSpinText3(self,event): |
---|
386 | self.Volume = max(10.,float(self.SpinText3.GetValue())) |
---|
387 | self.ifVol = True |
---|
388 | self.SetWaveEnergy(self.Wave) |
---|
389 | |
---|
390 | def OnSpinText4(self,event): |
---|
391 | self.Zcell = max(1,float(self.SpinText4.GetValue())) |
---|
392 | self.SetWaveEnergy(self.Wave) |
---|
393 | |
---|
394 | def OnSpinText5(self, event): |
---|
395 | self.Radius = max(0.01,float(self.SpinText5.GetValue())) |
---|
396 | self.SetWaveEnergy(self.Wave) |
---|
397 | |
---|
398 | def OnSpinText6(self, event): |
---|
399 | self.Pack = min(1.0,max(0.01,float(self.SpinText6.GetValue()))) |
---|
400 | self.SetWaveEnergy(self.Wave) |
---|
401 | |
---|
402 | def OnSpinButton(self, event): |
---|
403 | move = self.SpinButton.GetValue()/10000. |
---|
404 | self.Wave = min(max(self.Wave+move,self.Wmin),self.Wmax) |
---|
405 | self.SpinButton.SetValue(0) |
---|
406 | self.SetWaveEnergy(self.Wave) |
---|
407 | |
---|
408 | def OnSlider1(self, event): |
---|
409 | if self.ifWave: |
---|
410 | Wave = float(self.slider1.GetValue())/1000. |
---|
411 | else: |
---|
412 | Wave = self.Kev/(float(self.slider1.GetValue())/1000.) |
---|
413 | self.SetWaveEnergy(Wave) |
---|
414 | |
---|
415 | def SetWaveEnergy(self,Wave): |
---|
416 | self.Wave = Wave |
---|
417 | self.Energy = self.Kev/self.Wave |
---|
418 | self.Energy = round(self.Energy,4) |
---|
419 | E = self.Energy |
---|
420 | DE = E*self.Eres #smear by defined source resolution |
---|
421 | self.SpinText1.SetValue("%.4f" % (self.Wave)) |
---|
422 | self.SpinText2.SetValue("%.4f" % (self.Energy)) |
---|
423 | self.SpinText1.Update() |
---|
424 | self.SpinText2.Update() |
---|
425 | if self.ifWave: |
---|
426 | self.slider1.SetValue(int(1000.*self.Wave)) |
---|
427 | else: |
---|
428 | self.slider1.SetValue(int(1000.*self.Energy)) |
---|
429 | Text = '' |
---|
430 | if not self.ifVol: |
---|
431 | self.Volume = 0 |
---|
432 | for Elem in self.Elems: |
---|
433 | self.Volume += 10.*Elem[2] |
---|
434 | muT = 0 |
---|
435 | Mass = 0 |
---|
436 | Fo = 0 |
---|
437 | Fop = 0 |
---|
438 | for Elem in self.Elems: |
---|
439 | Mass += self.Zcell*Elem[2]*Elem[5]['Mass'] |
---|
440 | r1 = G2elem.FPcalc(Elem[4],E+DE) |
---|
441 | r2 = G2elem.FPcalc(Elem[4],E-DE) |
---|
442 | Els = Elem[0] |
---|
443 | Els = Els.ljust(2).lower().capitalize() |
---|
444 | mu = 0 |
---|
445 | Fo += Elem[2]*Elem[1] |
---|
446 | if Elem[1] > 78 and self.Energy+DE > self.Kev/0.16: |
---|
447 | mu = self.Zcell*Elem[2]*(r1[2]+r2[2])/2.0 |
---|
448 | Text += "%s\t%s%8.2f %s%6s %s%6.3f %s%10.2f %s\n" % ( |
---|
449 | 'Element= '+str(Els),"N = ",Elem[2]," f'=",'not valid', |
---|
450 | ' f"=',(r1[1]+r2[1])/2.0,' '+Gkmu+'=',mu,'barns') |
---|
451 | elif Elem[1] > 94 and self.Energy-DE < self.Kev/2.67: |
---|
452 | mu = 0 |
---|
453 | Text += "%s\t%s%8.2f %s%6s %s%6s %s%10s%s\n" % ( |
---|
454 | 'Element= '+str(Els),"N = ",Elem[2]," f'=",'not valid', |
---|
455 | ' f"=','not valid',' '+Gkmu+'=','not valid') |
---|
456 | else: |
---|
457 | mu = self.Zcell*Elem[2]*(r1[2]+r2[2])/2.0 |
---|
458 | Fop += Elem[2]*(Elem[1]+(r1[0]+r2[0])/2.0) |
---|
459 | Text += "%s\t%s%8.2f %s%6.3f %s%6.3f %s%10.2f %s\n" % ( |
---|
460 | 'Element= '+str(Els),"N = ",Elem[2]," f'=",(r1[0]+r2[0])/2.0, |
---|
461 | ' f"=',(r1[1]+r2[1])/2.0,' '+Gkmu+'=',mu,'barns') |
---|
462 | muT += mu |
---|
463 | |
---|
464 | if self.Volume: |
---|
465 | Text += "%s %s%10.4g %s" % ("Total",' '+Gkmu+'=',self.Pack*muT/self.Volume,'cm'+Pwrm1+', ') |
---|
466 | Text += "%s%10.4g%s" % ('Total '+Gkmu+'R=',self.Radius*self.Pack*muT/(10.0*self.Volume),', ') |
---|
467 | Text += "%s%10.4f%s\n" % ('Transmission exp(-2'+Gkmu+'R)=', \ |
---|
468 | 100.0*math.exp(-2*self.Radius*self.Pack*muT/(10.0*self.Volume)),'%') |
---|
469 | self.Results.SetValue(Text) |
---|
470 | den = Mass/(0.602*self.Volume) |
---|
471 | if self.ifVol: |
---|
472 | Text += '%s' % ('Theor. density=') |
---|
473 | else: |
---|
474 | Text += '%s' % ('Est. density=') |
---|
475 | Text += '%6.3f %s%.3f %s\n' % (den,'g/cm'+Pwr3+', Powder density=',self.Pack*den,'g/cm'+Pwr3) |
---|
476 | Text += '%s%10.2f%s\n'%('X-ray small angle scattering contrast',(28.179*Fo/self.Volume)**2,'*10'+Pwr20+'/cm'+Pwr4) |
---|
477 | if Fop: |
---|
478 | Text += '%s%10.2f%s\n'%('Anomalous X-ray small angle scattering contrast',(28.179*Fop/self.Volume)**2,'*10'+Pwr20+'/cm'+Pwr4) |
---|
479 | self.Results.SetValue(Text) |
---|
480 | self.Results.Update() |
---|
481 | self.SpinText3.SetValue("%.2f" % (self.Volume)) |
---|
482 | self.SpinText3.Update() |
---|
483 | self.SpinText4.SetValue("%d" % (self.Zcell)) |
---|
484 | self.SpinText4.Update() |
---|
485 | self.SpinText5.SetValue("%.2f" % (self.Radius)) |
---|
486 | self.SpinText5.Update() |
---|
487 | self.SpinText6.SetValue("%.2f" % (self.Pack)) |
---|
488 | self.SpinText6.Update() |
---|
489 | if len(self.Elems): |
---|
490 | self.CalcFPPS() |
---|
491 | self.UpDateAbsPlot(Wave,rePlot=True) |
---|
492 | |
---|
493 | def CalcFPPS(self): |
---|
494 | """generate f" curves for selected elements |
---|
495 | does constant delta-lambda/lambda steps over defined range |
---|
496 | """ |
---|
497 | FPPS = [] |
---|
498 | if self.Elems: |
---|
499 | wx.BeginBusyCursor() |
---|
500 | Corr = self.Zcell*self.Radius*self.Pack/(10.0*self.Volume) |
---|
501 | try: |
---|
502 | muT = [] |
---|
503 | for iE,Elem in enumerate(self.Elems): |
---|
504 | Els = Elem[0] |
---|
505 | Els = Els = Els.ljust(2).lower().capitalize() |
---|
506 | Wmin = self.Wmin |
---|
507 | Wmax = self.Wmax |
---|
508 | lWmin = math.log(Wmin) |
---|
509 | N = int(round(math.log(Wmax/Wmin)/self.Wres)) #number of constant delta-lam/lam steps |
---|
510 | I = range(N+1) |
---|
511 | Ws = [] |
---|
512 | for i in I: Ws.append(math.exp(i*self.Wres+lWmin)) |
---|
513 | mus = [] |
---|
514 | Es = [] |
---|
515 | for j,W in enumerate(Ws): |
---|
516 | E = self.Kev/W |
---|
517 | DE = E*self.Eres #smear by defined source resolution |
---|
518 | res1 = G2elem.FPcalc(Elem[4],E+DE) |
---|
519 | res2 = G2elem.FPcalc(Elem[4],E-DE) |
---|
520 | muR = Corr*Elem[2]*(res1[2]+res2[2])/2.0 |
---|
521 | mus.append(muR) |
---|
522 | if iE: |
---|
523 | muT[j] += muR |
---|
524 | else: |
---|
525 | muT.append(muR) |
---|
526 | Es.append(E) |
---|
527 | if self.ifWave: |
---|
528 | Fpps = (Els,Ws,mus) |
---|
529 | else: |
---|
530 | Fpps = (Els,Es,mus) |
---|
531 | FPPS.append(Fpps) |
---|
532 | if self.ifWave: |
---|
533 | Fpps = ('Total',Ws,muT) |
---|
534 | else: |
---|
535 | Fpps = ('Total',Es,muT) |
---|
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.SpinText1.SetValue("%6.4f" % (self.Wave)) |
---|
549 | self.SpinText2.SetValue("%7.4f" % (self.Energy)) |
---|
550 | else: |
---|
551 | self.ifWave = False |
---|
552 | self.NewFPPlot = True |
---|
553 | Emin = self.Kev/self.Wmax |
---|
554 | Emax = self.Kev/self.Wmin |
---|
555 | self.Energy = round(self.Energy,4) |
---|
556 | self.slider1.SetRange(int(1000.*Emin),int(1000.*Emax)) |
---|
557 | self.slider1.SetValue(int(1000.*self.Energy)) |
---|
558 | self.SpinText1.SetValue("%6.4f" % (self.Wave)) |
---|
559 | self.SpinText2.SetValue("%7.4f" % (self.Energy)) |
---|
560 | if len(self.Elems): |
---|
561 | self.CalcFPPS() |
---|
562 | self.UpDateAbsPlot(self.Wave,rePlot=False) |
---|
563 | |
---|
564 | def OnKeyPress(self,event): |
---|
565 | if event.key == 'g': |
---|
566 | mpl.rcParams['axes.grid'] = not mpl.rcParams['axes.grid'] |
---|
567 | self.UpDateAbsPlot(self.Wave,rePlot=False) |
---|
568 | |
---|
569 | def UpDateAbsPlot(self,Wave,rePlot=True): |
---|
570 | """Plot mu vs wavelength 0.05-3.0A""" |
---|
571 | xylim = [] |
---|
572 | try: |
---|
573 | if rePlot: |
---|
574 | asb = self.Page.figure.get_axes()[1] |
---|
575 | xylim = asb.get_xlim(),asb.get_ylim() |
---|
576 | newPlot = False |
---|
577 | except: |
---|
578 | new,plotNum,self.Page,self.fplot,lim = self.parent.G2plotNB.FindPlotTab('Absorb','mpl') |
---|
579 | self.Page.canvas.mpl_connect('pick_event', self.OnPick) |
---|
580 | self.Page.canvas.mpl_connect('button_release_event', self.OnRelease) |
---|
581 | self.Page.canvas.mpl_connect('motion_notify_event', self.OnMotion) |
---|
582 | self.Page.canvas.mpl_connect('key_press_event', self.OnKeyPress) |
---|
583 | newPlot = True |
---|
584 | self.ax = self.Page.figure.add_subplot(111,label='absorb') |
---|
585 | self.fplot.set_visible(False) |
---|
586 | self.Page.Choice = (' key press','g: toggle grid',) |
---|
587 | self.Page.keyPress = self.OnKeyPress |
---|
588 | self.ax.clear() |
---|
589 | self.ax.set_title('X-Ray Absorption',x=0,ha='left') |
---|
590 | self.ax.set_ylabel(r"$\mu R$",fontsize=14) |
---|
591 | Ymin = 0.0 |
---|
592 | Ymax = 0.0 |
---|
593 | if self.FPPS: |
---|
594 | for Fpps in self.FPPS: |
---|
595 | Ymin = min(Ymin,min(Fpps[2])) |
---|
596 | Ymax = max(Ymax,max(Fpps[2])) |
---|
597 | fppsP1 = np.array(Fpps[1]) |
---|
598 | fppsP2 = np.array(Fpps[2]) |
---|
599 | self.ax.plot(fppsP1,fppsP2,label=r'$\mu R$ '+Fpps[0]) |
---|
600 | if self.ifWave: |
---|
601 | self.ax.set_xlabel(r'$\mathsf{\lambda, \AA}$',fontsize=14) |
---|
602 | self.ax.axvline(x=Wave,picker=3,color='black') |
---|
603 | else: |
---|
604 | self.ax.set_xlabel(r'$\mathsf{E, keV}$',fontsize=14) |
---|
605 | self.ax.set_xscale('log') |
---|
606 | self.ax.axvline(x=self.Kev/Wave,picker=3,color='black') |
---|
607 | self.ax.axhline(y=1.0,color='b') |
---|
608 | self.ax.axhline(y=5.0,color='r') |
---|
609 | self.ax.set_ylim(Ymin,Ymax) |
---|
610 | if self.FPPS: |
---|
611 | self.ax.legend(loc='best') |
---|
612 | if newPlot: |
---|
613 | newPlot = False |
---|
614 | self.Page.canvas.draw() |
---|
615 | else: |
---|
616 | if rePlot: |
---|
617 | tb = self.Page.canvas.toolbar |
---|
618 | tb.push_current() |
---|
619 | self.ax.set_xlim(xylim[0]) |
---|
620 | self.ax.set_ylim(xylim[1]) |
---|
621 | xylim = [] |
---|
622 | tb.push_current() |
---|
623 | self.Page.canvas.draw() |
---|
624 | |
---|
625 | def OnPick(self, event): |
---|
626 | self.linePicked = event.artist |
---|
627 | |
---|
628 | def OnMotion(self,event): |
---|
629 | xpos = event.xdata |
---|
630 | if xpos and xpos>0.1: |
---|
631 | ypos = event.ydata |
---|
632 | if self.ifWave: |
---|
633 | Wave = xpos |
---|
634 | else: |
---|
635 | Wave = self.Kev/xpos |
---|
636 | Wave = min(max(Wave,self.Wmin),self.Wmax) |
---|
637 | self.parent.G2plotNB.status.SetStatusText('Wavelength: %.4f, Energy: %.3f, %sR: %.3f'%(Wave,self.Kev/Wave,Gkmu,ypos),1) |
---|
638 | if self.linePicked: |
---|
639 | self.SetWaveEnergy(Wave) |
---|
640 | |
---|
641 | def OnRelease(self, event): |
---|
642 | if self.linePicked is None: return |
---|
643 | self.linePicked = None |
---|
644 | xpos = event.xdata |
---|
645 | if xpos: |
---|
646 | if self.ifWave: |
---|
647 | Wave = xpos |
---|
648 | else: |
---|
649 | Wave = self.Kev/xpos |
---|
650 | self.SetWaveEnergy(Wave) |
---|
651 | |
---|
652 | def OnABOUTItems0Menu(self, event): |
---|
653 | ''' ''' |
---|
654 | try: |
---|
655 | import wx.adv as wxadv # AboutBox moved here in Phoenix |
---|
656 | except: |
---|
657 | wxadv = wx |
---|
658 | info = wxadv.AboutDialogInfo() |
---|
659 | info.Name = 'Absorb' |
---|
660 | info.Copyright = ''' |
---|
661 | Robert B. Von Dreele, 2009(C) |
---|
662 | Argonne National Laboratory |
---|
663 | This product includes software developed |
---|
664 | by the UChicago Argonne, LLC, as |
---|
665 | Operator of Argonne National Laboratory. ''' |
---|
666 | info.Description = ''' |
---|
667 | For calculating X-ray absorption factors to 250keV for cylindrical |
---|
668 | powder samples; based on Fortran program Fprime of Cromer & Liberman |
---|
669 | (D. T. Cromer and D. A. Liberman, Acta Cryst. (1981). A37, 267-268.) |
---|
670 | corrected for Kissel & Pratt energy term; Jensen term not included |
---|
671 | ''' |
---|
672 | wxadv.AboutBox(info) |
---|
673 | |
---|