source: sasview/invariantview/perspectives/invariant/invariant_panel.py @ e715e4f

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

add bookmark button to toolbar

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