source: sasview/src/sas/perspectives/calculator/slit_length_calculator_panel.py @ be34c71

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 be34c71 was 3db44fb, checked in by butler, 10 years ago

1) Fixed second issue that was caused by the recent cleanup of
DocumentationWindow?: loading html at anchor point for context help
(broken). In order to preserve the cleanup, the class was refactored to
take another parameter: html instruction string. This keeps it general
to accept not only the # anchor but alos queries of all sorts in the
future. Thus all modules using this class were also edited to match.

2) in process of editing the dozen or so instances did a bit of code
cleanup and pylint cleanup.

  • Property mode set to 100644
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.guiframe.panel_base import PanelBase
16
17from sas.guiframe.events import StatusEvent
18from sas.calculator.slit_length_calculator import SlitlengthCalculator
19from calculator_widgets import OutputTextCtrl
20from calculator_widgets import InterActiveOutputTextCtrl
21from sas.perspectives.calculator import calculator_widgets as widget
22from sas.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 == 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/perspectives/calculator/slit_calculator_help.html"
189        _doc_viewer = DocumentationWindow(self, -1, _TreeLocation, "",
190                                          "Slit Length Calculator Help")
191
192    def on_close(self, event):
193        """
194            close the window containing this panel
195        """
196        self.parent.Close()
197
198    def on_load_data(self, event):
199        """
200            Open a file dialog to allow the user to select a given file.
201            The user is only allow to load file with extension .DAT or .dat.
202            Display the slit size corresponding to the loaded data.
203        """
204        path = self.choose_data_file(location=self._default_save_location)
205
206        if path is None:
207            return
208        self._default_save_location = path
209        try:
210            #Load data
211            from load_thread import DataReader
212            ## If a thread is already started, stop it
213            if self.reader is not None and self.reader.isrunning():
214                self.reader.stop()
215            if self.parent.parent is not None:
216                wx.PostEvent(self.parent.parent,
217                                StatusEvent(status="Loading...",
218                                type="progress"))
219            self.reader = DataReader(path=path,
220                                    completefn=self.complete_loading,
221                                    updatefn=self.load_update)
222            self.reader.queue()
223            self.load_update()
224        except:
225            if self.parent.parent is None:
226                return
227            msg = "Slit Length Calculator: %s" % (sys.exc_value)
228            wx.PostEvent(self.parent.parent,
229                          StatusEvent(status=msg, type='stop'))
230            return
231
232    def load_update(self):
233        """
234        print update on the status bar
235        """
236        if self.parent.parent is None:
237                return
238        if self.reader.isrunning():
239            type = "progress"
240        else:
241            type = "stop"
242        wx.PostEvent(self.parent.parent, StatusEvent(status="",
243                                                  type=type))
244
245    def complete_loading(self, data=None, filename=''):
246        """
247            Complete the loading and compute the slit size
248        """
249        if data is None or data.__class__.__name__ == 'Data2D':
250            if self.parent.parent is None:
251                return
252            msg = "Slit Length cannot be computed for 2D Data"
253            wx.PostEvent(self.parent.parent,
254                         StatusEvent(status=msg, type='stop'))
255            return
256        self.data_name_tcl.SetValue(str(data.filename))
257        #compute the slit size
258        try:
259            x = data.x
260            y = data.y
261            if x == [] or  x is None or y == [] or y is None:
262                msg = "The current data is empty please check x and y"
263                raise ValueError, msg
264            slit_length_calculator = SlitlengthCalculator()
265            slit_length_calculator.set_data(x=x, y=y)
266            slit_length = slit_length_calculator.calculate_slit_length()
267        except:
268            if self.parent.parent is None:
269                return
270            msg = "Slit Size Calculator: %s" % (sys.exc_value)
271            wx.PostEvent(self.parent.parent,
272                          StatusEvent(status=msg, type='stop'))
273            return
274        self.slit_size_tcl.SetValue(str(slit_length))
275        #Display unit
276        self.slit_size_unit_tcl.SetValue('[Unknown]')
277        if self.parent.parent is None:
278            return
279        msg = "Load Complete"
280        wx.PostEvent(self.parent.parent, StatusEvent(status=msg, type='stop'))
281
282
283class SlitLengthCalculatorWindow(widget.CHILD_FRAME):
284    """
285    """
286    def __init__(self, parent=None, manager=None, title="Slit Size Calculator",
287                size=(PANEL_WIDTH, PANEL_HEIGHT), *args, **kwds):
288        """
289        """
290        kwds['size'] = size
291        kwds['title'] = title
292        widget.CHILD_FRAME.__init__(self, parent, *args, **kwds)
293        self.parent = parent
294        self.manager = manager
295        self.panel = SlitLengthCalculatorPanel(parent=self)
296        self.Bind(wx.EVT_CLOSE, self.on_close)
297        self.SetPosition((wx.LEFT, PANEL_TOP))
298        self.Show(True)
299
300    def on_close(self, event):
301        """
302        Close event
303        """
304        if self.manager != None:
305            self.manager.cal_slit_frame = None
306        self.Destroy()
307
308if __name__ == "__main__":
309    app = wx.PySimpleApp()
310    widget.CHILD_FRAME = wx.Frame
311    frame = SlitLengthCalculatorWindow()
312    frame.Show(True)
313    app.MainLoop()
Note: See TracBrowser for help on using the repository browser.