source: trunk/Absorb.py @ 4830

Last change on this file since 4830 was 4830, checked in by vondreele, 3 years 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.