source: sasview/invariantview/src/sans/perspectives/invariant/invariant_panel.py @ 001b930

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 001b930 was f6518f8, checked in by Gervaise Alina <gervyh@…>, 13 years ago

edit invariant panel for negative percentage

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