source: sasview/invariantview/perspectives/invariant/invariant_details.py @ a618972

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

change panel according to feedback

  • Property mode set to 100644
File size: 18.7 KB
Line 
1
2import wx
3import sys
4import colorsys
5import numpy
6from sans.guiframe.utils import format_number, check_float
7from invariant_widgets import OutputTextCtrl
8# Dimensions related to chart
9RECTANGLE_WIDTH  = 400.0 
10RECTANGLE_HEIGHT = 20
11#Invariant panel size
12_BOX_WIDTH = 76
13
14#scale to use for a bar of value zero
15RECTANGLE_SCALE  = 0.0001
16DEFAULT_QSTAR = 1.0 
17 
18if sys.platform.count("win32")>0:
19    _STATICBOX_WIDTH = 450
20    PANEL_WIDTH = 500
21    PANEL_HEIGHT = 430
22    FONT_VARIANT = 0
23else:
24    _STATICBOX_WIDTH = 480
25    PANEL_WIDTH = 530
26    PANEL_HEIGHT = 430
27    FONT_VARIANT = 1
28   
29 
30   
31class InvariantContainer(wx.Object):
32    def __init__(self):
33        #invariant at low range
34        self.qstar_low = 0.0
35        #invariant at low range error
36        self.qstar_low_err = 0.0
37        #invariant
38        self.qstar = 0.0
39        #invariant error
40        self.qstar_err = 0.0
41        #invariant at high range
42        self.qstar_high = 0.0
43        #invariant at high range error
44        self.qstar_high_err = 0.0
45        #invariant total
46        self.qstar_total = None
47        #invariant error
48        self.qstar_total_err = None
49        #scale
50        self.qstar_low_percent = 0.0
51        self.qstar_high_percent = 0.0
52        self.qstar_percent = 0.0
53        # warning message
54        self.existing_warning = False
55        self.warning_msg = "No Details on calculations available...\n"
56       
57    def compute_percentage(self):
58        """
59            Compute percentage of each invariant
60        """
61        if self.qstar_total is not None and self.qstar_total != 0:
62            #compute invariant percentage
63            if self.qstar is None:
64                self.qstar = 0.0
65            self.qstar_percent = self.qstar/self.qstar_total
66            #compute low q invariant percentage
67            if self.qstar_low is None:
68                self.qstar_low = 0.0
69            self.qstar_low_percent = self.qstar_low/self.qstar_total
70            #compute high q invariant percentage
71            if self.qstar_high is None:
72                self.qstar_high = 0.0
73            self.qstar_high_percent = self.qstar_high/self.qstar_total
74        self.check_values()
75   
76    def check_values(self):
77        """
78            check the validity if invariant
79        """
80        #warning to the user when the extrapolated invariant is greater than %5
81        if self.qstar_low_percent >= 0.05:
82            self.existing_warning = True
83            self.warning_msg += "Extrapolated contribution at Low Q is higher "
84            self.warning_msg += "than 5% of the invariant.\n"
85        if self.qstar_high_percent >= 0.05:
86            self.existing_warning = True
87            self.warning_msg += "Extrapolated contribution at High Q is higher "
88            self.warning_msg += "than 5% of the invariant.\n"
89        if self.qstar_low_percent + self.qstar_high_percent >= 0.05:
90            self.existing_warning = True
91            self.warning_msg += "The sum of all extrapolated contributions is higher "
92            self.warning_msg += "than 5% of the invariant.\n"
93           
94        if self.existing_warning:
95            self.warning_msg += "The calculations are likely to be unreliable!\n"
96        else:
97            self.warning_msg = "No Details on calculations available...\n"
98           
99class InvariantDetailsPanel(wx.Dialog):
100    """
101        This panel describes proportion of invariants
102    """
103    def __init__(self, parent=None, id=-1, qstar_container=None, title="",
104                 size=(PANEL_WIDTH, PANEL_HEIGHT)):
105        wx.Dialog.__init__(self, parent, id=id, title=title, size=size)
106       
107        #Font size
108        self.SetWindowVariant(variant=FONT_VARIANT)
109        self.parent = parent
110        #self.qstar_container
111        self.qstar_container = qstar_container
112        #warning message
113        self.warning_msg = self.qstar_container.warning_msg
114   
115        #Define scale of each bar
116        self.low_inv_percent = self.qstar_container.qstar_low_percent
117        self.low_scale = self.get_scale(percentage=self.low_inv_percent,
118                                         scale_name="Extrapolated at Low Q")
119        self.inv_percent = self.qstar_container.qstar_percent
120        self.inv_scale = self.get_scale(percentage=self.inv_percent, 
121                                            scale_name="Inv in Q range")
122        self.high_inv_percent = self.qstar_container.qstar_high_percent
123        self.high_scale = self.get_scale(percentage=self.high_inv_percent,
124                                         scale_name="Extrapolated at High Q")
125       
126        #Default color the extrapolation bar is grey
127        self.extrapolation_color_low = wx.Colour(169,  169, 168, 128)
128        self.extrapolation_color_high = wx.Colour(169,  169, 168, 128)
129        #change color of high and low bar when necessary
130        self.set_color_bar()
131        #draw the panel itself
132        self._do_layout()
133        self.set_values()
134   
135    def _define_structure(self):
136        """
137            Define main sizers needed for this panel
138        """
139        #Box sizers must be defined first before defining buttons/textctrls (MAC).
140        self.main_sizer = wx.BoxSizer(wx.VERTICAL)
141        #Sizer related to chart
142        chart_box = wx.StaticBox(self, -1, "Invariant Chart")
143        self.chart_sizer = wx.StaticBoxSizer(chart_box, wx.VERTICAL)
144        self.chart_sizer.SetMinSize((PANEL_WIDTH - 50,100))
145        #Sizer related to invariant values
146        self.invariant_sizer =  wx.GridBagSizer(4, 4)
147        invariant_box = wx.StaticBox(self, -1, "Numerical Values")
148        self.invariant_box_sizer = wx.StaticBoxSizer(invariant_box,
149                                                      wx.HORIZONTAL)
150
151        self.invariant_box_sizer.SetMinSize((PANEL_WIDTH - 50,-1))
152        #Sizer related to warning message
153        warning_box = wx.StaticBox(self, -1, "Warning")
154        self.warning_sizer = wx.StaticBoxSizer(warning_box, wx.VERTICAL)
155        self.warning_sizer.SetMinSize((PANEL_WIDTH-50,-1))
156        #Sizer related to button
157        self.button_sizer = wx.BoxSizer(wx.HORIZONTAL)
158     
159    def _layout_shart(self):
160        """
161            Draw widgets related to chart
162        """
163        self.panel_chart = wx.Panel(self)
164        self.panel_chart.Bind(wx.EVT_PAINT, self.on_paint)
165        self.chart_sizer.Add(self.panel_chart, 1, wx.EXPAND|wx.ALL, 0)
166       
167    def _layout_invariant(self):
168        """
169            Draw widgets related to invariant
170        """
171        uncertainty = "+/-" 
172        unit_invariant = '[1/(cm * A)]'
173     
174        invariant_txt = wx.StaticText(self, -1, 'Invariant')
175        self.invariant_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH,-1))
176        self.invariant_tcl.SetToolTipString("Invariant in the data set's Q range.")
177        self.invariant_err_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH,-1))
178        self.invariant_err_tcl.SetToolTipString("Uncertainty on the invariant.")
179        invariant_units_txt = wx.StaticText(self, -1, unit_invariant)
180       
181        invariant_low_txt = wx.StaticText(self, -1, 'Invariant in low-Q region')
182        self.invariant_low_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH,-1))
183        self.invariant_low_tcl.SetToolTipString("Invariant computed with the extrapolated low-Q data.")
184        self.invariant_low_err_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH,-1))
185        self.invariant_low_err_tcl.SetToolTipString("Uncertainty on the invariant.")
186        invariant_low_units_txt = wx.StaticText(self, -1,  unit_invariant)
187       
188        invariant_high_txt = wx.StaticText(self, -1, 'Invariant in high-Q region')
189        self.invariant_high_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH,-1))
190        self.invariant_high_tcl.SetToolTipString("Invariant computed with the extrapolated high-Q data")
191        self.invariant_high_err_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH,-1))
192        self.invariant_high_err_tcl.SetToolTipString("Uncertainty on the invariant.")
193        invariant_high_units_txt = wx.StaticText(self, -1,  unit_invariant)
194   
195        #Invariant low
196        iy = 0
197        ix = 0 
198        self.invariant_sizer.Add(invariant_low_txt, (iy, ix), (1,1),
199                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
200        ix += 1
201        self.invariant_sizer.Add(self.invariant_low_tcl, (iy, ix), (1,1),
202                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
203        ix += 1
204        self.invariant_sizer.Add( wx.StaticText(self, -1, uncertainty),
205                         (iy, ix),(1,1),wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
206        ix += 1
207        self.invariant_sizer.Add(self.invariant_low_err_tcl, (iy, ix), (1,1),
208                            wx.EXPAND|wx.ADJUST_MINSIZE, 0)
209        ix += 1
210        self.invariant_sizer.Add(invariant_low_units_txt
211                         ,(iy, ix),(1,1),wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
212        #Invariant
213        iy += 1
214        ix = 0 
215        self.invariant_sizer.Add(invariant_txt, (iy, ix), (1,1),
216                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
217        ix += 1
218        self.invariant_sizer.Add(self.invariant_tcl, (iy, ix), (1,1),
219                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
220        ix += 1
221        self.invariant_sizer.Add(wx.StaticText(self, -1, uncertainty),
222                         (iy, ix),(1,1),wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
223        ix += 1
224        self.invariant_sizer.Add(self.invariant_err_tcl, (iy, ix), (1,1),
225                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
226        ix +=1
227        self.invariant_sizer.Add(invariant_units_txt
228                         ,(iy, ix),(1,1),wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
229        #Invariant high
230        iy += 1
231        ix = 0 
232        self.invariant_sizer.Add(invariant_high_txt, (iy, ix), (1,1),
233                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
234        ix += 1
235        self.invariant_sizer.Add(self.invariant_high_tcl, (iy, ix), (1,1),
236                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
237        ix += 1
238        self.invariant_sizer.Add(wx.StaticText(self, -1, uncertainty),
239                         (iy, ix),(1,1),wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
240        ix += 1
241        self.invariant_sizer.Add(self.invariant_high_err_tcl, (iy, ix), (1,1),
242                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
243        ix += 1
244        self.invariant_sizer.Add(invariant_high_units_txt
245                         ,(iy, ix),(1,1),wx.EXPAND|wx.ADJUST_MINSIZE, 0)
246        self.invariant_box_sizer.Add(self.invariant_sizer, 0, wx.TOP|wx.BOTTOM, 10) 
247       
248    def _layout_warning(self):
249        """
250            Draw widgets related to warning
251        """
252        #Warning [string]
253        self.warning_msg_txt = wx.StaticText(self, -1,self.warning_msg) 
254        if self.qstar_container.existing_warning:
255            self.warning_msg_txt.SetForegroundColour('red') 
256        self.warning_sizer.AddMany([(self.warning_msg_txt, 0,
257                                     wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 10)])
258       
259    def _layout_button(self):
260        """
261            Draw widgets related to button
262        """
263        #Close button
264        id = wx.NewId()
265        button_ok = wx.Button(self, id, "Ok")
266        button_ok.SetToolTipString("Give Details on Computation")
267        self.Bind(wx.EVT_BUTTON, self.on_close, id=id)
268        self.button_sizer.AddMany([((20,20), 0 , wx.LEFT, 350),
269                                   (button_ok, 0 , wx.RIGHT, 10)])
270    def _do_layout(self):
271        """
272            Draw window content
273        """
274        self._define_structure()
275        self._layout_shart()
276        self._layout_invariant()
277        self._layout_warning()
278        self._layout_button()
279        self.main_sizer.AddMany([(self.chart_sizer, 0, wx.ALL, 10),
280                                 ( self.invariant_box_sizer, 0, wx.ALL, 10),
281                                  (self.warning_sizer, 0, wx.ALL, 10),
282                                  (self.button_sizer, 0, wx.ALL, 10)])
283        self.SetSizer(self.main_sizer)
284       
285       
286    def set_values(self):
287        """
288            Set value of txtcrtl
289        """
290        self.invariant_tcl.SetValue(format_number(self.qstar_container.qstar))
291        self.invariant_err_tcl.SetValue(format_number(self.qstar_container.qstar_err)) 
292        self.invariant_low_tcl.SetValue(format_number(self.qstar_container.qstar_low))
293        self.invariant_low_err_tcl.SetValue(format_number(self.qstar_container.qstar_low_err)) 
294        self.invariant_high_tcl.SetValue(format_number(self.qstar_container.qstar_high))
295        self.invariant_high_err_tcl.SetValue(format_number(self.qstar_container.qstar_high_err)) 
296
297    def get_scale(self, percentage, scale_name='scale'):
298        """
299            Check scale receive in this panel.
300        """
301        try: 
302            if percentage is None or percentage == 0.0:
303                 percentage = RECTANGLE_SCALE
304            percentage = float(percentage) 
305        except:
306            percentage = RECTANGLE_SCALE
307            self.warning_msg += "Receive an invalid scale for %s\n"
308            self.warning_msg += "check this value : %s\n"%(str(scale_name),str(percentage))
309        return  percentage
310   
311    def set_color_bar(self):
312        """
313            Change the color for low and high bar when necessary
314        """
315        #warning to the user when the extrapolated invariant is greater than %5
316        if self.low_scale >= 0.05:
317            self.extrapolation_color_low = wx.Colour(255,  0, 0, 128)
318        if self.high_scale >= 0.05:
319            self.extrapolation_color_high = wx.Colour(255,  0, 0, 128)
320           
321    def on_close(self, event):
322        """
323            Close the current window
324        """
325        self.Close()
326     
327    def on_paint(self, event):
328        """
329            Draw the chart
330        """
331        dc = wx.PaintDC(self.panel_chart)
332        try:
333            gc = wx.GraphicsContext.Create(dc)
334        except NotImplementedError:
335            dc.DrawText("This build of wxPython does not support the wx.GraphicsContext "
336                        "family of classes.", 25, 25)
337            return
338        #Start the drawing
339        font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
340        font.SetWeight(wx.BOLD)
341        gc.SetFont(font)
342        # Draw a rectangle
343        path = gc.CreatePath()
344        path.AddRectangle(-RECTANGLE_WIDTH/2,-RECTANGLE_HEIGHT/2,
345                          RECTANGLE_WIDTH/2,RECTANGLE_HEIGHT/2)
346        x_origine = 20
347        y_origine = 15
348        #Draw low rectangle
349        gc.PushState()       
350        label = "Q* At Low-Q"
351        PathFunc = gc.DrawPath
352        w, h = gc.GetTextExtent(label)
353        gc.DrawText(label, x_origine, y_origine)
354        #Translate the rectangle
355        x_center = x_origine + RECTANGLE_WIDTH * self.low_scale/2 + w +10
356        y_center = y_origine + h
357        gc.Translate(x_center, y_center)   
358        gc.SetPen(wx.Pen("black", 1))
359        gc.SetBrush(wx.Brush(self.extrapolation_color_low))
360        low_percent = format_number(self.low_inv_percent*100)+ '%'
361        x_center = 20
362        y_center = -h
363        gc.DrawText(low_percent, x_center, y_center)
364        # Increase width by self.low_scale
365        gc.Scale(self.low_scale, 1.0) 
366        PathFunc(path)
367        gc.PopState() 
368        #Draw rectangle for invariant   
369        gc.PushState()    # save it again
370        y_origine += 20         
371        gc.DrawText("Q* In range", x_origine, y_origine)
372        # offset to the lower part of the window
373        x_center = x_origine + RECTANGLE_WIDTH * self.inv_scale/2 + w + 10
374        y_center = y_origine + h
375        gc.Translate(x_center, y_center)
376        # 128 == half transparent
377        gc.SetBrush(wx.Brush(wx.Colour(67,  208,  128, 128))) 
378        # Increase width by self.inv_scale
379        inv_percent = format_number(self.inv_percent*100)+ '%'
380        x_center = 20 
381        y_center = -h
382        gc.DrawText(inv_percent, x_center, y_center)
383        gc.Scale(self.inv_scale, 1.0)   
384        gc.DrawPath(path)
385        gc.PopState()
386        # restore saved state
387        #Draw rectangle for high invariant
388        gc.PushState() 
389        y_origine += 20 
390        gc.DrawText("Q* At High-Q", x_origine, y_origine) 
391        #define the position of the new rectangle
392        x_center = x_origine + RECTANGLE_WIDTH * self.high_scale/2 + w + 10
393        y_center = y_origine + h
394        gc.Translate(x_center, y_center)
395        gc.SetBrush(wx.Brush(self.extrapolation_color_high)) 
396        # increase scale by self.high_scale
397        high_percent = format_number(self.high_inv_percent*100)+ '%'
398        x_center = 20
399        y_center = -h
400        gc.DrawText(high_percent, x_center, y_center)
401       
402        gc.Scale(self.high_scale, 1.0) 
403        gc.DrawPath(path)
404        gc.PopState()
405       
406class InvariantDetailsWindow(wx.Dialog):
407    def __init__(self, parent, qstar_container=None, *args, **kwds):
408        kwds["size"]= (PANEL_WIDTH +100, 450)
409        wx.Dialog.__init__(self, parent, *args, **kwds)
410        self.container = qstar_container
411        if self.container is None:
412            self.container = InvariantContainer()
413            self.container.qstar_total = 1.0
414            self.container.qstar = 0.75
415            self.container.qstar_low = 0.60
416            self.container.qstar_high = 0.0049
417        self.panel = InvariantDetailsPanel(parent=self, 
418                                           qstar_container=self.container)
419        self.Centre()
420        self.ShowModal()
421        self.Destroy()
422
423class InvariantDetailsTest(wx.Frame):
424    def __init__(self, parent, qstar_container=None, *args, **kwds):
425        kwds["size"]= (PANEL_WIDTH , PANEL_HEIGHT)
426        wx.Frame.__init__(self, parent, *args, **kwds)
427        self.container = qstar_container
428        if self.container is None:
429            self.container = InvariantContainer()
430            self.container.qstar_total = 1.0
431            self.container.qstar = 0.75
432            self.container.qstar_low = 0.60
433            self.container.qstar_high = 0.0049
434       
435        self.panel = InvariantDetailsPanel(parent=self, 
436                                           qstar_container=self.container)
437        self.panel.ShowModal()
438        self.panel.Destroy()
439        self.Show()
440   
441if __name__ =="__main__":
442    app  = wx.App()
443
444    container = InvariantContainer()
445    container.qstar_total = 100.0
446    container.qstar = 15.0
447    container.qstar_low = 0.001
448    container.qstar_high = 100.0
449    container.compute_percentage()
450   
451    window = InvariantDetailsTest(parent=None, id=-1,qstar_container=container,
452                                    title="Invariant Details")
453    window.Show()
454    app.MainLoop()
Note: See TracBrowser for help on using the repository browser.