source: sasview/sansview/perspectives/fitting/sldPanel.py @ 4faf4ba

ESS_GUIESS_GUI_DocsESS_GUI_batch_fittingESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_iss879ESS_GUI_iss959ESS_GUI_openclESS_GUI_orderingESS_GUI_sync_sascalccostrafo411magnetic_scattrelease-4.1.1release-4.1.2release-4.2.2release_4.0.1ticket-1009ticket-1094-headlessticket-1242-2d-resolutionticket-1243ticket-1249ticket885unittest-saveload
Last change on this file since 4faf4ba was 4faf4ba, checked in by Gervaise Alina <gervyh@…>, 15 years ago

sld calculator implemented using elements package

  • Property mode set to 100644
File size: 17.4 KB
Line 
1"""
2    This module intends to compute the neutron scattering length density of molecule
3    @author: Gervaise B. Alina
4"""
5
6import wx
7import sys
8
9import periodictable
10from periodictable import formula
11from periodictable.xsf import xray_energy, xray_sld_from_atoms
12from periodictable.constants import avogadro_number
13import periodictable.nsf
14neutron_sld_from_atoms= periodictable.nsf.neutron_sld_from_atoms
15
16from sans.guiframe.utils import format_number, check_float
17from sans.guicomm.events import StatusEvent 
18
19
20_BOX_WIDTH = 76
21_STATICBOX_WIDTH = 350
22_SCALE = 1e-6
23_DEFAULT_WAVELENGTH = 1.798
24
25
26class SldPanel(wx.Panel):
27    """
28        Provides the SLD calculator GUI.
29    """
30    def __init__(self, parent,base=None, id = -1):
31        wx.Panel.__init__(self, parent, id = id)
32        # Object that receive status event
33        self.base= base
34        self._do_layout()
35        self.SetAutoLayout(True)
36        self.Layout()
37       
38
39    def _do_layout(self):
40        """
41            Draw window content
42        """
43        sizer_input = wx.GridBagSizer(5,5)
44        sizer_output = wx.GridBagSizer(5,5)
45        sizer_button = wx.BoxSizer(wx.HORIZONTAL)
46        sizer1 = wx.BoxSizer(wx.HORIZONTAL)
47        sizer2 = wx.BoxSizer(wx.HORIZONTAL)
48        sizer3 = wx.BoxSizer(wx.HORIZONTAL)
49        #---------inputs----------------
50        inputbox = wx.StaticBox(self, -1, "Input")
51        boxsizer1 = wx.StaticBoxSizer(inputbox, wx.VERTICAL)
52        boxsizer1.SetMinSize((_STATICBOX_WIDTH,-1))
53       
54        compound_txt = wx.StaticText(self, -1, 'Compound')
55        self.compound_ctl = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,-1))
56        density_txt = wx.StaticText(self, -1, 'Density(g/cm^3)')
57        self.density_ctl = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,-1))
58        wavelength_txt = wx.StaticText(self, -1, 'Wavelength (A)')
59        self.wavelength_ctl = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,-1))
60        iy = 0
61        ix = 0
62        sizer_input.Add(compound_txt,(iy, ix),(1,1),\
63                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
64        ix +=1
65        sizer_input.Add(self.compound_ctl,(iy, ix),(1,1),\
66                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
67        iy += 1
68        ix = 0
69        sizer_input.Add(density_txt,(iy, ix),(1,1),\
70                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
71        ix +=1
72        sizer_input.Add(self.density_ctl,(iy, ix),(1,1),\
73                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
74        iy += 1
75        ix = 0
76        sizer_input.Add(wavelength_txt,(iy, ix),(1,1),\
77                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
78        ix +=1
79        sizer_input.Add(self.wavelength_ctl,(iy, ix),(1,1),\
80                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
81        boxsizer1.Add( sizer_input )
82        sizer1.Add(boxsizer1,0, wx.EXPAND | wx.ALL, 10)
83        #---------Outputs sizer--------
84        outputbox = wx.StaticBox(self, -1, "Output")
85        boxsizer2 = wx.StaticBoxSizer(outputbox, wx.VERTICAL)
86        boxsizer2.SetMinSize((_STATICBOX_WIDTH,-1))
87       
88        unit_a= '[A^(-2)]'
89        unit_cm1='[cm^(-1)]'
90        unit_cm='[cm]'
91        i_complex= '+ i'
92        neutron_sld_txt = wx.StaticText(self, -1, 'Neutron SLD')
93        self.neutron_sld_reel_ctl = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,-1))
94        self.neutron_sld_reel_ctl.SetEditable(False)
95        self.neutron_sld_reel_ctl.SetToolTipString("Neutron SLD reel.")
96        self.neutron_sld_im_ctl = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,-1))
97        self.neutron_sld_im_ctl.SetEditable(False)
98        self.neutron_sld_im_ctl.SetToolTipString("Neutron SLD imaginary.")
99        neutron_sld_units_txt = wx.StaticText(self, -1, unit_a)
100       
101        cu_ka_sld_txt = wx.StaticText(self, -1, 'Cu Ka SLD')
102        self.cu_ka_sld_reel_ctl = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,-1))
103        self.cu_ka_sld_reel_ctl.SetEditable(False)
104        self.cu_ka_sld_reel_ctl.SetToolTipString("Cu Ka SLD reel.")
105        self.cu_ka_sld_im_ctl = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,-1))
106        self.cu_ka_sld_im_ctl.SetEditable(False)
107        self.cu_ka_sld_im_ctl.SetToolTipString("Cu Ka SLD imaginary.")
108        cu_ka_sld_units_txt = wx.StaticText(self, -1, unit_a)
109       
110        mo_ka_sld_txt = wx.StaticText(self, -1, 'Mo Ka SLD')
111        self.mo_ka_sld_reel_ctl = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,-1))
112        self.mo_ka_sld_reel_ctl.SetEditable(False)
113        self.mo_ka_sld_reel_ctl.SetToolTipString("Mo Ka SLD reel.")
114        self.mo_ka_sld_im_ctl = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,-1))
115        self.mo_ka_sld_im_ctl.SetEditable(False)
116        self.mo_ka_sld_im_ctl.SetToolTipString("Mo Ka SLD reel.")
117        mo_ka_sld_units_txt = wx.StaticText(self, -1, unit_a)
118       
119        neutron_inc_txt = wx.StaticText(self, -1, 'Neutron Inc. Xs')
120        self.neutron_inc_ctl = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,-1))
121        self.neutron_inc_ctl.SetEditable(False)
122        self.neutron_inc_ctl.SetToolTipString("Neutron Inc. Xs")
123        neutron_inc_units_txt = wx.StaticText(self, -1,  unit_cm1)
124       
125        neutron_abs_txt = wx.StaticText(self, -1, 'Neutron Abs. Xs')
126        self.neutron_abs_ctl = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,-1))
127        self.neutron_abs_ctl.SetEditable(False)
128        self.neutron_abs_ctl.SetToolTipString("Neutron Abs. Xs")
129        neutron_abs_units_txt = wx.StaticText(self, -1,  unit_cm1)
130       
131        neutron_length_txt = wx.StaticText(self, -1, 'Neutron 1/e length')
132        self.neutron_length_ctl = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,-1))
133        self.neutron_length_ctl.SetEditable(False)
134        self.neutron_length_ctl.SetToolTipString("Neutron 1/e length")
135        neutron_length_units_txt = wx.StaticText(self, -1,  unit_cm)
136        iy = 0
137        ix = 0
138        sizer_output.Add(neutron_sld_txt,(iy, ix),(1,1),
139                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
140        ix +=1
141        sizer_output.Add(self.neutron_sld_reel_ctl,(iy, ix),(1,1),
142                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
143        ix +=1
144        sizer_output.Add(wx.StaticText(self, -1, i_complex)
145                         ,(iy, ix),(1,1),wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
146        ix +=1
147        sizer_output.Add(self.neutron_sld_im_ctl
148                         ,(iy, ix),(1,1),wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
149        ix +=1
150        sizer_output.Add(neutron_sld_units_txt
151                         ,(iy, ix),(1,1),wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
152        iy += 1
153        ix = 0
154        sizer_output.Add(cu_ka_sld_txt,(iy, ix),(1,1),
155                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
156        ix +=1
157        sizer_output.Add(self.cu_ka_sld_reel_ctl,(iy, ix),(1,1),
158                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
159        ix +=1
160        sizer_output.Add(wx.StaticText(self, -1, i_complex)
161                         ,(iy, ix),(1,1),wx.EXPAND|wx.ADJUST_MINSIZE, 0)
162        ix +=1
163        sizer_output.Add(self.cu_ka_sld_im_ctl
164                         ,(iy, ix),(1,1),wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
165        ix +=1
166        sizer_output.Add(cu_ka_sld_units_txt
167                         ,(iy, ix),(1,1),wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
168        iy += 1
169        ix = 0
170        sizer_output.Add(mo_ka_sld_txt,(iy, ix),(1,1),
171                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
172        ix +=1
173        sizer_output.Add(self.mo_ka_sld_reel_ctl,(iy, ix),(1,1),
174                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
175        ix +=1
176        sizer_output.Add(wx.StaticText(self, -1, i_complex)
177                         ,(iy, ix),(1,1),wx.EXPAND|wx.ADJUST_MINSIZE, 0)
178        ix +=1
179        sizer_output.Add(self.mo_ka_sld_im_ctl
180                         ,(iy, ix),(1,1),wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
181        ix +=1
182        sizer_output.Add(mo_ka_sld_units_txt
183                         ,(iy, ix),(1,1),wx.EXPAND|wx.ADJUST_MINSIZE, 0)
184        iy += 1
185        ix = 0
186        sizer_output.Add(neutron_inc_txt,(iy, ix),(1,1),
187                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
188        ix +=1
189        sizer_output.Add(self.neutron_inc_ctl,(iy, ix),(1,1),
190                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
191        ix +=2
192        sizer_output.Add(neutron_inc_units_txt,(iy, ix),(1,1),
193                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
194        iy += 1
195        ix = 0
196        sizer_output.Add(neutron_abs_txt,(iy, ix),(1,1),
197                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
198        ix +=1
199        sizer_output.Add(self.neutron_abs_ctl,(iy, ix),(1,1),
200                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
201        ix +=2
202        sizer_output.Add(neutron_abs_units_txt,(iy, ix),(1,1),
203                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
204        iy += 1
205        ix = 0
206        sizer_output.Add(neutron_length_txt,(iy, ix),(1,1),
207                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
208        ix +=1
209        sizer_output.Add(self.neutron_length_ctl,(iy, ix),(1,1),
210                            wx.EXPAND|wx.ADJUST_MINSIZE, 0)
211        ix +=2
212        sizer_output.Add(neutron_length_units_txt,(iy, ix),(1,1),
213                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
214        boxsizer2.Add( sizer_output )
215        sizer2.Add(boxsizer2,0, wx.EXPAND | wx.ALL, 10)
216        #-----Button  sizer------------
217        id = wx.NewId()
218        button_help = wx.Button(self, id, "Help")
219        button_help.SetToolTipString("Help  SlD calculations and formula.")
220        self.Bind(wx.EVT_BUTTON, self.onHelp, id = id) 
221         
222        id = wx.NewId()
223        button_calculate = wx.Button(self, id, "Calculate")
224        button_calculate.SetToolTipString("Calculate SlD of neutrons.")
225        self.Bind(wx.EVT_BUTTON, self.calculateSld, id = id)   
226       
227        sizer_button.Add((200, 20), 1, wx.EXPAND|wx.ADJUST_MINSIZE, 0)
228        sizer_button.Add(button_help, 0, wx.RIGHT|wx.ADJUST_MINSIZE,10)
229        sizer_button.Add(button_calculate, 0, wx.RIGHT|wx.ADJUST_MINSIZE,20)
230        sizer3.Add(sizer_button)
231        #---------layout----------------
232        vbox  = wx.BoxSizer(wx.VERTICAL)
233
234        vbox.Add(sizer1)
235        vbox.Add(sizer2)
236        vbox.Add(sizer3)
237        vbox.Fit(self) 
238        self.SetSizer(vbox)
239       
240    def check_inputs(self):
241        """Check validity user inputs"""
242        flag= True
243       
244        if check_float(self.density_ctl):
245            self.density = float(self.density_ctl.GetValue())
246        else:
247            flag=False
248            raise ValueError,"Error for Density value :expect float"
249   
250        self.wavelength= self.wavelength_ctl.GetValue()
251        if self.wavelength.lstrip().rstrip()=="":
252            self.wavelength = _DEFAULT_WAVELENGTH
253        else:
254            if check_float(self.wavelength_ctl):
255                self.wavelength= float(self.wavelength)
256            else:
257                flag = False
258                raise ValueError,"Error for wavelenth value :expect float"
259               
260        self.formulata_text= self.compound_ctl.GetValue().lstrip().rstrip()
261        if self.formulata_text!="":
262            self.compound_ctl.SetBackgroundColour(wx.WHITE)
263            self.compound_ctl.Refresh()
264        else:
265            self.compound_ctl.SetBackgroundColour("pink")
266            self.compound_ctl.Refresh()
267            flag=False
268            raise ValueError, "Enter a formula"
269        return flag
270       
271    def onHelp(self, event):
272        """
273            provide more hint on the SLD calculator
274        """
275        from helpPanel import  HelpWindow
276        frame = HelpWindow(None, -1, pageToOpen="doc/sld_calculator_help.html")   
277        frame.Show(True)
278        name = "SLD_calculator"
279        if frame.rhelp.HasAnchor(name):
280            frame.rhelp.ScrollToAnchor(name)
281        else:
282           msg= "Cannot find SLD Calculator description "
283           msg +="Please.Search in the Help window"
284           wx.PostEvent(self.base, StatusEvent(status = msg )) 
285           
286           
287    def calculateSld(self, event):
288        """
289            Calculate the neutron scattering density length of a molecule
290        """
291        try:
292            #Check validity user inputs
293            if self.check_inputs():
294                #get ready to compute
295                try:
296                    self.new_formula = formula(self.formulata_text, density= self.density)
297                    atom = self.new_formula.atoms
298                except:
299                    if self.base !=None:
300                        msg= "SLD Calculator: %s" % (sys.exc_value)
301                        wx.PostEvent(self.base, StatusEvent(status= msg ))
302                    else:
303                        raise
304                    return
305                # Compute the Cu SLD
306                Cu_reel, Cu_im = self.calculateXRaySld( "Cu", density= self.density,
307                                                        user_formula= self.new_formula)
308                self.cu_ka_sld_reel_ctl.SetValue(format_number(Cu_reel*_SCALE))
309                self.cu_ka_sld_im_ctl.SetValue(format_number(Cu_im*_SCALE))
310                # Compute the Mo SLD
311                Mo_reel, Mo_im = self.calculateXRaySld( "Mo", density= self.density,
312                                                        user_formula= self.new_formula)
313                self.mo_ka_sld_reel_ctl.SetValue(format_number(Mo_reel*_SCALE))
314                self.mo_ka_sld_im_ctl.SetValue(format_number(Mo_im*_SCALE))
315               
316                coh,absorp,inc= self.calculateNSld(self.density, wavelength= self.wavelength,
317                                                     user_formula= self.new_formula)
318                #Don't know if value is return in cm or  cm^(-1).assume return in cm
319                # to match result of neutron inc of Alan calculator
320                inc= inc*1/10
321                #Doesn't match result of Alan calculator for absorption factor of 2
322                #multiplication of 100 is going around
323                absorp= absorp *2*100
324                volume= (self.new_formula.mass /self.density)/avogadro_number*1.0e24
325                #im: imaginary part of neutron SLD
326                im=0
327                for el, count in atom.iteritems():
328                    if el.neutron.b_c_i !=None:
329                        im += el.neutron.b_c_i*count
330                im = im/volume
331               
332                self.neutron_sld_reel_ctl.SetValue(format_number(coh*_SCALE))
333                self.neutron_sld_im_ctl.SetValue(format_number(im*_SCALE))
334                self.neutron_inc_ctl.SetValue(format_number(inc ))
335                self.neutron_abs_ctl.SetValue(format_number(absorp))
336                #Don't know if value is return in cm or  cm^(-1).assume return in cm
337                # to match result of neutron inc of Alan calculator
338                length= (coh+ absorp+ inc)/volume
339                self.neutron_length_ctl.SetValue(format_number(length))
340        except:
341            if self.base !=None:
342                  msg= "SLD Calculator: %s" % (sys.exc_value)
343                  wx.PostEvent(self.base, StatusEvent(status= msg ))
344            else:
345                raise
346            return   
347
348    def calculateXRaySld(self, element, density,user_formula):
349        """
350            Get an element and compute the corresponding SLD for a given formula
351            @param element:  elementis a string of existing atom
352            @param formula: molecule enters by the user
353        """
354        try:
355            myformula = formula(str (element))
356            if len(myformula.atoms)!=1:
357                return 
358            element= myformula.atoms.keys()[0] 
359            energy = xray_energy(element.K_alpha)
360            atom = user_formula.atoms
361            atom_reel, atom_im = xray_sld_from_atoms( atom,
362                                                  density=density,
363                                                  energy= energy )
364            return atom_reel, atom_im
365        except:
366            if self.base !=None:
367                  msg= "SLD Calculator: %s" % (sys.exc_value)
368                  wx.PostEvent(self.base, StatusEvent(status= msg ))
369            else:
370                raise
371            return   
372       
373    def calculateNSld(self,density,wavelength,user_formula ):
374        """
375            Compute the neutron SLD for a given molecule
376            @return absorp: absorption
377            @return coh: coherence cross section
378            @return inc: incoherence cross section
379         
380        """
381        if density ==0:
382            raise ZeroDivisionError,"integer division or modulo by zero for density"
383            return 
384        atom = user_formula.atoms
385        coh,absorp,inc = neutron_sld_from_atoms(atom,density,wavelength)
386
387        return coh,absorp,inc
388   
389   
390 
391       
392               
393class SldWindow(wx.Frame):
394    def __init__(self, parent=None, id=1, title="SLD Calculator",base=None):
395        wx.Frame.__init__(self, parent, id, title, size=(400, 400))
396       
397        self.panel = SldPanel(self, base=base)
398        self.Centre()
399        self.Show(True)
400       
401class ViewApp(wx.App):
402    def OnInit(self):
403        frame = SldWindow(None, -1, 'SLD Calculator')   
404        frame.Show(True)
405        self.SetTopWindow(frame)
406       
407        return True
408       
409
410if __name__ == "__main__": 
411    app = ViewApp(0)
412    app.MainLoop()     
Note: See TracBrowser for help on using the repository browser.