source: sasview/invariantview/perspectives/invariant/invariant_panel.py @ 0cf97c5

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

added save button in toolbar, and repositioned menu items

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