source: trunk/Absorb.py @ 3967

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

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

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