source: sasview/prview/src/sans/perspectives/pr/inversion_panel.py @ a225dc7

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