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

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

working on proper display of invariant panel on vista

  • Property mode set to 100644
File size: 44.5 KB
Line 
1"""
2    This module provide GUI for the neutron scattering length density calculator
3    @author: Gervaise B. Alina
4"""
5
6import wx
7
8import sys
9from wx.lib.scrolledpanel import ScrolledPanel
10from sans.invariant import invariant
11from sans.guiframe.utils import format_number, check_float
12from sans.guicomm.events import NewPlotEvent, StatusEvent
13from invariant_details import InvariantDetailsPanel, InvariantContainer
14from invariant_widgets import OutputTextCtrl, InvTextCtrl
15# The minimum q-value to be used when extrapolating
16Q_MINIMUM  = 1e-5
17# The maximum q-value to be used when extrapolating
18Q_MAXIMUM  = 10
19# the maximum value to plot the theory data
20Q_MAXIMUM_PLOT = 2
21# the number of points to consider during fit
22NPTS = 10
23#Default value for background
24BACKGROUND = 0.0
25#default value for the scale
26SCALE = 1.0
27#default value of the contrast
28CONTRAST = 1.0
29#default value of the power used for power law
30POWER = 4.0
31#Invariant panel size
32_BOX_WIDTH = 76
33
34if sys.platform.count("win32")>0:
35    _STATICBOX_WIDTH = 450
36    PANEL_WIDTH = 500
37    PANEL_HEIGHT = 700
38    FONT_VARIANT = 0
39else:
40    _STATICBOX_WIDTH = 480
41    PANEL_WIDTH = 530
42    PANEL_HEIGHT = 700
43    FONT_VARIANT = 1
44
45
46class InvariantPanel(ScrolledPanel):
47    """
48        Provides the Invariant GUI.
49    """
50    ## Internal nickname for the window, used by the AUI manager
51    window_name = "Invariant"
52    ## Name to appear on the window title bar
53    window_caption = "Invariant"
54    ## Flag to tell the AUI manager to put this panel in the center pane
55    CENTER_PANE = True
56    def __init__(self, parent, data=None, manager=None):
57        ScrolledPanel.__init__(self, parent)
58        #Font size
59        self.SetWindowVariant(variant=FONT_VARIANT)
60        #Object that receive status event
61        self.parent = parent
62        #plug-in using this panel
63        self._manager = manager
64        #Data uses for computation
65        self._data = data
66        #container of invariant value
67        self.inv_container = None
68        #Draw the panel
69        self._do_layout()
70        self.reset_panel()
71        if self.parent is not None:
72            msg = ""
73            wx.PostEvent(self.parent, StatusEvent(status=msg))
74        self.SetupScrolling()
75       
76    def err_check_on_data(self):
77        """
78            Check if data is valid for further computation
79        """
80        flag = False
81        #edit the panel
82        if self._data is not None:
83            if len(self._data.x[self._data.x==0]) > 0:
84                flag = True
85                msg = "Invariant: one of your q-values is zero. Delete that entry before proceeding"
86                wx.PostEvent(self.parent, StatusEvent(status= msg, type="stop")) 
87        return flag
88   
89    def set_data(self, data):
90        """
91            Set the data
92        """
93        self._data = data
94        #edit the panel
95        if self._data is not None:
96            self.err_check_on_data()
97            data_name = self._data.name
98            data_qmin = min (self._data.x)
99            data_qmax = max (self._data.x)
100            self.data_name_tcl.SetValue(str(data_name))
101            self.data_min_tcl.SetLabel(str(data_qmin))
102            self.data_max_tcl.SetLabel(str(data_qmax))
103            self.hint_msg_txt.SetLabel('')
104            self.reset_panel()
105            self.compute_invariant(event=None)
106             
107    def set_message(self):
108        """
109            Display warning message if available
110        """
111        if self.inv_container is not None:
112            if self.inv_container.existing_warning:
113                msg = "Warning! Computations on invariant require your "
114                msg += "attention.\n Please click on Details button."
115                self.hint_msg_txt.SetForegroundColour("red")
116            else:
117                msg = "For more information, click on Details button."
118                self.hint_msg_txt.SetForegroundColour("black")
119            self.hint_msg_txt.SetLabel(msg)
120        self.data_name_boxsizer.Layout()
121       
122    def set_manager(self, manager):
123        """
124            set value for the manager
125        """
126        self._manager = manager
127   
128    def get_background(self):
129        """
130            @return the background textcrtl value as a float
131        """
132        background = self.background_tcl.GetValue().lstrip().rstrip()
133        if background == "":
134            raise ValueError, "Need a background"
135        if check_float(self.background_tcl):
136            return float(background)
137        else:
138            raise ValueError, "Receive invalid value for background : %s"%(background)
139   
140    def get_scale(self):
141        """
142            @return the scale textcrtl value as a float
143        """
144        scale = self.scale_tcl.GetValue().lstrip().rstrip()
145        if scale == "":
146            raise ValueError, "Need a background"
147        if check_float(self.scale_tcl):
148            return float(scale)
149        else:
150            raise ValueError, "Receive invalid value for background : %s"%(scale)
151       
152    def get_contrast(self):
153        """
154            @return the contrast textcrtl value as a float
155        """
156        par_str = self.contrast_tcl.GetValue().strip()
157        contrast = None
158        if par_str !="" and check_float(self.contrast_tcl):
159            contrast = float(par_str)
160        return contrast
161   
162    def get_extrapolation_type(self, low_q, high_q):
163        """
164        """
165        extrapolation = None
166        if low_q  and not high_q:
167            extrapolation = "low"
168        elif not low_q  and high_q:
169            extrapolation = "high"
170        elif low_q and high_q:
171            extrapolation = "both"
172        return extrapolation
173           
174    def get_porod_const(self):
175        """
176            @return the porod constant textcrtl value as a float
177        """
178        par_str = self.porod_constant_tcl.GetValue().strip()
179        porod_const = None
180        if par_str !="" and check_float(self.porod_constant_tcl):
181            porod_const = float(par_str)
182        return porod_const
183   
184    def get_volume(self, inv, contrast, extrapolation):
185        """
186        """
187        if contrast is not None:
188            try:
189                v, dv = inv.get_volume_fraction_with_error(contrast=contrast, 
190                                                           extrapolation=extrapolation)
191                self.volume_tcl.SetValue(format_number(v))
192                self.volume_err_tcl.SetValue(format_number(dv))
193            except:
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.porod_constant_tcl.SetValue('') 
431        self.npts_low_tcl.SetValue(str(NPTS))
432        self.enable_low_cbox.SetValue(False)
433        self.fix_enable_low.SetValue(True)
434        self.power_low_tcl.SetValue(str(POWER))
435        self.guinier.SetValue(True)
436        self.power_low_tcl.Disable()
437        self.enable_high_cbox.SetValue(False)
438        self.fix_enable_high.SetValue(True)
439        self.power_high_tcl.SetValue(str(POWER))
440        self.npts_high_tcl.SetValue(str(NPTS))
441        self.button_details.Disable()
442        #Change the state of txtcrtl to enable/disable
443        self._enable_low_q_section()
444        #Change the state of txtcrtl to enable/disable
445        self._enable_high_q_section()
446        self._reset_output()
447        self.button_calculate.SetFocus()
448       
449    def _reset_output(self):
450        """
451            clear outputs textcrtl
452        """
453        self.invariant_total_tcl.Clear()
454        self.invariant_total_err_tcl.Clear()
455        self.volume_tcl.Clear()
456        self.volume_err_tcl.Clear()
457        self.surface_tcl.Clear()
458        self.surface_err_tcl.Clear()
459        #prepare a new container to put result of invariant
460        self.inv_container = InvariantContainer()
461       
462    def _define_structure(self):
463        """
464            Define main sizers needed for this panel
465        """
466        ## Box sizers must be defined first before defining buttons/textctrls (MAC).
467        self.main_sizer = wx.BoxSizer(wx.VERTICAL)
468        #Sizer related to outputs
469        outputs_box = wx.StaticBox(self, -1, "Outputs")
470        self.outputs_sizer = wx.StaticBoxSizer(outputs_box, wx.VERTICAL)
471        self.outputs_sizer.SetMinSize((PANEL_WIDTH,-1))
472        #Sizer related to data
473        data_name_box = wx.StaticBox(self, -1, "I(q) Data Source")
474        self.data_name_boxsizer = wx.StaticBoxSizer(data_name_box, wx.VERTICAL)
475        self.data_name_boxsizer.SetMinSize((PANEL_WIDTH,-1))
476        self.hint_msg_sizer = wx.BoxSizer(wx.HORIZONTAL)
477        self.data_name_sizer = wx.BoxSizer(wx.HORIZONTAL)
478        self.data_range_sizer = wx.BoxSizer(wx.HORIZONTAL)
479        #Sizer related to background and scale
480        self.bkg_scale_sizer = wx.BoxSizer(wx.HORIZONTAL) 
481        #Sizer related to contrast and porod constant
482        self.contrast_porod_sizer = wx.BoxSizer(wx.HORIZONTAL) 
483        #Sizer related to inputs
484        inputs_box = wx.StaticBox(self, -1, "Customized Inputs")
485        self.inputs_sizer = wx.StaticBoxSizer(inputs_box, wx.VERTICAL)
486        #Sizer related to extrapolation
487        extrapolation_box = wx.StaticBox(self, -1, "Extrapolation")
488        self.extrapolation_sizer = wx.StaticBoxSizer(extrapolation_box,
489                                                        wx.VERTICAL)
490        self.extrapolation_sizer.SetMinSize((PANEL_WIDTH,-1))
491        self.extrapolation_range_sizer = wx.BoxSizer(wx.HORIZONTAL)
492        self.extrapolation_low_high_sizer = wx.BoxSizer(wx.HORIZONTAL)
493        #Sizer related to extrapolation at low q range
494        low_q_box = wx.StaticBox(self, -1, "Low Q")
495        self.low_extrapolation_sizer = wx.StaticBoxSizer(low_q_box, wx.VERTICAL)
496        self.low_q_sizer = wx.GridBagSizer(5,5)
497        #Sizer related to extrapolation at low q range
498        high_q_box = wx.StaticBox(self, -1, "High Q")
499        self.high_extrapolation_sizer = wx.StaticBoxSizer(high_q_box, wx.VERTICAL)
500        self.high_q_sizer = wx.GridBagSizer(5,5)
501        #sizer to define outputs
502        self.volume_surface_sizer = wx.GridBagSizer(5,5)
503        #Sizer related to invariant output
504        self.invariant_sizer = wx.GridBagSizer(5, 5)
505        #Sizer related to button
506        self.button_sizer = wx.BoxSizer(wx.HORIZONTAL)
507       
508    def _layout_data_name(self):
509        """
510            Draw widgets related to data's name
511        """
512        #Sizer hint
513        hint_msg = "First open data file from 'File' menu.  Then Highlight and right click on the data plot. \n"
514        hint_msg += "Finally, select 'Compute Invariant'. \n"
515        self.hint_msg_txt = wx.StaticText(self, -1, hint_msg) 
516        self.hint_msg_txt.SetForegroundColour("red")
517        msg = "Highlight = mouse the mouse's cursor on the data until the plot's color changes to yellow"
518        self.hint_msg_txt.SetToolTipString(msg)
519        self.hint_msg_sizer.Add(self.hint_msg_txt)
520        #Data name [string]
521        data_name_txt = wx.StaticText(self, -1, 'Data : ') 
522       
523        self.data_name_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH*5, 20), style=0) 
524        self.data_name_tcl.SetToolTipString("Data's name.")
525        self.data_name_sizer.AddMany([(data_name_txt, 0, wx.LEFT|wx.RIGHT, 10),
526                                       (self.data_name_tcl, 0, wx.EXPAND)])
527        #Data range [string]
528        data_range_txt = wx.StaticText(self, -1, 'Total Q Range (1/A): ') 
529        data_min_txt = wx.StaticText(self, -1, 'Min : ') 
530        self.data_min_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH, 20), style=0)
531        self.data_min_tcl.SetToolTipString("The minimum value of q range.")
532        data_max_txt = wx.StaticText(self, -1, 'Max : ') 
533        self.data_max_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH, 20), style=0) 
534        self.data_max_tcl.SetToolTipString("The maximum value of q range.")
535        self.data_range_sizer.AddMany([(data_range_txt, 0, wx.RIGHT, 10),
536                                       (data_min_txt, 0, wx.RIGHT, 10),
537                                       (self.data_min_tcl, 0, wx.RIGHT, 10),
538                                       (data_max_txt, 0, wx.RIGHT, 10),
539                                       (self.data_max_tcl, 0, wx.RIGHT, 10)])
540        self.data_name_boxsizer.AddMany([(self.hint_msg_sizer, 0 , wx.ALL, 10),
541                                         (self.data_name_sizer, 0 , wx.RIGHT, 10),
542                                         (self.data_range_sizer, 0 , wx.ALL, 10)])
543   
544    def _layout_bkg_scale(self):
545        """
546            Draw widgets related to background and scale
547        """
548        background_txt = wx.StaticText(self, -1, 'Background : ') 
549        self.background_tcl = InvTextCtrl(self, -1, size=(_BOX_WIDTH, 20), style=0) 
550        background_hint_txt = "background"
551        self.background_tcl.SetToolTipString(background_hint_txt)
552        background_unit_txt = wx.StaticText(self, -1, '[1/cm]') 
553        scale_txt = wx.StaticText(self, -1, 'Scale : ') 
554        self.scale_tcl = InvTextCtrl(self, -1, size=(_BOX_WIDTH, 20), style=0)
555        scale_hint_txt = "Scale"
556        self.scale_tcl.SetToolTipString(scale_hint_txt)
557        self.bkg_scale_sizer.AddMany([(background_txt, 0, wx.LEFT, 10),
558                                       (self.background_tcl, 0, wx.LEFT, 5),
559                                       (background_unit_txt, 0, wx.LEFT, 10),
560                                       (scale_txt, 0, wx.LEFT, 70),
561                                       (self.scale_tcl, 0, wx.LEFT, 40)])
562 
563    def _layout_contrast_porod(self):
564        """
565            Draw widgets related to porod constant and contrast
566        """
567        contrast_txt = wx.StaticText(self, -1, 'Contrast : ') 
568        self.contrast_tcl = InvTextCtrl(self, -1, size=(_BOX_WIDTH, 20), style=0)
569        contrast_hint_txt = "Contrast"
570        self.contrast_tcl.SetToolTipString(contrast_hint_txt)
571        contrast_unit_txt = wx.StaticText(self, -1, '[1/A^(2)]') 
572        porod_const_txt = wx.StaticText(self, -1, 'Porod Constant:') 
573        self.porod_constant_tcl = InvTextCtrl(self, -1, 
574                                              size=(_BOX_WIDTH, 20), style=0) 
575        porod_const_hint_txt = "Porod Constant"
576        self.porod_constant_tcl.SetToolTipString(porod_const_hint_txt)
577        optional_txt = wx.StaticText(self, -1, '(Optional)') 
578        self.contrast_porod_sizer.AddMany([(contrast_txt, 0, wx.LEFT, 10),
579                                           (self.contrast_tcl, 0, wx.LEFT, 20),
580                                           (contrast_unit_txt, 0, wx.LEFT, 10),
581                                           (porod_const_txt, 0, wx.LEFT, 50),
582                                       (self.porod_constant_tcl, 0, wx.LEFT, 0),
583                                       (optional_txt, 0, wx.LEFT, 10)])
584       
585    def _enable_fit_power_law_low(self, event=None):
586        """
587            Enable and disable the power value editing
588        """
589        if self.fix_enable_low.IsEnabled():
590            if self.fix_enable_low.GetValue():
591                self.power_low_tcl.Enable()
592            else:
593                self.power_low_tcl.Disable()
594           
595    def _enable_low_q_section(self, event=None):
596        """
597            Disable or enable some button if the user enable low q extrapolation
598        """
599        if self.enable_low_cbox.GetValue():
600            self.npts_low_tcl.Enable()
601            self.fix_enable_low.Enable()
602            self.fit_enable_low.Enable()
603            self.guinier.Enable()
604            self.power_law_low.Enable()
605
606        else:
607            self.npts_low_tcl.Disable()
608            self.fix_enable_low.Disable()
609            self.fit_enable_low.Disable()
610            self.guinier.Disable()
611            self.power_law_low.Disable()
612        self._enable_power_law_low()
613        self._enable_fit_power_law_low()
614        self.button_calculate.SetFocus()
615   
616    def _enable_power_law_low(self, event=None):
617        """
618            Enable editing power law section at low q range
619        """
620        if self.guinier.GetValue():
621            self.fix_enable_low.Disable()
622            self.fit_enable_low.Disable()
623            self.power_low_tcl.Disable()
624        else:
625            self.fix_enable_low.Enable()
626            self.fit_enable_low.Enable()
627            self.power_low_tcl.Enable()
628        self._enable_fit_power_law_low()
629           
630    def _layout_extrapolation_low(self):
631        """
632            Draw widgets related to extrapolation at low q range
633        """
634        self.enable_low_cbox = wx.CheckBox(self, -1, "Enable Extrapolate Low Q")
635        wx.EVT_CHECKBOX(self, self.enable_low_cbox.GetId(),
636                                         self._enable_low_q_section)
637        self.fix_enable_low = wx.RadioButton(self, -1, 'Fix',
638                                         (10, 10),style=wx.RB_GROUP)
639        self.fit_enable_low = wx.RadioButton(self, -1, 'Fit', (10, 10))
640        self.Bind(wx.EVT_RADIOBUTTON, self._enable_fit_power_law_low,
641                                     id=self.fix_enable_low.GetId())
642        self.Bind(wx.EVT_RADIOBUTTON, self._enable_fit_power_law_low, 
643                                        id=self.fit_enable_low.GetId())
644        self.guinier = wx.RadioButton(self, -1, 'Guinier',
645                                         (10, 10),style=wx.RB_GROUP)
646        self.power_law_low = wx.RadioButton(self, -1, 'Power Law', (10, 10))
647        self.Bind(wx.EVT_RADIOBUTTON, self._enable_power_law_low,
648                                     id=self.guinier.GetId())
649        self.Bind(wx.EVT_RADIOBUTTON, self._enable_power_law_low, 
650                                        id=self.power_law_low.GetId())
651       
652        npts_low_txt = wx.StaticText(self, -1, 'Npts')
653        self.npts_low_tcl = InvTextCtrl(self, -1, size=(_BOX_WIDTH*2/3, -1))
654        msg_hint = "Number of Q points to consider"
655        msg_hint +="while extrapolating the low-Q region"
656        self.npts_low_tcl.SetToolTipString(msg_hint)
657        power_txt = wx.StaticText(self, -1, 'Power')
658        self.power_low_tcl = InvTextCtrl(self, -1, size=(_BOX_WIDTH*2/3, -1))
659       
660        power_hint_txt = "Exponent to apply to the Power_law function."
661        self.power_low_tcl.SetToolTipString(power_hint_txt)
662        iy = 0
663        ix = 0
664        self.low_q_sizer.Add(self.enable_low_cbox,(iy, ix),(1,5),
665                            wx.TOP|wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
666        iy += 1
667        ix = 0
668        self.low_q_sizer.Add(npts_low_txt,(iy, ix),(1,1),
669                            wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
670        ix += 1
671        self.low_q_sizer.Add(self.npts_low_tcl, (iy, ix), (1,1),
672                            wx.EXPAND|wx.ADJUST_MINSIZE, 0)
673        iy += 1
674        ix = 0
675        self.low_q_sizer.Add(self.guinier,(iy, ix),(1,2),
676                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
677        iy += 1
678        ix = 0
679        self.low_q_sizer.Add(self.power_law_low,(iy, ix),(1,2),
680                            wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
681       
682        # Parameter controls for power law
683        ix = 1
684        iy += 1
685        self.low_q_sizer.Add(self.fix_enable_low,(iy, ix),(1,1),
686                            wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
687        ix += 1
688        self.low_q_sizer.Add(self.fit_enable_low,(iy, ix),(1,1),
689                           wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
690        ix = 1
691        iy += 1
692        self.low_q_sizer.Add(power_txt,(iy, ix),(1,1),
693                            wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
694        ix += 1
695        self.low_q_sizer.Add(self.power_low_tcl, (iy, ix), (1,1),
696                            wx.EXPAND|wx.ADJUST_MINSIZE, 0)
697        self.low_extrapolation_sizer.AddMany([(self.low_q_sizer, 0,
698                                                wx.BOTTOM|wx.RIGHT, 15)])
699       
700    def _enable_fit_power_law_high(self, event=None):
701        """
702            Enable and disable the power value editing
703        """
704        if self.fix_enable_high.IsEnabled():
705            if self.fix_enable_high.GetValue():
706                self.power_high_tcl.Enable()
707            else:
708                self.power_high_tcl.Disable()
709       
710    def _enable_high_q_section(self, event=None):
711        """
712            Disable or enable some button if the user enable high q extrapolation
713        """
714        if self.enable_high_cbox.GetValue():
715            self.npts_high_tcl.Enable()
716            self.power_law_high.Enable()
717            self.power_high_tcl.Enable()
718            self.fix_enable_high.Enable()
719            self.fit_enable_high.Enable()
720        else:
721            self.npts_high_tcl.Disable()
722            self.power_law_high.Disable()
723            self.power_high_tcl.Disable()
724            self.fix_enable_high.Disable()
725            self.fit_enable_high.Disable()
726        self._enable_fit_power_law_high()
727        self.button_calculate.SetFocus()
728 
729    def _layout_extrapolation_high(self):
730        """
731            Draw widgets related to extrapolation at high q range
732        """
733        self.enable_high_cbox = wx.CheckBox(self, -1, "Enable Extrapolate high-Q")
734        wx.EVT_CHECKBOX(self, self.enable_high_cbox.GetId(),
735                                         self._enable_high_q_section)
736     
737        self.fix_enable_high = wx.RadioButton(self, -1, 'Fix',
738                                         (10, 10),style=wx.RB_GROUP)
739        self.fit_enable_high = wx.RadioButton(self, -1, 'Fit', (10, 10))
740        self.Bind(wx.EVT_RADIOBUTTON, self._enable_fit_power_law_high,
741                                     id=self.fix_enable_high.GetId())
742        self.Bind(wx.EVT_RADIOBUTTON, self._enable_fit_power_law_high, 
743                                        id=self.fit_enable_high.GetId())
744       
745        self.power_law_high = wx.StaticText(self, -1, 'Power Law')
746        msg_hint ="Check to extrapolate data at high-Q"
747        self.power_law_high.SetToolTipString(msg_hint)
748        npts_high_txt = wx.StaticText(self, -1, 'Npts')
749        self.npts_high_tcl = InvTextCtrl(self, -1, size=(_BOX_WIDTH*2/3, -1))
750        msg_hint = "Number of Q points to consider"
751        msg_hint += "while extrapolating the high-Q region"
752        self.npts_high_tcl.SetToolTipString(msg_hint)
753        power_txt = wx.StaticText(self, -1, 'Power')
754        self.power_high_tcl = InvTextCtrl(self, -1, size=(_BOX_WIDTH*2/3, -1))
755        power_hint_txt = "Exponent to apply to the Power_law function."
756        self.power_high_tcl.SetToolTipString(power_hint_txt)
757        iy = 0
758        ix = 0
759        self.high_q_sizer.Add(self.enable_high_cbox,(iy, ix),(1,5),
760                            wx.TOP|wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
761        iy += 1
762        ix = 0
763        self.high_q_sizer.Add(npts_high_txt,(iy, ix),(1,1),
764                            wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
765        ix += 1
766        self.high_q_sizer.Add(self.npts_high_tcl, (iy, ix), (1,1),
767                            wx.EXPAND|wx.ADJUST_MINSIZE, 0)
768        iy += 2
769        ix = 0
770        self.high_q_sizer.Add(self.power_law_high,(iy, ix),(1,2),
771                            wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
772       
773        # Parameter controls for power law
774        ix = 1
775        iy += 1
776        self.high_q_sizer.Add(self.fix_enable_high,(iy, ix),(1,1),
777                            wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
778        ix += 1
779        self.high_q_sizer.Add(self.fit_enable_high,(iy, ix),(1,1),
780                           wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
781        ix = 1
782        iy += 1
783        self.high_q_sizer.Add(power_txt,(iy, ix),(1,1),
784                            wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
785        ix += 1
786        self.high_q_sizer.Add(self.power_high_tcl, (iy, ix), (1,1),
787                            wx.EXPAND|wx.ADJUST_MINSIZE, 0)
788        self.high_extrapolation_sizer.AddMany([(self.high_q_sizer, 0, 
789                                                wx.BOTTOM|wx.RIGHT, 10)])
790       
791    def _layout_extrapolation(self):
792        """
793            Draw widgets related to extrapolation
794        """
795        extra_hint = "Extrapolation Maximum Q Range [1/A]: "
796        extra_hint_txt = wx.StaticText(self, -1, extra_hint)
797        #Extrapolation range [string]
798        extrapolation_min_txt = wx.StaticText(self, -1, 'Min : ') 
799        self.extrapolation_min_tcl = OutputTextCtrl(self, -1, 
800                                                size=(_BOX_WIDTH, 20), style=0)
801        self.extrapolation_min_tcl.SetValue(str(Q_MINIMUM))
802        self.extrapolation_min_tcl.SetToolTipString("The minimum extrapolated q value.")
803        extrapolation_max_txt = wx.StaticText(self, -1, 'Max : ') 
804        self.extrapolation_max_tcl = OutputTextCtrl(self, -1,
805                                                  size=(_BOX_WIDTH, 20), style=0) 
806        self.extrapolation_max_tcl.SetValue(str(Q_MAXIMUM))
807        self.extrapolation_max_tcl.SetToolTipString("The maximum extrapolated q value.")
808        self.extrapolation_range_sizer.AddMany([(extra_hint_txt, 0, wx.LEFT, 10),
809                                                (extrapolation_min_txt, 0, wx.LEFT, 10),
810                                                (self.extrapolation_min_tcl,
811                                                            0, wx.LEFT, 10),
812                                                (extrapolation_max_txt, 0, wx.LEFT, 10),
813                                                (self.extrapolation_max_tcl,
814                                                            0, wx.LEFT, 10),
815                                                ])
816        self._layout_extrapolation_low()
817        self._layout_extrapolation_high()
818        self.extrapolation_low_high_sizer.AddMany([(self.low_extrapolation_sizer,
819                                                     0, wx.ALL, 10),
820                                                   (self.high_extrapolation_sizer,
821                                                    0, wx.ALL, 10)])
822        self.extrapolation_sizer.AddMany([(self.extrapolation_range_sizer, 0,
823                                            wx.RIGHT, 10),
824                                        (self.extrapolation_low_high_sizer, 0,
825                                           wx.ALL, 10)])
826       
827    def _layout_volume_surface_sizer(self):
828        """
829            Draw widgets related to volume and surface
830        """
831        unit_volume = ''
832        unit_surface = ''
833        uncertainty = "+/-" 
834        volume_txt = wx.StaticText(self, -1, 'Volume Fraction      ')
835        self.volume_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH,-1))
836        self.volume_tcl.SetToolTipString("Volume fraction.")
837        self.volume_err_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH,-1))
838        self.volume_err_tcl.SetToolTipString("Uncertainty on the volume fraction.")
839        volume_units_txt = wx.StaticText(self, -1, unit_volume)
840       
841        surface_txt = wx.StaticText(self, -1, 'Specific Surface')
842        self.surface_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH,-1))
843        self.surface_tcl.SetToolTipString("Specific surface value.")
844        self.surface_err_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH,-1))
845        self.surface_err_tcl.SetToolTipString("Uncertainty on the specific surface.")
846        surface_units_txt = wx.StaticText(self, -1, unit_surface)
847        iy = 0
848        ix = 0
849        self.volume_surface_sizer.Add(volume_txt, (iy, ix), (1,1),
850                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
851        ix += 1
852        self.volume_surface_sizer.Add(self.volume_tcl, (iy, ix), (1,1),
853                            wx.EXPAND|wx.ADJUST_MINSIZE, 10)
854        ix += 1
855        self.volume_surface_sizer.Add(wx.StaticText(self, -1, uncertainty),
856                         (iy, ix),(1,1),wx.EXPAND|wx.ADJUST_MINSIZE, 10) 
857        ix += 1
858        self.volume_surface_sizer.Add(self.volume_err_tcl, (iy, ix), (1,1),
859                            wx.EXPAND|wx.ADJUST_MINSIZE, 10) 
860        ix += 1
861        self.volume_surface_sizer.Add(volume_units_txt, (iy, ix), (1,1),
862                             wx.EXPAND|wx.ADJUST_MINSIZE, 10)
863        iy += 1
864        ix = 0
865        self.volume_surface_sizer.Add(surface_txt, (iy, ix), (1,1),
866                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
867        ix += 1
868        self.volume_surface_sizer.Add(self.surface_tcl, (iy, ix), (1,1),
869                            wx.EXPAND|wx.ADJUST_MINSIZE, 0)
870        ix += 1
871        self.volume_surface_sizer.Add(wx.StaticText(self, -1, uncertainty),
872                         (iy, ix),(1,1),wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
873        ix += 1
874        self.volume_surface_sizer.Add(self.surface_err_tcl, (iy, ix), (1,1),
875                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
876        ix += 1
877        self.volume_surface_sizer.Add(surface_units_txt, (iy, ix), (1,1),
878                            wx.EXPAND|wx.ADJUST_MINSIZE, 10)
879       
880    def _layout_invariant_sizer(self):
881        """
882            Draw widgets related to invariant
883        """
884        uncertainty = "+/-" 
885        unit_invariant = '[1/(cm * A)]'
886        invariant_total_txt = wx.StaticText(self, -1, 'Invariant Total [Q*]')
887        self.invariant_total_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH,-1))
888        msg_hint = "Total invariant [Q*], including extrapolated regions."
889        self.invariant_total_tcl.SetToolTipString(msg_hint)
890        self.invariant_total_err_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH,-1))
891        self.invariant_total_err_tcl.SetToolTipString("Uncertainty on invariant.")
892        invariant_total_units_txt = wx.StaticText(self, -1, unit_invariant)
893   
894        #Invariant total
895        iy = 0
896        ix = 0
897        self.invariant_sizer.Add(invariant_total_txt, (iy, ix), (1,1),
898                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
899        ix += 1
900        self.invariant_sizer.Add(self.invariant_total_tcl, (iy, ix), (1,1),
901                          wx.EXPAND|wx.ADJUST_MINSIZE, 10)
902        ix += 1
903        self.invariant_sizer.Add( wx.StaticText(self, -1, uncertainty),
904                         (iy, ix),(1,1),wx.EXPAND|wx.ADJUST_MINSIZE, 10) 
905        ix += 1
906        self.invariant_sizer.Add(self.invariant_total_err_tcl, (iy, ix), (1,1),
907                             wx.EXPAND|wx.ADJUST_MINSIZE, 10)
908        ix += 1
909        self.invariant_sizer.Add(invariant_total_units_txt,(iy, ix), (1,1),
910                          wx.EXPAND|wx.ADJUST_MINSIZE, 10)
911 
912    def _layout_inputs_sizer(self):
913        """
914            Draw widgets related to inputs
915        """
916        self._layout_bkg_scale()
917        self._layout_contrast_porod()
918        self.inputs_sizer.AddMany([(self.bkg_scale_sizer, 0, wx.ALL, 5),
919                                    (self.contrast_porod_sizer, 0, wx.ALL, 5)])
920       
921    def _layout_outputs_sizer(self):
922        """
923            Draw widgets related to outputs
924        """
925        self._layout_volume_surface_sizer()
926        self._layout_invariant_sizer()
927        static_line = wx.StaticLine(self, -1)
928        self.outputs_sizer.AddMany([(self.volume_surface_sizer, 0, wx.ALL, 10),
929                                    (static_line, 0, wx.EXPAND, 0),
930                                    (self.invariant_sizer, 0, wx.ALL, 10)])
931    def _layout_button(self): 
932        """
933            Do the layout for the button widgets
934        """ 
935        #compute button
936        id = wx.NewId()
937        self.button_calculate = wx.Button(self, id, "Compute")
938        self.button_calculate.SetToolTipString("Compute invariant")
939        self.Bind(wx.EVT_BUTTON, self.compute_invariant, id=id)   
940        #detail button
941        id = wx.NewId()
942        self.button_details = wx.Button(self, id, "Details?")
943        self.button_details.SetToolTipString("Give Details on Computation")
944        self.Bind(wx.EVT_BUTTON, self.display_details, id=id)
945        details = "Details on Invariant Total Calculations"
946        details_txt = wx.StaticText(self, -1, details)
947        self.button_sizer.AddMany([((10,10), 0 , wx.LEFT,0),
948                                   (details_txt, 0 , 
949                                    wx.RIGHT|wx.BOTTOM|wx.TOP, 10),
950                                   (self.button_details, 0 , wx.ALL, 10),
951                        (self.button_calculate, 0 , wx.RIGHT|wx.TOP|wx.BOTTOM, 10)])
952       
953    def _do_layout(self):
954        """
955            Draw window content
956        """
957        self._define_structure()
958        self._layout_data_name()
959        self._layout_extrapolation()
960        self._layout_inputs_sizer()
961        self._layout_outputs_sizer()
962        self._layout_button()
963        self.main_sizer.AddMany([(self.data_name_boxsizer, 1, wx.ALL, 10),
964                                  (self.outputs_sizer, 0,
965                                  wx.LEFT|wx.RIGHT|wx.BOTTOM, 10),
966                                  (self.button_sizer, 0,
967                                  wx.LEFT|wx.RIGHT|wx.BOTTOM, 10),
968                                 (self.inputs_sizer, 0,
969                                  wx.LEFT|wx.RIGHT|wx.BOTTOM, 10),
970                                  (self.extrapolation_sizer, 0,
971                                  wx.LEFT|wx.RIGHT|wx.BOTTOM, 10)])
972        self.SetSizer(self.main_sizer)
973        #self.SetAutoLayout(True)
974   
975class InvariantDialog(wx.Dialog):
976    def __init__(self, parent=None, id=1,graph=None,
977                 data=None, title="Invariant",base=None):
978        wx.Dialog.__init__(self, parent, id, title, size=(PANEL_WIDTH,
979                                                             PANEL_HEIGHT))
980        self.panel = InvariantPanel(self)
981        self.Centre()
982        self.Show(True)
983       
984class InvariantWindow(wx.Frame):
985    def __init__(self, parent=None, id=1,graph=None, 
986                 data=None, title="Invariant",base=None):
987       
988        wx.Frame.__init__(self, parent, id, title, size=(PANEL_WIDTH +100,
989                                                             PANEL_HEIGHT+100))
990       
991        self.panel = InvariantPanel(self)
992        self.Centre()
993        self.Show(True)
994       
995class MyApp(wx.App):
996    def OnInit(self):
997        wx.InitAllImageHandlers()
998        frame = InvariantWindow()
999        frame.Show(True)
1000        self.SetTopWindow(frame)
1001       
1002        return True
1003     
1004# end of class MyApp
1005
1006if __name__ == "__main__":
1007    app = MyApp(0)
1008    app.MainLoop()
Note: See TracBrowser for help on using the repository browser.