source: sasview/invariantview/perspectives/invariant/invariant_panel.py @ 0399c78

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

fixed some bug from datamanager

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