source: sasview/src/sas/sasgui/perspectives/calculator/slit_length_calculator_panel.py @ 5251ec6

magnetic_scattrelease-4.2.2ticket-1009ticket-1249
Last change on this file since 5251ec6 was 5251ec6, checked in by Paul Kienzle <pkienzle@…>, 21 months ago

improved support for py37 in sasgui

  • Property mode set to 100644
File size: 11.9 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 sas.sasgui.perspectives.calculator import calculator_widgets as widget
20from sas.sasgui.guiframe.documentation_window import DocumentationWindow
21from .calculator_widgets import OutputTextCtrl
22from .calculator_widgets import InterActiveOutputTextCtrl
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.FD_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 Exception as exc:
226            if self.parent.parent is None:
227                return
228            msg = "Slit Length Calculator: %s" % exc
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 isinstance(data, list):
251            data = data[0]
252        if data is None or data.__class__.__name__ == 'Data2D':
253            if self.parent.parent is None:
254                return
255            msg = "Slit Length cannot be computed for 2D Data"
256            wx.PostEvent(self.parent.parent,
257                         StatusEvent(status=msg, type='stop'))
258            return
259        self.data_name_tcl.SetValue(str(data.filename))
260        #compute the slit size
261        try:
262            x = data.x
263            y = data.y
264            if x == [] or  x is None or y == [] or y is None:
265                msg = "The current data is empty please check x and y"
266                raise ValueError(msg)
267            slit_length_calculator = SlitlengthCalculator()
268            slit_length_calculator.set_data(x=x, y=y)
269            slit_length = slit_length_calculator.calculate_slit_length()
270        except Exception as exc:
271            if self.parent.parent is None:
272                return
273            msg = "Slit Size Calculator: %s" % exc
274            wx.PostEvent(self.parent.parent,
275                          StatusEvent(status=msg, type='stop'))
276            return
277        self.slit_size_tcl.SetValue(str(slit_length))
278        #Display unit
279        self.slit_size_unit_tcl.SetValue('[Unknown]')
280        if self.parent.parent is None:
281            return
282        msg = "Load Complete"
283        wx.PostEvent(self.parent.parent, StatusEvent(status=msg, type='stop'))
284
285
286class SlitLengthCalculatorWindow(widget.CHILD_FRAME):
287    """
288    """
289    def __init__(self, parent=None, manager=None, title="Slit Size Calculator",
290                size=(PANEL_WIDTH, PANEL_HEIGHT), *args, **kwds):
291        """
292        """
293        kwds['size'] = size
294        kwds['title'] = title
295        widget.CHILD_FRAME.__init__(self, parent, *args, **kwds)
296        self.parent = parent
297        self.manager = manager
298        self.panel = SlitLengthCalculatorPanel(parent=self)
299        self.Bind(wx.EVT_CLOSE, self.on_close)
300        self.SetPosition((wx.LEFT, PANEL_TOP))
301        self.Show(True)
302
303    def on_close(self, event):
304        """
305        Close event
306        """
307        if self.manager is not None:
308            self.manager.cal_slit_frame = None
309        self.Destroy()
310
311if __name__ == "__main__":
312    app = wx.PySimpleApp()
313    widget.CHILD_FRAME = wx.Frame
314    frame = SlitLengthCalculatorWindow()
315    frame.Show(True)
316    app.MainLoop()
Note: See TracBrowser for help on using the repository browser.