source: sasview/invariantview/perspectives/invariant/invariant_panel.py @ 330c63b

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 330c63b was 330c63b, checked in by Gervaise Alina <gervyh@…>, 14 years ago

remove unused path

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