source: sasview/invariantview/perspectives/invariant/invariant_panel.py @ 6f28e70

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 6f28e70 was 04295ea, checked in by Jae Cho <jhjcho@…>, 14 years ago

This fixes the problems w/ status file open/close

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