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

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 d5f0f5e3 was be738e3, checked in by Jae Cho <jhjcho@…>, 14 years ago

a little fix on set state

  • Property mode set to 100644
File size: 75.7 KB
RevLine 
[c128284]1"""
[d7a39e5]2This module provide GUI for the neutron scattering length density calculator
3
[c128284]4"""
[4a2b054]5import copy
6import time
7import sys
8import os
[c128284]9import wx
[9abec44]10from wx.lib.scrolledpanel import ScrolledPanel
[272d91e]11from sans.invariant import invariant
[4a2b054]12from sans.guiframe.utils import format_number
13from sans.guiframe.utils import check_float
[f1e06a8e]14from sans.guiframe.events import StatusEvent
[cb69775]15from sans.guiframe.events import AppendBookmarkEvent
[f1e06a8e]16from .invariant_details import InvariantDetailsPanel
17from .invariant_details import InvariantContainer
18from .invariant_widgets import OutputTextCtrl
19from .invariant_widgets import InvTextCtrl
20from .invariant_state import InvariantState as IState
[6a0cbcf4]21from sans.guiframe.panel_base import PanelBase
[c128284]22# The minimum q-value to be used when extrapolating
23Q_MINIMUM  = 1e-5
24# The maximum q-value to be used when extrapolating
25Q_MAXIMUM  = 10
[90b9a17]26# the ratio of maximum q value/(qmax of data) to plot the theory data
27Q_MAXIMUM_PLOT = 3
[c128284]28# the number of points to consider during fit
29NPTS = 10
30#Default value for background
31BACKGROUND = 0.0
32#default value for the scale
33SCALE = 1.0
[9ce7641c]34#default value of the contrast
35CONTRAST = 1.0
[d0cc0bbc]36#default value of the power used for power law
37POWER = 4.0
[c128284]38#Invariant panel size
39_BOX_WIDTH = 76
40
[4e1c362]41
[4a2b054]42if sys.platform.count("win32") > 0:
[c128284]43    _STATICBOX_WIDTH = 450
[355b684]44    PANEL_WIDTH = 500 
[c128284]45    PANEL_HEIGHT = 700
46    FONT_VARIANT = 0
47else:
48    _STATICBOX_WIDTH = 480
49    PANEL_WIDTH = 530
50    PANEL_HEIGHT = 700
51    FONT_VARIANT = 1
[d0cc0bbc]52
53
[6a0cbcf4]54class InvariantPanel(ScrolledPanel, PanelBase):
[c128284]55    """
[d7a39e5]56    Provides the Invariant GUI.
[c128284]57    """
58    ## Internal nickname for the window, used by the AUI manager
59    window_name = "Invariant"
60    ## Name to appear on the window title bar
61    window_caption = "Invariant"
62    ## Flag to tell the AUI manager to put this panel in the center pane
63    CENTER_PANE = True
[4a2b054]64    def __init__(self, parent, data=None, manager=None, *args, **kwds):
65        kwds["size"] = (PANEL_WIDTH, PANEL_HEIGHT)
66        kwds["style"] = wx.FULL_REPAINT_ON_RESIZE
[355b684]67        ScrolledPanel.__init__(self, parent=parent, *args, **kwds)
[27f3831]68        PanelBase.__init__(self, parent)
[3de66c1]69        self.SetupScrolling()
[c128284]70        #Font size
71        self.SetWindowVariant(variant=FONT_VARIANT)
72        #Object that receive status event
73        self.parent = parent
[272d91e]74        #plug-in using this panel
75        self._manager = manager
76        #Data uses for computation
77        self._data = data
[6d55d81]78        self._scale = SCALE
79        self._background = BACKGROUND
[4e1c362]80        self._bmark = None
81        self.bookmark_num = 0
82       
[cb69775]83        #self._set_bookmark_menu()
[4e1c362]84        #Init state
85        self.set_state()
86        # default flags for state
87        self.new_state = False
[d318616]88        self.is_state_data = False
[f24925ab]89        self.is_power_out = False
[cef847c]90
[9ce7641c]91        #container of invariant value
92        self.inv_container = None
[c128284]93        #Draw the panel
94        self._do_layout()
[d0cc0bbc]95        self.reset_panel()
[4e1c362]96        self._reset_state_list()
97       
[a0a4486]98        if self.parent is not None:
99            msg = ""
[e3f721e4]100            wx.PostEvent(self.parent,StatusEvent(status=msg, info="info"))
[4e1c362]101           
102        ## Default file location for save
103        self._default_save_location = os.getcwd()
[cb69775]104        self._set_bookmark_flag(False)
[cef847c]105       
[35f2f49]106    def get_data(self):
107        """
108        """
109        return self._manager.get_data()
110   
111    def get_state(self):
112        """
113        """
114        return self.state
115   
[210ff4f]116    def set_data(self, data):
[343fdb6]117        """
[210ff4f]118        Set the data
[c128284]119        """
[272d91e]120        self._data = data
121        #edit the panel
[210ff4f]122        if self._data is not None:
[9b18735]123            self.get_state_by_num(0)
[272d91e]124            data_name = self._data.name
[210ff4f]125            data_qmin = min (self._data.x)
126            data_qmax = max (self._data.x)
127            self.data_name_tcl.SetValue(str(data_name))
[effce1d]128            self.data_min_tcl.SetValue(str(data_qmin))
129            self.data_max_tcl.SetValue(str(data_qmax))
[d0cc0bbc]130            self.reset_panel()
131            self.compute_invariant(event=None)
[b35d3d1]132            self.state.file = self._data.name
[9b18735]133            #Reset the list of states
134            self.state.data = copy.deepcopy(data)
[7065641]135            self._set_preview_flag(False)
[9b18735]136            self._reset_state_list()
[f1e06a8e]137           
[210ff4f]138        return True 
[4a2b054]139   
[d0cc0bbc]140    def set_message(self):
141        """
[d7a39e5]142        Display warning message if available
[d0cc0bbc]143        """
144        if self.inv_container is not None:
145            if self.inv_container.existing_warning:
146                msg = "Warning! Computations on invariant require your "
147                msg += "attention.\n Please click on Details button."
148                self.hint_msg_txt.SetForegroundColour("red")
[1c271f2]149   
[4a2b054]150                wx.PostEvent(self.parent,
151                             StatusEvent(status=msg,info="warning"))
[d0cc0bbc]152            else:
153                msg = "For more information, click on Details button."
154                self.hint_msg_txt.SetForegroundColour("black")
[4a2b054]155                wx.PostEvent(self.parent,
156                             StatusEvent(status=msg,info="info"))
[d0cc0bbc]157            self.hint_msg_txt.SetLabel(msg)
[cb274d9e]158           
[d0cc0bbc]159       
[c128284]160    def set_manager(self, manager):
161        """
[d7a39e5]162        set value for the manager
[c128284]163        """
[272d91e]164        self._manager = manager
[4e1c362]165       
166    def set_state(self,state=None,data=None):
167        """
[9b18735]168        set state when loading it from a .inv/.svs file
[4e1c362]169        """
[645f9b6]170        if state == None and data == None:
[4e1c362]171            self.state = IState()
[645f9b6]172        elif state == None or data == None: return
[4e1c362]173        else:
[f24925ab]174            self.new_state = True
[210ff4f]175            if not self.set_data(data):
[4e1c362]176                return
[b35d3d1]177            self.state = state
178            self.state.file = data.name   
[645f9b6]179
[4e1c362]180            num = self.state.saved_state['state_num']
[cb463b4]181            if num > 0 :
[27f3831]182                self._set_undo_flag(True)
[4a2b054]183            if num < len(state.state_list) - 1:
[27f3831]184                self._set_redo_flag(True)
[4e1c362]185               
186            # get bookmarks
187            self.bookmark_num = len(self.state.bookmark_list)
[cef847c]188
[4a2b054]189            total_bookmark_num = self.bookmark_num + 1
[4e1c362]190            for ind in range(1,total_bookmark_num):
191                #bookmark_num = ind
192                value = self.state.bookmark_list[ind]
193                name = "%d] bookmarked at %s on %s"% (ind,value[0], value[1])
194                # append it to menu
195                id = wx.NewId()
196                self.popUpMenu.Append(id,name,str(''))
[cef847c]197                wx.EVT_MENU(self, id, self._back_to_bookmark) 
[cb463b4]198
199            self.get_state_by_num(state_num=str(num))
200           
[1a3a03b]201            self._get_input_list() 
[4a2b054]202            #make sure that the data is reset (especially
203            # when loaded from a inv file)
[cb274d9e]204            self.state.data = self._data
[645f9b6]205
[4e1c362]206            self.new_state = False 
[f24925ab]207            self.is_state_data = False
[0399c78]208
[cb69775]209    def clear_panel(self):
[9b18735]210        """
211        Clear panel to defaults, used by set_state of manager
212        """
[cb69775]213       
214        self._data = None
215        # default data testctrl
216        self.hint_msg_txt.SetLabel('')
217        data_name = ''
218        data_qmin = ''
219        data_qmax = ''
220        self.data_name_tcl.SetValue(str(data_name))
221        self.data_min_tcl.SetValue(str(data_qmin))
222        self.data_max_tcl.SetValue(str(data_qmax))
223        #reset output textctrl
224        self._reset_output()
225        #reset panel
226        self.reset_panel()
227        #reset state w/o data
228        self.set_state()
229        # default flags for state
230        self.new_state = False
231        self.is_state_data = False
232        self.is_power_out = False
[4e1c362]233
[9ce7641c]234    def get_background(self):
[c128284]235        """
[d7a39e5]236        return the background textcrtl value as a float
[c128284]237        """
[9ce7641c]238        background = self.background_tcl.GetValue().lstrip().rstrip()
[c128284]239        if background == "":
[9ce7641c]240            raise ValueError, "Need a background"
241        if check_float(self.background_tcl):
242            return float(background)
243        else:
[4a2b054]244            msg = "Receive invalid value for background : %s" % (background)
245            raise ValueError, msg
[9ce7641c]246   
247    def get_scale(self):
248        """
[d7a39e5]249        return the scale textcrtl value as a float
[9ce7641c]250        """
251        scale = self.scale_tcl.GetValue().lstrip().rstrip()
[c128284]252        if scale == "":
[9ce7641c]253            raise ValueError, "Need a background"
254        if check_float(self.scale_tcl):
[4a2b054]255            if float(scale) <= 0.0:
[6d55d81]256                self.scale_tcl.SetBackgroundColour("pink")
257                self.scale_tcl.Refresh()
[4a2b054]258                msg = "Receive invalid value for scale: %s" % (scale)
259                raise ValueError, msg
[9ce7641c]260            return float(scale)
261        else:
[4a2b054]262            raise ValueError, "Receive invalid value for scale : %s" % (scale)
[9ce7641c]263       
264    def get_contrast(self):
265        """
[d7a39e5]266        return the contrast textcrtl value as a float
[9ce7641c]267        """
268        par_str = self.contrast_tcl.GetValue().strip()
269        contrast = None
[4a2b054]270        if par_str !=" " and check_float(self.contrast_tcl):
[9ce7641c]271            contrast = float(par_str)
272        return contrast
273   
274    def get_extrapolation_type(self, low_q, high_q):
275        """
276        """
277        extrapolation = None
278        if low_q  and not high_q:
279            extrapolation = "low"
280        elif not low_q  and high_q:
281            extrapolation = "high"
282        elif low_q and high_q:
283            extrapolation = "both"
284        return extrapolation
[272d91e]285           
[9ce7641c]286    def get_porod_const(self):
287        """
[d7a39e5]288        return the porod constant textcrtl value as a float
[9ce7641c]289        """
290        par_str = self.porod_constant_tcl.GetValue().strip()
291        porod_const = None
[4a2b054]292        if par_str != "" and check_float(self.porod_constant_tcl):
[9ce7641c]293            porod_const = float(par_str)
294        return porod_const
295   
296    def get_volume(self, inv, contrast, extrapolation):
297        """
298        """
299        if contrast is not None:
[c128284]300            try:
[9ce7641c]301                v, dv = inv.get_volume_fraction_with_error(contrast=contrast, 
[4a2b054]302                                                extrapolation=extrapolation)
[9ce7641c]303                self.volume_tcl.SetValue(format_number(v))
304                self.volume_err_tcl.SetValue(format_number(dv))
[c128284]305            except:
[0a8759f]306                self.volume_tcl.SetValue(format_number(None))
307                self.volume_err_tcl.SetValue(format_number(None))
[4a2b054]308                msg = "Error occurred computing volume "
309                msg += " fraction: %s" % sys.exc_value
[e3f721e4]310                wx.PostEvent(self.parent, StatusEvent(status=msg,
311                                                      info="error",
312                                                      type="stop"))
[9ce7641c]313               
314    def get_surface(self, inv, contrast, porod_const, extrapolation):
315        """
316        """
317        if contrast is not None and porod_const is not None:
[c128284]318            try:
[9ce7641c]319                s, ds = inv.get_surface_with_error(contrast=contrast,
320                                        porod_const=porod_const,
321                                        extrapolation=extrapolation)
322                self.surface_tcl.SetValue(format_number(s))
323                self.surface_err_tcl.SetValue(format_number(ds))
[c128284]324            except:
[0a8759f]325                self.surface_tcl.SetValue(format_number(None))
326                self.surface_err_tcl.SetValue(format_number(None))
[4a2b054]327                msg = "Error occurred computing "
328                msg += "specific surface: %s" % sys.exc_value
[e3f721e4]329                wx.PostEvent(self.parent, StatusEvent(status=msg, info="error",
330                                                       type="stop"))
[53b6b74]331               
[9ce7641c]332    def get_total_qstar(self, inv, extrapolation):
333        """
334        """
335        try:
336            qstar_total, qstar_total_err = inv.get_qstar_with_error(extrapolation)
[0a8759f]337           
[9ce7641c]338            self.invariant_total_tcl.SetValue(format_number(qstar_total))
[518d35d]339            self.invariant_total_err_tcl.SetValue(format_number(qstar_total_err))
[9ce7641c]340            self.inv_container.qstar_total = qstar_total
341            self.inv_container.qstar_total_err = qstar_total_err
[518d35d]342         
[9ce7641c]343        except:
[0a8759f]344            self.inv_container.qstar_total = "Error"
345            self.inv_container.qstar_total_err = "Error"
346            self.invariant_total_tcl.SetValue(format_number(None))
347            self.invariant_total_err_tcl.SetValue(format_number(None))
[4a2b054]348            msg = "Error occurred computing invariant using"
349            msg += " extrapolation: %s" % sys.exc_value
[9ce7641c]350            wx.PostEvent(self.parent, StatusEvent(status= msg, type="stop")) 
351           
352    def get_low_qstar(self, inv, npts_low, low_q=False):
353        """
354        """
355        if low_q:
356            try: 
357                qstar_low, qstar_low_err = inv.get_qstar_low()
358                self.inv_container.qstar_low = qstar_low
359                self.inv_container.qstar_low_err = qstar_low_err
360                extrapolated_data = inv.get_extra_data_low(npts_in=npts_low) 
361                power_low = inv.get_extrapolation_power(range='low') 
[518d35d]362                if self.power_law_low.GetValue():
[d0cc0bbc]363                    self.power_low_tcl.SetValue(format_number(power_low))
[9ce7641c]364                self._manager.plot_theory(data=extrapolated_data,
365                                           name="Low-Q extrapolation")
366            except:
[a07e72f]367                raise
[0a8759f]368                self.inv_container.qstar_low = "ERROR"
369                self.inv_container.qstar_low_err = "ERROR"
370                self._manager.plot_theory(name="Low-Q extrapolation")
[4a2b054]371                msg = "Error occurred computing low-Q "
372                msg += "invariant: %s" % sys.exc_value
373                wx.PostEvent(self.parent,
374                             StatusEvent(status=msg, type="stop"))
[c128284]375        else:
[4e1c362]376            try:
377                self._manager.plot_theory(name="Low-Q extrapolation")
378            except: pass
[9ce7641c]379           
380    def get_high_qstar(self, inv, high_q=False):
381        """
382        """
383        if high_q:
384            try: 
[90b9a17]385                qmax_plot = Q_MAXIMUM_PLOT * max(self._data.x)
386                if qmax_plot > Q_MAXIMUM: qmax_plot = Q_MAXIMUM
[9ce7641c]387                qstar_high, qstar_high_err = inv.get_qstar_high()
388                self.inv_container.qstar_high = qstar_high
389                self.inv_container.qstar_high_err = qstar_high_err
[518d35d]390                power_high = inv.get_extrapolation_power(range='high') 
[d0cc0bbc]391                self.power_high_tcl.SetValue(format_number(power_high))
[4a2b054]392                high_out_data = inv.get_extra_data_high(q_end=qmax_plot,
393                                                        npts=500)
[9ce7641c]394                self._manager.plot_theory(data=high_out_data,
395                                           name="High-Q extrapolation")
396            except:
[7065641]397                #raise
[0a8759f]398                self.inv_container.qstar_high = "ERROR"
399                self.inv_container.qstar_high_err = "ERROR"
400                self._manager.plot_theory(name="High-Q extrapolation")
[4a2b054]401                msg = "Error occurred computing high-Q "
402                msg += "invariant: %s" % sys.exc_value
403                wx.PostEvent(self.parent, StatusEvent(status=msg,
404                                                      type="stop"))
[9ce7641c]405        else:
[4e1c362]406            try:
407                self._manager.plot_theory(name="High-Q extrapolation")
408            except: pass
409
[9ce7641c]410    def get_qstar(self, inv):
411        """
412        """
413        qstar, qstar_err = inv.get_qstar_with_error()
414        self.inv_container.qstar = qstar
415        self.inv_container.qstar_err = qstar_err
416             
417    def set_extrapolation_low(self, inv, low_q=False):
418        """
[d7a39e5]419        return float value necessary to compute invariant a low q
[9ce7641c]420        """
421        #get funtion
422        if self.guinier.GetValue():
423            function_low = "guinier"
424        # get the function
[518d35d]425        power_low = None #2.0/3.0
[9ce7641c]426        if self.power_law_low.GetValue():
427            function_low = "power_law"
[518d35d]428            if self.fit_enable_low.GetValue():
[9ce7641c]429                #set value of power_low to none to allow fitting
430                power_low = None
431            else:
432                power_low = self.power_low_tcl.GetValue().lstrip().rstrip()
433                if check_float(self.power_low_tcl):
434                    power_low = float(power_low)
435                else:
436                    if low_q :
437                        #Raise error only when qstar at low q is requested
[4a2b054]438                        msg = "Expect float for power at low q, "
439                        msg += " got %s" % (power_low)
[9ce7641c]440                        raise ValueError, msg
[518d35d]441       
[9ce7641c]442        #Get the number of points to extrapolated
443        npts_low = self.npts_low_tcl.GetValue().lstrip().rstrip()   
444        if check_float(self.npts_low_tcl):
445            npts_low = float(npts_low)
446        else:
447            if low_q:
[4a2b054]448                msg = "Expect float for number of points at low q,"
449                msg += " got %s" % (npts_low)
[9ce7641c]450                raise ValueError, msg
451        #Set the invariant calculator
452        inv.set_extrapolation(range="low", npts=npts_low,
453                                   function=function_low, power=power_low)   
454        return inv, npts_low 
[4e1c362]455   
456
[9ce7641c]457    def set_extrapolation_high(self, inv, high_q=False):
458        """
[d7a39e5]459        return float value necessary to compute invariant a high q
[9ce7641c]460        """
461        power_high = None
[277fad8]462        #if self.power_law_high.GetValue():
463        function_high = "power_law"
464        if self.fit_enable_high.GetValue():
465            #set value of power_high to none to allow fitting
466            power_high = None
467        else:
468            power_high = self.power_high_tcl.GetValue().lstrip().rstrip()
469            if check_float(self.power_high_tcl):
470                power_high = float(power_high)
[9ce7641c]471            else:
[277fad8]472                if high_q :
473                    #Raise error only when qstar at high q is requested
[4a2b054]474                    msg = "Expect float for power at high q,"
475                    msg += " got %s" % (power_high)
[277fad8]476                    raise ValueError, msg
[9ce7641c]477                         
478        npts_high = self.npts_high_tcl.GetValue().lstrip().rstrip()   
479        if check_float(self.npts_high_tcl):
480            npts_high = float(npts_high)
481        else:
482            if high_q:
[4a2b054]483                msg = "Expect float for number of points at high q,"
484                msg += " got %s" % (npts_high)
[9ce7641c]485                raise ValueError, msg
486        inv.set_extrapolation(range="high", npts=npts_high,
487                                   function=function_high, power=power_high)
488        return inv, npts_high
489   
490    def display_details(self, event):
491        """
[d7a39e5]492        open another panel for more details on invariant calculation
[9ce7641c]493        """
[d3fac18]494        panel = InvariantDetailsPanel(parent=self, 
495                                           qstar_container=self.inv_container)
496        panel.ShowModal()
497        panel.Destroy()
[d0cc0bbc]498        self.button_calculate.SetFocus()
[9ce7641c]499       
[d0cc0bbc]500    def compute_invariant(self, event=None):
[9ce7641c]501        """
[d7a39e5]502        compute invariant
[9ce7641c]503        """
[4e1c362]504        if self._data == None:
[4a2b054]505            msg = "\n\nData must be loaded first in order"
506            msg += " to perform a compution..."
[4e1c362]507            wx.PostEvent(self.parent, StatusEvent(status=msg))
508        # set a state for this computation for saving
509        elif event != None: 
510            self._set_compute_state(state='compute')
[27f3831]511            self._set_bookmark_flag(True)
[4e1c362]512            msg= "\n\nStarting a new invariant computation..."           
513            wx.PostEvent(self.parent, StatusEvent(status=msg))
[cef847c]514           
[4e1c362]515
[cb69775]516        if self._data is None:
[9ce7641c]517            return
[cb69775]518        self.button_details.Enable()
[9ce7641c]519        #clear outputs textctrl
520        self._reset_output()
521        try:
522            background = self.get_background()
523            scale = self.get_scale()
524        except:
[4a2b054]525            msg = "Invariant Error: %s" % (sys.exc_value)
526            wx.PostEvent(self.parent, StatusEvent(status=msg, type="stop"))
[9ce7641c]527            return
528       
529        low_q = self.enable_low_cbox.GetValue()
[f1e06a8e]530        high_q = self.enable_high_cbox.GetValue() 
531        temp_data = copy.deepcopy(self._data)
532       
[9ce7641c]533        #set invariant calculator
[f1e06a8e]534        inv = invariant.InvariantCalculator(data=temp_data,
[9ce7641c]535                                            background=background,
536                                            scale=scale)
[437e639]537        try:
538            inv, npts_low = self.set_extrapolation_low(inv=inv, low_q=low_q)
539            inv, npts_high = self.set_extrapolation_high(inv=inv, high_q=high_q)
540        except:
[4a2b054]541            msg = "Error occurred computing invariant: %s" % sys.exc_value
[e3f721e4]542            wx.PostEvent(self.parent, StatusEvent(status=msg,
543                                                 info="warning",type="stop"))
[437e639]544            return
[9ce7641c]545        #check the type of extrapolation
546        extrapolation = self.get_extrapolation_type(low_q=low_q, high_q=high_q)
[a0a4486]547       
[9ce7641c]548        #Compute invariant
[6d55d81]549        bkg_changed = False
550        scale_changed = False
[9ce7641c]551        try:
552            self.get_qstar(inv=inv)
[6d55d81]553            #if scale_changed or bkg_changed:
[353f467]554            #self._manager.plot_data(data=inv.get_data())
[6d55d81]555           
[9ce7641c]556        except:
[4a2b054]557            msg= "Error occurred computing invariant: %s" % sys.exc_value
[e3f721e4]558            wx.PostEvent(self.parent, StatusEvent(status=msg, 
[4a2b054]559                                                  info="warning",
560                                                  type="stop"))
[c128284]561            return
[0a8759f]562       
[9ce7641c]563        #Compute qstar extrapolated to low q range
564        self.get_low_qstar(inv=inv, npts_low=npts_low, low_q=low_q)
565        #Compute qstar extrapolated to high q range
566        self.get_high_qstar(inv=inv, high_q=high_q)
567        #Compute qstar extrapolated to total q range and set value to txtcrtl
568        self.get_total_qstar(inv=inv, extrapolation=extrapolation)
569        # Parse additional parameters
570        porod_const = self.get_porod_const()       
571        contrast = self.get_contrast()
[4e1c362]572       
[f43827cc]573        try:
574            #Compute volume and set value to txtcrtl
[4a2b054]575            self.get_volume(inv=inv, contrast=contrast,
576                            extrapolation=extrapolation)
[f43827cc]577            #compute surface and set value to txtcrtl
578        except:
[4a2b054]579            msg = "Error occurred computing invariant: %s" % sys.exc_value
[e3f721e4]580            wx.PostEvent(self.parent, StatusEvent(status=msg,
[4a2b054]581                                                  info="warning",
582                                                  type="stop"))
[f43827cc]583        try:
[4a2b054]584            self.get_surface(inv=inv, contrast=contrast,
585                                    porod_const=porod_const, 
[9ce7641c]586                                    extrapolation=extrapolation)
[4e1c362]587           
[f43827cc]588        except:
[4a2b054]589            msg = "Error occurred computing invariant: %s" % sys.exc_value
[e3f721e4]590            wx.PostEvent(self.parent, StatusEvent(status=msg,
[4a2b054]591                                                  info="warning",
592                                                  type="stop"))
[d0cc0bbc]593           
594        #compute percentage of each invariant
595        self.inv_container.compute_percentage()
[4e1c362]596       
[d0cc0bbc]597        #display a message
598        self.set_message()
[645f9b6]599
[4e1c362]600        # reset power_out to default to get ready for another '_on_text'
601        if self.is_power_out == True:
602            self.state.container = copy.deepcopy(self.inv_container)
603            self.state.timestamp= self._get_time_stamp()
604            msg = self.state.__str__()
[97ec26b]605            #self.state.set_report_string()
[4e1c362]606            self.is_power_out = False
607            wx.PostEvent(self.parent, StatusEvent(status = msg ))
[cef847c]608
[9ce7641c]609        #enable the button_ok for more details
[cb69775]610        self._set_preview_flag(True)
[645f9b6]611       
[4e1c362]612        if event != None: 
[cb69775]613            self._set_preview_flag(True)
614            self._set_save_flag(True)
[4a2b054]615            wx.PostEvent(self.parent,
616                StatusEvent(status='\nFinished invariant computation...'))
[27f3831]617           
618    def on_undo(self,event=None):
[4e1c362]619        """
620        Go back to the previous state
621       
622        : param event: undo button event
623        """
[4a2b054]624        if event != None: 
625            event.Skip()
626        if self.state.state_num < 0:
627            return
[4e1c362]628        self.is_power_out = True
629        # get the previous state_num
630        pre_state_num = int(self.state.saved_state['state_num']) - 1
631        self.get_state_by_num(state_num=str(pre_state_num))
632       
[4a2b054]633        if float(pre_state_num) <= 0:
[27f3831]634            self._set_undo_flag(False)
[cb274d9e]635        else:
[27f3831]636            self._set_undo_flag(True)
637        self._set_redo_flag(True)
[4e1c362]638        self.is_power_out = False 
639        self._info_state_num()
640       
641       
[27f3831]642    def on_redo(self,event=None):
[4e1c362]643        """
644        Go forward to the previous state
645       
646        : param event: redo button event
647        """
[4a2b054]648        if event != None:
649            event.Skip()
[4e1c362]650        self.is_power_out = True
[cb274d9e]651        # get the next state_num
[4e1c362]652        next_state_num = int(self.state.saved_state['state_num']) + 1
653
654        self.get_state_by_num(state_num=str(next_state_num))
655       
656        if float(next_state_num)+2 > len(self.state.state_list):
[27f3831]657            self._set_redo_flag(False)
[178bfea]658        else:
[cb69775]659            self._set_redo_flag(True)
660   
[27f3831]661        self._set_undo_flag(True)
[4e1c362]662        self.is_power_out = False
663        self._info_state_num()
664       
[27f3831]665    def on_preview(self, event=None):
[cb463b4]666        """
667        Invoke report dialog panel
668       
669        : param event: report button event
670        """
[f1e06a8e]671        from .report_dialog import ReportDialog
[cb463b4]672
[a94c4e1]673        self.state.set_report_string()
[cb274d9e]674        report_html_str = self.state.report_str
675        report_text_str = self.state.__str__()
676        report_img = self.state.image
677        report_list = [report_html_str,report_text_str,report_img]
678        dialog = ReportDialog(report_list, None, -1, "")
[cb463b4]679        dialog.ShowModal()
680       
[4e1c362]681    def get_state_by_num(self,state_num=None):
682        """
683        Get the state given by number
684       
685        : param state_num: the given state number
[cb274d9e]686        """     
[4e1c362]687        if state_num == None:
688            return
689
690        backup_state_list = copy.deepcopy(self.state.state_list)
[cef847c]691       
[4e1c362]692        # get the previous state
693        try:
694            current_state = copy.deepcopy(self.state.state_list[str(state_num)])
[4a2b054]695            # get the previously computed state number
696            #(computation before the state changes happened)
[4e1c362]697            current_compute_num = str(current_state['compute_num'])
698        except :
[3641881]699            raise
700            #raise ValueError,  "No such state exists in history"
[cef847c]701       
[4e1c362]702        # get the state at pre_compute_num
703        comp_state = copy.deepcopy(self.state.state_list[current_compute_num])
704
705        # set the parameters
706        for key in comp_state:
707            value = comp_state[key]
708            try:
709                exec "self.%s.SetValue(str(%s))" % (key, value)
710            except TypeError:
711                exec "self.%s.SetValue(%s)" % (key, value)
712            except:
713                pass
[f1e06a8e]714       
[4e1c362]715        self.compute_invariant(event=None)
[f1e06a8e]716       
[4e1c362]717        # set the input params at the state at pre_state_num
718        for key in current_state:
719            # set the inputs and boxes
720            value = current_state[key]
721            try:
722                exec 'self.%s.SetValue(str(%s))' % (key, value)
723            except TypeError:
724                exec 'self.%s.SetValue(%s)' % (key, value)
725            except:
726                pass
727
728        self._enable_high_q_section(event=None)
729        self._enable_low_q_section(event=None)
730        self.state.state_list = backup_state_list
731        self.state.saved_state = current_state
732        self.state.state_num = state_num
[cb274d9e]733           
[4e1c362]734       
735    def get_bookmark_by_num(self, num=None):
736        """
737        Get the bookmark state given by number
738       
739        : param num: the given bookmark number
740       
741        """
742        current_state = {}
743        comp_state = {}
744        backup_state_list = copy.deepcopy(self.state.state_list)
745
746        # get the previous state
747        try:
748            time,date,current_state,comp_state = self.state.bookmark_list[int(num)] 
749        except :
750            raise ValueError,  "No such bookmark exists"
751
752        # set the parameters
753        for key in comp_state:
754            value = comp_state[key]
755            try:
756                exec "self.%s.SetValue(str(%s))" % (key, value)
757            except TypeError:
758                exec "self.%s.SetValue(%s)" % (key, value)
759            except:
760                pass
761
762        self.compute_invariant(event=None)
763        # set the input params at the state of pre_state_num
764        for key in current_state:
765            value = current_state[key]
766            try:
767                exec 'self.%s.SetValue(str(%s))' % (key, value)
768            except TypeError:
769                exec 'self.%s.SetValue(%s)' % (key, value)
770            except:
771                pass
772        self.state.saved_state = copy.deepcopy(current_state)
[cef847c]773       
[4e1c362]774        self._enable_high_q_section(event=None)
775        self._enable_low_q_section(event=None)
776        self.state.state_list = backup_state_list
777        #self.state.saved_state = current_state
778        #self.state.state_num = state_num
779
[f338d3b]780    def reset_panel(self):
781        """
[d7a39e5]782        set the panel at its initial state.
[f338d3b]783        """
[d0cc0bbc]784        self.background_tcl.SetValue(str(BACKGROUND))
785        self.scale_tcl.SetValue(str(SCALE)) 
[4e74e13]786        self.contrast_tcl.SetValue(str(CONTRAST))
787        self.porod_constant_tcl.SetValue('') 
[d0cc0bbc]788        self.npts_low_tcl.SetValue(str(NPTS))
789        self.enable_low_cbox.SetValue(False)
790        self.fix_enable_low.SetValue(True)
791        self.power_low_tcl.SetValue(str(POWER))
792        self.guinier.SetValue(True)
793        self.power_low_tcl.Disable()
794        self.enable_high_cbox.SetValue(False)
795        self.fix_enable_high.SetValue(True)
796        self.power_high_tcl.SetValue(str(POWER))
797        self.npts_high_tcl.SetValue(str(NPTS))
798        self.button_details.Disable()
799        #Change the state of txtcrtl to enable/disable
800        self._enable_low_q_section()
801        #Change the state of txtcrtl to enable/disable
802        self._enable_high_q_section()
803        self._reset_output()
[27f3831]804        self._set_undo_flag(False)
805        self._set_redo_flag(False)
806        self._set_bookmark_flag(False)
807        self._set_preview_flag(False)
808        self._set_save_flag(False)
[d0cc0bbc]809        self.button_calculate.SetFocus()
[4e1c362]810        #self.SetupScrolling()
811       
812    def _set_state(self, event):
813        """
814        Set the state list
815       
816        :param event: rb/cb event
817        """
818        if event == None:
819            return
820        obj = event.GetEventObject()
821        name = str(obj.GetName())
822        value = str(obj.GetValue())
[4a2b054]823        rb_list = [['power_law_low','guinier'],
824                   ['fit_enable_low','fix_enable_low'],
825                   ['fit_enable_high','fix_enable_high']]
[4e1c362]826
827        try:
828            if value == None or value.lstrip().rstrip() =='':
829                value = 'None'
830            exec 'self.state.%s = %s' % (name, value)
831            exec "self.state.saved_state['%s'] = %s" %  (name, value)
832           
[4a2b054]833            # set the count part of radio button clicked
834            #False for the saved_state
[4e1c362]835            for title,content in rb_list:
836                if name ==  title:
837                    name = content
838                    value = False     
839                elif name == content:
840                    name = title
841                    value = False 
842            exec "self.state.saved_state['%s'] = %s" %  (name, value)     
843           
844            # Instead of changing the future, create a new future.
[4a2b054]845            max_state_num = len(self.state.state_list) - 1   
[4e1c362]846            self.state.saved_state['state_num'] = max_state_num   
847           
[4a2b054]848            self.state.saved_state['state_num'] += 1
[4e1c362]849            self.state.state_num = self.state.saved_state['state_num']
850            self.state.state_list[str(self.state.state_num)] = self.state.clone_state()#copy.deepcopy(self.state.saved_state)
851        except:           
852            pass
[7065641]853       
[27f3831]854        self._set_undo_flag(True)
855        self._set_redo_flag(False)
[7065641]856        event.Skip()
857                   
[4e1c362]858    def _set_compute_state(self,state=None):
859        """
860        Notify the compute_invariant state to self.state
861       
[4a2b054]862        : param state: set 'compute' when the computation is
863        activated by the 'compute' button, else None
[4e1c362]864       
865        """
866        # reset the default
867        if state != 'compute':
868            self.new_state = False
869            self.is_power_out = False
870        else:
871            self.is_power_out = True
872        # Instead of changing the future, create a new future.
873        max_state_num = len(self.state.state_list)-1   
874        self.state.saved_state['state_num'] = max_state_num       
875        # A new computation is also A state
[4a2b054]876        #copy.deepcopy(self.state.saved_state)
877        temp_saved_states = self.state.clone_state()
878        temp_saved_states['state_num'] += 1
[4e1c362]879        self.state.state_num = temp_saved_states['state_num']
880
881               
882        # set the state number of the computation
883        if state == 'compute':
884            temp_saved_states['compute_num'] = self.state.state_num
885        self.state.saved_state= copy.deepcopy(temp_saved_states)
[4a2b054]886        #copy.deepcopy(self.state.saved_state)
887        self.state.state_list[str(self.state.state_num)] = self.state.clone_state()
[4e1c362]888       
[4a2b054]889        # A computation is a new state, so delete the states with any higher
890        # state numbers
[4e1c362]891        for i in range(self.state.state_num+1,len(self.state.state_list)):
892            try:
893                del (self.state.state_list[str(i)])
894            except: 
895                pass
896        # Enable the undo button if it was not
[27f3831]897        self._set_undo_flag(True)
898        self._set_redo_flag(False)
[cef847c]899       
[4a2b054]900    def _reset_state_list(self, data=None):
[4e1c362]901        """
[4a2b054]902        Reset the state_list just before data was loading:
903        Used in 'set_current_data()'
[4e1c362]904        """
905        #if data == None: return
[4a2b054]906        #temp_state = self.state.clone_state()
907        #copy.deepcopy(self.state.saved_state)
[4e1c362]908        # Clear the list
909        self.state.state_list.clear()
910        self.state.bookmark_list.clear()
911        # Set defaults
912        self.state.saved_state['state_num'] = 0
913        self.state.saved_state['compute_num'] = 0
914        if self._data != None:
915            self.state.saved_state['file'] = str(self._data.name)
916        else:
917            self.state.saved_state['file'] = 'None'
918        self.state.file = self.state.saved_state['file']
919
920        self.state.state_num = self.state.saved_state['state_num']
[cb463b4]921        self.state.timestamp = "('00:00:00', '00/00/0000')"
922
[4e1c362]923        # Put only the current state in the list
[4a2b054]924        #copy.deepcopy(self.state.saved_state)
925        self.state.state_list[str(self.state.state_num)] = self.state.clone_state()
[cb69775]926        self._set_undo_flag(False)
[be738e3]927        self._set_redo_flag(False)
928        self._set_bookmark_flag(False)
929        self._set_preview_flag(False)
930        self._set_save_flag(False)
931
[4e1c362]932       
933    def _on_text(self, event):
934        """
935        Catch text change event to add the state to the state_list
936       
937        :param event: txtctr event ; assumes not None
938       
939        """
940        if self._data == None: 
941            return
942        # check if this event is from do/undo button
943        if self.state.saved_state['is_time_machine'] or self.new_state:
944            event.Skip()
945            return
946       
947        # get the object
948        obj = event.GetEventObject()
949        name = str(obj.GetName())
950        value = str(obj.GetValue())
951        state_num = self.state.saved_state['state_num']
952
953        # text event is a new state, so delete the states with higher state_num
954        # i.e., change the future
955        for i in range(int(state_num)+1,len(self.state.state_list)):
956            try:
957                del (self.state.state_list[str(i)])
958            except: 
959                pass
960       
961        # Instead of changing the future, create a new future.
962        #max_state_num = len(self.state.state_list)-1   
963        #self.state.saved_state['state_num'] = max_state_num
964
965        # try to add new state of the text changes in the state_list
966        try:
967            if value.strip() == None: value = ''
968            exec "self.state.%s = '%s'" % (name, value)
969            exec "self.state.saved_state['%s'] = '%s'" %  (name, value)
970            exec "self.state.input_list['%s'] = '%s'" % (name, value)
971            if not self.is_power_out:
972                if name != 'power_low_tcl' and name !='power_high_tcl':
973                    self.state.saved_state['state_num'] += 1
974            self.state.state_num = self.state.saved_state['state_num']
[4a2b054]975            #copy.deepcopy(self.state.saved_state)
976            self.state.state_list[str(self.state.state_num)] = self.state.clone_state()
[4e1c362]977        except:
978            pass
979
980        event.Skip()
[27f3831]981        self._set_undo_flag(True)
982        self._set_redo_flag(False)
983        self._set_bookmark_flag(True)
984        self._set_preview_flag(False)
[cb463b4]985       
[4e1c362]986    def _on_out_text(self, event):     
987        """
988        Catch ouput text change to add the state
989       
990        :param event: txtctr event ; assumes not None
991       
992        """   
993        # get the object
994        obj = event.GetEventObject()
995        name = str(obj.GetName())
996        value = str(obj.GetValue())
997        try:
998            exec "self.state.saved_state['%s'] = '%s'" %  (name, value)
999            self.state.state_list[str(self.state.state_num)] = self.state.clone_state()
1000        except:
1001            pass
1002        if event != None: event.Skip()\
[1a3a03b]1003
1004    def _get_input_list(self):     
1005        """
1006        get input_list; called by set_state
1007        """   
1008        # get state num of the last compute state
1009        compute_num = self.state.saved_state['compute_num']
1010        # find values and put into the input list
1011        for key1,value1 in self.state.state_list[str(compute_num)].iteritems(): 
1012            for key,value in self.state.input_list.iteritems(): 
1013                if key == key1:
1014                    self.state.input_list[key]=value1
1015                    break
[4e1c362]1016       
1017    def _set_bookmark_menu(self):
1018        """
1019        Setup 'bookmark' context menu
1020        """
1021        ## Create context menu for page
1022        self.popUpMenu = wx.Menu()
1023        id = wx.NewId()
[4a2b054]1024        self._bmark = wx.MenuItem(self.popUpMenu,id,"BookMark",
1025                                  " Bookmark the panel to recall it later")
[4e1c362]1026        self.popUpMenu.AppendItem(self._bmark)
1027        self._bmark.Enable(True)
[27f3831]1028        wx.EVT_MENU(self, id, self.on_bookmark)
[4e1c362]1029        self.popUpMenu.AppendSeparator()
1030        self.Bind(wx.EVT_CONTEXT_MENU, self._on_context_menu)
1031       
[27f3831]1032    def on_bookmark(self,event):
[4e1c362]1033        """
[4a2b054]1034        Save the panel state in memory and add the list on
1035        the popup menu on bookmark context menu event
[4e1c362]1036        """ 
1037        if self._data == None: return
1038        if event == None: return
1039        self.bookmark_num += 1
1040        # date and time of the event
1041        #year, month, day,hour,minute,second,tda,ty,tm_isdst= time.localtime()
1042        #my_time= str(hour)+" : "+str(minute)+" : "+str(second)+" "
1043        #date= str( month)+"/"+str(day)+"/"+str(year)
1044        my_time, date = self._get_time_stamp()
1045        state_num = self.state.state_num
1046        compute_num = self.state.saved_state['compute_num']
1047        # name and message of the bookmark list
1048        msg=  "State saved at %s on %s"%(my_time, date)
1049         ## post help message for the selected model
[cb274d9e]1050        msg +=" Right click on the panel to retrieve this state"
[4e1c362]1051        #wx.PostEvent(self.parent.parent, StatusEvent(status = msg ))
[cb69775]1052        name = "%d] bookmarked at %s on %s"%(self.bookmark_num, my_time, date)
[4e1c362]1053       
1054        # append it to menu
[cb69775]1055        #id = wx.NewId()
1056        #self.popUpMenu.Append(id,name,str(msg))
1057        #wx.EVT_MENU(self, id, self._back_to_bookmark)
[4e1c362]1058        state = self.state.clone_state()
1059        comp_state = copy.deepcopy(self.state.state_list[str(compute_num)])
[4a2b054]1060        self.state.bookmark_list[self.bookmark_num] = [my_time, date,
1061                                                       state,comp_state]
[4e1c362]1062        self.state.toXML(self, doc=None, entry_node=None)
[cb274d9e]1063       
1064        wx.PostEvent(self.parent,StatusEvent(status=msg,info="info"))
[cb69775]1065        wx.PostEvent(self.parent, 
1066                     AppendBookmarkEvent(title=name, 
1067                                         hint=str(msg),
1068                                          handler=self._back_to_bookmark))
[4e1c362]1069
1070    def _back_to_bookmark(self,event):
1071        """
[4a2b054]1072        Bring the panel back to the state of bookmarked requested by
1073        context menu event
[4e1c362]1074        and set it as a new state
1075        """
[cb69775]1076        self._manager.on_perspective(event)
1077        menu = event.GetEventObject()
[4e1c362]1078        ## post help message for the selected model
[cb69775]1079        msg = menu.GetHelpString(event.GetId())
[4e1c362]1080        msg +=" reloaded"
1081        wx.PostEvent(self.parent, StatusEvent(status = msg ))
1082       
[cb69775]1083        name= menu.GetLabel(event.GetId())
1084       
[4e1c362]1085        num,time = name.split(']')
1086        current_state_num = self.state.state_num 
1087        self.get_bookmark_by_num(num)
1088        state_num = int(current_state_num)+1
1089       
1090        self.state.saved_state['state_num'] = state_num
[4a2b054]1091        #copy.deepcopy(self.state.saved_state)
1092        self.state.state_list[str(state_num)] = self.state.clone_state()
[4e1c362]1093        self.state.state_num = state_num
[cb69775]1094       
[27f3831]1095        self._set_undo_flag(True)
[4e1c362]1096        self._info_bookmark_num(event)
1097       
1098    def _info_bookmark_num(self,event=None):
1099        """
1100        print the bookmark number in info
1101       
1102        : event: popUpMenu event
1103        """
1104        if event == None: return
1105        # get the object
[cb69775]1106        menu = event.GetEventObject()
1107        item = menu.FindItemById(event.GetId())
[4e1c362]1108        text = item.GetText()
1109        num = text.split(']')[0]
1110        msg = "bookmark num = %s "% num
1111       
1112        wx.PostEvent(self.parent, StatusEvent(status = msg ))
1113       
1114    def _info_state_num(self):
1115        """
1116        print the current state number in info
1117        """
1118        msg = "state num = "
1119        msg += self.state.state_num
1120       
1121        wx.PostEvent(self.parent, StatusEvent(status = msg))
1122                         
1123    def _get_time_stamp(self):
1124        """
1125        return time and date stings
1126        """
1127        # date and time
1128        year, month, day,hour,minute,second,tda,ty,tm_isdst= time.localtime()
1129        my_time= str(hour)+":"+str(minute)+":"+str(second)
1130        date= str( month)+"/"+str(day)+"/"+str(year)
1131        return my_time, date
[cb69775]1132   
[4e1c362]1133           
[27f3831]1134    def on_save(self, evt=None): 
[4e1c362]1135        """
1136        Save invariant state into a file
1137        """
1138        # Ask the user the location of the file to write to.
1139        path = None
[4a2b054]1140        dlg = wx.FileDialog(self, "Choose a file",
1141                            self._default_save_location, "", "*.inv", wx.SAVE)
[4e1c362]1142        if dlg.ShowModal() == wx.ID_OK:
1143            path = dlg.GetPath()
1144            self._default_save_location = os.path.dirname(path)
1145        else:
1146            return None
1147       
1148        dlg.Destroy()
1149       
1150        self._manager.save_file(filepath=path, state=self.state)
1151       
1152    def _show_message(self, mssg='',msg='Warning'):
1153        """
1154        Show warning message when resetting data
1155        """
[f24925ab]1156        # no message for now
1157        return True
[0399c78]1158        count_bf = self.data_cbbox.GetCount()
1159        if count_bf > 1:
[4a2b054]1160            msg += "Loading a new data set will reset all the work"
1161            msg += " done in this panel. \n\r"
1162            mssg += "Please make sure to save it first... \n\r"
1163            answer = wx.MessageBox(mssg, msg,
1164                                   wx.CANCEL|wx.OK|wx.ICON_EXCLAMATION)
[0399c78]1165   
1166            if answer == wx.OK:
1167                return True
1168            else:
1169                return False
1170        else: True
[9ce7641c]1171       
[c128284]1172    def _reset_output(self):
1173        """
[d7a39e5]1174        clear outputs textcrtl
[c128284]1175        """
[9ce7641c]1176        self.invariant_total_tcl.Clear()
1177        self.invariant_total_err_tcl.Clear()
1178        self.volume_tcl.Clear()
1179        self.volume_err_tcl.Clear()
1180        self.surface_tcl.Clear()
1181        self.surface_err_tcl.Clear()
[a0a4486]1182        #prepare a new container to put result of invariant
1183        self.inv_container = InvariantContainer()
[4e1c362]1184
1185   
1186    def _on_context_menu(self,event):
1187       
1188        pos = event.GetPosition()
1189        pos = self.ScreenToClient(pos)
[b7f29fc]1190       
[4e1c362]1191        self.PopupMenu(self.popUpMenu, pos) 
1192     
[9ce7641c]1193    def _define_structure(self):
[c128284]1194        """
[d7a39e5]1195        Define main sizers needed for this panel
[c128284]1196        """
[4a2b054]1197        ## Box sizers must be defined first before
1198        #defining buttons/textctrls (MAC).
[9ce7641c]1199        self.main_sizer = wx.BoxSizer(wx.VERTICAL)
1200        #Sizer related to outputs
1201        outputs_box = wx.StaticBox(self, -1, "Outputs")
1202        self.outputs_sizer = wx.StaticBoxSizer(outputs_box, wx.VERTICAL)
1203        self.outputs_sizer.SetMinSize((PANEL_WIDTH,-1))
1204        #Sizer related to data
1205        data_name_box = wx.StaticBox(self, -1, "I(q) Data Source")
1206        self.data_name_boxsizer = wx.StaticBoxSizer(data_name_box, wx.VERTICAL)
1207        self.data_name_boxsizer.SetMinSize((PANEL_WIDTH,-1))
1208        self.hint_msg_sizer = wx.BoxSizer(wx.HORIZONTAL)
[210ff4f]1209        self.data_name_sizer = wx.BoxSizer(wx.HORIZONTAL)
[3641881]1210       
[9ce7641c]1211        self.data_range_sizer = wx.BoxSizer(wx.HORIZONTAL)
[d0cc0bbc]1212        #Sizer related to background and scale
1213        self.bkg_scale_sizer = wx.BoxSizer(wx.HORIZONTAL) 
1214        #Sizer related to contrast and porod constant
1215        self.contrast_porod_sizer = wx.BoxSizer(wx.HORIZONTAL) 
1216        #Sizer related to inputs
1217        inputs_box = wx.StaticBox(self, -1, "Customized Inputs")
1218        self.inputs_sizer = wx.StaticBoxSizer(inputs_box, wx.VERTICAL)
1219        #Sizer related to extrapolation
[d5f0dcb9]1220        extrapolation_box = wx.StaticBox(self, -1, "Extrapolation")
[9ce7641c]1221        self.extrapolation_sizer = wx.StaticBoxSizer(extrapolation_box,
1222                                                        wx.VERTICAL)
1223        self.extrapolation_sizer.SetMinSize((PANEL_WIDTH,-1))
1224        self.extrapolation_range_sizer = wx.BoxSizer(wx.HORIZONTAL)
1225        self.extrapolation_low_high_sizer = wx.BoxSizer(wx.HORIZONTAL)
1226        #Sizer related to extrapolation at low q range
[d5f0dcb9]1227        low_q_box = wx.StaticBox(self, -1, "Low Q")
[9ce7641c]1228        self.low_extrapolation_sizer = wx.StaticBoxSizer(low_q_box, wx.VERTICAL)
1229        self.low_q_sizer = wx.GridBagSizer(5,5)
1230        #Sizer related to extrapolation at low q range
1231        high_q_box = wx.StaticBox(self, -1, "High Q")
[4a2b054]1232        self.high_extrapolation_sizer = wx.StaticBoxSizer(high_q_box,
1233                                                          wx.VERTICAL)
[9ce7641c]1234        self.high_q_sizer = wx.GridBagSizer(5,5)
1235        #sizer to define outputs
1236        self.volume_surface_sizer = wx.GridBagSizer(5,5)
1237        #Sizer related to invariant output
[277fad8]1238        self.invariant_sizer = wx.GridBagSizer(5, 5)
[9ce7641c]1239        #Sizer related to button
1240        self.button_sizer = wx.BoxSizer(wx.HORIZONTAL)
[4e1c362]1241        #Sizer related to save button
1242        self.save_button_sizer = wx.BoxSizer(wx.HORIZONTAL)
1243       
[9ce7641c]1244    def _layout_data_name(self):
1245        """
[d7a39e5]1246        Draw widgets related to data's name
[9ce7641c]1247        """
1248        #Sizer hint
[cb69775]1249        hint_msg = ""
1250       
[277fad8]1251        self.hint_msg_txt = wx.StaticText(self, -1, hint_msg) 
1252        self.hint_msg_txt.SetForegroundColour("red")
[4a2b054]1253        msg = "Highlight = mouse the mouse's cursor on the data until"
1254        msg += " the plot's color changes to yellow"
[6848131]1255        self.hint_msg_txt.SetToolTipString(msg)
[277fad8]1256        self.hint_msg_sizer.Add(self.hint_msg_txt)
[210ff4f]1257        #Data name [string]
1258        data_name_txt = wx.StaticText(self, -1, 'Data : ') 
1259       
[4a2b054]1260        self.data_name_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH*5, 20),
1261                                            style=0) 
[210ff4f]1262        self.data_name_tcl.SetToolTipString("Data's name.")
1263        self.data_name_sizer.AddMany([(data_name_txt, 0, wx.LEFT|wx.RIGHT, 10),
1264                                       (self.data_name_tcl, 0, wx.EXPAND)])
[9ce7641c]1265        #Data range [string]
1266        data_range_txt = wx.StaticText(self, -1, 'Total Q Range (1/A): ') 
1267        data_min_txt = wx.StaticText(self, -1, 'Min : ') 
[4a2b054]1268        self.data_min_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH, 20),
1269                                           style=0, name='data_min_tcl')
[9ce7641c]1270        self.data_min_tcl.SetToolTipString("The minimum value of q range.")
1271        data_max_txt = wx.StaticText(self, -1, 'Max : ') 
[4a2b054]1272        self.data_max_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH, 20),
1273                                           style=0, name='data_max_tcl') 
[9ce7641c]1274        self.data_max_tcl.SetToolTipString("The maximum value of q range.")
1275        self.data_range_sizer.AddMany([(data_range_txt, 0, wx.RIGHT, 10),
1276                                       (data_min_txt, 0, wx.RIGHT, 10),
1277                                       (self.data_min_tcl, 0, wx.RIGHT, 10),
1278                                       (data_max_txt, 0, wx.RIGHT, 10),
1279                                       (self.data_max_tcl, 0, wx.RIGHT, 10)])
[4e1c362]1280        self.data_name_boxsizer.AddMany([(self.hint_msg_sizer, 0 , wx.ALL, 5),
[210ff4f]1281                            (self.data_name_sizer, 0 , wx.ALL, 10),
[343fdb6]1282                                     (self.data_range_sizer, 0 , wx.ALL, 10)])
[9ce7641c]1283   
[d0cc0bbc]1284    def _layout_bkg_scale(self):
[9ce7641c]1285        """
[d7a39e5]1286        Draw widgets related to background and scale
[9ce7641c]1287        """
1288        background_txt = wx.StaticText(self, -1, 'Background : ') 
[4a2b054]1289        self.background_tcl = InvTextCtrl(self, -1, size=(_BOX_WIDTH, 20),
1290                                          style=0, name='background_tcl') 
[4e1c362]1291        wx.EVT_TEXT(self, self.background_tcl.GetId(), self._on_text)
1292        background_hint_txt = "Background"
[518d35d]1293        self.background_tcl.SetToolTipString(background_hint_txt)
1294        background_unit_txt = wx.StaticText(self, -1, '[1/cm]') 
[9ce7641c]1295        scale_txt = wx.StaticText(self, -1, 'Scale : ') 
[4a2b054]1296        self.scale_tcl = InvTextCtrl(self, -1, size=(_BOX_WIDTH, 20), style=0,
1297                                     name='scale_tcl')
[4e1c362]1298        wx.EVT_TEXT(self, self.scale_tcl.GetId(), self._on_text)
[518d35d]1299        scale_hint_txt = "Scale"
1300        self.scale_tcl.SetToolTipString(scale_hint_txt)
[d0cc0bbc]1301        self.bkg_scale_sizer.AddMany([(background_txt, 0, wx.LEFT, 10),
1302                                       (self.background_tcl, 0, wx.LEFT, 5),
1303                                       (background_unit_txt, 0, wx.LEFT, 10),
1304                                       (scale_txt, 0, wx.LEFT, 70),
1305                                       (self.scale_tcl, 0, wx.LEFT, 40)])
1306 
1307    def _layout_contrast_porod(self):
[9ce7641c]1308        """
[d7a39e5]1309        Draw widgets related to porod constant and contrast
[9ce7641c]1310        """
1311        contrast_txt = wx.StaticText(self, -1, 'Contrast : ') 
[4a2b054]1312        self.contrast_tcl = InvTextCtrl(self, -1, size=(_BOX_WIDTH, 20),
1313                                        style=0,name='contrast_tcl')
[4e1c362]1314        wx.EVT_TEXT(self, self.contrast_tcl.GetId(), self._on_text)
[518d35d]1315        contrast_hint_txt = "Contrast"
1316        self.contrast_tcl.SetToolTipString(contrast_hint_txt)
1317        contrast_unit_txt = wx.StaticText(self, -1, '[1/A^(2)]') 
[9ce7641c]1318        porod_const_txt = wx.StaticText(self, -1, 'Porod Constant:') 
[518d35d]1319        self.porod_constant_tcl = InvTextCtrl(self, -1, 
[4a2b054]1320                                              size=(_BOX_WIDTH, 20), style=0,
1321                                              name='porod_constant_tcl') 
[4e1c362]1322        wx.EVT_TEXT(self, self.porod_constant_tcl.GetId(), self._on_text)
[518d35d]1323        porod_const_hint_txt = "Porod Constant"
1324        self.porod_constant_tcl.SetToolTipString(porod_const_hint_txt)
[9ce7641c]1325        optional_txt = wx.StaticText(self, -1, '(Optional)') 
[d0cc0bbc]1326        self.contrast_porod_sizer.AddMany([(contrast_txt, 0, wx.LEFT, 10),
1327                                           (self.contrast_tcl, 0, wx.LEFT, 20),
1328                                           (contrast_unit_txt, 0, wx.LEFT, 10),
1329                                           (porod_const_txt, 0, wx.LEFT, 50),
[9ce7641c]1330                                       (self.porod_constant_tcl, 0, wx.LEFT, 0),
1331                                       (optional_txt, 0, wx.LEFT, 10)])
1332       
[518d35d]1333    def _enable_fit_power_law_low(self, event=None):
1334        """
[d7a39e5]1335        Enable and disable the power value editing
[518d35d]1336        """
[4e1c362]1337        if event != None: 
[27f3831]1338            self._set_bookmark_flag(True)
1339            self._set_preview_flag(False)
[cb69775]1340   
[518d35d]1341        if self.fix_enable_low.IsEnabled():
[4e1c362]1342           
[518d35d]1343            if self.fix_enable_low.GetValue():
[4e1c362]1344                self.fit_enable_low.SetValue(False)
[518d35d]1345                self.power_low_tcl.Enable()
1346            else:
[4e1c362]1347                self.fit_enable_low.SetValue(True)
[518d35d]1348                self.power_low_tcl.Disable()
[4e1c362]1349        self._set_state(event=event)
1350           
[518d35d]1351    def _enable_low_q_section(self, event=None):
1352        """
[d7a39e5]1353        Disable or enable some button if the user enable low q extrapolation
[518d35d]1354        """
[cb463b4]1355        if event != None: 
[27f3831]1356            self._set_bookmark_flag(True)
1357            self._set_preview_flag(False)
[cb463b4]1358           
[518d35d]1359        if self.enable_low_cbox.GetValue():
1360            self.npts_low_tcl.Enable()
1361            self.fix_enable_low.Enable()
1362            self.fit_enable_low.Enable()
1363            self.guinier.Enable()
1364            self.power_law_low.Enable()
1365
1366        else:
1367            self.npts_low_tcl.Disable()
1368            self.fix_enable_low.Disable()
1369            self.fit_enable_low.Disable()
1370            self.guinier.Disable()
1371            self.power_law_low.Disable()
[4e1c362]1372       
[518d35d]1373        self._enable_power_law_low()
1374        self._enable_fit_power_law_low()
[4e1c362]1375        self._set_state(event=event)
[d0cc0bbc]1376        self.button_calculate.SetFocus()
[4e1c362]1377       
[518d35d]1378    def _enable_power_law_low(self, event=None):
1379        """
[d7a39e5]1380        Enable editing power law section at low q range
[518d35d]1381        """
[cb463b4]1382        if event != None: 
[27f3831]1383            self._set_bookmark_flag(True)
1384            self._set_preview_flag(False)
[518d35d]1385        if self.guinier.GetValue():
[4e1c362]1386            self.power_law_low.SetValue(False)
[518d35d]1387            self.fix_enable_low.Disable()
1388            self.fit_enable_low.Disable()
1389            self.power_low_tcl.Disable()
1390        else:
[4e1c362]1391            self.power_law_low.SetValue(True)
[518d35d]1392            self.fix_enable_low.Enable()
1393            self.fit_enable_low.Enable()
1394            self.power_low_tcl.Enable()
1395        self._enable_fit_power_law_low()
[4e1c362]1396        self._set_state(event=event)
[518d35d]1397           
[9ce7641c]1398    def _layout_extrapolation_low(self):
1399        """
[d7a39e5]1400        Draw widgets related to extrapolation at low q range
[9ce7641c]1401        """
[4a2b054]1402        self.enable_low_cbox = wx.CheckBox(self, -1,
1403                                           "Enable Extrapolate Low Q",
1404                                           name='enable_low_cbox')
[518d35d]1405        wx.EVT_CHECKBOX(self, self.enable_low_cbox.GetId(),
1406                                         self._enable_low_q_section)
1407        self.fix_enable_low = wx.RadioButton(self, -1, 'Fix',
[4a2b054]1408                                         (10, 10), style=wx.RB_GROUP,
1409                                         name='fix_enable_low')
[518d35d]1410        self.Bind(wx.EVT_RADIOBUTTON, self._enable_fit_power_law_low,
1411                                     id=self.fix_enable_low.GetId())
[4a2b054]1412        self.fit_enable_low = wx.RadioButton(self, -1, 'Fit', (10, 10),
1413                                             name='fit_enable_low')
[518d35d]1414        self.Bind(wx.EVT_RADIOBUTTON, self._enable_fit_power_law_low, 
1415                                        id=self.fit_enable_low.GetId())
[c128284]1416        self.guinier = wx.RadioButton(self, -1, 'Guinier',
[4a2b054]1417                                         (10, 10), style=wx.RB_GROUP,
1418                                         name='guinier')
[518d35d]1419        self.Bind(wx.EVT_RADIOBUTTON, self._enable_power_law_low,
[4e1c362]1420                                     id=self.guinier.GetId())       
[4a2b054]1421        self.power_law_low = wx.RadioButton(self, -1, 'Power Law',
1422                                            (10, 10), name='power_law_low')
[518d35d]1423        self.Bind(wx.EVT_RADIOBUTTON, self._enable_power_law_low, 
1424                                        id=self.power_law_low.GetId())
1425       
[c128284]1426        npts_low_txt = wx.StaticText(self, -1, 'Npts')
[4a2b054]1427        self.npts_low_tcl = InvTextCtrl(self, -1,
1428                                        size=(_BOX_WIDTH*2/3, -1),
1429                                        name='npts_low_tcl')
[4e1c362]1430        wx.EVT_TEXT(self, self.npts_low_tcl.GetId(), self._on_text)
[2661d8b]1431        msg_hint = "Number of Q points to consider"
1432        msg_hint +="while extrapolating the low-Q region"
[9ce7641c]1433        self.npts_low_tcl.SetToolTipString(msg_hint)
1434        power_txt = wx.StaticText(self, -1, 'Power')
[4a2b054]1435        self.power_low_tcl = InvTextCtrl(self, -1, size=(_BOX_WIDTH*2/3, -1),
1436                                         name='power_low_tcl')
[4e1c362]1437        wx.EVT_TEXT(self, self.power_low_tcl.GetId(), self._on_text)
[d0cc0bbc]1438       
[9ce7641c]1439        power_hint_txt = "Exponent to apply to the Power_law function."
1440        self.power_low_tcl.SetToolTipString(power_hint_txt)
[c128284]1441        iy = 0
1442        ix = 0
[4a2b054]1443        self.low_q_sizer.Add(self.enable_low_cbox,(iy, ix), (1, 5),
[518d35d]1444                            wx.TOP|wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
1445        iy += 1
1446        ix = 0
[4a2b054]1447        self.low_q_sizer.Add(npts_low_txt,(iy, ix), (1, 1),
[518d35d]1448                            wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
1449        ix += 1
1450        self.low_q_sizer.Add(self.npts_low_tcl, (iy, ix), (1,1),
1451                            wx.EXPAND|wx.ADJUST_MINSIZE, 0)
1452        iy += 1
1453        ix = 0
[9ce7641c]1454        self.low_q_sizer.Add(self.guinier,(iy, ix),(1,2),
[c128284]1455                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
1456        iy += 1
1457        ix = 0
[4a2b054]1458        self.low_q_sizer.Add(self.power_law_low,(iy, ix), (1, 2),
[2661d8b]1459                            wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
[518d35d]1460       
[2661d8b]1461        # Parameter controls for power law
1462        ix = 1
1463        iy += 1
[4a2b054]1464        self.low_q_sizer.Add(self.fix_enable_low,(iy, ix), (1, 1),
[518d35d]1465                            wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
1466        ix += 1
1467        self.low_q_sizer.Add(self.fit_enable_low,(iy, ix),(1,1),
1468                           wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
[9ce7641c]1469        ix = 1
1470        iy += 1
[4a2b054]1471        self.low_q_sizer.Add(power_txt,(iy, ix), (1, 1),
[518d35d]1472                            wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
[c128284]1473        ix += 1
[4a2b054]1474        self.low_q_sizer.Add(self.power_low_tcl, (iy, ix), (1, 1),
[c128284]1475                            wx.EXPAND|wx.ADJUST_MINSIZE, 0)
[9ce7641c]1476        self.low_extrapolation_sizer.AddMany([(self.low_q_sizer, 0,
[d0cc0bbc]1477                                                wx.BOTTOM|wx.RIGHT, 15)])
1478       
[518d35d]1479    def _enable_fit_power_law_high(self, event=None):
1480        """
[d7a39e5]1481        Enable and disable the power value editing
[518d35d]1482        """
[cb463b4]1483        if event != None: 
[27f3831]1484            self._set_bookmark_flag(True)
[cb69775]1485   
[27f3831]1486            self._set_preview_flag(False)
[518d35d]1487        if self.fix_enable_high.IsEnabled():
1488            if self.fix_enable_high.GetValue():
[4e1c362]1489                self.fit_enable_high.SetValue(False)
[518d35d]1490                self.power_high_tcl.Enable()
1491            else:
[4e1c362]1492                self.fit_enable_high.SetValue(True)
[518d35d]1493                self.power_high_tcl.Disable()
[4e1c362]1494        self._set_state(event=event)
[9ce7641c]1495       
[518d35d]1496    def _enable_high_q_section(self, event=None):
1497        """
[d7a39e5]1498        Disable or enable some button if the user enable high q extrapolation
[518d35d]1499        """
[cb463b4]1500        if event != None: 
[27f3831]1501            self._set_bookmark_flag(True)
1502            self._set_preview_flag(False)
[518d35d]1503        if self.enable_high_cbox.GetValue():
1504            self.npts_high_tcl.Enable()
1505            self.power_law_high.Enable()
1506            self.power_high_tcl.Enable()
1507            self.fix_enable_high.Enable()
1508            self.fit_enable_high.Enable()
1509        else:
1510            self.npts_high_tcl.Disable()
1511            self.power_law_high.Disable()
1512            self.power_high_tcl.Disable()
1513            self.fix_enable_high.Disable()
1514            self.fit_enable_high.Disable()
1515        self._enable_fit_power_law_high()
[4e1c362]1516        self._set_state(event=event)
[d0cc0bbc]1517        self.button_calculate.SetFocus()
[b7f29fc]1518 
[9ce7641c]1519    def _layout_extrapolation_high(self):
1520        """
[d7a39e5]1521        Draw widgets related to extrapolation at high q range
[9ce7641c]1522        """
[4a2b054]1523        self.enable_high_cbox = wx.CheckBox(self, -1,
1524                                            "Enable Extrapolate high-Q",
1525                                            name='enable_high_cbox')
[518d35d]1526        wx.EVT_CHECKBOX(self, self.enable_high_cbox.GetId(),
1527                                         self._enable_high_q_section)
1528        self.fix_enable_high = wx.RadioButton(self, -1, 'Fix',
[4a2b054]1529                                         (10, 10), style=wx.RB_GROUP,
1530                                         name='fix_enable_high')
[518d35d]1531        self.Bind(wx.EVT_RADIOBUTTON, self._enable_fit_power_law_high,
1532                                     id=self.fix_enable_high.GetId())
[4a2b054]1533        self.fit_enable_high = wx.RadioButton(self, -1, 'Fit', (10, 10),
1534                                              name='fit_enable_high')     
[518d35d]1535        self.Bind(wx.EVT_RADIOBUTTON, self._enable_fit_power_law_high, 
1536                                        id=self.fit_enable_high.GetId())
1537       
[277fad8]1538        self.power_law_high = wx.StaticText(self, -1, 'Power Law')
[d0cc0bbc]1539        msg_hint ="Check to extrapolate data at high-Q"
1540        self.power_law_high.SetToolTipString(msg_hint)
[c128284]1541        npts_high_txt = wx.StaticText(self, -1, 'Npts')
[4a2b054]1542        self.npts_high_tcl = InvTextCtrl(self, -1, size=(_BOX_WIDTH*2/3, -1),
1543                                         name='npts_high_tcl')
[4e1c362]1544        wx.EVT_TEXT(self, self.npts_high_tcl.GetId(), self._on_text)
[2661d8b]1545        msg_hint = "Number of Q points to consider"
1546        msg_hint += "while extrapolating the high-Q region"
[9ce7641c]1547        self.npts_high_tcl.SetToolTipString(msg_hint)
1548        power_txt = wx.StaticText(self, -1, 'Power')
[4a2b054]1549        self.power_high_tcl = InvTextCtrl(self, -1, size=(_BOX_WIDTH*2/3, -1),
1550                                          name='power_high_tcl')
[4e1c362]1551        wx.EVT_TEXT(self, self.power_high_tcl.GetId(), self._on_text)
[9ce7641c]1552        power_hint_txt = "Exponent to apply to the Power_law function."
1553        self.power_high_tcl.SetToolTipString(power_hint_txt)
[518d35d]1554        iy = 0
1555        ix = 0
[4a2b054]1556        self.high_q_sizer.Add(self.enable_high_cbox, (iy, ix), (1, 5),
[518d35d]1557                            wx.TOP|wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
1558        iy += 1
1559        ix = 0
[4a2b054]1560        self.high_q_sizer.Add(npts_high_txt, (iy, ix), (1, 1),
[518d35d]1561                            wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
1562        ix += 1
[4a2b054]1563        self.high_q_sizer.Add(self.npts_high_tcl, (iy, ix), (1, 1),
[518d35d]1564                            wx.EXPAND|wx.ADJUST_MINSIZE, 0)
1565        iy += 2
[c128284]1566        ix = 0
[4a2b054]1567        self.high_q_sizer.Add(self.power_law_high, (iy, ix),(1, 2),
[2661d8b]1568                            wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
[518d35d]1569       
1570        # Parameter controls for power law
[2661d8b]1571        ix = 1
1572        iy += 1
[4a2b054]1573        self.high_q_sizer.Add(self.fix_enable_high,(iy, ix), (1, 1),
[518d35d]1574                            wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
1575        ix += 1
[4a2b054]1576        self.high_q_sizer.Add(self.fit_enable_high,(iy, ix), (1, 1),
[518d35d]1577                           wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
[9ce7641c]1578        ix = 1
1579        iy += 1
[4a2b054]1580        self.high_q_sizer.Add(power_txt,(iy, ix), (1, 1),
[c128284]1581                            wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
1582        ix += 1
[4a2b054]1583        self.high_q_sizer.Add(self.power_high_tcl, (iy, ix),  (1, 1),
[c128284]1584                            wx.EXPAND|wx.ADJUST_MINSIZE, 0)
[d0cc0bbc]1585        self.high_extrapolation_sizer.AddMany([(self.high_q_sizer, 0, 
1586                                                wx.BOTTOM|wx.RIGHT, 10)])
[c128284]1587       
[9ce7641c]1588    def _layout_extrapolation(self):
1589        """
[d7a39e5]1590        Draw widgets related to extrapolation
[9ce7641c]1591        """
[518d35d]1592        extra_hint = "Extrapolation Maximum Q Range [1/A]: "
[9ce7641c]1593        extra_hint_txt = wx.StaticText(self, -1, extra_hint)
1594        #Extrapolation range [string]
[4e1c362]1595        extrapolation_min_txt = wx.StaticText(self, -1, 'Min :') 
[518d35d]1596        self.extrapolation_min_tcl = OutputTextCtrl(self, -1, 
[4a2b054]1597                                                size=(_BOX_WIDTH, 20), style=0,
1598                                                name='extrapolation_min_tcl')
[9ce7641c]1599        self.extrapolation_min_tcl.SetValue(str(Q_MINIMUM))
[4a2b054]1600        hint_msg = "The minimum extrapolated q value."
1601        self.extrapolation_min_tcl.SetToolTipString(hint_msg)
[4e1c362]1602        extrapolation_max_txt = wx.StaticText(self, -1, 'Max :') 
[518d35d]1603        self.extrapolation_max_tcl = OutputTextCtrl(self, -1,
[4a2b054]1604                                                  size=(_BOX_WIDTH, 20),
1605                                                  style=0,
1606                                                  name='extrapolation_max_tcl') 
[9ce7641c]1607        self.extrapolation_max_tcl.SetValue(str(Q_MAXIMUM))
[4a2b054]1608        hint_msg = "The maximum extrapolated q value."
1609        self.extrapolation_max_tcl.SetToolTipString(hint_msg)
1610        self.extrapolation_range_sizer.AddMany([(extra_hint_txt, 0, 
1611                                                 wx.LEFT, 10),
1612                                                (extrapolation_min_txt, 0,
1613                                                 wx.LEFT, 10),
[9ce7641c]1614                                                (self.extrapolation_min_tcl,
1615                                                            0, wx.LEFT, 10),
[4a2b054]1616                                                (extrapolation_max_txt, 0,
1617                                                 wx.LEFT, 10),
[9ce7641c]1618                                                (self.extrapolation_max_tcl,
1619                                                            0, wx.LEFT, 10),
1620                                                ])
1621        self._layout_extrapolation_low()
1622        self._layout_extrapolation_high()
1623        self.extrapolation_low_high_sizer.AddMany([(self.low_extrapolation_sizer,
[4e1c362]1624                                                     0, wx.ALL, 5),
[9ce7641c]1625                                                   (self.high_extrapolation_sizer,
[4e1c362]1626                                                    0, wx.ALL, 5)])
[9ce7641c]1627        self.extrapolation_sizer.AddMany([(self.extrapolation_range_sizer, 0,
[4e1c362]1628                                            wx.RIGHT, 5),
[9ce7641c]1629                                        (self.extrapolation_low_high_sizer, 0,
[4e1c362]1630                                           wx.ALL, 5)])
[9ce7641c]1631       
1632    def _layout_volume_surface_sizer(self):
1633        """
[d7a39e5]1634        Draw widgets related to volume and surface
[9ce7641c]1635        """
1636        unit_volume = ''
1637        unit_surface = ''
1638        uncertainty = "+/-" 
[dce0756]1639        volume_txt = wx.StaticText(self, -1, 'Volume Fraction      ')
[4a2b054]1640        self.volume_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH, -1),
1641                                         name='volume_tcl')
[4e1c362]1642        wx.EVT_TEXT(self, self.volume_tcl.GetId(), self._on_out_text)
[9ce7641c]1643        self.volume_tcl.SetToolTipString("Volume fraction.")
[4a2b054]1644        self.volume_err_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH, -1),
1645                                             name='volume_err_tcl')
[4e1c362]1646        wx.EVT_TEXT(self, self.volume_err_tcl.GetId(), self._on_out_text)
[4a2b054]1647        hint_msg = "Uncertainty on the volume fraction."
1648        self.volume_err_tcl.SetToolTipString(hint_msg)
[c128284]1649        volume_units_txt = wx.StaticText(self, -1, unit_volume)
1650       
[277fad8]1651        surface_txt = wx.StaticText(self, -1, 'Specific Surface')
[4a2b054]1652        self.surface_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH, -1),
1653                                          name='surface_tcl')
[4e1c362]1654        wx.EVT_TEXT(self, self.surface_tcl.GetId(), self._on_out_text)
[9ce7641c]1655        self.surface_tcl.SetToolTipString("Specific surface value.")
[4a2b054]1656        self.surface_err_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH, -1),
1657                                              name='surface_err_tcl')
[4e1c362]1658        wx.EVT_TEXT(self, self.surface_err_tcl.GetId(), self._on_out_text)
[4a2b054]1659        hint_msg = "Uncertainty on the specific surface."
1660        self.surface_err_tcl.SetToolTipString(hint_msg)
[c128284]1661        surface_units_txt = wx.StaticText(self, -1, unit_surface)
1662        iy = 0
1663        ix = 0
[4a2b054]1664        self.volume_surface_sizer.Add(volume_txt, (iy, ix), (1, 1),
[c128284]1665                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
[9ce7641c]1666        ix += 1
[4a2b054]1667        self.volume_surface_sizer.Add(self.volume_tcl, (iy, ix), (1, 1),
[9ce7641c]1668                            wx.EXPAND|wx.ADJUST_MINSIZE, 10)
1669        ix += 1
1670        self.volume_surface_sizer.Add(wx.StaticText(self, -1, uncertainty),
1671                         (iy, ix),(1,1),wx.EXPAND|wx.ADJUST_MINSIZE, 10) 
1672        ix += 1
[4a2b054]1673        self.volume_surface_sizer.Add(self.volume_err_tcl, (iy, ix), (1, 1),
[9ce7641c]1674                            wx.EXPAND|wx.ADJUST_MINSIZE, 10) 
1675        ix += 1
[4a2b054]1676        self.volume_surface_sizer.Add(volume_units_txt, (iy, ix), (1, 1),
[9ce7641c]1677                             wx.EXPAND|wx.ADJUST_MINSIZE, 10)
[c128284]1678        iy += 1
1679        ix = 0
[4a2b054]1680        self.volume_surface_sizer.Add(surface_txt, (iy, ix), (1, 1),
[9ce7641c]1681                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
[c128284]1682        ix += 1
[4a2b054]1683        self.volume_surface_sizer.Add(self.surface_tcl, (iy, ix), (1, 1),
[9ce7641c]1684                            wx.EXPAND|wx.ADJUST_MINSIZE, 0)
[c128284]1685        ix += 1
[9ce7641c]1686        self.volume_surface_sizer.Add(wx.StaticText(self, -1, uncertainty),
[c128284]1687                         (iy, ix),(1,1),wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
1688        ix += 1
[4a2b054]1689        self.volume_surface_sizer.Add(self.surface_err_tcl, (iy, ix), (1, 1),
[c128284]1690                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
1691        ix += 1
[4a2b054]1692        self.volume_surface_sizer.Add(surface_units_txt, (iy, ix), (1, 1),
[9ce7641c]1693                            wx.EXPAND|wx.ADJUST_MINSIZE, 10)
1694       
1695    def _layout_invariant_sizer(self):
1696        """
[d7a39e5]1697        Draw widgets related to invariant
[9ce7641c]1698        """
1699        uncertainty = "+/-" 
[277fad8]1700        unit_invariant = '[1/(cm * A)]'
[eed601e]1701        invariant_total_txt = wx.StaticText(self, -1, 'Invariant Total [Q*]')
[4a2b054]1702        self.invariant_total_tcl = OutputTextCtrl(self, -1,
1703                                                  size=(_BOX_WIDTH,-1),
1704                                                  name='invariant_total_tcl')
[eed601e]1705        msg_hint = "Total invariant [Q*], including extrapolated regions."
[9ce7641c]1706        self.invariant_total_tcl.SetToolTipString(msg_hint)
[4a2b054]1707        self.invariant_total_err_tcl = OutputTextCtrl(self, -1,
1708                                                      size=(_BOX_WIDTH,-1),
1709                                                name='invariant_total_err_tcl')
1710        hint_msg = "Uncertainty on invariant."
1711        self.invariant_total_err_tcl.SetToolTipString(hint_msg)
[9ce7641c]1712        invariant_total_units_txt = wx.StaticText(self, -1, unit_invariant)
1713   
1714        #Invariant total
1715        iy = 0
[c128284]1716        ix = 0
[4a2b054]1717        self.invariant_sizer.Add(invariant_total_txt, (iy, ix), (1, 1),
[c128284]1718                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
[9ce7641c]1719        ix += 1
[4a2b054]1720        self.invariant_sizer.Add(self.invariant_total_tcl, (iy, ix), (1, 1),
[dce0756]1721                          wx.EXPAND|wx.ADJUST_MINSIZE, 10)
[c128284]1722        ix += 1
[9ce7641c]1723        self.invariant_sizer.Add( wx.StaticText(self, -1, uncertainty),
[277fad8]1724                         (iy, ix),(1,1),wx.EXPAND|wx.ADJUST_MINSIZE, 10) 
[c128284]1725        ix += 1
[4a2b054]1726        self.invariant_sizer.Add(self.invariant_total_err_tcl, (iy, ix), (1, 1),
[277fad8]1727                             wx.EXPAND|wx.ADJUST_MINSIZE, 10)
[c128284]1728        ix += 1
[4a2b054]1729        self.invariant_sizer.Add(invariant_total_units_txt,(iy, ix), (1, 1),
[277fad8]1730                          wx.EXPAND|wx.ADJUST_MINSIZE, 10)
[9ce7641c]1731 
[d0cc0bbc]1732    def _layout_inputs_sizer(self):
1733        """
[d7a39e5]1734        Draw widgets related to inputs
[d0cc0bbc]1735        """
1736        self._layout_bkg_scale()
1737        self._layout_contrast_porod()
1738        self.inputs_sizer.AddMany([(self.bkg_scale_sizer, 0, wx.ALL, 5),
1739                                    (self.contrast_porod_sizer, 0, wx.ALL, 5)])
1740       
[9ce7641c]1741    def _layout_outputs_sizer(self):
1742        """
[d7a39e5]1743        Draw widgets related to outputs
[9ce7641c]1744        """
1745        self._layout_volume_surface_sizer()
1746        self._layout_invariant_sizer()
1747        static_line = wx.StaticLine(self, -1)
1748        self.outputs_sizer.AddMany([(self.volume_surface_sizer, 0, wx.ALL, 10),
1749                                    (static_line, 0, wx.EXPAND, 0),
1750                                    (self.invariant_sizer, 0, wx.ALL, 10)])
1751    def _layout_button(self): 
1752        """
[d7a39e5]1753        Do the layout for the button widgets
[9ce7641c]1754        """ 
1755        #compute button
[c128284]1756        id = wx.NewId()
[4a2b054]1757        self.button_calculate = wx.Button(self, id, "Compute",
1758                                          name='compute_invariant')
[d0cc0bbc]1759        self.button_calculate.SetToolTipString("Compute invariant")
[9ce7641c]1760        self.Bind(wx.EVT_BUTTON, self.compute_invariant, id=id)   
1761        #detail button
1762        id = wx.NewId()
[d0cc0bbc]1763        self.button_details = wx.Button(self, id, "Details?")
[4a2b054]1764        hint_msg = "Details about the results of the computation"
1765        self.button_details.SetToolTipString(hint_msg)
[9ce7641c]1766        self.Bind(wx.EVT_BUTTON, self.display_details, id=id)
1767        details = "Details on Invariant Total Calculations"
1768        details_txt = wx.StaticText(self, -1, details)
[4e1c362]1769        self.button_sizer.AddMany([((50,10), 0 , wx.LEFT,0),
[d0cc0bbc]1770                                   (details_txt, 0 , 
1771                                    wx.RIGHT|wx.BOTTOM|wx.TOP, 10),
1772                                   (self.button_details, 0 , wx.ALL, 10),
[4a2b054]1773                        (self.button_calculate, 0 ,
[cb69775]1774                         wx.RIGHT|wx.TOP|wx.BOTTOM, 10)])
[9ce7641c]1775    def _do_layout(self):
1776        """
[d7a39e5]1777        Draw window content
[9ce7641c]1778        """
1779        self._define_structure()
1780        self._layout_data_name()
1781        self._layout_extrapolation()
[d0cc0bbc]1782        self._layout_inputs_sizer()
[9ce7641c]1783        self._layout_outputs_sizer()
1784        self._layout_button()
[355b684]1785        self.main_sizer.AddMany([(self.data_name_boxsizer,0, wx.ALL, 10),
[9ce7641c]1786                                  (self.outputs_sizer, 0,
1787                                  wx.LEFT|wx.RIGHT|wx.BOTTOM, 10),
[355b684]1788                                  (self.button_sizer,0,
[d0cc0bbc]1789                                  wx.LEFT|wx.RIGHT|wx.BOTTOM, 10),
1790                                 (self.inputs_sizer, 0,
1791                                  wx.LEFT|wx.RIGHT|wx.BOTTOM, 10),
1792                                  (self.extrapolation_sizer, 0,
[9ce7641c]1793                                  wx.LEFT|wx.RIGHT|wx.BOTTOM, 10)])
1794        self.SetSizer(self.main_sizer)
[355b684]1795        self.SetAutoLayout(True)
[0399c78]1796       
1797       
[c128284]1798class InvariantDialog(wx.Dialog):
[d7a39e5]1799    """
1800    """
[c128284]1801    def __init__(self, parent=None, id=1,graph=None,
[272d91e]1802                 data=None, title="Invariant",base=None):
1803        wx.Dialog.__init__(self, parent, id, title, size=(PANEL_WIDTH,
[c128284]1804                                                             PANEL_HEIGHT))
[272d91e]1805        self.panel = InvariantPanel(self)
[c128284]1806        self.Centre()
1807        self.Show(True)
1808       
1809class InvariantWindow(wx.Frame):
[d7a39e5]1810    """
1811    """
[4a2b054]1812    def __init__(self, parent=None, id=1, graph=None, 
1813                 data=None, title="Invariant", base=None):
[c128284]1814       
[9ce7641c]1815        wx.Frame.__init__(self, parent, id, title, size=(PANEL_WIDTH +100,
1816                                                             PANEL_HEIGHT+100))
[4e1c362]1817        from DataLoader.loader import  Loader
1818        self.loader = Loader()
1819        import invariant
[4a2b054]1820        path = "C:/ECLPS/workspace/trunk/DataLoader/test/ascii_test_3.txt"
1821        data= self.loader.load(path)
[272d91e]1822        self.panel = InvariantPanel(self)
[4e1c362]1823
1824        data.name = data.filename
[210ff4f]1825        self.panel.set_data(data)
[c128284]1826        self.Centre()
1827        self.Show(True)
1828       
1829class MyApp(wx.App):
1830    def OnInit(self):
1831        wx.InitAllImageHandlers()
1832        frame = InvariantWindow()
1833        frame.Show(True)
1834        self.SetTopWindow(frame)
1835       
1836        return True
[272d91e]1837     
[c128284]1838# end of class MyApp
1839
1840if __name__ == "__main__":
1841    app = MyApp(0)
1842    app.MainLoop()
Note: See TracBrowser for help on using the repository browser.