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

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 0d8642c9 was 6a0cbcf4, checked in by Gervaise Alina <gervyh@…>, 14 years ago

make panel inheriting from PanelBase?

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