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

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 c1bffa5 was c1bffa5, checked in by Doucet, Mathieu <doucetm@…>, 10 years ago

This should fix the suggested value buttons.

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