source: sasview/invariantview/perspectives/invariant/invariant_panel.py @ 5cc393b8

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 5cc393b8 was 4a2b054, checked in by Gervaise Alina <gervyh@…>, 14 years ago

working on pylint

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