source: sasview/prview/perspectives/pr/inversion_panel.py @ b3de3a45

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

prview: added setup script to install pr perspective as module. Modified perspective for use in SansView? (see standalone mode).

  • Property mode set to 100644
File size: 46.2 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
343        state.file = self.data_file.GetValue()
344       
345        # Background evaluation checkbox
346        state.estimate_bck = self.bck_chk.IsChecked()
347       
348        # Estimates
349        state.nterms_estimate = self.nterms_estimate
350        state.alpha_estimate = self.alpha_estimate
351       
352        # Read the output values
353        state.chi2    = self.chi2
354        state.elapsed = self.elapsed
355        state.osc     = self.oscillation
356        state.pos     = self.pos
357        state.pos_err = self.pos_err
358        state.rg      = self.rg
359        state.iq0     = self.iq0
360        state.bck     = self.bck
361           
362        state.toXML(path)
363        return state
364   
365    def set_state(self, state):
366        """
367            Set the state of the panel and inversion problem to
368            the state passed as a parameter.
369            Execute the inversion immediately after filling the
370            controls.
371           
372            @param state: InversionState object
373        """
374        self.nfunc = state.nfunc
375        self.d_max = state.d_max
376        self.alpha = state.alpha
377        self.q_min  = state.qmin
378        self.q_max  = state.qmax
379        self.slit_width = state.width
380        self.slit_height = state.height
381       
382        # Data file
383        self.data_file.SetValue(str(state.file))
384   
385        # Background evaluation checkbox
386        self.bck_chk.SetValue(state.estimate_bck)
387       
388        # Estimates
389        self.nterms_estimate = state.nterms_estimate
390        self.alpha_estimate = state.alpha_estimate
391   
392       
393        # Read the output values
394        self.chi2    = state.chi2
395        self.elapsed = state.elapsed
396        self.oscillation = state.osc
397        self.positive = state.pos
398        self.pos_err = state.pos_err
399        self.rg      = state.rg
400        self.iq0     = state.iq0
401        self.bck     = state.bck
402
403        # Check whether the file is accessible, if so,
404        # load it a recompute P(r) using the new parameters
405        if os.path.isfile(state.file):
406            self._change_file(filepath=state.file)
407            self._on_invert(None)   
408        else:
409            message = "Could not find [%s] on the file system." % state.file
410            wx.PostEvent(self.manager.parent, StatusEvent(status=message))
411   
412           
413       
[f3d51f6]414    def set_manager(self, manager):
415        self.manager = manager
416        # Get data
417       
418        # Push data to form
419       
420       
421    def _do_layout(self):
[4318af7f]422        vbox = wx.GridBagSizer(0,0)
423        iy_vb = 0
[f3d51f6]424
425        # ----- I(q) data -----
[aa4b8379]426        databox = wx.StaticBox(self, -1, "I(q) data source")
[f3d51f6]427       
428        boxsizer1 = wx.StaticBoxSizer(databox, wx.VERTICAL)
429        boxsizer1.SetMinSize((320,50))
430        pars_sizer = wx.GridBagSizer(5,5)
431
432        iy = 0
[d2ee6f6]433        self.file_radio = wx.StaticText(self, -1, "Data:")
[f3d51f6]434        pars_sizer.Add(self.file_radio, (iy,0), (1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
435       
[d2ee6f6]436        if self.standalone==True:
437            self.data_file = wx.TextCtrl(self, -1, size=(220,20))
438            self.data_file.SetEditable(False)
439            self.data_file.SetValue("")
440            pars_sizer.Add(self.data_file, (iy,1), (1,1), wx.ADJUST_MINSIZE, 15)
441        else:
442            self.plot_data = wx.TextCtrl(self, -1, size=(220,20))
[aa4b8379]443            self.plot_data.SetEditable(False)
444            pars_sizer.Add(self.plot_data, (iy,1), (1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 15)
[f3d51f6]445       
[a4bd2ac]446        self.bck_chk = wx.CheckBox(self, -1, "Estimate background level")
447        self.bck_chk.SetToolTipString("Check box to let the fit estimate the constant background level.")
448        self.bck_chk.Bind(wx.EVT_CHECKBOX, self._on_pars_changed)
449        iy += 1
450        pars_sizer.Add(self.bck_chk, (iy,0), (1,2), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
451        boxsizer1.Add(pars_sizer, 0, wx.EXPAND) 
[4318af7f]452        vbox.Add(boxsizer1, (iy_vb,0), (1,1), wx.RIGHT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
[a4bd2ac]453       
454        # ----- Add slit parameters -----
[2a92852]455        if True:
[a4bd2ac]456            sbox = wx.StaticBox(self, -1, "Slit parameters")
457            sboxsizer = wx.StaticBoxSizer(sbox, wx.VERTICAL)
458            sboxsizer.SetMinSize((320,20))
459           
460            sizer_slit = wx.GridBagSizer(5,5)
461   
[4318af7f]462            label_sheight = wx.StaticText(self, -1, "Height", size=(40,20))
463            label_swidth = wx.StaticText(self, -1, "Width", size=(40,20))
[a4bd2ac]464            #label_sunits1 = wx.StaticText(self, -1, "[A^(-1)]")
[4318af7f]465            label_sunits2 = wx.StaticText(self, -1, "[A^(-1)]", size=(55,20))
[a4bd2ac]466            self.sheight_ctl = wx.TextCtrl(self, -1, size=(60,20))
467            self.swidth_ctl = wx.TextCtrl(self, -1, size=(60,20))
468            self.sheight_ctl.SetToolTipString("Enter slit height in units of Q or leave blank.")
469            self.swidth_ctl.SetToolTipString("Enter slit width in units of Q or leave blank.")
[2a92852]470            #self.sheight_ctl.Bind(wx.EVT_TEXT, self._on_pars_changed)
471            #self.swidth_ctl.Bind(wx.EVT_TEXT,  self._on_pars_changed)
[a4bd2ac]472           
473            iy = 0
[357b79b]474            sizer_slit.Add(label_sheight,    (iy,0), (1,1), wx.LEFT|wx.EXPAND, 5)
475            sizer_slit.Add(self.sheight_ctl, (iy,1), (1,1), wx.LEFT|wx.EXPAND, 5)
[a4bd2ac]476            #sizer_slit.Add(label_sunits1,    (iy,2), (1,1), wx.LEFT|wx.EXPAND, 10)
[357b79b]477            sizer_slit.Add(label_swidth,     (iy,2), (1,1), wx.LEFT|wx.EXPAND, 5)
478            sizer_slit.Add(self.swidth_ctl,  (iy,3), (1,1), wx.LEFT|wx.EXPAND, 5)
479            sizer_slit.Add(label_sunits2,    (iy,4), (1,1), wx.LEFT|wx.EXPAND, 5)
[a4bd2ac]480           
481            sboxsizer.Add(sizer_slit, wx.TOP, 15)
[4318af7f]482            iy_vb += 1
483            vbox.Add(sboxsizer, (iy_vb,0), (1,1), wx.RIGHT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
[a4bd2ac]484       
[357b79b]485       
486        # ----- Q range -----
487        qbox = wx.StaticBox(self, -1, "Q range")
488        qboxsizer = wx.StaticBoxSizer(qbox, wx.VERTICAL)
489        qboxsizer.SetMinSize((320,20))
490       
491        sizer_q = wx.GridBagSizer(5,5)
492
[4318af7f]493        label_qmin = wx.StaticText(self, -1, "Q min", size=(40,20))
494        label_qmax = wx.StaticText(self, -1, "Q max", size=(40,20))
[357b79b]495        #label_qunits1 = wx.StaticText(self, -1, "[A^(-1)]")
[4318af7f]496        label_qunits2 = wx.StaticText(self, -1, "[A^(-1)]", size=(55,20))
[357b79b]497        self.qmin_ctl = wx.TextCtrl(self, -1, size=(60,20))
498        self.qmax_ctl = wx.TextCtrl(self, -1, size=(60,20))
499        self.qmin_ctl.SetToolTipString("Select a lower bound for Q or leave blank.")
500        self.qmax_ctl.SetToolTipString("Select an upper bound for Q or leave blank.")
501        self.qmin_ctl.Bind(wx.EVT_TEXT, self._on_pars_changed)
502        self.qmax_ctl.Bind(wx.EVT_TEXT, self._on_pars_changed)
503       
504        iy = 0
505        sizer_q.Add(label_qmin,    (iy,0), (1,1), wx.LEFT|wx.EXPAND, 5)
506        sizer_q.Add(self.qmin_ctl, (iy,1), (1,1), wx.LEFT|wx.EXPAND, 5)
507        #sizer_q.Add(label_qunits1, (iy,2), (1,1), wx.LEFT|wx.EXPAND, 15)
508        sizer_q.Add(label_qmax,    (iy,2), (1,1), wx.LEFT|wx.EXPAND, 5)
509        sizer_q.Add(self.qmax_ctl, (iy,3), (1,1), wx.LEFT|wx.EXPAND, 5)
510        sizer_q.Add(label_qunits2, (iy,4), (1,1), wx.LEFT|wx.EXPAND, 5)
511        qboxsizer.Add(sizer_q, wx.TOP, 15)
[4318af7f]512
513        iy_vb += 1
514        vbox.Add(qboxsizer, (iy_vb,0), (1,1), wx.RIGHT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
[357b79b]515       
516       
517       
[f3d51f6]518
519        # ----- Parameters -----
520        parsbox = wx.StaticBox(self, -1, "Parameters")
521        boxsizer2 = wx.StaticBoxSizer(parsbox, wx.VERTICAL)
522        boxsizer2.SetMinSize((320,50))
523       
[32dffae4]524        explanation  = "P(r) is found by fitting a set of base functions to I(Q). "
525        explanation += "The minimization involves a regularization term to ensure "
[0bae207]526        explanation += "a smooth P(r). The regularization constant gives the size of that " 
[119a11d]527        explanation += "term. The suggested value is the value above which the "
[32dffae4]528        explanation += "output P(r) will have only one peak."
529        label_explain = wx.StaticText(self, -1, explanation, size=(280,80))
530        boxsizer2.Add(label_explain,  wx.LEFT|wx.BOTTOM, 5)
531       
532       
533       
[f3d51f6]534        label_nfunc = wx.StaticText(self, -1, "Number of terms")
535        label_nfunc.SetMinSize((120,20))
536        label_alpha = wx.StaticText(self, -1, "Regularization constant")
537        label_dmax  = wx.StaticText(self, -1, "Max distance [A]")
[634f1cf]538        self.label_sugg  = wx.StaticText(self, -1, "Suggested value")
539        #self.label_sugg.Hide()
[f3d51f6]540       
541        self.nfunc_ctl = wx.TextCtrl(self, -1, size=(60,20))
[32dffae4]542        self.nfunc_ctl.SetToolTipString("Number of terms in the expansion.")
[f3d51f6]543        self.alpha_ctl = wx.TextCtrl(self, -1, size=(60,20))
[32dffae4]544        self.alpha_ctl.SetToolTipString("Control parameter for the size of the regularization term.")
[f3d51f6]545        self.dmax_ctl  = wx.TextCtrl(self, -1, size=(60,20))
[32dffae4]546        self.dmax_ctl.SetToolTipString("Maximum distance between any two points in the system.")
[634f1cf]547        id = wx.NewId()
548        self.alpha_estimate_ctl  = wx.Button(self, id, "")
549        #self.alpha_estimate_ctl.Hide()
550        self.Bind(wx.EVT_BUTTON, self._on_accept_alpha, id = id)   
[f3d51f6]551        self.alpha_estimate_ctl.Enable(False)
[634f1cf]552        #self.alpha_estimate_ctl.SetBackgroundColour('#ffdf85')
553        #self.alpha_estimate_ctl.SetBackgroundColour(self.GetBackgroundColour())
554        self.alpha_estimate_ctl.SetToolTipString("Waiting for estimate...")
[f3d51f6]555       
[35adaf6]556        id = wx.NewId()
557        self.nterms_estimate_ctl  = wx.Button(self, id, "")
558        #self.nterms_estimate_ctl.Hide()
559        self.Bind(wx.EVT_BUTTON, self._on_accept_nterms, id = id)   
560        self.nterms_estimate_ctl.Enable(False)
561        #self.nterms_estimate_ctl.SetBackgroundColour('#ffdf85')
562        #self.nterms_estimate_ctl.SetBackgroundColour(self.GetBackgroundColour())
563        self.nterms_estimate_ctl.SetToolTipString("Waiting for estimate...")
564       
[d6113849]565        self.nfunc_ctl.Bind(wx.EVT_TEXT, self._read_pars)
[a4bd2ac]566        self.alpha_ctl.Bind(wx.EVT_TEXT, self._read_pars)
567        self.dmax_ctl.Bind(wx.EVT_TEXT, self._on_pars_changed)
568       
569       
570       
[f3d51f6]571        sizer_params = wx.GridBagSizer(5,5)
572
573        iy = 0
[634f1cf]574        sizer_params.Add(self.label_sugg,       (iy,2), (1,1), wx.LEFT, 15)
[f3d51f6]575        iy += 1
[32dffae4]576        sizer_params.Add(label_nfunc,      (iy,0), (1,1), wx.LEFT, 15)
577        sizer_params.Add(self.nfunc_ctl,   (iy,1), (1,1), wx.RIGHT, 0)
[35adaf6]578        sizer_params.Add(self.nterms_estimate_ctl, (iy,2), (1,1), wx.LEFT, 15)
[f3d51f6]579        iy += 1
[32dffae4]580        sizer_params.Add(label_alpha,      (iy,0), (1,1), wx.LEFT, 15)
581        sizer_params.Add(self.alpha_ctl,   (iy,1), (1,1), wx.RIGHT, 0)
582        sizer_params.Add(self.alpha_estimate_ctl, (iy,2), (1,1), wx.LEFT, 15)
[f3d51f6]583        iy += 1
[32dffae4]584        sizer_params.Add(label_dmax, (iy,0), (1,1), wx.LEFT, 15)
585        sizer_params.Add(self.dmax_ctl,   (iy,1), (1,1), wx.RIGHT, 0)
[f3d51f6]586
587        boxsizer2.Add(sizer_params, 0)
[634f1cf]588       
[4318af7f]589        iy_vb += 1
590        vbox.Add(boxsizer2, (iy_vb,0), (1,1), wx.RIGHT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
[f3d51f6]591
[634f1cf]592
[f3d51f6]593        # ----- Results -----
594        resbox = wx.StaticBox(self, -1, "Outputs")
595        ressizer = wx.StaticBoxSizer(resbox, wx.VERTICAL)
596        ressizer.SetMinSize((320,50))
597       
[a4bd2ac]598        label_rg       = wx.StaticText(self, -1, "Rg")
599        label_rg_unit  = wx.StaticText(self, -1, "[A]")
600        label_iq0      = wx.StaticText(self, -1, "I(Q=0)")
601        label_iq0_unit = wx.StaticText(self, -1, "[A^(-1)]")
602        label_bck      = wx.StaticText(self, -1, "Background")
603        label_bck_unit = wx.StaticText(self, -1, "[A^(-1)]")
604        self.rg_ctl    = wx.TextCtrl(self, -1, size=(60,20))
605        self.rg_ctl.SetEditable(False)
606        self.rg_ctl.SetToolTipString("Radius of gyration for the computed P(r).")
607        self.iq0_ctl   = wx.TextCtrl(self, -1, size=(60,20))
608        self.iq0_ctl.SetEditable(False)
609        self.iq0_ctl.SetToolTipString("Scattering intensity at Q=0 for the computed P(r).")
610        self.bck_ctl   = wx.TextCtrl(self, -1, size=(60,20))
611        self.bck_ctl.SetEditable(False)
612        self.bck_ctl.SetToolTipString("Value of estimated constant background.")
613       
[f3d51f6]614        label_time = wx.StaticText(self, -1, "Computation time")
615        label_time_unit = wx.StaticText(self, -1, "secs")
616        label_time.SetMinSize((120,20))
617        label_chi2 = wx.StaticText(self, -1, "Chi2/dof")
618        label_osc = wx.StaticText(self, -1, "Oscillations")
[dfb58f8]619        label_pos = wx.StaticText(self, -1, "Positive fraction")
620        label_pos_err = wx.StaticText(self, -1, "1-sigma positive fraction")
[f3d51f6]621       
622        self.time_ctl = wx.TextCtrl(self, -1, size=(60,20))
623        self.time_ctl.SetEditable(False)
[32dffae4]624        self.time_ctl.SetToolTipString("Computation time for the last inversion, in seconds.")
625       
[f3d51f6]626        self.chi2_ctl = wx.TextCtrl(self, -1, size=(60,20))
627        self.chi2_ctl.SetEditable(False)
[32dffae4]628        self.chi2_ctl.SetToolTipString("Chi^2 over degrees of freedom.")
629       
[dfb58f8]630        # Oscillation parameter
[f3d51f6]631        self.osc_ctl = wx.TextCtrl(self, -1, size=(60,20))
632        self.osc_ctl.SetEditable(False)
[32dffae4]633        self.osc_ctl.SetToolTipString("Oscillation parameter. P(r) for a sphere has an oscillation parameter of 1.1.")
[f3d51f6]634       
[dfb58f8]635        # Positive fraction figure of merit
636        self.pos_ctl = wx.TextCtrl(self, -1, size=(60,20))
637        self.pos_ctl.SetEditable(False)
638        self.pos_ctl.SetToolTipString("Fraction of P(r) that is positive. Theoretically, P(r) is defined positive.")
639       
640        # 1-simga positive fraction figure of merit
641        self.pos_err_ctl = wx.TextCtrl(self, -1, size=(60,20))
642        self.pos_err_ctl.SetEditable(False)
643        message  = "Fraction of P(r) that is at least 1 standard deviation greater than zero.\n"
644        message += "This figure of merit tells you about the size of the P(r) errors.\n"
645        message += "If it is close to 1 and the other figures of merit are bad, consider changing "
646        message += "the maximum distance."
647        self.pos_err_ctl.SetToolTipString(message)
648       
[f3d51f6]649        sizer_res = wx.GridBagSizer(5,5)
650
651        iy = 0
[a4bd2ac]652        sizer_res.Add(label_rg, (iy,0), (1,1), wx.LEFT|wx.EXPAND, 15)
653        sizer_res.Add(self.rg_ctl,   (iy,1), (1,1), wx.RIGHT|wx.EXPAND, 15)
654        sizer_res.Add(label_rg_unit,   (iy,2), (1,1), wx.RIGHT|wx.EXPAND, 15)
655        iy += 1
656        sizer_res.Add(label_iq0, (iy,0), (1,1), wx.LEFT|wx.EXPAND, 15)
657        sizer_res.Add(self.iq0_ctl,   (iy,1), (1,1), wx.RIGHT|wx.EXPAND, 15)
658        sizer_res.Add(label_iq0_unit,   (iy,2), (1,1), wx.RIGHT|wx.EXPAND, 15)
659        iy += 1
660        sizer_res.Add(label_bck, (iy,0), (1,1), wx.LEFT|wx.EXPAND, 15)
661        sizer_res.Add(self.bck_ctl,   (iy,1), (1,1), wx.RIGHT|wx.EXPAND, 15)
662        sizer_res.Add(label_bck_unit,   (iy,2), (1,1), wx.RIGHT|wx.EXPAND, 15)
663        iy += 1
[f3d51f6]664        sizer_res.Add(label_time, (iy,0), (1,1), wx.LEFT|wx.EXPAND, 15)
665        sizer_res.Add(self.time_ctl,   (iy,1), (1,1), wx.RIGHT|wx.EXPAND, 15)
666        sizer_res.Add(label_time_unit,   (iy,2), (1,1), wx.RIGHT|wx.EXPAND, 15)
667        iy += 1
668        sizer_res.Add(label_chi2, (iy,0), (1,1), wx.LEFT|wx.EXPAND, 15)
669        sizer_res.Add(self.chi2_ctl,   (iy,1), (1,1), wx.RIGHT|wx.EXPAND, 15)
670        iy += 1
671        sizer_res.Add(label_osc, (iy,0), (1,1), wx.LEFT|wx.EXPAND, 15)
672        sizer_res.Add(self.osc_ctl,   (iy,1), (1,1), wx.RIGHT|wx.EXPAND, 15)
673
[dfb58f8]674        iy += 1
675        sizer_res.Add(label_pos, (iy,0), (1,1), wx.LEFT|wx.EXPAND, 15)
676        sizer_res.Add(self.pos_ctl,   (iy,1), (1,1), wx.RIGHT|wx.EXPAND, 15)
677
678        iy += 1
679        sizer_res.Add(label_pos_err, (iy,0), (1,1), wx.LEFT|wx.EXPAND, 15)
680        sizer_res.Add(self.pos_err_ctl,   (iy,1), (1,1), wx.RIGHT|wx.EXPAND, 15)
681
[f3d51f6]682        ressizer.Add(sizer_res, 0)
[4318af7f]683        iy_vb += 1
684        vbox.Add(ressizer, (iy_vb,0), (1,1), wx.RIGHT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
[f3d51f6]685
686        # ----- Buttons -----
687        id = wx.NewId()
688        button_OK = wx.Button(self, id, "Compute")
[32dffae4]689        button_OK.SetToolTipString("Perform P(r) inversion.")
[f3d51f6]690        self.Bind(wx.EVT_BUTTON, self._on_invert, id = id)   
[b659551]691       
692        id = wx.NewId()
693        button_Reset = wx.Button(self, id, "Reset")
694        button_Reset.SetToolTipString("Reset inversion parameters to default.")
695        self.Bind(wx.EVT_BUTTON, self._on_reset, id = id)   
[f3d51f6]696        #button_Cancel = wx.Button(self, wx.ID_CANCEL, "Cancel")
697       
[5d98370]698        id = wx.NewId()
699        button_Save = wx.Button(self, id, "Save")
700        button_Save.SetToolTipString("Save the current P(r) work to file.")
701        self.Bind(wx.EVT_BUTTON, self._save_state, id = id)   
702       
[f3d51f6]703        sizer_button = wx.BoxSizer(wx.HORIZONTAL)
704        sizer_button.Add((20, 20), 1, wx.EXPAND|wx.ADJUST_MINSIZE, 0)
[5d98370]705        sizer_button.Add(button_Save, 0, wx.LEFT|wx.ADJUST_MINSIZE, 10)
[b659551]706        sizer_button.Add(button_Reset, 0, wx.LEFT|wx.ADJUST_MINSIZE, 10)
[f3d51f6]707        sizer_button.Add(button_OK, 0, wx.LEFT|wx.ADJUST_MINSIZE, 10)
708        #sizer_button.Add(button_Cancel, 0, wx.LEFT|wx.RIGHT|wx.ADJUST_MINSIZE, 10)       
[4318af7f]709        iy_vb += 1
710        vbox.Add(sizer_button, (iy_vb,0), (1,1), wx.EXPAND|wx.BOTTOM|wx.TOP, 10)
[f3d51f6]711
712
713        self.SetSizer(vbox)
714       
[634f1cf]715    def _on_accept_alpha(self, evt):
716        """
717            User has accepted the estimated alpha,
718            set it as part of the input parameters
719        """
720        try:
721            alpha = self.alpha_estimate_ctl.GetLabel()
722            tmp = float(alpha)
723            self.alpha_ctl.SetValue(alpha)
724        except:
725            # No estimate or bad estimate, either do nothing
726            import sys
727            print "InversionControl._on_accept_alpha: %s" % sys.exc_value
728            pass
[35adaf6]729   
730    def _on_accept_nterms(self, evt):
731        """
732            User has accepted the estimated number of terms,
733            set it as part of the input parameters
734        """
735        try:
736            nterms = self.nterms_estimate_ctl.GetLabel()
737            tmp = float(nterms)
738            self.nfunc_ctl.SetValue(nterms)
739        except:
740            # No estimate or bad estimate, either do nothing
741            import sys
742            print "InversionControl._on_accept_nterms: %s" % sys.exc_value
743            pass
[634f1cf]744       
[b659551]745    def _on_reset(self, evt):
746        """
747            Resets inversion parameters
748        """
749        self.nfunc = self.manager.DEFAULT_NFUNC
750        self.d_max = self.manager.DEFAULT_DMAX
751        self.alpha = self.manager.DEFAULT_ALPHA
752        self.qmin_ctl.SetValue("")
753        self.qmax_ctl.SetValue("")
754        self.time_ctl.SetValue("")
[a4bd2ac]755        self.rg_ctl.SetValue("")
756        self.iq0_ctl.SetValue("")
757        self.bck_ctl.SetValue("")
[b659551]758        self.chi2_ctl.SetValue("")
759        self.osc_ctl.SetValue("")
760        self.pos_ctl.SetValue("")
761        self.pos_err_ctl.SetValue("")
762        self.alpha_estimate_ctl.Enable(False)
763        self.alpha_estimate_ctl.SetLabel("")
[35adaf6]764        self.nterms_estimate_ctl.Enable(False)
765        self.nterms_estimate_ctl.SetLabel("")
[b659551]766        self._on_pars_changed()
[634f1cf]767       
[b659551]768    def _on_pars_changed(self, evt=None):
[f3d51f6]769        """
770            Called when an input parameter has changed
771            We will estimate the alpha parameter behind the
772            scenes.
773        """
[2a92852]774        flag, alpha, dmax, nfunc, qmin, qmax, height, width = self._read_pars()
[a4bd2ac]775        has_bck = self.bck_chk.IsChecked()
[f3d51f6]776       
777        # If the pars are valid, estimate alpha
778        if flag:
[2a92852]779            self.nterms_estimate_ctl.Enable(False)
780            self.alpha_estimate_ctl.Enable(False)
781           
[d2ee6f6]782            if self.standalone==False:
[f3d51f6]783                dataset = self.plot_data.GetValue()
784                self.manager.estimate_plot_inversion(alpha=alpha, nfunc=nfunc, 
[634f1cf]785                                                     d_max=dmax,
[a4bd2ac]786                                                     q_min=qmin, q_max=qmax,
[2a92852]787                                                     bck=has_bck, 
788                                                     height=height,
789                                                     width=width)
[f3d51f6]790            else:
791                path = self.data_file.GetValue()
792                self.manager.estimate_file_inversion(alpha=alpha, nfunc=nfunc, 
[634f1cf]793                                                     d_max=dmax, path=path,
[a4bd2ac]794                                                     q_min=qmin, q_max=qmax,
[2a92852]795                                                     bck=has_bck,
796                                                     height=height,
797                                                     width=width)
[f3d51f6]798       
799       
[634f1cf]800    def _read_pars(self, evt=None):   
[f3d51f6]801        alpha = 0
802        nfunc = 5
803        dmax  = 120
[3fd1ebc]804        qmin  = 0
805        qmax  = 0
[2a92852]806        height = 0
807        width  = 0
[f3d51f6]808       
809        flag = True
810       
[2a92852]811       
812        # Read slit height
813        try:
814            height_str = self.sheight_ctl.GetValue()
815            if len(height_str.lstrip().rstrip())==0:
816                height = 0
817            else:
818                height = float(height_str)
819                self.sheight_ctl.SetBackgroundColour(wx.WHITE)
820                self.sheight_ctl.Refresh()
821        except:
822            flag = False
823            self.sheight_ctl.SetBackgroundColour("pink")
824            self.sheight_ctl.Refresh()
825           
826        # Read slit width
827        try:
828            width_str = self.swidth_ctl.GetValue()
829            if len(width_str.lstrip().rstrip())==0:
830                width = 0
831            else:
832                width = float(width_str)
833                self.swidth_ctl.SetBackgroundColour(wx.WHITE)
834                self.swidth_ctl.Refresh()
835        except:
836            flag = False
837            self.swidth_ctl.SetBackgroundColour("pink")
838            self.swidth_ctl.Refresh()
839       
[f3d51f6]840        # Read alpha
841        try:
842            alpha = float(self.alpha_ctl.GetValue())
843            self.alpha_ctl.SetBackgroundColour(wx.WHITE)
844            self.alpha_ctl.Refresh()
845        except:
846            flag = False
847            self.alpha_ctl.SetBackgroundColour("pink")
848            self.alpha_ctl.Refresh()
849       
850        # Read d_max   
851        try:
852            dmax = float(self.dmax_ctl.GetValue())
853            self.dmax_ctl.SetBackgroundColour(wx.WHITE)
854            self.dmax_ctl.Refresh()
855        except:
856            flag = False
857            self.dmax_ctl.SetBackgroundColour("pink")
858            self.dmax_ctl.Refresh()
859           
860        # Read nfunc
861        try:
862            nfunc = int(self.nfunc_ctl.GetValue())
[b659551]863            npts = self.manager.get_npts()
864            if npts>0 and nfunc>npts:
865                message = "Number of function terms should be smaller than the number of points"
866                wx.PostEvent(self.manager.parent, StatusEvent(status=message))
867                raise ValueError, message
[f3d51f6]868            self.nfunc_ctl.SetBackgroundColour(wx.WHITE)
869            self.nfunc_ctl.Refresh()
870        except:
871            flag = False
872            self.nfunc_ctl.SetBackgroundColour("pink")
873            self.nfunc_ctl.Refresh()
874       
[634f1cf]875        # Read qmin
876        try:
877            qmin_str = self.qmin_ctl.GetValue()
878            if len(qmin_str.lstrip().rstrip())==0:
879                qmin = None
880            else:
881                qmin = float(qmin_str)
882                self.qmin_ctl.SetBackgroundColour(wx.WHITE)
883                self.qmin_ctl.Refresh()
884        except:
885            flag = False
886            self.qmin_ctl.SetBackgroundColour("pink")
887            self.qmin_ctl.Refresh()
888       
889        # Read qmax
890        try:
891            qmax_str = self.qmax_ctl.GetValue()
892            if len(qmax_str.lstrip().rstrip())==0:
893                qmax = None
894            else:
895                qmax = float(qmax_str)
896                self.qmax_ctl.SetBackgroundColour(wx.WHITE)
897                self.qmax_ctl.Refresh()
898        except:
899            flag = False
900            self.qmax_ctl.SetBackgroundColour("pink")
901            self.qmax_ctl.Refresh()
902       
[2a92852]903        return flag, alpha, dmax, nfunc, qmin, qmax, height, width
[f3d51f6]904   
905    def _on_invert(self, evt):
906        """
907            Perform inversion
908            @param silent: when True, there will be no output for the user
909        """
910        # Get the data from the form
911        # Push it to the manager
912       
[2a92852]913        flag, alpha, dmax, nfunc, qmin, qmax, height, width = self._read_pars()
[a4bd2ac]914        has_bck = self.bck_chk.IsChecked()
[f3d51f6]915       
916        if flag:
[d2ee6f6]917            if self.standalone==False:
[f3d51f6]918                dataset = self.plot_data.GetValue()
[aa4b8379]919                if len(dataset.strip())==0:
920                    message = "No data to invert. Select a data set before proceeding with P(r) inversion."
921                    wx.PostEvent(self.manager.parent, StatusEvent(status=message))
922                else:
923                    self.manager.setup_plot_inversion(alpha=alpha, nfunc=nfunc, 
924                                                      d_max=dmax,
[a4bd2ac]925                                                      q_min=qmin, q_max=qmax,
[2a92852]926                                                      bck=has_bck,
927                                                      height=height,
928                                                      width=width)
[f3d51f6]929            else:
930                path = self.data_file.GetValue()
[aa4b8379]931                if len(path.strip())==0:
932                    message = "No data to invert. Select a data set before proceeding with P(r) inversion."
933                    wx.PostEvent(self.manager.parent, StatusEvent(status=message))
934                else:
935                    self.manager.setup_file_inversion(alpha=alpha, nfunc=nfunc, 
936                                                      d_max=dmax, path=path,
[a4bd2ac]937                                                      q_min=qmin, q_max=qmax,
[2a92852]938                                                      bck=has_bck,
939                                                      height=height,
940                                                      width=width)
[f3d51f6]941               
942        else:
943            message = "The P(r) form contains invalid values: please submit it again."
944            wx.PostEvent(self.parent, StatusEvent(status=message))
945       
[5d98370]946    def _change_file(self, evt=None, filepath=None):
[f3d51f6]947        """
948            Choose a new input file for I(q)
949        """
950        import os
951        if not self.manager==None:
[5d98370]952            path = self.manager.choose_file(path=filepath)
[f3d51f6]953           
954            if path and os.path.isfile(path):
955                self.data_file.SetValue(str(path))
[2a92852]956                self.manager.show_data(path, reset=True)
[0bae207]957                self._on_pars_changed(None)
[119a11d]958
959class HelpDialog(wx.Dialog):
960    def __init__(self, parent, id):
961        from sans.pr.invertor import help
[fc4ab6e]962        wx.Dialog.__init__(self, parent, id, size=(400, 420))
[119a11d]963        self.SetTitle("P(r) help") 
964       
965
966        vbox = wx.BoxSizer(wx.VERTICAL)
967
968        explanation = help()
969           
[fc4ab6e]970        label_explain = wx.StaticText(self, -1, explanation, size=(350,320))
[119a11d]971           
972        vbox.Add(label_explain, 0, wx.ALL|wx.EXPAND, 15)
973
974
975        static_line = wx.StaticLine(self, -1)
976        vbox.Add(static_line, 0, wx.EXPAND, 0)
977       
978        button_OK = wx.Button(self, wx.ID_OK, "OK")
979        #button_Cancel = wx.Button(self, wx.ID_CANCEL, "Cancel")
980       
981        sizer_button = wx.BoxSizer(wx.HORIZONTAL)
982        sizer_button.Add((20, 20), 1, wx.EXPAND|wx.ADJUST_MINSIZE, 0)
983        sizer_button.Add(button_OK, 0, wx.LEFT|wx.RIGHT|wx.ADJUST_MINSIZE, 10)
984        #sizer_button.Add(button_Cancel, 0, wx.LEFT|wx.RIGHT|wx.ADJUST_MINSIZE, 10)       
985        vbox.Add(sizer_button, 0, wx.EXPAND|wx.BOTTOM|wx.TOP, 10)
986
987        self.SetSizer(vbox)
988        self.SetAutoLayout(True)
989       
990        self.Layout()
991        self.Centre()
992
[b659551]993class PrDistDialog(wx.Dialog):
994    """
995        Property dialog to let the user change the number
996        of points on the P(r) plot.
997    """
998    def __init__(self, parent, id):
999        from sans.pr.invertor import help
1000        wx.Dialog.__init__(self, parent, id, size=(250, 120))
1001        self.SetTitle("P(r) distribution") 
1002       
1003
1004        vbox = wx.BoxSizer(wx.VERTICAL)
1005       
1006        label_npts = wx.StaticText(self, -1, "Number of points")
1007        self.npts_ctl = wx.TextCtrl(self, -1, size=(100,20))
1008                 
1009        pars_sizer = wx.GridBagSizer(5,5)
1010        iy = 0
1011        pars_sizer.Add(label_npts,      (iy,0), (1,1), wx.LEFT, 15)
1012        pars_sizer.Add(self.npts_ctl,   (iy,1), (1,1), wx.RIGHT, 0)
1013       
1014        vbox.Add(pars_sizer, 0, wx.ALL|wx.EXPAND, 15)
1015
1016
1017        static_line = wx.StaticLine(self, -1)
1018        vbox.Add(static_line, 0, wx.EXPAND, 0)
1019       
1020        button_OK = wx.Button(self, wx.ID_OK, "OK")
1021        self.Bind(wx.EVT_BUTTON, self._checkValues, button_OK)
1022        button_Cancel = wx.Button(self, wx.ID_CANCEL, "Cancel")
1023       
1024        sizer_button = wx.BoxSizer(wx.HORIZONTAL)
1025        sizer_button.Add((20, 20), 1, wx.EXPAND|wx.ADJUST_MINSIZE, 0)
1026        sizer_button.Add(button_OK, 0, wx.LEFT|wx.RIGHT|wx.ADJUST_MINSIZE, 10)
1027        sizer_button.Add(button_Cancel, 0, wx.LEFT|wx.RIGHT|wx.ADJUST_MINSIZE, 10)       
1028        vbox.Add(sizer_button, 0, wx.EXPAND|wx.BOTTOM|wx.TOP, 10)
1029
1030        self.SetSizer(vbox)
1031        self.SetAutoLayout(True)
1032       
1033        self.Layout()
1034        self.Centre()
1035
1036    def _checkValues(self, event):
1037        """
1038            Check the dialog content.
1039        """
1040        flag = True
1041        try:
1042            int(self.npts_ctl.GetValue())
1043            self.npts_ctl.SetBackgroundColour(wx.WHITE)
1044            self.npts_ctl.Refresh()
1045        except:
1046            flag = False
1047            self.npts_ctl.SetBackgroundColour("pink")
1048            self.npts_ctl.Refresh()
1049        if flag:
1050            event.Skip(True)
1051
1052    def get_content(self):
1053        """
1054            Return the content of the dialog.
1055            At this point the values have already been
1056            checked.
1057        """
1058        value = int(self.npts_ctl.GetValue())
1059        return value
1060   
1061    def set_content(self, npts):
1062        """
1063            Initialize the content of the dialog.
1064        """
1065        self.npts_ctl.SetValue("%i" % npts)
1066
[119a11d]1067
[f3d51f6]1068class ParsDialog(wx.Panel):
1069    """
1070        Dialog box to let the user edit detector settings
1071    """
1072   
1073    def __init__(self, parent, id = id, file=True, **kwargs):
1074
1075        wx.Panel.__init__(self, parent, id = id, **kwargs)
1076        self.file = file
1077       
1078        self.label_nfunc = wx.StaticText(self, -1, "Number of terms")
1079        self.label_alpha = wx.StaticText(self, -1, "Regularization constant")
1080        self.label_dmax  = wx.StaticText(self, -1, "Max distance [A]")
1081       
1082        # Npts, q max
1083        self.nfunc_ctl = wx.TextCtrl(self, -1, size=(60,20))
1084        self.alpha_ctl = wx.TextCtrl(self, -1, size=(60,20))
1085        self.dmax_ctl  = wx.TextCtrl(self, -1, size=(60,20))
1086
1087        self.label_file = None
1088        self.file_ctl   = None
1089
1090        self.static_line_3 = wx.StaticLine(self, -1)
1091       
1092       
1093
1094        self.__do_layout()
1095
1096        self.Fit()
1097       
1098    def _load_file(self, evt):
1099        import os
1100        path = None
1101        dlg = wx.FileDialog(self, "Choose a file", os.getcwd(), "", "*.txt", wx.OPEN)
1102        if dlg.ShowModal() == wx.ID_OK:
1103            path = dlg.GetPath()
1104            mypath = os.path.basename(path)
1105        dlg.Destroy()
1106       
1107        if path and os.path.isfile(path):
1108            self.file_ctl.SetValue(str(path))
1109
1110       
1111    def checkValues(self, event):
1112        flag = True
1113        try:
1114            float(self.alpha_ctl.GetValue())
1115            self.alpha_ctl.SetBackgroundColour(wx.WHITE)
1116            self.alpha_ctl.Refresh()
1117        except:
1118            flag = False
1119            self.alpha_ctl.SetBackgroundColour("pink")
1120            self.alpha_ctl.Refresh()
1121           
1122        try:
1123            float(self.dmax_ctl.GetValue())
1124            self.dmax_ctl.SetBackgroundColour(wx.WHITE)
1125            self.dmax_ctl.Refresh()
1126        except:
1127            flag = False
1128            self.dmax_ctl.SetBackgroundColour("pink")
1129            self.dmax_ctl.Refresh()
1130           
1131        try:
1132            int(self.nfunc_ctl.GetValue())
1133            self.nfunc_ctl.SetBackgroundColour(wx.WHITE)
1134            self.nfunc_ctl.Refresh()
1135        except:
1136            flag = False
1137            self.nfunc_ctl.SetBackgroundColour("pink")
1138            self.nfunc_ctl.Refresh()
1139       
1140        if flag:
1141            event.Skip(True)
1142   
1143    def setContent(self, nfunc, alpha, dmax, file):
1144        self.nfunc_ctl.SetValue(str(nfunc))
1145        self.alpha_ctl.SetValue(str(alpha))
1146        self.dmax_ctl.SetValue(str(dmax))
1147        if self.file:
1148            self.file_ctl.SetValue(str(file))
1149
1150    def getContent(self):
1151        nfunc = int(self.nfunc_ctl.GetValue())
1152        alpha = float(self.alpha_ctl.GetValue())
1153        dmax = float(self.dmax_ctl.GetValue())
1154        file = None
1155        if self.file:
1156            file = self.file_ctl.GetValue()
1157        return nfunc, alpha, dmax, file
1158
1159
1160    def __do_layout(self):
1161        sizer_main = wx.BoxSizer(wx.VERTICAL)
1162        sizer_params = wx.GridBagSizer(5,5)
1163
1164        iy = 0
1165        sizer_params.Add(self.label_nfunc, (iy,0), (1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
1166        sizer_params.Add(self.nfunc_ctl,   (iy,1), (1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
1167        iy += 1
1168        sizer_params.Add(self.label_alpha, (iy,0), (1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
1169        sizer_params.Add(self.alpha_ctl,   (iy,1), (1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
1170        iy += 1
1171        sizer_params.Add(self.label_dmax, (iy,0), (1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
1172        sizer_params.Add(self.dmax_ctl,   (iy,1), (1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
1173        iy += 1
1174        if self.file:
1175            self.label_file  = wx.StaticText(self, -1, "Input file")
1176            self.file_ctl  = wx.TextCtrl(self, -1, size=(120,20))
1177            sizer_params.Add(self.label_file, (iy,0), (1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
1178            sizer_params.Add(self.file_ctl,   (iy,1), (1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
1179
1180        sizer_main.Add(sizer_params, 0, wx.EXPAND|wx.ALL, 10)
1181       
1182       
1183        if self.file:
1184            sizer_button = wx.BoxSizer(wx.HORIZONTAL)
1185            self.button_load = wx.Button(self, 1, "Choose file")
1186            self.Bind(wx.EVT_BUTTON, self._load_file, id = 1)       
1187            sizer_button.Add(self.button_load, 0, wx.LEFT|wx.ADJUST_MINSIZE, 10)
1188       
1189       
1190            sizer_main.Add(sizer_button, 0, wx.EXPAND|wx.BOTTOM|wx.TOP, 10)
1191        self.SetAutoLayout(True)
1192        self.SetSizer(sizer_main)
1193        self.Layout()
1194        self.Centre()
1195        # end wxGlade
1196
1197
1198# end of class DialogAbout
1199
1200##### testing code ############################################################
1201class TestPlot:
1202    def __init__(self, text):
1203        self.name = text
1204   
1205class MyApp(wx.App):
1206    def OnInit(self):
1207        wx.InitAllImageHandlers()
[b659551]1208        dialog = PrDistDialog(None, -1)
[f3d51f6]1209        if dialog.ShowModal() == wx.ID_OK:
[119a11d]1210            pass
[f3d51f6]1211        dialog.Destroy()
1212       
1213        return 1
1214
1215# end of class MyApp
1216
1217if __name__ == "__main__":
1218    app = MyApp(0)
1219    app.MainLoop()
1220   
1221##### end of testing code #####################################################   
Note: See TracBrowser for help on using the repository browser.