source: sasview/invariantview/perspectives/invariant/invariant_panel.py @ 9b18735

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

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

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