source: trunk/Absorb.py

Last change on this file was 4830, checked in by vondreele, 19 months ago

show more places in Absorb output
improve image absorption calcs for cylinders now seems to work OK
reorganize Image controls GUI & add option for vertical samples
hide printing of LS cycles if Rrint=False in HessianLSQ
implement (& not use) Klein-Nishina PDF correction
Fix bug in if importer

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Author Revision URL Id
File size: 26.6 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 matplotlib as mpl
13import GSASIIpath
14GSASIIpath.SetVersionNumber("$Revision: 4830 $")
15import GSASIIElem as G2elem
16import GSASIIElemGUI as G2elemGUI
17
18try:
19    wx.NewIdRef
20    wx.NewId = wx.NewIdRef
21except AttributeError:
22    pass
23
24if '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
41else:
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
72class 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 ('''
85Absorb.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
89without 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 = '''
661Robert B. Von Dreele, 2009(C)
662Argonne National Laboratory
663This product includes software developed
664by the UChicago Argonne, LLC, as
665Operator of Argonne National Laboratory.        '''
666        info.Description = '''
667For calculating X-ray absorption factors to 250keV for cylindrical     
668powder samples; based on Fortran program Fprime of Cromer & Liberman
669(D. T. Cromer and D. A. Liberman, Acta Cryst. (1981). A37, 267-268.)
670corrected for Kissel & Pratt energy term; Jensen term not included
671        '''
672        wxadv.AboutBox(info)
673
Note: See TracBrowser for help on using the repository browser.