source: sasview/invariantview/perspectives/invariant/invariant_panel.py @ 0bf2c6f

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 0bf2c6f was a0a4486, checked in by Gervaise Alina <gervyh@…>, 15 years ago

error checking on data

  • Property mode set to 100644
File size: 44.8 KB
Line 
1"""
2    This module provide GUI for the neutron scattering length density calculator
3    @author: Gervaise B. Alina
4"""
5
6import wx
7import sys
8
9from sans.invariant import invariant
10from sans.guiframe.utils import format_number, check_float
11from sans.guicomm.events import NewPlotEvent, StatusEvent
12from invariant_details import InvariantDetailsPanel
13from invariant_widgets import OutputTextCtrl, InvTextCtrl
14# The minimum q-value to be used when extrapolating
15Q_MINIMUM  = 1e-5
16# The maximum q-value to be used when extrapolating
17Q_MAXIMUM  = 10
18# the maximum value to plot the theory data
19Q_MAXIMUM_PLOT = 2
20# the number of points to consider during fit
21NPTS = 10
22#Default value for background
23BACKGROUND = 0.0
24#default value for the scale
25SCALE = 1.0
26#default value of the contrast
27CONTRAST = 1.0
28#Invariant panel size
29_BOX_WIDTH = 76
30#scale to use for a bar of value zero
31RECTANGLE_SCALE  = 0.0001
32
33if sys.platform.count("win32")>0:
34    _STATICBOX_WIDTH = 450
35    PANEL_WIDTH = 500
36    PANEL_HEIGHT = 700
37    FONT_VARIANT = 0
38else:
39    _STATICBOX_WIDTH = 480
40    PANEL_WIDTH = 530
41    PANEL_HEIGHT = 700
42    FONT_VARIANT = 1
43   
44class InvariantContainer(wx.Object):
45    def __init__(self):
46        #invariant at low range
47        self.qstar_low = None
48        #invariant at low range error
49        self.qstar_low_err = None
50        #invariant
51        self.qstar = None
52        #invariant error
53        self.qstar_err = None
54        #invariant at high range
55        self.qstar_high = None
56        #invariant at high range error
57        self.qstar_high_err = None
58        #invariant total
59        self.qstar_total = None
60        #invariant error
61        self.qstar_total_err = None
62        #scale
63        self.qstar_low_scale = RECTANGLE_SCALE
64        self.qstar_scale = RECTANGLE_SCALE
65        self.qstar_high_scale = RECTANGLE_SCALE
66 
67class InvariantPanel(wx.ScrolledWindow):
68    """
69        Provides the Invariant GUI.
70    """
71    ## Internal nickname for the window, used by the AUI manager
72    window_name = "Invariant"
73    ## Name to appear on the window title bar
74    window_caption = "Invariant"
75    ## Flag to tell the AUI manager to put this panel in the center pane
76    CENTER_PANE = True
77    def __init__(self, parent, data=None, manager=None):
78        wx.ScrolledWindow.__init__(self, parent, style= wx.FULL_REPAINT_ON_RESIZE )
79        #Font size
80        self.SetWindowVariant(variant=FONT_VARIANT)
81        #Object that receive status event
82        self.parent = parent
83        #plug-in using this panel
84        self._manager = manager
85        #Default power value
86        self.power_law_exponant = 4 
87        #Data uses for computation
88        self._data = data
89        #container of invariant value
90        self.inv_container = None
91        #Draw the panel
92        self._do_layout()
93        if self.parent is not None:
94            msg = ""
95            wx.PostEvent(self.parent, StatusEvent(status= msg))
96       
97    def err_check_on_data(self):
98        """
99            Check if data is valid for further computation
100        """
101        flag = False
102        #edit the panel
103        if self._data is not None:
104            if len(self._data.x[self._data.x==0]) > 0:
105                flag = True
106                msg = "Invariant: one of your q-values is zero. Delete that entry before proceeding"
107                wx.PostEvent(self.parent, StatusEvent(status= msg, type="stop")) 
108        return flag
109   
110    def set_data(self, data):
111        """
112            Set the data
113        """
114        self._data = data
115        #edit the panel
116        if self._data is not None:
117            self.err_check_on_data()
118            data_name = self._data.name
119            data_qmin = min (self._data.x)
120            data_qmax = max (self._data.x)
121            self.data_name_tcl.SetValue(str(data_name))
122            self.data_min_tcl.SetLabel(str(data_qmin))
123            self.data_max_tcl.SetLabel(str(data_qmax))
124       
125    def set_manager(self, manager):
126        """
127            set value for the manager
128        """
129        self._manager = manager
130   
131    def get_background(self):
132        """
133            @return the background textcrtl value as a float
134        """
135        background = self.background_tcl.GetValue().lstrip().rstrip()
136        if background == "":
137            raise ValueError, "Need a background"
138        if check_float(self.background_tcl):
139            return float(background)
140        else:
141            raise ValueError, "Receive invalid value for background : %s"%(background)
142   
143    def get_scale(self):
144        """
145            @return the scale textcrtl value as a float
146        """
147        scale = self.scale_tcl.GetValue().lstrip().rstrip()
148        if scale == "":
149            raise ValueError, "Need a background"
150        if check_float(self.scale_tcl):
151            return float(scale)
152        else:
153            raise ValueError, "Receive invalid value for background : %s"%(scale)
154       
155    def get_contrast(self):
156        """
157            @return the contrast textcrtl value as a float
158        """
159        par_str = self.contrast_tcl.GetValue().strip()
160        contrast = None
161        if par_str !="" and check_float(self.contrast_tcl):
162            contrast = float(par_str)
163        return contrast
164   
165    def get_extrapolation_type(self, low_q, high_q):
166        """
167        """
168        extrapolation = None
169        if low_q  and not high_q:
170            extrapolation = "low"
171        elif not low_q  and high_q:
172            extrapolation = "high"
173        elif low_q and high_q:
174            extrapolation = "both"
175        return extrapolation
176           
177    def get_porod_const(self):
178        """
179            @return the porod constant textcrtl value as a float
180        """
181        par_str = self.porod_constant_tcl.GetValue().strip()
182        porod_const = None
183        if par_str !="" and check_float(self.porod_constant_tcl):
184            porod_const = float(par_str)
185        return porod_const
186   
187    def get_volume(self, inv, contrast, extrapolation):
188        """
189        """
190        if contrast is not None:
191            try:
192                v, dv = inv.get_volume_fraction_with_error(contrast=contrast, 
193                                                           extrapolation=extrapolation)
194                self.volume_tcl.SetValue(format_number(v))
195                self.volume_err_tcl.SetValue(format_number(dv))
196            except:
197                raise
198                msg= "Error occurred computing volume fraction: %s"%sys.exc_value
199                wx.PostEvent(self.parent, StatusEvent(status= msg, type="stop"))
200               
201    def get_surface(self, inv, contrast, porod_const, extrapolation):
202        """
203        """
204        if contrast is not None and porod_const is not None:
205            try:
206                s, ds = inv.get_surface_with_error(contrast=contrast,
207                                        porod_const=porod_const,
208                                        extrapolation=extrapolation)
209                self.surface_tcl.SetValue(format_number(s))
210                self.surface_err_tcl.SetValue(format_number(ds))
211            except:
212                msg= "Error occurred computing specific surface: %s"%sys.exc_value
213                wx.PostEvent(self.parent, StatusEvent(status= msg, type="stop"))
214               
215    def get_total_qstar(self, inv, extrapolation):
216        """
217        """
218        try:
219            qstar_total, qstar_total_err = inv.get_qstar_with_error(extrapolation)
220            self.invariant_total_tcl.SetValue(format_number(qstar_total))
221            self.invariant_total_err_tcl.SetValue(format_number(qstar_total_err))
222            self.inv_container.qstar_total = qstar_total
223            self.inv_container.qstar_total_err = qstar_total_err
224         
225        except:
226            msg= "Error occurred computing invariant using extrapolation: %s"%sys.exc_value
227            wx.PostEvent(self.parent, StatusEvent(status= msg, type="stop")) 
228           
229    def get_low_qstar(self, inv, npts_low, low_q=False):
230        """
231        """
232        if low_q:
233            try: 
234                qstar_low, qstar_low_err = inv.get_qstar_low()
235                self.inv_container.qstar_low = qstar_low
236                self.inv_container.qstar_low_err = qstar_low_err
237                extrapolated_data = inv.get_extra_data_low(npts_in=npts_low) 
238                power_low = inv.get_extrapolation_power(range='low') 
239                if self.power_law_low.GetValue():
240                    self.power_low_tcl.SetValue(str(power_low))
241                self._manager.plot_theory(data=extrapolated_data,
242                                           name="Low-Q extrapolation")
243            except:
244                msg= "Error occurred computing low-Q invariant: %s"%sys.exc_value
245                wx.PostEvent(self.parent, StatusEvent(status= msg, type="stop"))
246        else:
247            self._manager.plot_theory(name="Low-Q extrapolation")
248           
249    def get_high_qstar(self, inv, high_q=False):
250        """
251        """
252        if high_q:
253            try: 
254                qstar_high, qstar_high_err = inv.get_qstar_high()
255                self.inv_container.qstar_high = qstar_high
256                self.inv_container.qstar_high_err = qstar_high_err
257                power_high = inv.get_extrapolation_power(range='high') 
258                self.power_high_tcl.SetValue(str(power_high))
259                high_out_data = inv.get_extra_data_high(q_end=Q_MAXIMUM_PLOT)
260                self._manager.plot_theory(data=high_out_data,
261                                           name="High-Q extrapolation")
262            except:
263                msg= "Error occurred computing high-Q invariant: %s"%sys.exc_value
264                wx.PostEvent(self.parent, StatusEvent(status= msg, type="stop"))
265        else:
266            self._manager.plot_theory(name="High-Q extrapolation")
267           
268    def get_qstar(self, inv):
269        """
270        """
271        qstar, qstar_err = inv.get_qstar_with_error()
272        self.inv_container.qstar = qstar
273        self.inv_container.qstar_err = qstar_err
274             
275    def set_extrapolation_low(self, inv, low_q=False):
276        """
277            @return float value necessary to compute invariant a low q
278        """
279        #get funtion
280        if self.guinier.GetValue():
281            function_low = "guinier"
282        # get the function
283        power_low = None #2.0/3.0
284        if self.power_law_low.GetValue():
285            function_low = "power_law"
286            if self.fit_enable_low.GetValue():
287                #set value of power_low to none to allow fitting
288                power_low = None
289            else:
290                power_low = self.power_low_tcl.GetValue().lstrip().rstrip()
291                if check_float(self.power_low_tcl):
292                    power_low = float(power_low)
293                else:
294                    if low_q :
295                        #Raise error only when qstar at low q is requested
296                        msg = "Expect float for power at low q , got %s"%(power_low)
297                        raise ValueError, msg
298       
299        #Get the number of points to extrapolated
300        npts_low = self.npts_low_tcl.GetValue().lstrip().rstrip()   
301        if check_float(self.npts_low_tcl):
302            npts_low = float(npts_low)
303        else:
304            if low_q:
305                msg = "Expect float for number of points at low q , got %s"%(npts_low)
306                raise ValueError, msg
307        #Set the invariant calculator
308        inv.set_extrapolation(range="low", npts=npts_low,
309                                   function=function_low, power=power_low)   
310        return inv, npts_low 
311       
312    def set_extrapolation_high(self, inv, high_q=False):
313        """
314            @return float value necessary to compute invariant a high q
315        """
316        function_high = "power_law"
317        power_high = None
318        if self.power_law_high.GetValue():
319            function_high = "power_law"
320            if self.fit_enable_high.GetValue():
321                #set value of power_high to none to allow fitting
322                power_high = None
323            else:
324                power_high = self.power_high_tcl.GetValue().lstrip().rstrip()
325                if check_float(self.power_high_tcl):
326                    power_high = float(power_high)
327                else:
328                    if high_q :
329                        #Raise error only when qstar at high q is requested
330                        msg = "Expect float for power at high q , got %s"%(power_high)
331                        raise ValueError, msg
332                         
333        npts_high = self.npts_high_tcl.GetValue().lstrip().rstrip()   
334        if check_float(self.npts_high_tcl):
335            npts_high = float(npts_high)
336        else:
337            if high_q:
338                msg = "Expect float for number of points at high q , got %s"%(npts_high)
339                raise ValueError, msg
340        inv.set_extrapolation(range="high", npts=npts_high,
341                                   function=function_high, power=power_high)
342        return inv, npts_high
343   
344    def display_details(self, event):
345        """
346            open another panel for more details on invariant calculation
347        """
348        #panel = InvariantDetailsWindow(parent=self.parent,
349        #                               qstar_container=self.inv_container)
350        panel = InvariantDetailsPanel(parent=self, 
351                                           qstar_container=self.inv_container)
352        panel.ShowModal()
353        panel.Destroy()
354       
355    def compute_invariant(self, event):
356        """
357            compute invariant
358        """
359        msg= ""
360        wx.PostEvent(self.parent, StatusEvent(status= msg))
361        if self._data is None or self.err_check_on_data():
362            return
363   
364        #clear outputs textctrl
365        self._reset_output()
366        try:
367            background = self.get_background()
368            scale = self.get_scale()
369        except:
370            msg= "Invariant Error: %s"%(sys.exc_value)
371            wx.PostEvent(self.parent, StatusEvent(status= msg, type="stop"))
372            return
373       
374        low_q = self.enable_low_cbox.GetValue()
375        high_q = self.enable_high_cbox.GetValue() 
376        #set invariant calculator
377        inv = invariant.InvariantCalculator(data=self._data,
378                                            background=background,
379                                            scale=scale)
380        try:
381            inv, npts_low = self.set_extrapolation_low(inv=inv, low_q=low_q)
382            inv, npts_high = self.set_extrapolation_high(inv=inv, high_q=high_q)
383        except:
384            raise
385            #msg= "Error occurred computing invariant: %s"%sys.exc_value
386            #wx.PostEvent(self.parent, StatusEvent(status= msg, type="stop"))
387            return
388        #check the type of extrapolation
389        extrapolation = self.get_extrapolation_type(low_q=low_q, high_q=high_q)
390       
391        #Compute invariant
392        try:
393            self.get_qstar(inv=inv)
394        except:
395            msg= "Error occurred computing invariant: %s"%sys.exc_value
396            wx.PostEvent(self.parent, StatusEvent(status= msg, type="stop"))
397            return
398        #Compute qstar extrapolated to low q range
399        self.get_low_qstar(inv=inv, npts_low=npts_low, low_q=low_q)
400        #Compute qstar extrapolated to high q range
401        self.get_high_qstar(inv=inv, high_q=high_q)
402        #Compute qstar extrapolated to total q range and set value to txtcrtl
403        self.get_total_qstar(inv=inv, extrapolation=extrapolation)
404        # Parse additional parameters
405        porod_const = self.get_porod_const()       
406        contrast = self.get_contrast()
407        try:
408            #Compute volume and set value to txtcrtl
409            self.get_volume(inv=inv, contrast=contrast, extrapolation=extrapolation)
410            #compute surface and set value to txtcrtl
411        except:
412            msg= "Error occurred computing invariant: %s"%sys.exc_value
413            wx.PostEvent(self.parent, StatusEvent(status= msg))
414        try:
415            self.get_surface(inv=inv, contrast=contrast, porod_const=porod_const, 
416                                    extrapolation=extrapolation)
417        except:
418            msg= "Error occurred computing invariant: %s"%sys.exc_value
419            wx.PostEvent(self.parent, StatusEvent(status= msg))
420     
421        #enable the button_ok for more details
422        self.button_ok.Enable()
423       
424    def _reset_output(self):
425        """
426            clear outputs textcrtl
427        """
428        self.invariant_total_tcl.Clear()
429        self.invariant_total_err_tcl.Clear()
430        self.volume_tcl.Clear()
431        self.volume_err_tcl.Clear()
432        self.surface_tcl.Clear()
433        self.surface_err_tcl.Clear()
434        #prepare a new container to put result of invariant
435        self.inv_container = InvariantContainer()
436       
437    def _define_structure(self):
438        """
439            Define main sizers needed for this panel
440        """
441        ## Box sizers must be defined first before defining buttons/textctrls (MAC).
442        self.main_sizer = wx.BoxSizer(wx.VERTICAL)
443        #Sizer related to outputs
444        outputs_box = wx.StaticBox(self, -1, "Outputs")
445        self.outputs_sizer = wx.StaticBoxSizer(outputs_box, wx.VERTICAL)
446        self.outputs_sizer.SetMinSize((PANEL_WIDTH,-1))
447        #Sizer related to data
448        data_name_box = wx.StaticBox(self, -1, "I(q) Data Source")
449        self.data_name_boxsizer = wx.StaticBoxSizer(data_name_box, wx.VERTICAL)
450        self.data_name_boxsizer.SetMinSize((PANEL_WIDTH,-1))
451        self.hint_msg_sizer = wx.BoxSizer(wx.HORIZONTAL)
452        self.data_name_sizer = wx.BoxSizer(wx.HORIZONTAL)
453        self.data_range_sizer = wx.BoxSizer(wx.HORIZONTAL)
454        #Sizer related to background
455        self.background_sizer = wx.BoxSizer(wx.HORIZONTAL) 
456        #Sizer related to scale
457        self.scale_sizer = wx.BoxSizer(wx.HORIZONTAL) 
458        #Sizer related to contrast
459        self.contrast_sizer = wx.BoxSizer(wx.HORIZONTAL) 
460        #Sizer related to Porod Constant
461        self.porod_constant_sizer = wx.BoxSizer(wx.HORIZONTAL) 
462        extrapolation_box = wx.StaticBox(self, -1, "Extrapolation")
463        self.extrapolation_sizer = wx.StaticBoxSizer(extrapolation_box,
464                                                        wx.VERTICAL)
465        self.extrapolation_sizer.SetMinSize((PANEL_WIDTH,-1))
466        self.extrapolation_hint_sizer = wx.BoxSizer(wx.HORIZONTAL)
467        self.extrapolation_range_sizer = wx.BoxSizer(wx.HORIZONTAL)
468        self.extrapolation_low_high_sizer = wx.BoxSizer(wx.HORIZONTAL)
469        #Sizer related to extrapolation at low q range
470        low_q_box = wx.StaticBox(self, -1, "Low Q")
471        self.low_extrapolation_sizer = wx.StaticBoxSizer(low_q_box, wx.VERTICAL)
472        self.low_q_sizer = wx.GridBagSizer(5,5)
473        #Sizer related to extrapolation at low q range
474        high_q_box = wx.StaticBox(self, -1, "High Q")
475        self.high_extrapolation_sizer = wx.StaticBoxSizer(high_q_box, wx.VERTICAL)
476        self.high_q_sizer = wx.GridBagSizer(5,5)
477        #sizer to define outputs
478        self.volume_surface_sizer = wx.GridBagSizer(5,5)
479        #Sizer related to invariant output
480        self.invariant_sizer = wx.GridBagSizer(4, 4)
481        #Sizer related to button
482        self.button_sizer = wx.BoxSizer(wx.HORIZONTAL)
483       
484    def _layout_data_name(self):
485        """
486            Draw widgets related to data's name
487        """
488        #Sizer hint
489        hint_msg = "Load Data then right click to add the data on this panel! "
490        hint_msg_txt = wx.StaticText(self, -1, hint_msg) 
491        hint_msg_txt.SetForegroundColour("red")
492        self.hint_msg_sizer.Add(hint_msg_txt)
493        #Data name [string]
494        data_name_txt = wx.StaticText(self, -1, 'Data : ') 
495       
496        self.data_name_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH*5, 20), style=0) 
497        self.data_name_tcl.SetToolTipString("Data's name.")
498        self.data_name_sizer.AddMany([(data_name_txt, 0, wx.LEFT|wx.RIGHT, 10),
499                                       (self.data_name_tcl, 0, wx.EXPAND)])
500        #Data range [string]
501        data_range_txt = wx.StaticText(self, -1, 'Total Q Range (1/A): ') 
502        data_min_txt = wx.StaticText(self, -1, 'Min : ') 
503        self.data_min_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH, 20), style=0)
504        self.data_min_tcl.SetToolTipString("The minimum value of q range.")
505        data_max_txt = wx.StaticText(self, -1, 'Max : ') 
506        self.data_max_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH, 20), style=0) 
507        self.data_max_tcl.SetToolTipString("The maximum value of q range.")
508        self.data_range_sizer.AddMany([(data_range_txt, 0, wx.RIGHT, 10),
509                                       (data_min_txt, 0, wx.RIGHT, 10),
510                                       (self.data_min_tcl, 0, wx.RIGHT, 10),
511                                       (data_max_txt, 0, wx.RIGHT, 10),
512                                       (self.data_max_tcl, 0, wx.RIGHT, 10)])
513        self.data_name_boxsizer.AddMany([(self.hint_msg_sizer, 0 , wx.ALL, 10),
514                                         (self.data_name_sizer, 0 , wx.RIGHT, 10),
515                                         (self.data_range_sizer, 0 , wx.ALL, 10)])
516   
517    def _layout_background(self):
518        """
519            Draw widgets related to background
520        """
521        background_txt = wx.StaticText(self, -1, 'Background : ') 
522        self.background_tcl = InvTextCtrl(self, -1, size=(_BOX_WIDTH, 20), style=0) 
523        self.background_tcl.SetValue(str(BACKGROUND))
524        background_hint_txt = "background"
525        self.background_tcl.SetToolTipString(background_hint_txt)
526        background_unit_txt = wx.StaticText(self, -1, '[1/cm]') 
527        self.background_sizer.AddMany([(background_txt, 0, wx.LEFT|wx.RIGHT, 10),
528                                       (self.background_tcl, 0, wx.RIGHT, 10),
529                                       (background_unit_txt)])
530    def _layout_scale(self):
531        """
532            Draw widgets related to scale
533        """
534        scale_txt = wx.StaticText(self, -1, 'Scale : ') 
535        self.scale_tcl = InvTextCtrl(self, -1, size=(_BOX_WIDTH, 20), style=0)
536        scale_hint_txt = "Scale"
537        self.scale_tcl.SetToolTipString(scale_hint_txt)
538        self.scale_tcl.SetValue(str(SCALE)) 
539        self.scale_sizer.AddMany([(scale_txt, 0, wx.LEFT|wx.RIGHT, 10),
540                                       (self.scale_tcl, 0, wx.LEFT, 30)])
541       
542    def _layout_contrast(self):
543        """
544            Draw widgets related to contrast
545        """
546        contrast_txt = wx.StaticText(self, -1, 'Contrast : ') 
547        self.contrast_tcl = InvTextCtrl(self, -1, size=(_BOX_WIDTH, 20), style=0)
548        self.contrast_tcl.SetValue(str(CONTRAST)) 
549        contrast_hint_txt = "Contrast"
550        self.contrast_tcl.SetToolTipString(contrast_hint_txt)
551        contrast_unit_txt = wx.StaticText(self, -1, '[1/A^(2)]') 
552        self.contrast_sizer.AddMany([(contrast_txt, 0, wx.LEFT|wx.RIGHT, 10),
553                                       (self.contrast_tcl, 0, wx.LEFT, 15),
554                                       (contrast_unit_txt, 0, wx.LEFT, 10)])
555   
556    def _layout_porod_constant(self):
557        """
558            Draw widgets related to porod constant
559        """
560        porod_const_txt = wx.StaticText(self, -1, 'Porod Constant:') 
561        self.porod_constant_tcl = InvTextCtrl(self, -1, 
562                                              size=(_BOX_WIDTH, 20), style=0) 
563        porod_const_hint_txt = "Porod Constant"
564        self.porod_constant_tcl.SetToolTipString(porod_const_hint_txt)
565        optional_txt = wx.StaticText(self, -1, '(Optional)') 
566        self.porod_constant_sizer.AddMany([(porod_const_txt, 0, wx.LEFT, 10),
567                                       (self.porod_constant_tcl, 0, wx.LEFT, 0),
568                                       (optional_txt, 0, wx.LEFT, 10)])
569       
570    def _enable_fit_power_law_low(self, event=None):
571        """
572            Enable and disable the power value editing
573        """
574        if self.fix_enable_low.IsEnabled():
575            if self.fix_enable_low.GetValue():
576                self.power_low_tcl.Enable()
577            else:
578                self.power_low_tcl.Disable()
579           
580    def _enable_low_q_section(self, event=None):
581        """
582            Disable or enable some button if the user enable low q extrapolation
583        """
584        if self.enable_low_cbox.GetValue():
585            self.npts_low_tcl.Enable()
586            self.fix_enable_low.Enable()
587            self.fit_enable_low.Enable()
588            self.guinier.Enable()
589            self.power_law_low.Enable()
590
591        else:
592            self.npts_low_tcl.Disable()
593            self.fix_enable_low.Disable()
594            self.fit_enable_low.Disable()
595            self.guinier.Disable()
596            self.power_law_low.Disable()
597        self._enable_power_law_low()
598        self._enable_fit_power_law_low()
599   
600    def _enable_power_law_low(self, event=None):
601        """
602            Enable editing power law section at low q range
603        """
604        if self.guinier.GetValue():
605            self.fix_enable_low.Disable()
606            self.fit_enable_low.Disable()
607            self.power_low_tcl.Disable()
608        else:
609            self.fix_enable_low.Enable()
610            self.fit_enable_low.Enable()
611            self.power_low_tcl.Enable()
612        self._enable_fit_power_law_low()
613           
614    def _layout_extrapolation_low(self):
615        """
616            Draw widgets related to extrapolation at low q range
617        """
618        self.enable_low_cbox = wx.CheckBox(self, -1, "Enable Extrapolate Low Q")
619        self.enable_low_cbox.SetForegroundColour('red')
620        self.enable_low_cbox.SetValue(False)
621        wx.EVT_CHECKBOX(self, self.enable_low_cbox.GetId(),
622                                         self._enable_low_q_section)
623        self.fix_enable_low = wx.RadioButton(self, -1, 'Fix',
624                                         (10, 10),style=wx.RB_GROUP)
625        self.fix_enable_low.SetValue(True)
626        self.fit_enable_low = wx.RadioButton(self, -1, 'Fit', (10, 10))
627        self.Bind(wx.EVT_RADIOBUTTON, self._enable_fit_power_law_low,
628                                     id=self.fix_enable_low.GetId())
629        self.Bind(wx.EVT_RADIOBUTTON, self._enable_fit_power_law_low, 
630                                        id=self.fit_enable_low.GetId())
631        self.guinier = wx.RadioButton(self, -1, 'Guinier',
632                                         (10, 10),style=wx.RB_GROUP)
633        self.guinier.SetValue(True)
634        self.power_law_low = wx.RadioButton(self, -1, 'Power Law', (10, 10))
635        self.Bind(wx.EVT_RADIOBUTTON, self._enable_power_law_low,
636                                     id=self.guinier.GetId())
637        self.Bind(wx.EVT_RADIOBUTTON, self._enable_power_law_low, 
638                                        id=self.power_law_low.GetId())
639       
640        npts_low_txt = wx.StaticText(self, -1, 'Npts')
641        self.npts_low_tcl = InvTextCtrl(self, -1, size=(_BOX_WIDTH*2/3, -1))
642        self.npts_low_tcl.SetValue(str(NPTS))
643        msg_hint = "Number of Q points to consider"
644        msg_hint +="while extrapolating the low-Q region"
645        self.npts_low_tcl.SetToolTipString(msg_hint)
646        power_txt = wx.StaticText(self, -1, 'Power')
647        self.power_low_tcl = InvTextCtrl(self, -1, size=(_BOX_WIDTH*2/3, -1))
648        self.power_low_tcl.SetValue(str(self.power_law_exponant))
649        self.power_low_tcl.Disable()
650        power_hint_txt = "Exponent to apply to the Power_law function."
651        self.power_low_tcl.SetToolTipString(power_hint_txt)
652        iy = 0
653        ix = 0
654        self.low_q_sizer.Add(self.enable_low_cbox,(iy, ix),(1,5),
655                            wx.TOP|wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
656        iy += 1
657        ix = 0
658        self.low_q_sizer.Add(npts_low_txt,(iy, ix),(1,1),
659                            wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
660        ix += 1
661        self.low_q_sizer.Add(self.npts_low_tcl, (iy, ix), (1,1),
662                            wx.EXPAND|wx.ADJUST_MINSIZE, 0)
663        iy += 1
664        ix = 0
665        self.low_q_sizer.Add(self.guinier,(iy, ix),(1,2),
666                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
667        iy += 1
668        ix = 0
669        self.low_q_sizer.Add(self.power_law_low,(iy, ix),(1,2),
670                            wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
671       
672        # Parameter controls for power law
673        ix = 1
674        iy += 1
675        self.low_q_sizer.Add(self.fix_enable_low,(iy, ix),(1,1),
676                            wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
677        ix += 1
678        self.low_q_sizer.Add(self.fit_enable_low,(iy, ix),(1,1),
679                           wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
680        ix = 1
681        iy += 1
682        self.low_q_sizer.Add(power_txt,(iy, ix),(1,1),
683                            wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
684        ix += 1
685        self.low_q_sizer.Add(self.power_low_tcl, (iy, ix), (1,1),
686                            wx.EXPAND|wx.ADJUST_MINSIZE, 0)
687        #Change the state of txtcrtl to enable/disable
688        self._enable_low_q_section()
689        self.low_extrapolation_sizer.AddMany([(self.low_q_sizer, 0,
690                                                wx.BOTTOM|wx.RIGHT, 10)])
691    def _enable_fit_power_law_high(self, event=None):
692        """
693            Enable and disable the power value editing
694        """
695        if self.fix_enable_high.IsEnabled():
696            if self.fix_enable_high.GetValue():
697                self.power_high_tcl.Enable()
698            else:
699                self.power_high_tcl.Disable()
700       
701    def _enable_high_q_section(self, event=None):
702        """
703            Disable or enable some button if the user enable high q extrapolation
704        """
705        if self.enable_high_cbox.GetValue():
706            self.npts_high_tcl.Enable()
707            self.power_law_high.Enable()
708            self.power_high_tcl.Enable()
709            self.fix_enable_high.Enable()
710            self.fit_enable_high.Enable()
711        else:
712            self.npts_high_tcl.Disable()
713            self.power_law_high.Disable()
714            self.power_high_tcl.Disable()
715            self.fix_enable_high.Disable()
716            self.fit_enable_high.Disable()
717        self._enable_fit_power_law_high()
718 
719    def _layout_extrapolation_high(self):
720        """
721            Draw widgets related to extrapolation at high q range
722        """
723        self.enable_high_cbox = wx.CheckBox(self, -1, "Enable Extrapolate high-Q")
724        self.enable_high_cbox.SetForegroundColour('red')
725        self.enable_high_cbox.SetValue(False)
726        wx.EVT_CHECKBOX(self, self.enable_high_cbox.GetId(),
727                                         self._enable_high_q_section)
728     
729        self.fix_enable_high = wx.RadioButton(self, -1, 'Fix',
730                                         (10, 10),style=wx.RB_GROUP)
731        self.fix_enable_high.SetValue(True)
732        self.fit_enable_high = wx.RadioButton(self, -1, 'Fit', (10, 10))
733        self.Bind(wx.EVT_RADIOBUTTON, self._enable_fit_power_law_high,
734                                     id=self.fix_enable_high.GetId())
735        self.Bind(wx.EVT_RADIOBUTTON, self._enable_fit_power_law_high, 
736                                        id=self.fit_enable_high.GetId())
737       
738        self.power_law_high = wx.RadioButton(self, -1, 'Power Law',
739                                              (10, 10), style=wx.RB_GROUP)
740        msg_hint ="Check to extrapolate data at high-Q"
741        self.power_law_high.SetToolTipString(msg_hint)
742        self.power_law_high.SetValue(True)
743        npts_high_txt = wx.StaticText(self, -1, 'Npts')
744        self.npts_high_tcl = InvTextCtrl(self, -1, size=(_BOX_WIDTH*2/3, -1))
745        msg_hint = "Number of Q points to consider"
746        msg_hint += "while extrapolating the high-Q region"
747        self.npts_high_tcl.SetToolTipString(msg_hint)
748        self.npts_high_tcl.SetValue(str(NPTS))
749        power_txt = wx.StaticText(self, -1, 'Power')
750        self.power_high_tcl = InvTextCtrl(self, -1, size=(_BOX_WIDTH*2/3, -1))
751        self.power_high_tcl.SetValue(str(self.power_law_exponant))
752        power_hint_txt = "Exponent to apply to the Power_law function."
753        self.power_high_tcl.SetToolTipString(power_hint_txt)
754        iy = 0
755        ix = 0
756        self.high_q_sizer.Add(self.enable_high_cbox,(iy, ix),(1,5),
757                            wx.TOP|wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
758        iy += 1
759        ix = 0
760        self.high_q_sizer.Add(npts_high_txt,(iy, ix),(1,1),
761                            wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
762        ix += 1
763        self.high_q_sizer.Add(self.npts_high_tcl, (iy, ix), (1,1),
764                            wx.EXPAND|wx.ADJUST_MINSIZE, 0)
765        iy += 2
766        ix = 0
767        self.high_q_sizer.Add(self.power_law_high,(iy, ix),(1,2),
768                            wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
769       
770        # Parameter controls for power law
771        ix = 1
772        iy += 1
773        self.high_q_sizer.Add(self.fix_enable_high,(iy, ix),(1,1),
774                            wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
775        ix += 1
776        self.high_q_sizer.Add(self.fit_enable_high,(iy, ix),(1,1),
777                           wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
778        ix = 1
779        iy += 1
780        self.high_q_sizer.Add(power_txt,(iy, ix),(1,1),
781                            wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
782        ix += 1
783        self.high_q_sizer.Add(self.power_high_tcl, (iy, ix), (1,1),
784                            wx.EXPAND|wx.ADJUST_MINSIZE, 0)
785        #Change the state of txtcrtl to enable/disable
786        self._enable_high_q_section()
787        self.high_extrapolation_sizer.AddMany([(self.high_q_sizer, 0, wx.RIGHT, 10)])
788       
789    def _layout_extrapolation(self):
790        """
791            Draw widgets related to extrapolation
792        """
793        extra_hint = "Extrapolation Maximum Q Range [1/A]: "
794        extra_hint_txt = wx.StaticText(self, -1, extra_hint)
795        #Extrapolation range [string]
796        extrapolation_min_txt = wx.StaticText(self, -1, 'Min : ') 
797        self.extrapolation_min_tcl = OutputTextCtrl(self, -1, 
798                                                size=(_BOX_WIDTH, 20), style=0)
799        self.extrapolation_min_tcl.SetValue(str(Q_MINIMUM))
800        self.extrapolation_min_tcl.SetToolTipString("The minimum extrapolated q value.")
801        extrapolation_max_txt = wx.StaticText(self, -1, 'Max : ') 
802        self.extrapolation_max_tcl = OutputTextCtrl(self, -1,
803                                                  size=(_BOX_WIDTH, 20), style=0) 
804        self.extrapolation_max_tcl.SetValue(str(Q_MAXIMUM))
805        self.extrapolation_max_tcl.SetToolTipString("The maximum extrapolated q value.")
806        self.extrapolation_range_sizer.AddMany([(extra_hint_txt, 0, wx.LEFT, 10),
807                                                (extrapolation_min_txt, 0, wx.LEFT, 10),
808                                                (self.extrapolation_min_tcl,
809                                                            0, wx.LEFT, 10),
810                                                (extrapolation_max_txt, 0, wx.LEFT, 10),
811                                                (self.extrapolation_max_tcl,
812                                                            0, wx.LEFT, 10),
813                                                ])
814        extra_enable_hint = "Hint: Check any box to enable a specific extrapolation !"
815        extra_enable_hint_txt = wx.StaticText(self, -1, extra_enable_hint )
816        self.extrapolation_hint_sizer.AddMany([(extra_enable_hint_txt, 0, wx.LEFT, 0)
817                                               ])
818        self._layout_extrapolation_low()
819        self._layout_extrapolation_high()
820        self.extrapolation_low_high_sizer.AddMany([(self.low_extrapolation_sizer,
821                                                     0, wx.ALL, 10),
822                                                   (self.high_extrapolation_sizer,
823                                                    0, wx.ALL, 10)])
824        self.extrapolation_sizer.AddMany([(self.extrapolation_range_sizer, 0,
825                                            wx.RIGHT, 10),
826                                         (self.extrapolation_hint_sizer, 0,
827                                           wx.ALL, 10),
828                                        (self.extrapolation_low_high_sizer, 0,
829                                           wx.ALL, 10)])
830       
831    def _layout_volume_surface_sizer(self):
832        """
833            Draw widgets related to volume and surface
834        """
835        unit_volume = ''
836        unit_surface = ''
837        uncertainty = "+/-" 
838        volume_txt = wx.StaticText(self, -1, 'Volume Fraction')
839        self.volume_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH,-1))
840        self.volume_tcl.SetToolTipString("Volume fraction.")
841        self.volume_err_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH,-1))
842        self.volume_err_tcl.SetToolTipString("Uncertainty on the volume fraction.")
843        volume_units_txt = wx.StaticText(self, -1, unit_volume)
844       
845        surface_txt = wx.StaticText(self, -1, 'Specific surface')
846        self.surface_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH,-1))
847        self.surface_tcl.SetToolTipString("Specific surface value.")
848        self.surface_err_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH,-1))
849        self.surface_err_tcl.SetToolTipString("Uncertainty on the specific surface.")
850        surface_units_txt = wx.StaticText(self, -1, unit_surface)
851        iy = 0
852        ix = 0
853        self.volume_surface_sizer.Add(volume_txt, (iy, ix), (1,1),
854                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
855        ix += 1
856        self.volume_surface_sizer.Add(self.volume_tcl, (iy, ix), (1,1),
857                            wx.EXPAND|wx.ADJUST_MINSIZE, 10)
858        ix += 1
859        self.volume_surface_sizer.Add(wx.StaticText(self, -1, uncertainty),
860                         (iy, ix),(1,1),wx.EXPAND|wx.ADJUST_MINSIZE, 10) 
861        ix += 1
862        self.volume_surface_sizer.Add(self.volume_err_tcl, (iy, ix), (1,1),
863                            wx.EXPAND|wx.ADJUST_MINSIZE, 10) 
864        ix += 1
865        self.volume_surface_sizer.Add(volume_units_txt, (iy, ix), (1,1),
866                             wx.EXPAND|wx.ADJUST_MINSIZE, 10)
867        iy += 1
868        ix = 0
869        self.volume_surface_sizer.Add(surface_txt, (iy, ix), (1,1),
870                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
871        ix += 1
872        self.volume_surface_sizer.Add(self.surface_tcl, (iy, ix), (1,1),
873                            wx.EXPAND|wx.ADJUST_MINSIZE, 0)
874        ix += 1
875        self.volume_surface_sizer.Add(wx.StaticText(self, -1, uncertainty),
876                         (iy, ix),(1,1),wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
877        ix += 1
878        self.volume_surface_sizer.Add(self.surface_err_tcl, (iy, ix), (1,1),
879                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
880        ix += 1
881        self.volume_surface_sizer.Add(surface_units_txt, (iy, ix), (1,1),
882                            wx.EXPAND|wx.ADJUST_MINSIZE, 10)
883       
884    def _layout_invariant_sizer(self):
885        """
886            Draw widgets related to invariant
887        """
888        uncertainty = "+/-" 
889        unit_invariant = '[1/cm][1/A]'
890        invariant_total_txt = wx.StaticText(self, -1, 'Invariant Total')
891        self.invariant_total_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH,-1))
892        msg_hint = "Total invariant, including extrapolated regions."
893        self.invariant_total_tcl.SetToolTipString(msg_hint)
894        self.invariant_total_err_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH,-1))
895        self.invariant_total_err_tcl.SetToolTipString("Uncertainty on invariant.")
896        invariant_total_units_txt = wx.StaticText(self, -1, unit_invariant)
897   
898        #Invariant total
899        iy = 0
900        ix = 0
901        self.invariant_sizer.Add(invariant_total_txt, (iy, ix), (1,1),
902                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
903        ix += 1
904        self.invariant_sizer.Add(self.invariant_total_tcl, (iy, ix), (1,1),
905                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
906        ix += 1
907        self.invariant_sizer.Add( wx.StaticText(self, -1, uncertainty),
908                         (iy, ix),(1,1),wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
909        ix += 1
910        self.invariant_sizer.Add(self.invariant_total_err_tcl, (iy, ix), (1,1),
911                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
912        ix += 1
913        self.invariant_sizer.Add(invariant_total_units_txt
914                         ,(iy, ix),(1,1),wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
915 
916    def _layout_outputs_sizer(self):
917        """
918            Draw widgets related to outputs
919        """
920        self._layout_volume_surface_sizer()
921        self._layout_invariant_sizer()
922        static_line = wx.StaticLine(self, -1)
923        self.outputs_sizer.AddMany([(self.volume_surface_sizer, 0, wx.ALL, 10),
924                                    (static_line, 0, wx.EXPAND, 0),
925                                    (self.invariant_sizer, 0, wx.ALL, 10)])
926    def _layout_button(self): 
927        """
928            Do the layout for the button widgets
929        """ 
930        #compute button
931        id = wx.NewId()
932        button_calculate = wx.Button(self, id, "Compute")
933        button_calculate.SetToolTipString("Compute invariant")
934        self.Bind(wx.EVT_BUTTON, self.compute_invariant, id=id)   
935        #detail button
936        id = wx.NewId()
937        self.button_ok = wx.Button(self, id, "Details?")
938        self.button_ok.SetToolTipString("Give Details on Computation")
939        self.Bind(wx.EVT_BUTTON, self.display_details, id=id)
940        self.button_ok.Disable()
941        details = "Details on Invariant Total Calculations"
942        details_txt = wx.StaticText(self, -1, details)
943        self.button_sizer.AddMany([((20,20), 0 , wx.LEFT, 100),
944                                   (details_txt, 0 , wx.ALL, 10),
945                                   (self.button_ok, 0 , wx.ALL, 10),
946                        (button_calculate, 0 , wx.RIGHT|wx.TOP|wx.BOTTOM, 10)])
947       
948    def _do_layout(self):
949        """
950            Draw window content
951        """
952        self._define_structure()
953        self._layout_data_name()
954        self._layout_background()
955        self._layout_scale()
956        self._layout_contrast()
957        self._layout_porod_constant()
958        self._layout_extrapolation()
959        self._layout_outputs_sizer()
960        self._layout_button()
961        self.main_sizer.AddMany([(self.data_name_boxsizer, 0, wx.ALL, 10),
962                                 (self.background_sizer, 0,
963                                   wx.LEFT|wx.RIGHT|wx.BOTTOM, 10),
964                                 (self.scale_sizer, 0,
965                                   wx.LEFT|wx.RIGHT|wx.BOTTOM, 10),
966                                 (self.contrast_sizer, 0,
967                                  wx.LEFT|wx.RIGHT|wx.BOTTOM, 10),
968                                  (self.porod_constant_sizer, 0,
969                                  wx.LEFT|wx.RIGHT|wx.BOTTOM, 10),
970                                  (self.extrapolation_sizer, 0,
971                                  wx.LEFT|wx.RIGHT|wx.BOTTOM, 10),
972                                  (self.outputs_sizer, 0,
973                                  wx.LEFT|wx.RIGHT|wx.BOTTOM, 10),
974                                  (self.button_sizer, 0,
975                                  wx.LEFT|wx.RIGHT|wx.BOTTOM, 10)])
976        self.SetSizer(self.main_sizer)
977        self.SetScrollbars(20,20,25,65)
978        self.SetAutoLayout(True)
979   
980class InvariantDialog(wx.Dialog):
981    def __init__(self, parent=None, id=1,graph=None,
982                 data=None, title="Invariant",base=None):
983        wx.Dialog.__init__(self, parent, id, title, size=(PANEL_WIDTH,
984                                                             PANEL_HEIGHT))
985        self.panel = InvariantPanel(self)
986        self.Centre()
987        self.Show(True)
988       
989class InvariantWindow(wx.Frame):
990    def __init__(self, parent=None, id=1,graph=None, 
991                 data=None, title="Invariant",base=None):
992       
993        wx.Frame.__init__(self, parent, id, title, size=(PANEL_WIDTH +100,
994                                                             PANEL_HEIGHT+100))
995       
996        self.panel = InvariantPanel(self)
997        self.Centre()
998        self.Show(True)
999       
1000class MyApp(wx.App):
1001    def OnInit(self):
1002        wx.InitAllImageHandlers()
1003        frame = InvariantWindow()
1004        frame.Show(True)
1005        self.SetTopWindow(frame)
1006       
1007        return True
1008     
1009# end of class MyApp
1010
1011if __name__ == "__main__":
1012    app = MyApp(0)
1013    app.MainLoop()
Note: See TracBrowser for help on using the repository browser.