source: sasview/invariantview/perspectives/invariant/invariant_panel.py @ b63dc6e

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 b63dc6e was 9b18735, checked in by Jae Cho <jhjcho@…>, 14 years ago

now all panels are reset when opening svs files: except prview

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