source: sasview/invariantview/perspectives/invariant/invariant_details.py @ 2e27cf85

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 2e27cf85 was 5dc4236, checked in by Jae Cho <jhjcho@…>, 15 years ago

Adjusted detail sizer sizer to fit well with MAC

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