source: sasview/invariantview/perspectives/invariant/invariant_panel.py @ 4523b68

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 4523b68 was 645f9b6, checked in by Jae Cho <jhjcho@…>, 14 years ago

fixed minor bugs on set_state that did not totally update state information and not pass to state object.

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