source: sasview/invariantview/perspectives/invariant/invariant_panel.py @ 8f12385

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

remove other type of data into sansview

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