source: sasview/invariantview/perspectives/invariant/invariant_panel.py @ 45f896f

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

save project function for invariant added

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