source: sasview/src/sas/perspectives/pr/inversion_panel.py @ 26500ec

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 26500ec was 79492222, checked in by krzywon, 10 years ago

Changed the file and folder names to remove all SANS references.

  • Property mode set to 100644
File size: 41.1 KB
RevLine 
[f3d51f6]1#!/usr/bin/env python
2
3# version
4__id__ = "$Id: aboutdialog.py 1193 2007-05-03 17:29:59Z dmitriy $"
5__revision__ = "$Revision: 1193 $"
6
7import wx
[5d98370]8import os
[ceaf16e]9import sys
10import logging
[9ff861b]11from wx.lib.scrolledpanel import ScrolledPanel
[79492222]12from sas.guiframe.events import StatusEvent   
13from sas.guiframe.panel_base import PanelBase
[5d98370]14from inversion_state import InversionState
[3e41f43]15from pr_widgets import PrTextCtrl
16from pr_widgets import DataFileTextCtrl
17from pr_widgets import OutputTextCtrl
[f3d51f6]18
[b8ff610]19if sys.platform.count("win32") > 0:
[7d9e7a9]20    FONT_VARIANT = 0
21else:
22    FONT_VARIANT = 1
[f3d51f6]23
[75df58b]24class InversionControl(ScrolledPanel, PanelBase):
[7116b6e0]25    """
26    """
[f3d51f6]27    window_name = 'pr_control'
28    window_caption = "P(r) control panel"
29    CENTER_PANE = True
30   
31    # Figure of merit parameters [default]
[dfb58f8]32   
33    ## Oscillation parameters (sin function = 1.1)
[f3d51f6]34    oscillation_max = 1.5
35   
[3e41f43]36    def __init__(self, parent, id=-1, plots=None, 
37                 standalone=False, **kwargs):
[7116b6e0]38        """
39        """
[3e41f43]40        ScrolledPanel.__init__(self, parent, id=id, **kwargs)
[3f0351c6]41        PanelBase.__init__(self, parent)
[9ff861b]42        self.SetupScrolling()
[7d9e7a9]43        #Set window's font size
44        self.SetWindowVariant(variant=FONT_VARIANT)
[f3d51f6]45       
46        self.plots = plots
47        self.radio_buttons = {}
[ae84427]48        self.parent = parent.parent
[f3d51f6]49       
50        ## Data file TextCtrl
[a4bd2ac]51        self.data_file  = None
52        self.plot_data  = None
53        self.nfunc_ctl  = None
54        self.alpha_ctl  = None
55        self.dmax_ctl   = None
56        self.time_ctl   = None
57        self.chi2_ctl   = None
58        self.osc_ctl    = None
[f3d51f6]59        self.file_radio = None
60        self.plot_radio = None
[634f1cf]61        self.label_sugg = None
[a4bd2ac]62        self.qmin_ctl   = None
63        self.qmax_ctl   = None
[5d98370]64        self.swidth_ctl = None
65        self.sheight_ctl = None
[a4bd2ac]66       
67        self.rg_ctl     = None
68        self.iq0_ctl    = None
69        self.bck_chk    = None
70        self.bck_ctl    = None
[f3d51f6]71       
[dfb58f8]72        # TextCtrl for fraction of positive P(r)
73        self.pos_ctl = None
74       
75        # TextCtrl for fraction of 1 sigma positive P(r)
76        self.pos_err_ctl = None 
77       
[f3d51f6]78        ## Estimates
79        self.alpha_estimate_ctl = None
[35adaf6]80        self.nterms_estimate_ctl = None
[a00ee4c]81        ## D_max distance explorator
82        self.distance_explorator_ctl = None
[f3d51f6]83        ## Data manager
[6d3d5ff]84        self._manager   = None
[aa4b8379]85        ## Standalone flage
86        self.standalone = standalone
[5d98370]87        ## Default file location for save
88        self._default_save_location = os.getcwd()
[c4ae1c2]89        if self.parent is not None:
90            self._default_save_location =\
91                        self.parent._default_save_location
92       
[0ccd214]93        # Default width
94        self._default_width = 350
[f3d51f6]95        self._do_layout()
96       
97    def __setattr__(self, name, value):
98        """
[7116b6e0]99        Allow direct hooks to text boxes
[f3d51f6]100        """
[3e41f43]101        if name == 'nfunc':
[5d98370]102            self.nfunc_ctl.SetValue(str(int(value)))
[3e41f43]103        elif name == 'd_max':
[f3d51f6]104            self.dmax_ctl.SetValue(str(value))
[3e41f43]105        elif name == 'alpha':
[f3d51f6]106            self.alpha_ctl.SetValue(str(value))
[3e41f43]107        elif name == 'chi2':
[a4bd2ac]108            self.chi2_ctl.SetValue("%-5.2g" % value)
[3e41f43]109        elif name == 'bck':
[a4bd2ac]110            self.bck_ctl.SetValue("%-5.2g" % value)
[3e41f43]111        elif name == 'q_min':
[a4bd2ac]112            self.qmin_ctl.SetValue("%-5.2g" % value)
[3e41f43]113        elif name == 'q_max':
[a4bd2ac]114            self.qmax_ctl.SetValue("%-5.2g" % value)
[3e41f43]115        elif name == 'elapsed':
[f3d51f6]116            self.time_ctl.SetValue("%-5.2g" % value)
[4c65725]117        elif name =='rg':
[a4bd2ac]118            self.rg_ctl.SetValue("%-5.2g" % value)
[3e41f43]119        elif name == 'iq0':
[a4bd2ac]120            self.iq0_ctl.SetValue("%-5.2g" % value)
[3e41f43]121        elif name == 'oscillation':
[f3d51f6]122            self.osc_ctl.SetValue("%-5.2g" % value)
[3e41f43]123        elif name == 'slit_width':
[5d98370]124            self.swidth_ctl.SetValue("%-5.2g" % value)
[3e41f43]125        elif name == 'slit_height':
[5d98370]126            self.sheight_ctl.SetValue("%-5.2g" % value)
[3e41f43]127        elif name == 'positive':
[dfb58f8]128            self.pos_ctl.SetValue("%-5.2g" % value)
[3e41f43]129        elif name == 'pos_err':
[dfb58f8]130            self.pos_err_ctl.SetValue("%-5.2g" % value)
[3e41f43]131        elif name == 'alpha_estimate':
[634f1cf]132            self.alpha_estimate_ctl.SetToolTipString("Click to accept value.")
133            self.alpha_estimate_ctl.Enable(True)
134            self.alpha_estimate_ctl.SetLabel("%-3.1g" % value)
135            #self.alpha_estimate_ctl.Show()
136            #self.label_sugg.Show()
[3e41f43]137        elif name == 'nterms_estimate':
[35adaf6]138            self.nterms_estimate_ctl.SetToolTipString("Click to accept value.")
139            self.nterms_estimate_ctl.Enable(True)
140            self.nterms_estimate_ctl.SetLabel("%-g" % value)
[3e41f43]141        elif name == 'plotname':
[0d88a09]142            self.plot_data.SetValue(str(value))
143            self._on_pars_changed(None)
[3e41f43]144        elif name == 'datafile':
[0d88a09]145            self.plot_data.SetValue(str(value))
146            self._on_pars_changed(None)
[f3d51f6]147        else:
148            wx.Panel.__setattr__(self, name, value)
149       
150    def __getattr__(self, name):
151        """
[7116b6e0]152        Allow direct hooks to text boxes
[f3d51f6]153        """
[3e41f43]154        if name == 'nfunc':
[3fd1ebc]155            try:
156                return int(self.nfunc_ctl.GetValue())
157            except:
158                return -1
[3e41f43]159        elif name == 'd_max':
[3fd1ebc]160            try:
161                return self.dmax_ctl.GetValue()
162            except:
163                return -1.0
[3e41f43]164        elif name == 'alpha':
[3fd1ebc]165            try:
166                return self.alpha_ctl.GetValue()
167            except:
168                return -1.0
[3e41f43]169        elif name == 'chi2':
[3fd1ebc]170            try:
171                return float(self.chi2_ctl.GetValue())
172            except:
[5d98370]173                return None
[3e41f43]174        elif name == 'bck':
[a4bd2ac]175            try:
176                return float(self.bck_ctl.GetValue())
177            except:
[5d98370]178                return None
[3e41f43]179        elif name == 'q_min':
[3fd1ebc]180            try:
181                return float(self.qmin_ctl.GetValue())
182            except:
183                return 0.0
[634f1cf]184        elif name=='q_max':
[3fd1ebc]185            try:
186                return float(self.qmax_ctl.GetValue())
187            except:
188                return 0.0
[3e41f43]189        elif name == 'elapsed':
[3fd1ebc]190            try:
191                return float(self.time_ctl.GetValue())
192            except:
[5d98370]193                return None
[3e41f43]194        elif name == 'rg':
[a4bd2ac]195            try:
196                return float(self.rg_ctl.GetValue())
197            except:
[5d98370]198                return None
[a4bd2ac]199        elif name=='iq0':
200            try:
201                return float(self.iq0_ctl.GetValue())
202            except:
[5d98370]203                return None
[3e41f43]204        elif name == 'oscillation':
[3fd1ebc]205            try:
206                return float(self.osc_ctl.GetValue())
207            except:
[5d98370]208                return None
[3e41f43]209        elif name == 'slit_width':
[5d98370]210            try:
211                return float(self.swidth_ctl.GetValue())
212            except:
213                return None
214        elif name=='slit_height':
215            try:
216                return float(self.sheight_ctl.GetValue())
217            except:
218                return None
[3e41f43]219        elif name == 'pos':
[3fd1ebc]220            try:
221                return float(self.pos_ctl.GetValue())
222            except:
[5d98370]223                return None
[3e41f43]224        elif name == 'pos_err':
[5d98370]225            try:
226                return float(self.pos_err_ctl.GetValue())
227            except:
228                return None
[3e41f43]229        elif name == 'alpha_estimate':
[5d98370]230            try:
231                return float(self.alpha_estimate_ctl.GetLabel())
232            except:
233                return None
[3e41f43]234        elif name == 'nterms_estimate':
[5d98370]235            try:
236                return int(self.nterms_estimate_ctl.GetLabel())
237            except:
238                return None
[3e41f43]239        elif name == 'plotname':
[0d88a09]240            return self.plot_data.GetValue()
[3e41f43]241        elif name == 'datafile':
[0d88a09]242            return self.plot_data.GetValue()
[f3d51f6]243        else:
[a00ee4c]244            return wx.Panel.__getattribute__(self, name)
[f3d51f6]245       
[d85ee8c]246    def save_project(self, doc=None):
247        """
248        return an xml node containing state of the panel
249         that guiframe can write to file
250        """
251        data = self.get_data()
252        state = self.get_state()
253        if data is not None:
254            new_doc = self._manager.state_reader.write_toXML(data, state)
255            if new_doc is not None:
256                if doc is not None and hasattr(doc, "firstChild"):
[92a2ecd]257                    child = new_doc.getElementsByTagName("SASentry")
258                    for item in child:
259                        doc.firstChild.appendChild(item)
[d85ee8c]260                else:
261                    doc = new_doc
262        return doc   
263   
[3f0351c6]264    def on_save(self, evt=None):
[5d98370]265        """
[7116b6e0]266        Method used to create a memento of the current state
[5d98370]267           
[7116b6e0]268        :return: state object
[5d98370]269        """
270        # Ask the user the location of the file to write to.
271        path = None
[c4ae1c2]272        if self.parent != None:
273            self._default_save_location =\
274             self.parent._default_save_location
[3e41f43]275        dlg = wx.FileDialog(self, "Choose a file",
[c4ae1c2]276                            self._default_save_location,\
277                            self.window_caption, "*.prv", wx.SAVE)
[5d98370]278        if dlg.ShowModal() == wx.ID_OK:
279            path = dlg.GetPath()
280            self._default_save_location = os.path.dirname(path)
[c4ae1c2]281            if self.parent != None:
282                self.parent._default_save_location =\
283                self._default_save_location
[0d88a09]284        else:
285            return None
286       
[5d98370]287        dlg.Destroy()
[b35d3d1]288       
289        state = self.get_state()
[23cdeab]290       
291        # MAC always needs the extension for saving
292        extens = ".prv"
293        # Make sure the ext included in the file name
294        fName = os.path.splitext(path)[0] + extens
295        self._manager.save_data(filepath=fName, prstate=state)
[b35d3d1]296       
297        return state
298   
[6d3d5ff]299    def get_data(self):
300        """
301        """
302        return self._manager.get_data()
303   
[b35d3d1]304    def get_state(self):
305        """
306        Get the current state
307       
308        : return: state object
309        """
[5d98370]310        # Construct the state object   
311        state = InversionState()
312       
313        # Read the panel's parameters
314        flag, alpha, dmax, nfunc, qmin, \
315        qmax, height, width = self._read_pars()
316       
317        state.nfunc = nfunc
318        state.d_max = dmax
319        state.alpha = alpha
320        state.qmin  = qmin
321        state.qmax  = qmax
322        state.width = width
323        state.height = height
324       
325        # Data file
[0d88a09]326        state.file = self.plot_data.GetValue()
[5d98370]327       
328        # Background evaluation checkbox
329        state.estimate_bck = self.bck_chk.IsChecked()
330       
331        # Estimates
332        state.nterms_estimate = self.nterms_estimate
333        state.alpha_estimate = self.alpha_estimate
334       
335        # Read the output values
336        state.chi2    = self.chi2
337        state.elapsed = self.elapsed
338        state.osc     = self.oscillation
339        state.pos     = self.pos
340        state.pos_err = self.pos_err
341        state.rg      = self.rg
342        state.iq0     = self.iq0
343        state.bck     = self.bck
[fde249c]344       
[5d98370]345        return state
346   
347    def set_state(self, state):
348        """
[7116b6e0]349        Set the state of the panel and inversion problem to
350        the state passed as a parameter.
351        Execute the inversion immediately after filling the
352        controls.
353       
354        :param state: InversionState object
[5d98370]355        """
[fde249c]356        if state.nfunc is not None:
357            self.nfunc = state.nfunc
358        if state.d_max is not None:
359            self.d_max = state.d_max
360        if state.alpha is not None:
361            self.alpha = state.alpha
362        if state.qmin is not None:
363            self.q_min  = state.qmin
364        if state.qmax is not None:
365            self.q_max  = state.qmax
366        if state.width is not None:
367            self.slit_width = state.width
368        if state.height is not None:
369            self.slit_height = state.height
[5d98370]370       
371        # Data file
[0d88a09]372        self.plot_data.SetValue(str(state.file))
[5d98370]373   
374        # Background evaluation checkbox
375        self.bck_chk.SetValue(state.estimate_bck)
376       
377        # Estimates
[fde249c]378        if state.nterms_estimate is not None:
379            self.nterms_estimate = state.nterms_estimate
380        if state.alpha_estimate is not None: 
381            self.alpha_estimate = state.alpha_estimate
[5d98370]382   
383       
384        # Read the output values
[fde249c]385        if state.chi2 is not None:
386            self.chi2    = state.chi2
387        if state.elapsed is not None:
388            self.elapsed = state.elapsed
389        if state.osc is not None:
390            self.oscillation = state.osc
391        if state.pos is not None:
392            self.positive = state.pos
393        if state.pos_err is not None:
394            self.pos_err = state.pos_err
395        if state.rg is not None:
396            self.rg      = state.rg
397        if state.iq0 is not None:
398            self.iq0     = state.iq0
399        if state.bck is not None:
400            self.bck     = state.bck
[5d98370]401
[0d88a09]402        # Perform inversion
[dd03efb]403        self._on_invert(None)   
[5d98370]404       
[f3d51f6]405    def set_manager(self, manager):
[6d3d5ff]406        self._manager = manager
[f3d51f6]407       
408    def _do_layout(self):
[4318af7f]409        vbox = wx.GridBagSizer(0,0)
410        iy_vb = 0
[f3d51f6]411
412        # ----- I(q) data -----
[aa4b8379]413        databox = wx.StaticBox(self, -1, "I(q) data source")
[f3d51f6]414       
415        boxsizer1 = wx.StaticBoxSizer(databox, wx.VERTICAL)
[3e41f43]416        boxsizer1.SetMinSize((self._default_width, 50))
417        pars_sizer = wx.GridBagSizer(5, 5)
[0d21ac1]418
[f3d51f6]419        iy = 0
[57b551e]420        self.file_radio = wx.StaticText(self, -1, "Name:")
[3e41f43]421        pars_sizer.Add(self.file_radio, (iy, 0), (1, 1),
422                       wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
[f3d51f6]423       
[9ff861b]424        self.plot_data = DataFileTextCtrl(self, -1, size=(260,20))
425       
[3e41f43]426        pars_sizer.Add(self.plot_data, (iy, 1), (1, 1),
427                       wx.EXPAND|wx.LEFT|wx.RIGHT|wx.ADJUST_MINSIZE, 15)
[f3d51f6]428       
[a4bd2ac]429        self.bck_chk = wx.CheckBox(self, -1, "Estimate background level")
[3e41f43]430        hint_msg = "Check box to let the fit estimate "
431        hint_msg += "the constant background level."
432        self.bck_chk.SetToolTipString(hint_msg)
[a4bd2ac]433        self.bck_chk.Bind(wx.EVT_CHECKBOX, self._on_pars_changed)
434        iy += 1
[3e41f43]435        pars_sizer.Add(self.bck_chk, (iy, 0), (1, 2),
436                       wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
[a4bd2ac]437        boxsizer1.Add(pars_sizer, 0, wx.EXPAND) 
[3e41f43]438        vbox.Add(boxsizer1, (iy_vb, 0), (1, 1),
439                 wx.LEFT|wx.RIGHT|wx.EXPAND|wx.ADJUST_MINSIZE|wx.TOP, 5)
[a4bd2ac]440       
441        # ----- Add slit parameters -----
[2a92852]442        if True:
[a4bd2ac]443            sbox = wx.StaticBox(self, -1, "Slit parameters")
444            sboxsizer = wx.StaticBoxSizer(sbox, wx.VERTICAL)
[3e41f43]445            sboxsizer.SetMinSize((self._default_width, 20))
[a4bd2ac]446           
[3e41f43]447            sizer_slit = wx.GridBagSizer(5, 5)
[a4bd2ac]448   
[3e41f43]449            label_sheight = wx.StaticText(self, -1, "Height", size=(40, 20))
450            label_swidth = wx.StaticText(self, -1, "Width", size=(40, 20))
[a4bd2ac]451            #label_sunits1 = wx.StaticText(self, -1, "[A^(-1)]")
[4318af7f]452            label_sunits2 = wx.StaticText(self, -1, "[A^(-1)]", size=(55,20))
[3e41f43]453            self.sheight_ctl = PrTextCtrl(self, -1, style=wx.TE_PROCESS_ENTER,
454                                          size=(60,20))
455            self.swidth_ctl = PrTextCtrl(self, -1, style=wx.TE_PROCESS_ENTER,
456                                         size=(60,20))
457            hint_msg = "Enter slit height in units of Q or leave blank."
458            self.sheight_ctl.SetToolTipString(hint_msg)
459            hint_msg = "Enter slit width in units of Q or leave blank."
460            self.swidth_ctl.SetToolTipString(hint_msg)
[2a92852]461            #self.sheight_ctl.Bind(wx.EVT_TEXT, self._on_pars_changed)
462            #self.swidth_ctl.Bind(wx.EVT_TEXT,  self._on_pars_changed)
[a4bd2ac]463           
464            iy = 0
[3e41f43]465            sizer_slit.Add(label_sheight,    (iy, 0), (1, 1),
466                           wx.LEFT|wx.EXPAND, 5)
467            sizer_slit.Add(self.sheight_ctl, (iy, 1), (1, 1),
468                           wx.LEFT|wx.EXPAND, 5)
469   
470            sizer_slit.Add(label_swidth,     (iy, 2), (1, 1),
471                           wx.LEFT|wx.EXPAND, 5)
472            sizer_slit.Add(self.swidth_ctl,  (iy, 3), (1, 1),
473                           wx.LEFT|wx.EXPAND, 5)
474            sizer_slit.Add(label_sunits2,    (iy, 4), (1, 1),
475                           wx.LEFT|wx.EXPAND, 5)
[a4bd2ac]476           
477            sboxsizer.Add(sizer_slit, wx.TOP, 15)
[4318af7f]478            iy_vb += 1
[3e41f43]479            vbox.Add(sboxsizer, (iy_vb, 0), (1, 1),
480                     wx.LEFT|wx.RIGHT|wx.EXPAND|wx.ADJUST_MINSIZE, 5)
[a4bd2ac]481       
[357b79b]482       
483        # ----- Q range -----
484        qbox = wx.StaticBox(self, -1, "Q range")
485        qboxsizer = wx.StaticBoxSizer(qbox, wx.VERTICAL)
[3e41f43]486        qboxsizer.SetMinSize((self._default_width, 20))
[357b79b]487       
[3e41f43]488        sizer_q = wx.GridBagSizer(5, 5)
[357b79b]489
[3e41f43]490        label_qmin = wx.StaticText(self, -1, "Q min", size=(40, 20))
491        label_qmax = wx.StaticText(self, -1, "Q max", size=(40, 20))
[357b79b]492        #label_qunits1 = wx.StaticText(self, -1, "[A^(-1)]")
[3e41f43]493        label_qunits2 = wx.StaticText(self, -1, "[A^(-1)]", size=(55, 20))
494        self.qmin_ctl = PrTextCtrl(self, -1, style=wx.TE_PROCESS_ENTER,
495                                   size=(60,20))
496        self.qmax_ctl = PrTextCtrl(self, -1, style=wx.TE_PROCESS_ENTER,
497                                   size=(60,20))
498        hint_msg = "Select a lower bound for Q or leave blank."
499        self.qmin_ctl.SetToolTipString(hint_msg)
500        hint_msg = "Select an upper bound for Q or leave blank."
501        self.qmax_ctl.SetToolTipString(hint_msg)
[357b79b]502        self.qmin_ctl.Bind(wx.EVT_TEXT, self._on_pars_changed)
503        self.qmax_ctl.Bind(wx.EVT_TEXT, self._on_pars_changed)
504       
505        iy = 0
[3e41f43]506        sizer_q.Add(label_qmin,    (iy, 0), (1, 1), wx.LEFT|wx.EXPAND, 5)
507        sizer_q.Add(self.qmin_ctl, (iy, 1), (1, 1), wx.LEFT|wx.EXPAND, 5)
[357b79b]508        #sizer_q.Add(label_qunits1, (iy,2), (1,1), wx.LEFT|wx.EXPAND, 15)
[3e41f43]509        sizer_q.Add(label_qmax,    (iy, 2), (1, 1), wx.LEFT|wx.EXPAND, 5)
510        sizer_q.Add(self.qmax_ctl, (iy, 3), (1, 1), wx.LEFT|wx.EXPAND, 5)
511        sizer_q.Add(label_qunits2, (iy, 4), (1, 1), wx.LEFT|wx.EXPAND, 5)
[357b79b]512        qboxsizer.Add(sizer_q, wx.TOP, 15)
[4318af7f]513
514        iy_vb += 1
[3e41f43]515        vbox.Add(qboxsizer, (iy_vb,0), (1,1),
516                 wx.LEFT|wx.RIGHT|wx.EXPAND|wx.ADJUST_MINSIZE, 5)
517   
[f3d51f6]518        # ----- Parameters -----
519        parsbox = wx.StaticBox(self, -1, "Parameters")
520        boxsizer2 = wx.StaticBoxSizer(parsbox, wx.VERTICAL)
[0ccd214]521        boxsizer2.SetMinSize((self._default_width,50))
[f3d51f6]522       
[3e41f43]523        explanation  = "P(r) is found by fitting a set of base functions"
524        explanation += " to I(Q). The minimization involves"
525        explanation += " a regularization term to ensure a smooth P(r)."
526        explanation += " The regularization constant gives the size of that " 
527        explanation += "term. The suggested value is the value above which the"
528        explanation += " output P(r) will have only one peak."
[f199764]529        label_explain = wx.StaticText(self, -1, explanation, size=(280,90))
[32dffae4]530        boxsizer2.Add(label_explain,  wx.LEFT|wx.BOTTOM, 5)
531       
532       
533       
[f3d51f6]534        label_nfunc = wx.StaticText(self, -1, "Number of terms")
[3e41f43]535        label_nfunc.SetMinSize((120, 20))
[f3d51f6]536        label_alpha = wx.StaticText(self, -1, "Regularization constant")
537        label_dmax  = wx.StaticText(self, -1, "Max distance [A]")
[634f1cf]538        self.label_sugg  = wx.StaticText(self, -1, "Suggested value")
539        #self.label_sugg.Hide()
[f3d51f6]540       
[3e41f43]541        self.nfunc_ctl = PrTextCtrl(self, -1, style=wx.TE_PROCESS_ENTER,
542                                    size=(60,20))
[32dffae4]543        self.nfunc_ctl.SetToolTipString("Number of terms in the expansion.")
[3e41f43]544        self.alpha_ctl = PrTextCtrl(self, -1, style=wx.TE_PROCESS_ENTER,
545                                    size=(60,20))
546        hint_msg = "Control parameter for the size of the regularization term."
547        self.alpha_ctl.SetToolTipString(hint_msg)
548        self.dmax_ctl  = PrTextCtrl(self, -1, style=wx.TE_PROCESS_ENTER,
549                                    size=(60,20))
550        hint_msg = "Maximum distance between any two points in the system."
551        self.dmax_ctl.SetToolTipString(hint_msg)
[634f1cf]552        id = wx.NewId()
553        self.alpha_estimate_ctl  = wx.Button(self, id, "")
554        #self.alpha_estimate_ctl.Hide()
555        self.Bind(wx.EVT_BUTTON, self._on_accept_alpha, id = id)   
[f3d51f6]556        self.alpha_estimate_ctl.Enable(False)
[634f1cf]557        #self.alpha_estimate_ctl.SetBackgroundColour('#ffdf85')
558        #self.alpha_estimate_ctl.SetBackgroundColour(self.GetBackgroundColour())
559        self.alpha_estimate_ctl.SetToolTipString("Waiting for estimate...")
[f3d51f6]560       
[35adaf6]561        id = wx.NewId()
562        self.nterms_estimate_ctl  = wx.Button(self, id, "")
563        #self.nterms_estimate_ctl.Hide()
564        self.Bind(wx.EVT_BUTTON, self._on_accept_nterms, id = id)   
565        self.nterms_estimate_ctl.Enable(False)
[3e41f43]566     
[35adaf6]567        self.nterms_estimate_ctl.SetToolTipString("Waiting for estimate...")
568       
[d6113849]569        self.nfunc_ctl.Bind(wx.EVT_TEXT, self._read_pars)
[a4bd2ac]570        self.alpha_ctl.Bind(wx.EVT_TEXT, self._read_pars)
571        self.dmax_ctl.Bind(wx.EVT_TEXT, self._on_pars_changed)
572       
[a00ee4c]573        # Distance explorator
574        id = wx.NewId()
575        self.distance_explorator_ctl = wx.Button(self, id, "Explore")
576        self.Bind(wx.EVT_BUTTON, self._on_explore, id = id)           
[a4bd2ac]577       
578       
[f3d51f6]579        sizer_params = wx.GridBagSizer(5,5)
580
581        iy = 0
[3e41f43]582        sizer_params.Add(self.label_sugg, (iy, 2), (1, 1), wx.LEFT, 15)
[f3d51f6]583        iy += 1
[3e41f43]584        sizer_params.Add(label_nfunc,      (iy, 0), (1, 1), wx.LEFT, 15)
585        sizer_params.Add(self.nfunc_ctl,   (iy, 1), (1, 1), wx.RIGHT, 0)
586        sizer_params.Add(self.nterms_estimate_ctl, (iy, 2), (1, 1), wx.LEFT, 15)
[f3d51f6]587        iy += 1
[3e41f43]588        sizer_params.Add(label_alpha,      (iy, 0), (1, 1), wx.LEFT, 15)
589        sizer_params.Add(self.alpha_ctl,   (iy, 1), (1, 1), wx.RIGHT, 0)
590        sizer_params.Add(self.alpha_estimate_ctl, (iy, 2), (1, 1), wx.LEFT, 15)
[f3d51f6]591        iy += 1
[3e41f43]592        sizer_params.Add(label_dmax, (iy, 0), (1, 1), wx.LEFT, 15)
593        sizer_params.Add(self.dmax_ctl,   (iy, 1), (1, 1), wx.RIGHT, 0)
594        sizer_params.Add(self.distance_explorator_ctl, (iy, 2),
595                         (1, 1), wx.LEFT, 15)
[f3d51f6]596
597        boxsizer2.Add(sizer_params, 0)
[634f1cf]598       
[4318af7f]599        iy_vb += 1
[3e41f43]600        vbox.Add(boxsizer2, (iy_vb, 0), (1, 1),
601                 wx.LEFT|wx.RIGHT|wx.EXPAND|wx.ADJUST_MINSIZE, 5)
[f3d51f6]602
[634f1cf]603
[f3d51f6]604        # ----- Results -----
605        resbox = wx.StaticBox(self, -1, "Outputs")
606        ressizer = wx.StaticBoxSizer(resbox, wx.VERTICAL)
[3e41f43]607        ressizer.SetMinSize((self._default_width, 50))
[f3d51f6]608       
[a4bd2ac]609        label_rg       = wx.StaticText(self, -1, "Rg")
610        label_rg_unit  = wx.StaticText(self, -1, "[A]")
611        label_iq0      = wx.StaticText(self, -1, "I(Q=0)")
612        label_iq0_unit = wx.StaticText(self, -1, "[A^(-1)]")
613        label_bck      = wx.StaticText(self, -1, "Background")
614        label_bck_unit = wx.StaticText(self, -1, "[A^(-1)]")
[9ff861b]615        self.rg_ctl    = OutputTextCtrl(self, -1, size=(60,20))
[3e41f43]616        hint_msg = "Radius of gyration for the computed P(r)."
617        self.rg_ctl.SetToolTipString(hint_msg)
[75df58b]618        self.iq0_ctl   = OutputTextCtrl(self, -1, size=(60, 20))
[3e41f43]619        hint_msg = "Scattering intensity at Q=0 for the computed P(r)."
620        self.iq0_ctl.SetToolTipString(hint_msg)
[75df58b]621        self.bck_ctl   = OutputTextCtrl(self, -1, size=(60, 20))
[a4bd2ac]622        self.bck_ctl.SetToolTipString("Value of estimated constant background.")
623       
[f3d51f6]624        label_time = wx.StaticText(self, -1, "Computation time")
625        label_time_unit = wx.StaticText(self, -1, "secs")
626        label_time.SetMinSize((120,20))
627        label_chi2 = wx.StaticText(self, -1, "Chi2/dof")
628        label_osc = wx.StaticText(self, -1, "Oscillations")
[dfb58f8]629        label_pos = wx.StaticText(self, -1, "Positive fraction")
630        label_pos_err = wx.StaticText(self, -1, "1-sigma positive fraction")
[f3d51f6]631       
[75df58b]632        self.time_ctl = OutputTextCtrl(self, -1, size=(60, 20))
[3e41f43]633        hint_msg = "Computation time for the last inversion, in seconds."
634        self.time_ctl.SetToolTipString(hint_msg)
[32dffae4]635       
[75df58b]636        self.chi2_ctl = OutputTextCtrl(self, -1, size=(60, 20))
[32dffae4]637        self.chi2_ctl.SetToolTipString("Chi^2 over degrees of freedom.")
638       
[dfb58f8]639        # Oscillation parameter
[75df58b]640        self.osc_ctl = OutputTextCtrl(self, -1, size=(60, 20))
[3e41f43]641        hint_msg = "Oscillation parameter. P(r) for a sphere has an "
642        hint_msg += " oscillation parameter of 1.1."
643        self.osc_ctl.SetToolTipString(hint_msg)
[f3d51f6]644       
[dfb58f8]645        # Positive fraction figure of merit
[75df58b]646        self.pos_ctl = OutputTextCtrl(self, -1, size=(60, 20))
[3e41f43]647        hint_msg = "Fraction of P(r) that is positive. "
648        hint_msg += "Theoretically, P(r) is defined positive."
649        self.pos_ctl.SetToolTipString(hint_msg)
[dfb58f8]650       
651        # 1-simga positive fraction figure of merit
[75df58b]652        self.pos_err_ctl = OutputTextCtrl(self, -1, size=(60, 20))
[3e41f43]653        message  = "Fraction of P(r) that is at least 1 standard deviation"
654        message += " greater than zero.\n"
655        message += "This figure of merit tells you about the size of the "
656        message += "P(r) errors.\n"
657        message += "If it is close to 1 and the other figures of merit are bad,"
658        message += " consider changing the maximum distance."
[dfb58f8]659        self.pos_err_ctl.SetToolTipString(message)
660       
[3e41f43]661        sizer_res = wx.GridBagSizer(5, 5)
[f3d51f6]662
663        iy = 0
[3e41f43]664        sizer_res.Add(label_rg, (iy, 0), (1, 1), wx.LEFT|wx.EXPAND, 15)
665        sizer_res.Add(self.rg_ctl,   (iy, 1), (1, 1), wx.RIGHT|wx.EXPAND, 15)
666        sizer_res.Add(label_rg_unit,   (iy, 2), (1, 1), wx.RIGHT|wx.EXPAND, 15)
[a4bd2ac]667        iy += 1
[3e41f43]668        sizer_res.Add(label_iq0, (iy, 0), (1, 1), wx.LEFT|wx.EXPAND, 15)
669        sizer_res.Add(self.iq0_ctl,   (iy, 1), (1, 1), wx.RIGHT|wx.EXPAND, 15)
670        sizer_res.Add(label_iq0_unit, (iy, 2), (1, 1), wx.RIGHT|wx.EXPAND, 15)
[a4bd2ac]671        iy += 1
[3e41f43]672        sizer_res.Add(label_bck, (iy, 0), (1, 1), wx.LEFT|wx.EXPAND, 15)
673        sizer_res.Add(self.bck_ctl, (iy, 1), (1, 1), wx.RIGHT|wx.EXPAND, 15)
674        sizer_res.Add(label_bck_unit, (iy, 2), (1, 1), wx.RIGHT|wx.EXPAND, 15)
[a4bd2ac]675        iy += 1
[3e41f43]676        sizer_res.Add(label_time, (iy, 0), (1, 1), wx.LEFT|wx.EXPAND, 15)
677        sizer_res.Add(self.time_ctl,   (iy, 1), (1, 1), wx.RIGHT|wx.EXPAND, 15)
678        sizer_res.Add(label_time_unit, (iy, 2), (1, 1), wx.RIGHT|wx.EXPAND, 15)
[f3d51f6]679        iy += 1
[3e41f43]680        sizer_res.Add(label_chi2, (iy, 0), (1, 1), wx.LEFT|wx.EXPAND, 15)
681        sizer_res.Add(self.chi2_ctl,   (iy, 1), (1, 1), wx.RIGHT|wx.EXPAND, 15)
[f3d51f6]682        iy += 1
[3e41f43]683        sizer_res.Add(label_osc, (iy, 0), (1, 1), wx.LEFT|wx.EXPAND, 15)
684        sizer_res.Add(self.osc_ctl,   (iy, 1), (1, 1), wx.RIGHT|wx.EXPAND, 15)
[f3d51f6]685
[dfb58f8]686        iy += 1
[3e41f43]687        sizer_res.Add(label_pos, (iy, 0), (1, 1), wx.LEFT|wx.EXPAND, 15)
688        sizer_res.Add(self.pos_ctl, (iy, 1), (1, 1), wx.RIGHT|wx.EXPAND, 15)
[dfb58f8]689
690        iy += 1
[3e41f43]691        sizer_res.Add(label_pos_err, (iy, 0), (1, 1), wx.LEFT|wx.EXPAND, 15)
692        sizer_res.Add(self.pos_err_ctl,  (iy,1), (1, 1), wx.RIGHT|wx.EXPAND, 15)
[dfb58f8]693
[f3d51f6]694        ressizer.Add(sizer_res, 0)
[4318af7f]695        iy_vb += 1
[3e41f43]696        vbox.Add(ressizer, (iy_vb, 0), (1, 1),
697                 wx.LEFT|wx.RIGHT|wx.EXPAND|wx.ADJUST_MINSIZE, 5)
[f3d51f6]698
699        # ----- Buttons -----
700        id = wx.NewId()
701        button_OK = wx.Button(self, id, "Compute")
[32dffae4]702        button_OK.SetToolTipString("Perform P(r) inversion.")
[f3d51f6]703        self.Bind(wx.EVT_BUTTON, self._on_invert, id = id)   
[b659551]704       
[5771ea3]705        self._set_reset_flag(True)
[3f0351c6]706        self._set_save_flag(True)
[f3d51f6]707        sizer_button = wx.BoxSizer(wx.HORIZONTAL)
708        sizer_button.Add((20, 20), 1, wx.EXPAND|wx.ADJUST_MINSIZE, 0)
709        sizer_button.Add(button_OK, 0, wx.LEFT|wx.ADJUST_MINSIZE, 10)
[3e41f43]710       
[4318af7f]711        iy_vb += 1
[3e41f43]712        vbox.Add(sizer_button, (iy_vb, 0), (1, 1),
713                 wx.EXPAND|wx.BOTTOM|wx.TOP|wx.RIGHT, 10)
[f3d51f6]714
[a00ee4c]715        self.Bind(wx.EVT_TEXT_ENTER, self._on_invert)
[f3d51f6]716
717        self.SetSizer(vbox)
718       
[634f1cf]719    def _on_accept_alpha(self, evt):
720        """
[7116b6e0]721        User has accepted the estimated alpha,
722        set it as part of the input parameters
[634f1cf]723        """
724        try:
725            alpha = self.alpha_estimate_ctl.GetLabel()
726            tmp = float(alpha)
727            self.alpha_ctl.SetValue(alpha)
728        except:
729            # No estimate or bad estimate, either do nothing
[3e41f43]730            #import sys
[634f1cf]731            print "InversionControl._on_accept_alpha: %s" % sys.exc_value
732            pass
[35adaf6]733   
734    def _on_accept_nterms(self, evt):
735        """
[7116b6e0]736        User has accepted the estimated number of terms,
737        set it as part of the input parameters
[35adaf6]738        """
739        try:
740            nterms = self.nterms_estimate_ctl.GetLabel()
741            tmp = float(nterms)
742            self.nfunc_ctl.SetValue(nterms)
743        except:
744            # No estimate or bad estimate, either do nothing
745            import sys
746            print "InversionControl._on_accept_nterms: %s" % sys.exc_value
747            pass
[634f1cf]748       
[91d910d]749    def clear_panel(self):
750        """
751        """
752        self.plot_data.SetValue("")
753        self.on_reset(event=None)
754       
755    def on_reset(self, event=None):
[b659551]756        """
[7116b6e0]757        Resets inversion parameters
[b659551]758        """
[6d3d5ff]759        self.nfunc = self._manager.DEFAULT_NFUNC
760        self.d_max = self._manager.DEFAULT_DMAX
761        self.alpha = self._manager.DEFAULT_ALPHA
[b659551]762        self.qmin_ctl.SetValue("")
763        self.qmax_ctl.SetValue("")
764        self.time_ctl.SetValue("")
[a4bd2ac]765        self.rg_ctl.SetValue("")
766        self.iq0_ctl.SetValue("")
767        self.bck_ctl.SetValue("")
[b659551]768        self.chi2_ctl.SetValue("")
769        self.osc_ctl.SetValue("")
770        self.pos_ctl.SetValue("")
771        self.pos_err_ctl.SetValue("")
772        self.alpha_estimate_ctl.Enable(False)
773        self.alpha_estimate_ctl.SetLabel("")
[35adaf6]774        self.nterms_estimate_ctl.Enable(False)
775        self.nterms_estimate_ctl.SetLabel("")
[b659551]776        self._on_pars_changed()
[634f1cf]777       
[b659551]778    def _on_pars_changed(self, evt=None):
[f3d51f6]779        """
[7116b6e0]780        Called when an input parameter has changed
781        We will estimate the alpha parameter behind the
782        scenes.
[f3d51f6]783        """
[2a92852]784        flag, alpha, dmax, nfunc, qmin, qmax, height, width = self._read_pars()
[a4bd2ac]785        has_bck = self.bck_chk.IsChecked()
[f3d51f6]786       
787        # If the pars are valid, estimate alpha
788        if flag:
[2a92852]789            self.nterms_estimate_ctl.Enable(False)
790            self.alpha_estimate_ctl.Enable(False)
791           
[0d88a09]792            dataset = self.plot_data.GetValue()
[6ce7201]793            if dataset is not None and dataset.strip() != "":
[91d910d]794                self._manager.estimate_plot_inversion(alpha=alpha, nfunc=nfunc, 
[0d88a09]795                                                 d_max=dmax,
796                                                 q_min=qmin, q_max=qmax,
797                                                 bck=has_bck, 
798                                                 height=height,
799                                                 width=width)
[f3d51f6]800       
[7116b6e0]801    def _read_pars(self, evt=None):
802        """
803        """   
[f3d51f6]804        alpha = 0
805        nfunc = 5
806        dmax  = 120
[3fd1ebc]807        qmin  = 0
808        qmax  = 0
[2a92852]809        height = 0
810        width  = 0
[f3d51f6]811        flag = True
[2a92852]812        # Read slit height
813        try:
814            height_str = self.sheight_ctl.GetValue()
[3e41f43]815            if len(height_str.lstrip().rstrip()) == 0:
[2a92852]816                height = 0
817            else:
818                height = float(height_str)
819                self.sheight_ctl.SetBackgroundColour(wx.WHITE)
820                self.sheight_ctl.Refresh()
821        except:
822            flag = False
823            self.sheight_ctl.SetBackgroundColour("pink")
824            self.sheight_ctl.Refresh()
825           
826        # Read slit width
827        try:
828            width_str = self.swidth_ctl.GetValue()
829            if len(width_str.lstrip().rstrip())==0:
830                width = 0
831            else:
832                width = float(width_str)
833                self.swidth_ctl.SetBackgroundColour(wx.WHITE)
834                self.swidth_ctl.Refresh()
835        except:
836            flag = False
837            self.swidth_ctl.SetBackgroundColour("pink")
838            self.swidth_ctl.Refresh()
839       
[f3d51f6]840        # Read alpha
841        try:
842            alpha = float(self.alpha_ctl.GetValue())
843            self.alpha_ctl.SetBackgroundColour(wx.WHITE)
844            self.alpha_ctl.Refresh()
845        except:
846            flag = False
847            self.alpha_ctl.SetBackgroundColour("pink")
848            self.alpha_ctl.Refresh()
849       
850        # Read d_max   
851        try:
852            dmax = float(self.dmax_ctl.GetValue())
853            self.dmax_ctl.SetBackgroundColour(wx.WHITE)
854            self.dmax_ctl.Refresh()
855        except:
856            flag = False
857            self.dmax_ctl.SetBackgroundColour("pink")
858            self.dmax_ctl.Refresh()
859           
860        # Read nfunc
861        try:
862            nfunc = int(self.nfunc_ctl.GetValue())
[6d3d5ff]863            npts = self._manager.get_npts()
[3e41f43]864            if npts > 0 and nfunc > npts:
865                message = "Number of function terms should be smaller "
866                message += "than the number of points"
[6d3d5ff]867                wx.PostEvent(self._manager.parent, StatusEvent(status=message))
[b659551]868                raise ValueError, message
[f3d51f6]869            self.nfunc_ctl.SetBackgroundColour(wx.WHITE)
870            self.nfunc_ctl.Refresh()
871        except:
872            flag = False
873            self.nfunc_ctl.SetBackgroundColour("pink")
874            self.nfunc_ctl.Refresh()
875       
[634f1cf]876        # Read qmin
877        try:
878            qmin_str = self.qmin_ctl.GetValue()
[3e41f43]879            if len(qmin_str.lstrip().rstrip()) == 0:
[634f1cf]880                qmin = None
881            else:
882                qmin = float(qmin_str)
883                self.qmin_ctl.SetBackgroundColour(wx.WHITE)
884                self.qmin_ctl.Refresh()
885        except:
886            flag = False
887            self.qmin_ctl.SetBackgroundColour("pink")
888            self.qmin_ctl.Refresh()
889       
890        # Read qmax
891        try:
892            qmax_str = self.qmax_ctl.GetValue()
[3e41f43]893            if len(qmax_str.lstrip().rstrip()) == 0:
[634f1cf]894                qmax = None
895            else:
896                qmax = float(qmax_str)
897                self.qmax_ctl.SetBackgroundColour(wx.WHITE)
898                self.qmax_ctl.Refresh()
899        except:
900            flag = False
901            self.qmax_ctl.SetBackgroundColour("pink")
902            self.qmax_ctl.Refresh()
903       
[2a92852]904        return flag, alpha, dmax, nfunc, qmin, qmax, height, width
[f3d51f6]905   
[a00ee4c]906    def _on_explore(self, evt):
907        """
[7116b6e0]908        Invoke the d_max exploration dialog
[a00ee4c]909        """
910        from explore_dialog import ExploreDialog
[6d3d5ff]911        if self._manager._last_pr is not None:
912            pr = self._manager._create_plot_pr()
[a00ee4c]913            dialog = ExploreDialog(pr, 10, None, -1, "")
914            dialog.ShowModal()
915        else:
916            message = "No data to analyze. Please load a data set to proceed."
[6d3d5ff]917            wx.PostEvent(self._manager.parent, StatusEvent(status=message))
[a00ee4c]918           
[f3d51f6]919    def _on_invert(self, evt):
920        """
[7116b6e0]921        Perform inversion
922       
923        :param silent: when True, there will be no output for the user
924       
[f3d51f6]925        """
926        # Get the data from the form
927        # Push it to the manager
928       
[2a92852]929        flag, alpha, dmax, nfunc, qmin, qmax, height, width = self._read_pars()
[a4bd2ac]930        has_bck = self.bck_chk.IsChecked()
[f3d51f6]931       
932        if flag:
[0d88a09]933            dataset = self.plot_data.GetValue()
[9bc4ed23]934            if dataset==None or len(dataset.strip())==0:
[3e41f43]935                message = "No data to invert. Select a data set before"
936                message += " proceeding with P(r) inversion."
[6d3d5ff]937                wx.PostEvent(self._manager.parent, StatusEvent(status=message))
[f3d51f6]938            else:
[f199764]939                self._manager.setup_plot_inversion(alpha=alpha, nfunc=nfunc, 
940                                                  d_max=dmax,
941                                                  q_min=qmin, q_max=qmax,
942                                                  bck=has_bck,
943                                                  height=height,
944                                                  width=width)
[f3d51f6]945        else:
[3e41f43]946            message = "The P(r) form contains invalid values: "
947            message += "please submit it again."
[f3d51f6]948            wx.PostEvent(self.parent, StatusEvent(status=message))
949       
[75df58b]950    def _change_file(self, evt=None, filepath=None, data=None):
[f3d51f6]951        """
[7116b6e0]952        Choose a new input file for I(q)
[f3d51f6]953        """
[6d3d5ff]954        if not self._manager is None:
[75df58b]955            self.plot_data.SetValue(str(data.name))
956            try:
[6d3d5ff]957                self._manager.show_data(data=data, reset=True)
[75df58b]958                self._on_pars_changed(None)
959                self._on_invert(None)
960            except:
961                msg = "InversionControl._change_file: %s" % sys.exc_value
962                logging.error(msg)                   
[119a11d]963
964class HelpDialog(wx.Dialog):
[7116b6e0]965    """
966    """
[119a11d]967    def __init__(self, parent, id):
[7116b6e0]968        """
969        """
[79492222]970        from sas.pr.invertor import help
[657e52c]971        wx.Dialog.__init__(self, parent, id, size=(400, 450))
[119a11d]972        self.SetTitle("P(r) help") 
[657e52c]973        self.SetWindowVariant(variant=FONT_VARIANT)
[119a11d]974
975        vbox = wx.BoxSizer(wx.VERTICAL)
976
977        explanation = help()
978           
[657e52c]979        label_explain = wx.StaticText(self, -1, explanation, size=(360, 350))
[119a11d]980           
981        vbox.Add(label_explain, 0, wx.ALL|wx.EXPAND, 15)
982
983
984        static_line = wx.StaticLine(self, -1)
985        vbox.Add(static_line, 0, wx.EXPAND, 0)
986       
987        button_OK = wx.Button(self, wx.ID_OK, "OK")
988        #button_Cancel = wx.Button(self, wx.ID_CANCEL, "Cancel")
989       
990        sizer_button = wx.BoxSizer(wx.HORIZONTAL)
991        sizer_button.Add((20, 20), 1, wx.EXPAND|wx.ADJUST_MINSIZE, 0)
992        sizer_button.Add(button_OK, 0, wx.LEFT|wx.RIGHT|wx.ADJUST_MINSIZE, 10)
[3e41f43]993       
[119a11d]994        vbox.Add(sizer_button, 0, wx.EXPAND|wx.BOTTOM|wx.TOP, 10)
995
996        self.SetSizer(vbox)
997        self.SetAutoLayout(True)
998       
999        self.Layout()
1000        self.Centre()
1001
[b659551]1002class PrDistDialog(wx.Dialog):
1003    """
[7116b6e0]1004    Property dialog to let the user change the number
1005    of points on the P(r) plot.
[b659551]1006    """
1007    def __init__(self, parent, id):
[79492222]1008        from sas.pr.invertor import help
[b659551]1009        wx.Dialog.__init__(self, parent, id, size=(250, 120))
1010        self.SetTitle("P(r) distribution") 
1011       
1012
1013        vbox = wx.BoxSizer(wx.VERTICAL)
1014       
1015        label_npts = wx.StaticText(self, -1, "Number of points")
[75df58b]1016        self.npts_ctl = PrTextCtrl(self, -1, size=(100, 20))
[b659551]1017                 
[75df58b]1018        pars_sizer = wx.GridBagSizer(5, 5)
[b659551]1019        iy = 0
[75df58b]1020        pars_sizer.Add(label_npts, (iy, 0), (1, 1), wx.LEFT, 15)
1021        pars_sizer.Add(self.npts_ctl, (iy, 1), (1, 1), wx.RIGHT, 0)
[b659551]1022       
1023        vbox.Add(pars_sizer, 0, wx.ALL|wx.EXPAND, 15)
1024
1025        static_line = wx.StaticLine(self, -1)
1026        vbox.Add(static_line, 0, wx.EXPAND, 0)
1027       
1028        button_OK = wx.Button(self, wx.ID_OK, "OK")
1029        self.Bind(wx.EVT_BUTTON, self._checkValues, button_OK)
1030        button_Cancel = wx.Button(self, wx.ID_CANCEL, "Cancel")
1031       
1032        sizer_button = wx.BoxSizer(wx.HORIZONTAL)
1033        sizer_button.Add((20, 20), 1, wx.EXPAND|wx.ADJUST_MINSIZE, 0)
1034        sizer_button.Add(button_OK, 0, wx.LEFT|wx.RIGHT|wx.ADJUST_MINSIZE, 10)
[3e41f43]1035        sizer_button.Add(button_Cancel, 0,
1036                         wx.LEFT|wx.RIGHT|wx.ADJUST_MINSIZE, 10)       
[b659551]1037        vbox.Add(sizer_button, 0, wx.EXPAND|wx.BOTTOM|wx.TOP, 10)
1038
1039        self.SetSizer(vbox)
1040        self.SetAutoLayout(True)
1041       
1042        self.Layout()
1043        self.Centre()
1044
1045    def _checkValues(self, event):
1046        """
[7116b6e0]1047        Check the dialog content.
[b659551]1048        """
1049        flag = True
1050        try:
1051            int(self.npts_ctl.GetValue())
1052            self.npts_ctl.SetBackgroundColour(wx.WHITE)
1053            self.npts_ctl.Refresh()
1054        except:
1055            flag = False
1056            self.npts_ctl.SetBackgroundColour("pink")
1057            self.npts_ctl.Refresh()
1058        if flag:
1059            event.Skip(True)
1060
1061    def get_content(self):
1062        """
[7116b6e0]1063        Return the content of the dialog.
1064        At this point the values have already been
1065        checked.
[b659551]1066        """
1067        value = int(self.npts_ctl.GetValue())
1068        return value
1069   
1070    def set_content(self, npts):
1071        """
[7116b6e0]1072        Initialize the content of the dialog.
[b659551]1073        """
1074        self.npts_ctl.SetValue("%i" % npts)
1075
[f3d51f6]1076##### testing code ############################################################
[7116b6e0]1077"""
1078Example: ::
1079
[f3d51f6]1080class TestPlot:
1081    def __init__(self, text):
1082        self.name = text
1083   
1084class MyApp(wx.App):
1085    def OnInit(self):
1086        wx.InitAllImageHandlers()
[b659551]1087        dialog = PrDistDialog(None, -1)
[f3d51f6]1088        if dialog.ShowModal() == wx.ID_OK:
[119a11d]1089            pass
[f3d51f6]1090        dialog.Destroy()
1091       
1092        return 1
1093
1094# end of class MyApp
1095
1096if __name__ == "__main__":
1097    app = MyApp(0)
1098    app.MainLoop()
1099   
[7116b6e0]1100"""
[f3d51f6]1101##### end of testing code #####################################################   
Note: See TracBrowser for help on using the repository browser.