source: sasview/invariantview/perspectives/invariant/invariant_panel.py @ 8cd029b

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 8cd029b was 27f3831, checked in by Gervaise Alina <gervyh@…>, 14 years ago

binding invirant button with guiframe toolbar

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