source: sasview/invariantview/src/sans/perspectives/invariant/invariant_panel.py @ 699df7f

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 699df7f was 699df7f, checked in by Jae Cho <jhjcho@…>, 12 years ago

invariant_panel: pylint fix#1

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