source: sasview/invariantview/perspectives/invariant/invariant_panel.py @ a618972

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 a618972 was d0cc0bbc, checked in by Gervaise Alina <gervyh@…>, 15 years ago

change panel according to feedback

  • Property mode set to 100644
File size: 44.3 KB
Line 
1"""
2    This module provide GUI for the neutron scattering length density calculator
3    @author: Gervaise B. Alina
4"""
5
6import wx
7import sys
8
9from sans.invariant import invariant
10from sans.guiframe.utils import format_number, check_float
11from sans.guicomm.events import NewPlotEvent, StatusEvent
12from invariant_details import InvariantDetailsPanel, InvariantContainer
13from invariant_widgets import OutputTextCtrl, InvTextCtrl
14# The minimum q-value to be used when extrapolating
15Q_MINIMUM  = 1e-5
16# The maximum q-value to be used when extrapolating
17Q_MAXIMUM  = 10
18# the maximum value to plot the theory data
19Q_MAXIMUM_PLOT = 2
20# the number of points to consider during fit
21NPTS = 10
22#Default value for background
23BACKGROUND = 0.0
24#default value for the scale
25SCALE = 1.0
26#default value of the contrast
27CONTRAST = 1.0
28#default value of the power used for power law
29POWER = 4.0
30#Invariant panel size
31_BOX_WIDTH = 76
32
33if sys.platform.count("win32")>0:
34    _STATICBOX_WIDTH = 450
35    PANEL_WIDTH = 500
36    PANEL_HEIGHT = 700
37    FONT_VARIANT = 0
38else:
39    _STATICBOX_WIDTH = 480
40    PANEL_WIDTH = 530
41    PANEL_HEIGHT = 700
42    FONT_VARIANT = 1
43
44
45class InvariantPanel(wx.ScrolledWindow):
46    """
47        Provides the Invariant GUI.
48    """
49    ## Internal nickname for the window, used by the AUI manager
50    window_name = "Invariant"
51    ## Name to appear on the window title bar
52    window_caption = "Invariant"
53    ## Flag to tell the AUI manager to put this panel in the center pane
54    CENTER_PANE = True
55    def __init__(self, parent, data=None, manager=None):
56        wx.ScrolledWindow.__init__(self, parent, style= wx.FULL_REPAINT_ON_RESIZE )
57        #Font size
58        self.SetWindowVariant(variant=FONT_VARIANT)
59        #Object that receive status event
60        self.parent = parent
61        #plug-in using this panel
62        self._manager = manager
63        #Data uses for computation
64        self._data = data
65        #container of invariant value
66        self.inv_container = None
67        #Draw the panel
68        self._do_layout()
69        self.reset_panel()
70        if self.parent is not None:
71            msg = ""
72            wx.PostEvent(self.parent, StatusEvent(status= msg))
73       
74    def err_check_on_data(self):
75        """
76            Check if data is valid for further computation
77        """
78        flag = False
79        #edit the panel
80        if self._data is not None:
81            if len(self._data.x[self._data.x==0]) > 0:
82                flag = True
83                msg = "Invariant: one of your q-values is zero. Delete that entry before proceeding"
84                wx.PostEvent(self.parent, StatusEvent(status= msg, type="stop")) 
85        return flag
86   
87    def set_data(self, data):
88        """
89            Set the data
90        """
91        self._data = data
92        #edit the panel
93        if self._data is not None:
94            self.err_check_on_data()
95            data_name = self._data.name
96            data_qmin = min (self._data.x)
97            data_qmax = max (self._data.x)
98            self.data_name_tcl.SetValue(str(data_name))
99            self.data_min_tcl.SetLabel(str(data_qmin))
100            self.data_max_tcl.SetLabel(str(data_qmax))
101            self.hint_msg_txt.SetLabel('')
102            self.reset_panel()
103            self.compute_invariant(event=None)
104           
105    def set_message(self):
106        """
107            Display warning message if available
108        """
109        if self.inv_container is not None:
110            if self.inv_container.existing_warning:
111                msg = "Warning! Computations on invariant require your "
112                msg += "attention.\n Please click on Details button."
113                self.hint_msg_txt.SetForegroundColour("red")
114            else:
115                msg = "For more information, click on Details button."
116                self.hint_msg_txt.SetForegroundColour("black")
117            self.hint_msg_txt.SetLabel(msg)
118            wx.PostEvent(self.parent, StatusEvent(status=msg))
119        self.data_name_boxsizer.Layout()
120       
121    def set_manager(self, manager):
122        """
123            set value for the manager
124        """
125        self._manager = manager
126   
127    def get_background(self):
128        """
129            @return the background textcrtl value as a float
130        """
131        background = self.background_tcl.GetValue().lstrip().rstrip()
132        if background == "":
133            raise ValueError, "Need a background"
134        if check_float(self.background_tcl):
135            return float(background)
136        else:
137            raise ValueError, "Receive invalid value for background : %s"%(background)
138   
139    def get_scale(self):
140        """
141            @return the scale textcrtl value as a float
142        """
143        scale = self.scale_tcl.GetValue().lstrip().rstrip()
144        if scale == "":
145            raise ValueError, "Need a background"
146        if check_float(self.scale_tcl):
147            return float(scale)
148        else:
149            raise ValueError, "Receive invalid value for background : %s"%(scale)
150       
151    def get_contrast(self):
152        """
153            @return the contrast textcrtl value as a float
154        """
155        par_str = self.contrast_tcl.GetValue().strip()
156        contrast = None
157        if par_str !="" and check_float(self.contrast_tcl):
158            contrast = float(par_str)
159        return contrast
160   
161    def get_extrapolation_type(self, low_q, high_q):
162        """
163        """
164        extrapolation = None
165        if low_q  and not high_q:
166            extrapolation = "low"
167        elif not low_q  and high_q:
168            extrapolation = "high"
169        elif low_q and high_q:
170            extrapolation = "both"
171        return extrapolation
172           
173    def get_porod_const(self):
174        """
175            @return the porod constant textcrtl value as a float
176        """
177        par_str = self.porod_constant_tcl.GetValue().strip()
178        porod_const = None
179        if par_str !="" and check_float(self.porod_constant_tcl):
180            porod_const = float(par_str)
181        return porod_const
182   
183    def get_volume(self, inv, contrast, extrapolation):
184        """
185        """
186        if contrast is not None:
187            try:
188                v, dv = inv.get_volume_fraction_with_error(contrast=contrast, 
189                                                           extrapolation=extrapolation)
190                self.volume_tcl.SetValue(format_number(v))
191                self.volume_err_tcl.SetValue(format_number(dv))
192            except:
193                raise
194                msg= "Error occurred computing volume fraction: %s"%sys.exc_value
195                wx.PostEvent(self.parent, StatusEvent(status= msg, type="stop"))
196               
197    def get_surface(self, inv, contrast, porod_const, extrapolation):
198        """
199        """
200        if contrast is not None and porod_const is not None:
201            try:
202                s, ds = inv.get_surface_with_error(contrast=contrast,
203                                        porod_const=porod_const,
204                                        extrapolation=extrapolation)
205                self.surface_tcl.SetValue(format_number(s))
206                self.surface_err_tcl.SetValue(format_number(ds))
207            except:
208                msg= "Error occurred computing specific surface: %s"%sys.exc_value
209                wx.PostEvent(self.parent, StatusEvent(status= msg, type="stop"))
210               
211    def get_total_qstar(self, inv, extrapolation):
212        """
213        """
214        try:
215            qstar_total, qstar_total_err = inv.get_qstar_with_error(extrapolation)
216            self.invariant_total_tcl.SetValue(format_number(qstar_total))
217            self.invariant_total_err_tcl.SetValue(format_number(qstar_total_err))
218            self.inv_container.qstar_total = qstar_total
219            self.inv_container.qstar_total_err = qstar_total_err
220         
221        except:
222            msg= "Error occurred computing invariant using extrapolation: %s"%sys.exc_value
223            wx.PostEvent(self.parent, StatusEvent(status= msg, type="stop")) 
224           
225    def get_low_qstar(self, inv, npts_low, low_q=False):
226        """
227        """
228        if low_q:
229            try: 
230                qstar_low, qstar_low_err = inv.get_qstar_low()
231                self.inv_container.qstar_low = qstar_low
232                self.inv_container.qstar_low_err = qstar_low_err
233                extrapolated_data = inv.get_extra_data_low(npts_in=npts_low) 
234                power_low = inv.get_extrapolation_power(range='low') 
235                if self.power_law_low.GetValue():
236                    self.power_low_tcl.SetValue(format_number(power_low))
237                self._manager.plot_theory(data=extrapolated_data,
238                                           name="Low-Q extrapolation")
239            except:
240                msg= "Error occurred computing low-Q invariant: %s"%sys.exc_value
241                wx.PostEvent(self.parent, StatusEvent(status= msg, type="stop"))
242        else:
243            self._manager.plot_theory(name="Low-Q extrapolation")
244           
245    def get_high_qstar(self, inv, high_q=False):
246        """
247        """
248        if high_q:
249            try: 
250                qstar_high, qstar_high_err = inv.get_qstar_high()
251                self.inv_container.qstar_high = qstar_high
252                self.inv_container.qstar_high_err = qstar_high_err
253                power_high = inv.get_extrapolation_power(range='high') 
254                self.power_high_tcl.SetValue(format_number(power_high))
255                high_out_data = inv.get_extra_data_high(q_end=Q_MAXIMUM_PLOT)
256                self._manager.plot_theory(data=high_out_data,
257                                           name="High-Q extrapolation")
258            except:
259                msg= "Error occurred computing high-Q invariant: %s"%sys.exc_value
260                wx.PostEvent(self.parent, StatusEvent(status= msg, type="stop"))
261        else:
262            self._manager.plot_theory(name="High-Q extrapolation")
263           
264    def get_qstar(self, inv):
265        """
266        """
267        qstar, qstar_err = inv.get_qstar_with_error()
268        self.inv_container.qstar = qstar
269        self.inv_container.qstar_err = qstar_err
270             
271    def set_extrapolation_low(self, inv, low_q=False):
272        """
273            @return float value necessary to compute invariant a low q
274        """
275        #get funtion
276        if self.guinier.GetValue():
277            function_low = "guinier"
278        # get the function
279        power_low = None #2.0/3.0
280        if self.power_law_low.GetValue():
281            function_low = "power_law"
282            if self.fit_enable_low.GetValue():
283                #set value of power_low to none to allow fitting
284                power_low = None
285            else:
286                power_low = self.power_low_tcl.GetValue().lstrip().rstrip()
287                if check_float(self.power_low_tcl):
288                    power_low = float(power_low)
289                else:
290                    if low_q :
291                        #Raise error only when qstar at low q is requested
292                        msg = "Expect float for power at low q , got %s"%(power_low)
293                        raise ValueError, msg
294       
295        #Get the number of points to extrapolated
296        npts_low = self.npts_low_tcl.GetValue().lstrip().rstrip()   
297        if check_float(self.npts_low_tcl):
298            npts_low = float(npts_low)
299        else:
300            if low_q:
301                msg = "Expect float for number of points at low q , got %s"%(npts_low)
302                raise ValueError, msg
303        #Set the invariant calculator
304        inv.set_extrapolation(range="low", npts=npts_low,
305                                   function=function_low, power=power_low)   
306        return inv, npts_low 
307       
308    def set_extrapolation_high(self, inv, high_q=False):
309        """
310            @return float value necessary to compute invariant a high q
311        """
312        power_high = None
313        #if self.power_law_high.GetValue():
314        function_high = "power_law"
315        if self.fit_enable_high.GetValue():
316            #set value of power_high to none to allow fitting
317            power_high = None
318        else:
319            power_high = self.power_high_tcl.GetValue().lstrip().rstrip()
320            if check_float(self.power_high_tcl):
321                power_high = float(power_high)
322            else:
323                if high_q :
324                    #Raise error only when qstar at high q is requested
325                    msg = "Expect float for power at high q , got %s"%(power_high)
326                    raise ValueError, msg
327                         
328        npts_high = self.npts_high_tcl.GetValue().lstrip().rstrip()   
329        if check_float(self.npts_high_tcl):
330            npts_high = float(npts_high)
331        else:
332            if high_q:
333                msg = "Expect float for number of points at high q , got %s"%(npts_high)
334                raise ValueError, msg
335        inv.set_extrapolation(range="high", npts=npts_high,
336                                   function=function_high, power=power_high)
337        return inv, npts_high
338   
339    def display_details(self, event):
340        """
341            open another panel for more details on invariant calculation
342        """
343        panel = InvariantDetailsPanel(parent=self, 
344                                           qstar_container=self.inv_container)
345        panel.ShowModal()
346        panel.Destroy()
347        self.button_calculate.SetFocus()
348       
349    def compute_invariant(self, event=None):
350        """
351            compute invariant
352        """
353        msg= ""
354        wx.PostEvent(self.parent, StatusEvent(status= msg))
355        if self._data is None or self.err_check_on_data():
356            return
357   
358        #clear outputs textctrl
359        self._reset_output()
360        try:
361            background = self.get_background()
362            scale = self.get_scale()
363        except:
364            msg= "Invariant Error: %s"%(sys.exc_value)
365            wx.PostEvent(self.parent, StatusEvent(status= msg, type="stop"))
366            return
367       
368        low_q = self.enable_low_cbox.GetValue()
369        high_q = self.enable_high_cbox.GetValue() 
370        #set invariant calculator
371        inv = invariant.InvariantCalculator(data=self._data,
372                                            background=background,
373                                            scale=scale)
374        try:
375            inv, npts_low = self.set_extrapolation_low(inv=inv, low_q=low_q)
376            inv, npts_high = self.set_extrapolation_high(inv=inv, high_q=high_q)
377        except:
378            raise
379            #msg= "Error occurred computing invariant: %s"%sys.exc_value
380            #wx.PostEvent(self.parent, StatusEvent(status= msg, type="stop"))
381            return
382        #check the type of extrapolation
383        extrapolation = self.get_extrapolation_type(low_q=low_q, high_q=high_q)
384       
385        #Compute invariant
386        try:
387            self.get_qstar(inv=inv)
388        except:
389            msg= "Error occurred computing invariant: %s"%sys.exc_value
390            wx.PostEvent(self.parent, StatusEvent(status= msg, type="stop"))
391            return
392        #Compute qstar extrapolated to low q range
393        self.get_low_qstar(inv=inv, npts_low=npts_low, low_q=low_q)
394        #Compute qstar extrapolated to high q range
395        self.get_high_qstar(inv=inv, high_q=high_q)
396        #Compute qstar extrapolated to total q range and set value to txtcrtl
397        self.get_total_qstar(inv=inv, extrapolation=extrapolation)
398        # Parse additional parameters
399        porod_const = self.get_porod_const()       
400        contrast = self.get_contrast()
401        try:
402            #Compute volume and set value to txtcrtl
403            self.get_volume(inv=inv, contrast=contrast, extrapolation=extrapolation)
404            #compute surface and set value to txtcrtl
405        except:
406            msg= "Error occurred computing invariant: %s"%sys.exc_value
407            wx.PostEvent(self.parent, StatusEvent(status= msg))
408        try:
409            self.get_surface(inv=inv, contrast=contrast, porod_const=porod_const, 
410                                    extrapolation=extrapolation)
411        except:
412            msg= "Error occurred computing invariant: %s"%sys.exc_value
413            wx.PostEvent(self.parent, StatusEvent(status= msg))
414           
415        #compute percentage of each invariant
416        self.inv_container.compute_percentage()
417        #display a message
418        self.set_message()
419        #enable the button_ok for more details
420        self.button_details.Enable()
421        self.button_details.SetFocus()
422   
423    def reset_panel(self):
424        """
425            set the panel at its initial state.
426        """
427        self.background_tcl.SetValue(str(BACKGROUND))
428        self.scale_tcl.SetValue(str(SCALE)) 
429        self.contrast_tcl.SetValue(str(CONTRAST)) 
430        self.npts_low_tcl.SetValue(str(NPTS))
431        self.enable_low_cbox.SetValue(False)
432        self.fix_enable_low.SetValue(True)
433        self.power_low_tcl.SetValue(str(POWER))
434        self.guinier.SetValue(True)
435        self.power_low_tcl.Disable()
436        self.enable_high_cbox.SetValue(False)
437        self.fix_enable_high.SetValue(True)
438        self.power_high_tcl.SetValue(str(POWER))
439        self.npts_high_tcl.SetValue(str(NPTS))
440        self.button_details.Disable()
441        #Change the state of txtcrtl to enable/disable
442        self._enable_low_q_section()
443        #Change the state of txtcrtl to enable/disable
444        self._enable_high_q_section()
445        self._reset_output()
446        self.button_calculate.SetFocus()
447       
448    def _reset_output(self):
449        """
450            clear outputs textcrtl
451        """
452        self.invariant_total_tcl.Clear()
453        self.invariant_total_err_tcl.Clear()
454        self.volume_tcl.Clear()
455        self.volume_err_tcl.Clear()
456        self.surface_tcl.Clear()
457        self.surface_err_tcl.Clear()
458        #prepare a new container to put result of invariant
459        self.inv_container = InvariantContainer()
460       
461    def _define_structure(self):
462        """
463            Define main sizers needed for this panel
464        """
465        ## Box sizers must be defined first before defining buttons/textctrls (MAC).
466        self.main_sizer = wx.BoxSizer(wx.VERTICAL)
467        #Sizer related to outputs
468        outputs_box = wx.StaticBox(self, -1, "Outputs")
469        self.outputs_sizer = wx.StaticBoxSizer(outputs_box, wx.VERTICAL)
470        self.outputs_sizer.SetMinSize((PANEL_WIDTH,-1))
471        #Sizer related to data
472        data_name_box = wx.StaticBox(self, -1, "I(q) Data Source")
473        self.data_name_boxsizer = wx.StaticBoxSizer(data_name_box, wx.VERTICAL)
474        self.data_name_boxsizer.SetMinSize((PANEL_WIDTH,-1))
475        self.hint_msg_sizer = wx.BoxSizer(wx.HORIZONTAL)
476        self.data_name_sizer = wx.BoxSizer(wx.HORIZONTAL)
477        self.data_range_sizer = wx.BoxSizer(wx.HORIZONTAL)
478        #Sizer related to background and scale
479        self.bkg_scale_sizer = wx.BoxSizer(wx.HORIZONTAL) 
480        #Sizer related to contrast and porod constant
481        self.contrast_porod_sizer = wx.BoxSizer(wx.HORIZONTAL) 
482        #Sizer related to inputs
483        inputs_box = wx.StaticBox(self, -1, "Customized Inputs")
484        self.inputs_sizer = wx.StaticBoxSizer(inputs_box, wx.VERTICAL)
485        #Sizer related to extrapolation
486        extrapolation_box = wx.StaticBox(self, -1, "Extrapolation")
487        self.extrapolation_sizer = wx.StaticBoxSizer(extrapolation_box,
488                                                        wx.VERTICAL)
489        self.extrapolation_sizer.SetMinSize((PANEL_WIDTH,-1))
490        self.extrapolation_range_sizer = wx.BoxSizer(wx.HORIZONTAL)
491        self.extrapolation_low_high_sizer = wx.BoxSizer(wx.HORIZONTAL)
492        #Sizer related to extrapolation at low q range
493        low_q_box = wx.StaticBox(self, -1, "Low Q")
494        self.low_extrapolation_sizer = wx.StaticBoxSizer(low_q_box, wx.VERTICAL)
495        self.low_q_sizer = wx.GridBagSizer(5,5)
496        #Sizer related to extrapolation at low q range
497        high_q_box = wx.StaticBox(self, -1, "High Q")
498        self.high_extrapolation_sizer = wx.StaticBoxSizer(high_q_box, wx.VERTICAL)
499        self.high_q_sizer = wx.GridBagSizer(5,5)
500        #sizer to define outputs
501        self.volume_surface_sizer = wx.GridBagSizer(5,5)
502        #Sizer related to invariant output
503        self.invariant_sizer = wx.GridBagSizer(5, 5)
504        #Sizer related to button
505        self.button_sizer = wx.BoxSizer(wx.HORIZONTAL)
506       
507    def _layout_data_name(self):
508        """
509            Draw widgets related to data's name
510        """
511        #Sizer hint
512        hint_msg = "Load Data then right click to add the data on this panel! "
513        self.hint_msg_txt = wx.StaticText(self, -1, hint_msg) 
514        self.hint_msg_txt.SetForegroundColour("red")
515        self.hint_msg_sizer.Add(self.hint_msg_txt)
516        #Data name [string]
517        data_name_txt = wx.StaticText(self, -1, 'Data : ') 
518       
519        self.data_name_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH*5, 20), style=0) 
520        self.data_name_tcl.SetToolTipString("Data's name.")
521        self.data_name_sizer.AddMany([(data_name_txt, 0, wx.LEFT|wx.RIGHT, 10),
522                                       (self.data_name_tcl, 0, wx.EXPAND)])
523        #Data range [string]
524        data_range_txt = wx.StaticText(self, -1, 'Total Q Range (1/A): ') 
525        data_min_txt = wx.StaticText(self, -1, 'Min : ') 
526        self.data_min_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH, 20), style=0)
527        self.data_min_tcl.SetToolTipString("The minimum value of q range.")
528        data_max_txt = wx.StaticText(self, -1, 'Max : ') 
529        self.data_max_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH, 20), style=0) 
530        self.data_max_tcl.SetToolTipString("The maximum value of q range.")
531        self.data_range_sizer.AddMany([(data_range_txt, 0, wx.RIGHT, 10),
532                                       (data_min_txt, 0, wx.RIGHT, 10),
533                                       (self.data_min_tcl, 0, wx.RIGHT, 10),
534                                       (data_max_txt, 0, wx.RIGHT, 10),
535                                       (self.data_max_tcl, 0, wx.RIGHT, 10)])
536        self.data_name_boxsizer.AddMany([(self.hint_msg_sizer, 0 , wx.ALL, 10),
537                                         (self.data_name_sizer, 0 , wx.RIGHT, 10),
538                                         (self.data_range_sizer, 0 , wx.ALL, 10)])
539   
540    def _layout_bkg_scale(self):
541        """
542            Draw widgets related to background and scale
543        """
544        background_txt = wx.StaticText(self, -1, 'Background : ') 
545        self.background_tcl = InvTextCtrl(self, -1, size=(_BOX_WIDTH, 20), style=0) 
546        background_hint_txt = "background"
547        self.background_tcl.SetToolTipString(background_hint_txt)
548        background_unit_txt = wx.StaticText(self, -1, '[1/cm]') 
549        scale_txt = wx.StaticText(self, -1, 'Scale : ') 
550        self.scale_tcl = InvTextCtrl(self, -1, size=(_BOX_WIDTH, 20), style=0)
551        scale_hint_txt = "Scale"
552        self.scale_tcl.SetToolTipString(scale_hint_txt)
553        self.bkg_scale_sizer.AddMany([(background_txt, 0, wx.LEFT, 10),
554                                       (self.background_tcl, 0, wx.LEFT, 5),
555                                       (background_unit_txt, 0, wx.LEFT, 10),
556                                       (scale_txt, 0, wx.LEFT, 70),
557                                       (self.scale_tcl, 0, wx.LEFT, 40)])
558 
559    def _layout_contrast_porod(self):
560        """
561            Draw widgets related to porod constant and contrast
562        """
563        contrast_txt = wx.StaticText(self, -1, 'Contrast : ') 
564        self.contrast_tcl = InvTextCtrl(self, -1, size=(_BOX_WIDTH, 20), style=0)
565        contrast_hint_txt = "Contrast"
566        self.contrast_tcl.SetToolTipString(contrast_hint_txt)
567        contrast_unit_txt = wx.StaticText(self, -1, '[1/A^(2)]') 
568        porod_const_txt = wx.StaticText(self, -1, 'Porod Constant:') 
569        self.porod_constant_tcl = InvTextCtrl(self, -1, 
570                                              size=(_BOX_WIDTH, 20), style=0) 
571        porod_const_hint_txt = "Porod Constant"
572        self.porod_constant_tcl.SetToolTipString(porod_const_hint_txt)
573        optional_txt = wx.StaticText(self, -1, '(Optional)') 
574        self.contrast_porod_sizer.AddMany([(contrast_txt, 0, wx.LEFT, 10),
575                                           (self.contrast_tcl, 0, wx.LEFT, 20),
576                                           (contrast_unit_txt, 0, wx.LEFT, 10),
577                                           (porod_const_txt, 0, wx.LEFT, 50),
578                                       (self.porod_constant_tcl, 0, wx.LEFT, 0),
579                                       (optional_txt, 0, wx.LEFT, 10)])
580       
581    def _enable_fit_power_law_low(self, event=None):
582        """
583            Enable and disable the power value editing
584        """
585        if self.fix_enable_low.IsEnabled():
586            if self.fix_enable_low.GetValue():
587                self.power_low_tcl.Enable()
588            else:
589                self.power_low_tcl.Disable()
590           
591    def _enable_low_q_section(self, event=None):
592        """
593            Disable or enable some button if the user enable low q extrapolation
594        """
595        if self.enable_low_cbox.GetValue():
596            self.npts_low_tcl.Enable()
597            self.fix_enable_low.Enable()
598            self.fit_enable_low.Enable()
599            self.guinier.Enable()
600            self.power_law_low.Enable()
601
602        else:
603            self.npts_low_tcl.Disable()
604            self.fix_enable_low.Disable()
605            self.fit_enable_low.Disable()
606            self.guinier.Disable()
607            self.power_law_low.Disable()
608        self._enable_power_law_low()
609        self._enable_fit_power_law_low()
610        self.button_calculate.SetFocus()
611   
612    def _enable_power_law_low(self, event=None):
613        """
614            Enable editing power law section at low q range
615        """
616        if self.guinier.GetValue():
617            self.fix_enable_low.Disable()
618            self.fit_enable_low.Disable()
619            self.power_low_tcl.Disable()
620        else:
621            self.fix_enable_low.Enable()
622            self.fit_enable_low.Enable()
623            self.power_low_tcl.Enable()
624        self._enable_fit_power_law_low()
625           
626    def _layout_extrapolation_low(self):
627        """
628            Draw widgets related to extrapolation at low q range
629        """
630        self.enable_low_cbox = wx.CheckBox(self, -1, "Enable Extrapolate Low Q")
631        wx.EVT_CHECKBOX(self, self.enable_low_cbox.GetId(),
632                                         self._enable_low_q_section)
633        self.fix_enable_low = wx.RadioButton(self, -1, 'Fix',
634                                         (10, 10),style=wx.RB_GROUP)
635        self.fit_enable_low = wx.RadioButton(self, -1, 'Fit', (10, 10))
636        self.Bind(wx.EVT_RADIOBUTTON, self._enable_fit_power_law_low,
637                                     id=self.fix_enable_low.GetId())
638        self.Bind(wx.EVT_RADIOBUTTON, self._enable_fit_power_law_low, 
639                                        id=self.fit_enable_low.GetId())
640        self.guinier = wx.RadioButton(self, -1, 'Guinier',
641                                         (10, 10),style=wx.RB_GROUP)
642        self.power_law_low = wx.RadioButton(self, -1, 'Power Law', (10, 10))
643        self.Bind(wx.EVT_RADIOBUTTON, self._enable_power_law_low,
644                                     id=self.guinier.GetId())
645        self.Bind(wx.EVT_RADIOBUTTON, self._enable_power_law_low, 
646                                        id=self.power_law_low.GetId())
647       
648        npts_low_txt = wx.StaticText(self, -1, 'Npts')
649        self.npts_low_tcl = InvTextCtrl(self, -1, size=(_BOX_WIDTH*2/3, -1))
650        msg_hint = "Number of Q points to consider"
651        msg_hint +="while extrapolating the low-Q region"
652        self.npts_low_tcl.SetToolTipString(msg_hint)
653        power_txt = wx.StaticText(self, -1, 'Power')
654        self.power_low_tcl = InvTextCtrl(self, -1, size=(_BOX_WIDTH*2/3, -1))
655       
656        power_hint_txt = "Exponent to apply to the Power_law function."
657        self.power_low_tcl.SetToolTipString(power_hint_txt)
658        iy = 0
659        ix = 0
660        self.low_q_sizer.Add(self.enable_low_cbox,(iy, ix),(1,5),
661                            wx.TOP|wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
662        iy += 1
663        ix = 0
664        self.low_q_sizer.Add(npts_low_txt,(iy, ix),(1,1),
665                            wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
666        ix += 1
667        self.low_q_sizer.Add(self.npts_low_tcl, (iy, ix), (1,1),
668                            wx.EXPAND|wx.ADJUST_MINSIZE, 0)
669        iy += 1
670        ix = 0
671        self.low_q_sizer.Add(self.guinier,(iy, ix),(1,2),
672                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
673        iy += 1
674        ix = 0
675        self.low_q_sizer.Add(self.power_law_low,(iy, ix),(1,2),
676                            wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
677       
678        # Parameter controls for power law
679        ix = 1
680        iy += 1
681        self.low_q_sizer.Add(self.fix_enable_low,(iy, ix),(1,1),
682                            wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
683        ix += 1
684        self.low_q_sizer.Add(self.fit_enable_low,(iy, ix),(1,1),
685                           wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
686        ix = 1
687        iy += 1
688        self.low_q_sizer.Add(power_txt,(iy, ix),(1,1),
689                            wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
690        ix += 1
691        self.low_q_sizer.Add(self.power_low_tcl, (iy, ix), (1,1),
692                            wx.EXPAND|wx.ADJUST_MINSIZE, 0)
693        self.low_extrapolation_sizer.AddMany([(self.low_q_sizer, 0,
694                                                wx.BOTTOM|wx.RIGHT, 15)])
695       
696    def _enable_fit_power_law_high(self, event=None):
697        """
698            Enable and disable the power value editing
699        """
700        if self.fix_enable_high.IsEnabled():
701            if self.fix_enable_high.GetValue():
702                self.power_high_tcl.Enable()
703            else:
704                self.power_high_tcl.Disable()
705       
706    def _enable_high_q_section(self, event=None):
707        """
708            Disable or enable some button if the user enable high q extrapolation
709        """
710        if self.enable_high_cbox.GetValue():
711            self.npts_high_tcl.Enable()
712            self.power_law_high.Enable()
713            self.power_high_tcl.Enable()
714            self.fix_enable_high.Enable()
715            self.fit_enable_high.Enable()
716        else:
717            self.npts_high_tcl.Disable()
718            self.power_law_high.Disable()
719            self.power_high_tcl.Disable()
720            self.fix_enable_high.Disable()
721            self.fit_enable_high.Disable()
722        self._enable_fit_power_law_high()
723        self.button_calculate.SetFocus()
724 
725    def _layout_extrapolation_high(self):
726        """
727            Draw widgets related to extrapolation at high q range
728        """
729        self.enable_high_cbox = wx.CheckBox(self, -1, "Enable Extrapolate high-Q")
730        wx.EVT_CHECKBOX(self, self.enable_high_cbox.GetId(),
731                                         self._enable_high_q_section)
732     
733        self.fix_enable_high = wx.RadioButton(self, -1, 'Fix',
734                                         (10, 10),style=wx.RB_GROUP)
735        self.fit_enable_high = wx.RadioButton(self, -1, 'Fit', (10, 10))
736        self.Bind(wx.EVT_RADIOBUTTON, self._enable_fit_power_law_high,
737                                     id=self.fix_enable_high.GetId())
738        self.Bind(wx.EVT_RADIOBUTTON, self._enable_fit_power_law_high, 
739                                        id=self.fit_enable_high.GetId())
740       
741        self.power_law_high = wx.StaticText(self, -1, 'Power Law')
742        msg_hint ="Check to extrapolate data at high-Q"
743        self.power_law_high.SetToolTipString(msg_hint)
744        npts_high_txt = wx.StaticText(self, -1, 'Npts')
745        self.npts_high_tcl = InvTextCtrl(self, -1, size=(_BOX_WIDTH*2/3, -1))
746        msg_hint = "Number of Q points to consider"
747        msg_hint += "while extrapolating the high-Q region"
748        self.npts_high_tcl.SetToolTipString(msg_hint)
749        power_txt = wx.StaticText(self, -1, 'Power')
750        self.power_high_tcl = InvTextCtrl(self, -1, size=(_BOX_WIDTH*2/3, -1))
751        power_hint_txt = "Exponent to apply to the Power_law function."
752        self.power_high_tcl.SetToolTipString(power_hint_txt)
753        iy = 0
754        ix = 0
755        self.high_q_sizer.Add(self.enable_high_cbox,(iy, ix),(1,5),
756                            wx.TOP|wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
757        iy += 1
758        ix = 0
759        self.high_q_sizer.Add(npts_high_txt,(iy, ix),(1,1),
760                            wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
761        ix += 1
762        self.high_q_sizer.Add(self.npts_high_tcl, (iy, ix), (1,1),
763                            wx.EXPAND|wx.ADJUST_MINSIZE, 0)
764        iy += 2
765        ix = 0
766        self.high_q_sizer.Add(self.power_law_high,(iy, ix),(1,2),
767                            wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
768       
769        # Parameter controls for power law
770        ix = 1
771        iy += 1
772        self.high_q_sizer.Add(self.fix_enable_high,(iy, ix),(1,1),
773                            wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
774        ix += 1
775        self.high_q_sizer.Add(self.fit_enable_high,(iy, ix),(1,1),
776                           wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
777        ix = 1
778        iy += 1
779        self.high_q_sizer.Add(power_txt,(iy, ix),(1,1),
780                            wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
781        ix += 1
782        self.high_q_sizer.Add(self.power_high_tcl, (iy, ix), (1,1),
783                            wx.EXPAND|wx.ADJUST_MINSIZE, 0)
784        self.high_extrapolation_sizer.AddMany([(self.high_q_sizer, 0, 
785                                                wx.BOTTOM|wx.RIGHT, 10)])
786       
787    def _layout_extrapolation(self):
788        """
789            Draw widgets related to extrapolation
790        """
791        extra_hint = "Extrapolation Maximum Q Range [1/A]: "
792        extra_hint_txt = wx.StaticText(self, -1, extra_hint)
793        #Extrapolation range [string]
794        extrapolation_min_txt = wx.StaticText(self, -1, 'Min : ') 
795        self.extrapolation_min_tcl = OutputTextCtrl(self, -1, 
796                                                size=(_BOX_WIDTH, 20), style=0)
797        self.extrapolation_min_tcl.SetValue(str(Q_MINIMUM))
798        self.extrapolation_min_tcl.SetToolTipString("The minimum extrapolated q value.")
799        extrapolation_max_txt = wx.StaticText(self, -1, 'Max : ') 
800        self.extrapolation_max_tcl = OutputTextCtrl(self, -1,
801                                                  size=(_BOX_WIDTH, 20), style=0) 
802        self.extrapolation_max_tcl.SetValue(str(Q_MAXIMUM))
803        self.extrapolation_max_tcl.SetToolTipString("The maximum extrapolated q value.")
804        self.extrapolation_range_sizer.AddMany([(extra_hint_txt, 0, wx.LEFT, 10),
805                                                (extrapolation_min_txt, 0, wx.LEFT, 10),
806                                                (self.extrapolation_min_tcl,
807                                                            0, wx.LEFT, 10),
808                                                (extrapolation_max_txt, 0, wx.LEFT, 10),
809                                                (self.extrapolation_max_tcl,
810                                                            0, wx.LEFT, 10),
811                                                ])
812        self._layout_extrapolation_low()
813        self._layout_extrapolation_high()
814        self.extrapolation_low_high_sizer.AddMany([(self.low_extrapolation_sizer,
815                                                     0, wx.ALL, 10),
816                                                   (self.high_extrapolation_sizer,
817                                                    0, wx.ALL, 10)])
818        self.extrapolation_sizer.AddMany([(self.extrapolation_range_sizer, 0,
819                                            wx.RIGHT, 10),
820                                        (self.extrapolation_low_high_sizer, 0,
821                                           wx.ALL, 10)])
822       
823    def _layout_volume_surface_sizer(self):
824        """
825            Draw widgets related to volume and surface
826        """
827        unit_volume = ''
828        unit_surface = ''
829        uncertainty = "+/-" 
830        volume_txt = wx.StaticText(self, -1, 'Volume Fraction')
831        self.volume_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH,-1))
832        self.volume_tcl.SetToolTipString("Volume fraction.")
833        self.volume_err_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH,-1))
834        self.volume_err_tcl.SetToolTipString("Uncertainty on the volume fraction.")
835        volume_units_txt = wx.StaticText(self, -1, unit_volume)
836       
837        surface_txt = wx.StaticText(self, -1, 'Specific Surface')
838        self.surface_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH,-1))
839        self.surface_tcl.SetToolTipString("Specific surface value.")
840        self.surface_err_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH,-1))
841        self.surface_err_tcl.SetToolTipString("Uncertainty on the specific surface.")
842        surface_units_txt = wx.StaticText(self, -1, unit_surface)
843        iy = 0
844        ix = 0
845        self.volume_surface_sizer.Add(volume_txt, (iy, ix), (1,1),
846                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
847        ix += 1
848        self.volume_surface_sizer.Add(self.volume_tcl, (iy, ix), (1,1),
849                            wx.EXPAND|wx.ADJUST_MINSIZE, 10)
850        ix += 1
851        self.volume_surface_sizer.Add(wx.StaticText(self, -1, uncertainty),
852                         (iy, ix),(1,1),wx.EXPAND|wx.ADJUST_MINSIZE, 10) 
853        ix += 1
854        self.volume_surface_sizer.Add(self.volume_err_tcl, (iy, ix), (1,1),
855                            wx.EXPAND|wx.ADJUST_MINSIZE, 10) 
856        ix += 1
857        self.volume_surface_sizer.Add(volume_units_txt, (iy, ix), (1,1),
858                             wx.EXPAND|wx.ADJUST_MINSIZE, 10)
859        iy += 1
860        ix = 0
861        self.volume_surface_sizer.Add(surface_txt, (iy, ix), (1,1),
862                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
863        ix += 1
864        self.volume_surface_sizer.Add(self.surface_tcl, (iy, ix), (1,1),
865                            wx.EXPAND|wx.ADJUST_MINSIZE, 0)
866        ix += 1
867        self.volume_surface_sizer.Add(wx.StaticText(self, -1, uncertainty),
868                         (iy, ix),(1,1),wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
869        ix += 1
870        self.volume_surface_sizer.Add(self.surface_err_tcl, (iy, ix), (1,1),
871                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
872        ix += 1
873        self.volume_surface_sizer.Add(surface_units_txt, (iy, ix), (1,1),
874                            wx.EXPAND|wx.ADJUST_MINSIZE, 10)
875       
876    def _layout_invariant_sizer(self):
877        """
878            Draw widgets related to invariant
879        """
880        uncertainty = "+/-" 
881        unit_invariant = '[1/(cm * A)]'
882        invariant_total_txt = wx.StaticText(self, -1, 'Invariant Total')
883        self.invariant_total_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH,-1))
884        msg_hint = "Total invariant, including extrapolated regions."
885        self.invariant_total_tcl.SetToolTipString(msg_hint)
886        self.invariant_total_err_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH,-1))
887        self.invariant_total_err_tcl.SetToolTipString("Uncertainty on invariant.")
888        invariant_total_units_txt = wx.StaticText(self, -1, unit_invariant)
889   
890        #Invariant total
891        iy = 0
892        ix = 0
893        self.invariant_sizer.Add(invariant_total_txt, (iy, ix), (1,1),
894                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
895        ix += 1
896        self.invariant_sizer.Add(self.invariant_total_tcl, (iy, ix), (1,1),
897                           wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 5)
898        ix += 1
899        self.invariant_sizer.Add( wx.StaticText(self, -1, uncertainty),
900                         (iy, ix),(1,1),wx.EXPAND|wx.ADJUST_MINSIZE, 10) 
901        ix += 1
902        self.invariant_sizer.Add(self.invariant_total_err_tcl, (iy, ix), (1,1),
903                             wx.EXPAND|wx.ADJUST_MINSIZE, 10)
904        ix += 1
905        self.invariant_sizer.Add(invariant_total_units_txt,(iy, ix), (1,1),
906                          wx.EXPAND|wx.ADJUST_MINSIZE, 10)
907 
908    def _layout_inputs_sizer(self):
909        """
910            Draw widgets related to inputs
911        """
912        self._layout_bkg_scale()
913        self._layout_contrast_porod()
914        self.inputs_sizer.AddMany([(self.bkg_scale_sizer, 0, wx.ALL, 5),
915                                    (self.contrast_porod_sizer, 0, wx.ALL, 5)])
916       
917    def _layout_outputs_sizer(self):
918        """
919            Draw widgets related to outputs
920        """
921        self._layout_volume_surface_sizer()
922        self._layout_invariant_sizer()
923        static_line = wx.StaticLine(self, -1)
924        self.outputs_sizer.AddMany([(self.volume_surface_sizer, 0, wx.ALL, 10),
925                                    (static_line, 0, wx.EXPAND, 0),
926                                    (self.invariant_sizer, 0, wx.ALL, 10)])
927    def _layout_button(self): 
928        """
929            Do the layout for the button widgets
930        """ 
931        #compute button
932        id = wx.NewId()
933        self.button_calculate = wx.Button(self, id, "Compute")
934        self.button_calculate.SetToolTipString("Compute invariant")
935        self.Bind(wx.EVT_BUTTON, self.compute_invariant, id=id)   
936        #detail button
937        id = wx.NewId()
938        self.button_details = wx.Button(self, id, "Details?")
939        self.button_details.SetToolTipString("Give Details on Computation")
940        self.Bind(wx.EVT_BUTTON, self.display_details, id=id)
941        details = "Details on Invariant Total Calculations"
942        details_txt = wx.StaticText(self, -1, details)
943        self.button_sizer.AddMany([((10,10), 0 , wx.LEFT,0),
944                                   (details_txt, 0 , 
945                                    wx.RIGHT|wx.BOTTOM|wx.TOP, 10),
946                                   (self.button_details, 0 , wx.ALL, 10),
947                        (self.button_calculate, 0 , wx.RIGHT|wx.TOP|wx.BOTTOM, 10)])
948       
949    def _do_layout(self):
950        """
951            Draw window content
952        """
953        self._define_structure()
954        self._layout_data_name()
955        self._layout_extrapolation()
956        self._layout_inputs_sizer()
957        self._layout_outputs_sizer()
958        self._layout_button()
959        self.main_sizer.AddMany([(self.data_name_boxsizer, 1, wx.ALL, 10),
960                                  (self.outputs_sizer, 0,
961                                  wx.LEFT|wx.RIGHT|wx.BOTTOM, 10),
962                                  (self.button_sizer, 0,
963                                  wx.LEFT|wx.RIGHT|wx.BOTTOM, 10),
964                                 (self.inputs_sizer, 0,
965                                  wx.LEFT|wx.RIGHT|wx.BOTTOM, 10),
966                                  (self.extrapolation_sizer, 0,
967                                  wx.LEFT|wx.RIGHT|wx.BOTTOM, 10)])
968        self.SetSizer(self.main_sizer)
969        self.SetScrollbars(20,20,25,65)
970        self.SetAutoLayout(True)
971   
972class InvariantDialog(wx.Dialog):
973    def __init__(self, parent=None, id=1,graph=None,
974                 data=None, title="Invariant",base=None):
975        wx.Dialog.__init__(self, parent, id, title, size=(PANEL_WIDTH,
976                                                             PANEL_HEIGHT))
977        self.panel = InvariantPanel(self)
978        self.Centre()
979        self.Show(True)
980       
981class InvariantWindow(wx.Frame):
982    def __init__(self, parent=None, id=1,graph=None, 
983                 data=None, title="Invariant",base=None):
984       
985        wx.Frame.__init__(self, parent, id, title, size=(PANEL_WIDTH +100,
986                                                             PANEL_HEIGHT+100))
987       
988        self.panel = InvariantPanel(self)
989        self.Centre()
990        self.Show(True)
991       
992class MyApp(wx.App):
993    def OnInit(self):
994        wx.InitAllImageHandlers()
995        frame = InvariantWindow()
996        frame.Show(True)
997        self.SetTopWindow(frame)
998       
999        return True
1000     
1001# end of class MyApp
1002
1003if __name__ == "__main__":
1004    app = MyApp(0)
1005    app.MainLoop()
Note: See TracBrowser for help on using the repository browser.