source: trunk/Absorb.py @ 3771

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

cleanup of fprime & absorb

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