source: sasview/invariantview/perspectives/invariant/invariant_panel.py @ 59b9b675

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

add bookmark button to toolbar

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