source: sasview/prview/perspectives/pr/inversion_panel.py @ 410aad8

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 410aad8 was 91128648, checked in by Mathieu Doucet <doucetm@…>, 15 years ago

prview: extending the module to add flexibility necessary for SansView?. Adding compatibility with CanSAS format when saving a P(r) fit result to file.

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