source: sasview/src/sas/sasgui/perspectives/calculator/slit_length_calculator_panel.py @ 3a3f192

ESS_GUI_bumps_abstraction
Last change on this file since 3a3f192 was fa81e94, checked in by Piotr Rozyczko <rozyczko@…>, 6 years ago

Initial commit of the P(r) inversion perspective.
Code merged from Jeff Krzywon's ESS_GUI_Pr branch.
Also, minor 2to3 mods to sascalc/sasgui to enble error free setup.

  • Property mode set to 100755
File size: 11.8 KB
Line 
1"""
2This software was developed by the University of Tennessee as part of the
3Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
4project funded by the US National Science Foundation.
5
6See the license text in license.txt
7
8copyright 2008, 2009, University of Tennessee
9"""
10
11import wx
12import sys
13import os
14
15from sas.sasgui.guiframe.panel_base import PanelBase
16
17from sas.sasgui.guiframe.events import StatusEvent
18from sas.sascalc.calculator.slit_length_calculator import SlitlengthCalculator
19from .calculator_widgets import OutputTextCtrl
20from .calculator_widgets import InterActiveOutputTextCtrl
21from sas.sasgui.perspectives.calculator import calculator_widgets as widget
22from sas.sasgui.guiframe.documentation_window import DocumentationWindow
23
24_BOX_WIDTH = 76
25#Slit length panel size
26if sys.platform.count("win32") > 0:
27    PANEL_TOP = 0
28    PANEL_WIDTH = 500
29    PANEL_HEIGHT = 210
30    FONT_VARIANT = 0
31else:
32    PANEL_TOP = 60
33    PANEL_WIDTH = 530
34    PANEL_HEIGHT = 210
35    FONT_VARIANT = 1
36
37class SlitLengthCalculatorPanel(wx.Panel, PanelBase):
38    """
39        Provides the slit length calculator GUI.
40    """
41    ## Internal nickname for the window, used by the AUI manager
42    window_name = "Slit Size Calculator"
43    ## Name to appear on the window title bar
44    window_caption = "Slit Size Calculator"
45    ## Flag to tell the AUI manager to put this panel in the center pane
46    CENTER_PANE = True
47
48    def __init__(self, parent, *args, **kwds):
49        wx.Panel.__init__(self, parent, *args, **kwds)
50        PanelBase.__init__(self)
51        #Font size
52        self.SetWindowVariant(variant=FONT_VARIANT)
53        #thread to read data
54        self.reader = None
55        # Default location
56        self._default_save_location = os.getcwd()
57        # Object that receive status event
58        self.parent = parent
59        self._do_layout()
60
61    def _define_structure(self):
62        """
63            Define the main sizers building to build this application.
64        """
65        self.main_sizer = wx.BoxSizer(wx.VERTICAL)
66        self.box_source = wx.StaticBox(self, -1, str("Slit Size Calculator"))
67        self.boxsizer_source = wx.StaticBoxSizer(self.box_source,
68                                                    wx.VERTICAL)
69        self.data_name_sizer = wx.BoxSizer(wx.HORIZONTAL)
70        self.slit_size_sizer = wx.BoxSizer(wx.HORIZONTAL)
71        self.hint_sizer = wx.BoxSizer(wx.HORIZONTAL)
72        self.button_sizer = wx.BoxSizer(wx.HORIZONTAL)
73
74    def _layout_data_name(self):
75        """
76            Fill the sizer containing data's name
77        """
78        data_name_txt = wx.StaticText(self, -1, 'Data: ')
79        self.data_name_tcl = OutputTextCtrl(self, -1,
80                                            size=(_BOX_WIDTH * 4, -1))
81        data_hint = "Loaded data"
82        self.data_name_tcl.SetToolTipString(data_hint)
83        #control that triggers importing data
84        id = wx.NewId()
85        self.browse_button = wx.Button(self, id, "Browse")
86        hint_on_browse = "Click on this button to import data in this panel."
87        self.browse_button.SetToolTipString(hint_on_browse)
88        self.Bind(wx.EVT_BUTTON, self.on_load_data, id=id)
89        self.data_name_sizer.AddMany([(data_name_txt, 0, wx.LEFT, 15),
90                                      (self.data_name_tcl, 0, wx.LEFT, 10),
91                                      (self.browse_button, 0, wx.LEFT, 10)])
92    def _layout_slit_size(self):
93        """
94            Fill the sizer containing slit size information
95        """
96        slit_size_txt = wx.StaticText(self, -1, 'Slit Size (FWHM/2): ')
97        self.slit_size_tcl = InterActiveOutputTextCtrl(self, -1,
98                                                       size=(_BOX_WIDTH, -1))
99        slit_size_hint = " Estimated full slit size"
100        self.slit_size_tcl.SetToolTipString(slit_size_hint)
101        slit_size_unit_txt = wx.StaticText(self, -1, 'Unit: ')
102        self.slit_size_unit_tcl = OutputTextCtrl(self, -1,
103                                                 size=(_BOX_WIDTH, -1))
104        slit_size_unit_hint = "Full slit size's unit"
105        self.slit_size_unit_tcl.SetToolTipString(slit_size_unit_hint)
106        self.slit_size_sizer.AddMany([(slit_size_txt, 0, wx.LEFT, 15),
107                                      (self.slit_size_tcl, 0, wx.LEFT, 10),
108                                      (slit_size_unit_txt, 0, wx.LEFT, 10),
109                                    (self.slit_size_unit_tcl, 0, wx.LEFT, 10)])
110
111    def _layout_hint(self):
112        """
113            Fill the sizer containing hint
114        """
115        hint_msg = "This calculation works only for  SAXSess beam profile data."
116        self.hint_txt = wx.StaticText(self, -1, hint_msg)
117        self.hint_sizer.AddMany([(self.hint_txt, 0, wx.LEFT, 15)])
118
119    def _layout_button(self):
120        """
121            Do the layout for the button widgets
122        """
123        self.bt_close = wx.Button(self, wx.ID_CANCEL, 'Close')
124        self.bt_close.Bind(wx.EVT_BUTTON, self.on_close)
125        self.bt_close.SetToolTipString("Close this window.")
126
127        id = wx.NewId()
128        self.button_help = wx.Button(self, id, "HELP")
129        self.button_help.SetToolTipString("Help for slit length calculator.")
130        self.Bind(wx.EVT_BUTTON, self.on_help, id=id)
131
132        self.button_sizer.AddMany([(self.button_help, 0, wx.LEFT, 280),
133                                   (self.bt_close, 0, wx.LEFT, 20)])
134
135    def _do_layout(self):
136        """
137            Draw window content
138        """
139        self._define_structure()
140        self._layout_data_name()
141        self._layout_slit_size()
142        self._layout_hint()
143        self._layout_button()
144        self.boxsizer_source.AddMany([(self.data_name_sizer, 0,
145                                          wx.EXPAND | wx.TOP | wx.BOTTOM, 5),
146                                   (self.slit_size_sizer, 0,
147                                     wx.EXPAND | wx.TOP | wx.BOTTOM, 5),
148                                     (self.hint_sizer, 0,
149                                     wx.EXPAND | wx.TOP | wx.BOTTOM, 5)])
150        self.main_sizer.AddMany([(self.boxsizer_source, 0, wx.ALL, 10),
151                                  (self.button_sizer, 0,
152                                    wx.EXPAND | wx.TOP | wx.BOTTOM, 5)])
153        self.SetSizer(self.main_sizer)
154        self.SetAutoLayout(True)
155
156    def choose_data_file(self, location=None):
157        path = None
158        filename = ''
159        if location is None:
160            location = os.getcwd()
161
162        wildcard = "SAXSess Data 1D (*.DAT, *.dat)|*.DAT"
163
164        dlg = wx.FileDialog(self, "Choose a file", location,
165                            "", wildcard, wx.OPEN)
166        if dlg.ShowModal() == wx.ID_OK:
167            path = dlg.GetPath()
168            filename = os.path.basename(path)
169        dlg.Destroy()
170
171        return path
172
173    def on_help(self, event):
174        """
175        Bring up the slit length calculator Documentation whenever
176        the HELP button is clicked.
177
178        Calls DocumentationWindow with the path of the location within the
179        documentation tree (after /doc/ ....".  Note that when using old
180        versions of Wx (before 2.9) and thus not the release version of
181        installers, the help comes up at the top level of the file as
182        webbrowser does not pass anything past the # to the browser when it is
183        running "file:///...."
184
185    :param evt: Triggers on clicking the help button
186    """
187
188        _TreeLocation = "user/sasgui/perspectives/calculator/"
189        _TreeLocation += "slit_calculator_help.html"
190        _doc_viewer = DocumentationWindow(self, -1, _TreeLocation, "",
191                                          "Slit Length Calculator Help")
192
193    def on_close(self, event):
194        """
195            close the window containing this panel
196        """
197        self.parent.Close()
198
199    def on_load_data(self, event):
200        """
201            Open a file dialog to allow the user to select a given file.
202            The user is only allow to load file with extension .DAT or .dat.
203            Display the slit size corresponding to the loaded data.
204        """
205        path = self.choose_data_file(location=self._default_save_location)
206
207        if path is None:
208            return
209        self._default_save_location = path
210        try:
211            #Load data
212            from .load_thread import DataReader
213            ## If a thread is already started, stop it
214            if self.reader is not None and self.reader.isrunning():
215                self.reader.stop()
216            if self.parent.parent is not None:
217                wx.PostEvent(self.parent.parent,
218                                StatusEvent(status="Loading...",
219                                type="progress"))
220            self.reader = DataReader(path=path,
221                                    completefn=self.complete_loading,
222                                    updatefn=self.load_update)
223            self.reader.queue()
224            self.load_update()
225        except:
226            if self.parent.parent is None:
227                return
228            msg = "Slit Length Calculator: %s" % (sys.exc_info()[1])
229            wx.PostEvent(self.parent.parent,
230                          StatusEvent(status=msg, type='stop'))
231            return
232
233    def load_update(self):
234        """
235        print update on the status bar
236        """
237        if self.parent.parent is None:
238                return
239        if self.reader.isrunning():
240            type = "progress"
241        else:
242            type = "stop"
243        wx.PostEvent(self.parent.parent, StatusEvent(status="",
244                                                  type=type))
245
246    def complete_loading(self, data=None, filename=''):
247        """
248            Complete the loading and compute the slit size
249        """
250        if data is None or data.__class__.__name__ == 'Data2D':
251            if self.parent.parent is None:
252                return
253            msg = "Slit Length cannot be computed for 2D Data"
254            wx.PostEvent(self.parent.parent,
255                         StatusEvent(status=msg, type='stop'))
256            return
257        self.data_name_tcl.SetValue(str(data.filename))
258        #compute the slit size
259        try:
260            x = data.x
261            y = data.y
262            if x == [] or  x is None or y == [] or y is None:
263                msg = "The current data is empty please check x and y"
264                raise ValueError(msg)
265            slit_length_calculator = SlitlengthCalculator()
266            slit_length_calculator.set_data(x=x, y=y)
267            slit_length = slit_length_calculator.calculate_slit_length()
268        except:
269            if self.parent.parent is None:
270                return
271            msg = "Slit Size Calculator: %s" % (sys.exc_info()[1])
272            wx.PostEvent(self.parent.parent,
273                          StatusEvent(status=msg, type='stop'))
274            return
275        self.slit_size_tcl.SetValue(str(slit_length))
276        #Display unit
277        self.slit_size_unit_tcl.SetValue('[Unknown]')
278        if self.parent.parent is None:
279            return
280        msg = "Load Complete"
281        wx.PostEvent(self.parent.parent, StatusEvent(status=msg, type='stop'))
282
283
284class SlitLengthCalculatorWindow(widget.CHILD_FRAME):
285    """
286    """
287    def __init__(self, parent=None, manager=None, title="Slit Size Calculator",
288                size=(PANEL_WIDTH, PANEL_HEIGHT), *args, **kwds):
289        """
290        """
291        kwds['size'] = size
292        kwds['title'] = title
293        widget.CHILD_FRAME.__init__(self, parent, *args, **kwds)
294        self.parent = parent
295        self.manager = manager
296        self.panel = SlitLengthCalculatorPanel(parent=self)
297        self.Bind(wx.EVT_CLOSE, self.on_close)
298        self.SetPosition((wx.LEFT, PANEL_TOP))
299        self.Show(True)
300
301    def on_close(self, event):
302        """
303        Close event
304        """
305        if self.manager is not None:
306            self.manager.cal_slit_frame = None
307        self.Destroy()
308
309if __name__ == "__main__":
310    app = wx.PySimpleApp()
311    widget.CHILD_FRAME = wx.Frame
312    frame = SlitLengthCalculatorWindow()
313    frame.Show(True)
314    app.MainLoop()
Note: See TracBrowser for help on using the repository browser.