source: sasview/src/sas/sasview/sasview.py @ 6af5d75

unittest-saveload
Last change on this file since 6af5d75 was 6af5d75, checked in by Jeff Krzywon <jkrzywon@…>, 6 years ago

Don't start the SasView? main loop if running in threaded mode.

  • Property mode set to 100644
File size: 11.5 KB
Line 
1# -*- coding: utf-8 -*-
2"""
3Base module for loading and running the main SasView application.
4"""
5################################################################################
6# This software was developed by the University of Tennessee as part of the
7# Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
8# project funded by the US National Science Foundation.
9#
10# See the license text in license.txt
11#
12# copyright 2009, University of Tennessee
13################################################################################
14import os
15import os.path
16import sys
17import traceback
18import logging
19
20try:
21    reload(sys)
22    sys.setdefaultencoding("iso-8859-1")
23except NameError:
24    # On python 3 sys.setdefaultencoding does nothing, so pass.
25    # We know we are in python 3 at this point since reload is no longer in
26    # builtins, but instead has been moved to importlib, hence the NameError.
27    pass
28
29import sas
30
31APP_NAME = 'SasView'
32PLUGIN_MODEL_DIR = 'plugin_models'
33
34class SasView(object):
35    """
36    Main class for running the SasView application
37    """
38    def __init__(self, threaded=False):
39        """
40        """
41        logger = logging.getLogger(__name__)
42
43        from sas.sasgui.guiframe.gui_manager import SasViewApp
44        self.gui = SasViewApp(0)
45        if sys.platform == "darwin":
46            self.check_sasmodels_compiler()
47        # Set the application manager for the GUI
48        self.gui.set_manager(self)
49        # Add perspectives to the basic application
50        # Additional perspectives can still be loaded
51        # dynamically
52        # Note: py2exe can't find dynamically loaded
53        # modules. We load the fitting module here
54        # to ensure a complete Windows executable build.
55
56        # Rebuild .sasview/categories.json.  This triggers a load of sasmodels
57        # and all the plugins.
58        try:
59            from sas.sascalc.fit.models import ModelManager
60            from sas.sasgui.guiframe.CategoryInstaller import CategoryInstaller
61            model_list = ModelManager().cat_model_list()
62            CategoryInstaller.check_install(model_list=model_list)
63        except Exception:
64            logger.error("%s: could not load SasView models")
65            logger.error(traceback.format_exc())
66
67        # Fitting perspective
68        try:
69            import sas.sasgui.perspectives.fitting as module
70            fitting_plug = module.Plugin()
71            self.gui.add_perspective(fitting_plug)
72        except Exception:
73            logger.error("%s: could not find Fitting plug-in module", APP_NAME)
74            logger.error(traceback.format_exc())
75
76        # P(r) perspective
77        try:
78            import sas.sasgui.perspectives.pr as module
79            pr_plug = module.Plugin()
80            self.gui.add_perspective(pr_plug)
81        except Exception:
82            logger.error("%s: could not find P(r) plug-in module", APP_NAME)
83            logger.error(traceback.format_exc())
84
85        # Invariant perspective
86        try:
87            import sas.sasgui.perspectives.invariant as module
88            invariant_plug = module.Plugin()
89            self.gui.add_perspective(invariant_plug)
90        except Exception:
91            logger.error("%s: could not find Invariant plug-in module",
92                         APP_NAME)
93            logger.error(traceback.format_exc())
94
95        # Corfunc perspective
96        try:
97            import sas.sasgui.perspectives.corfunc as module
98            corfunc_plug = module.Plugin()
99            self.gui.add_perspective(corfunc_plug)
100        except Exception:
101            logger.error("Unable to load corfunc module")
102
103        # Calculator perspective
104        try:
105            import sas.sasgui.perspectives.calculator as module
106            calculator_plug = module.Plugin()
107            self.gui.add_perspective(calculator_plug)
108        except Exception:
109            logger.error("%s: could not find Calculator plug-in module",
110                         APP_NAME)
111            logger.error(traceback.format_exc())
112
113        # File converter tool
114        try:
115            import sas.sasgui.perspectives.file_converter as module
116            converter_plug = module.Plugin()
117            self.gui.add_perspective(converter_plug)
118        except Exception:
119            logger.error("%s: could not find File Converter plug-in module",
120                         APP_NAME)
121            logger.error(traceback.format_exc())
122
123        # Add welcome page
124        from .welcome_panel import WelcomePanel
125        self.gui.set_welcome_panel(WelcomePanel)
126
127        # Build the GUI
128        self.gui.build_gui()
129        # delete unused model folder
130        self.gui.clean_plugin_models(PLUGIN_MODEL_DIR)
131        if not threaded:
132            # Start the main loop
133            self.gui.MainLoop()
134
135    def check_sasmodels_compiler(self):
136        """
137        Checking c compiler for sasmodels and raises xcode command line
138        tools for installation
139        """
140        #wx should be importable at this stage
141        import wx
142        import subprocess
143        #Generic message box created becuase standard MessageBox is not moveable
144        class GenericMessageBox(wx.Dialog):
145            def __init__(self, parent, text, title = ''):
146
147                wx.Dialog.__init__(self, parent, -1, title = title,
148                               size = (360,200), pos=(20,60),
149                               style = wx.STAY_ON_TOP | wx.DEFAULT_DIALOG_STYLE)
150                panel = wx.Panel(self, -1)
151                top_row_sizer = wx.BoxSizer(wx.HORIZONTAL)
152
153                error_bitmap = wx.ArtProvider.GetBitmap(
154                    wx.ART_ERROR, wx.ART_MESSAGE_BOX
155                )
156                error_bitmap_ctrl = wx.StaticBitmap(panel, -1)
157                error_bitmap_ctrl.SetBitmap(error_bitmap)
158                label = wx.StaticText(panel, -1, text)
159                top_row_sizer.Add(error_bitmap_ctrl, flag=wx.ALL, border=10)
160                top_row_sizer.Add(label, flag=wx.ALIGN_CENTER_VERTICAL)
161
162                #Create the OK button in the bottom row.
163                ok_button = wx.Button(panel, wx.ID_OK )
164                self.Bind(wx.EVT_BUTTON, self.on_ok, source=ok_button)
165                ok_button.SetFocus()
166                ok_button.SetDefault()
167
168                sizer = wx.BoxSizer(wx.VERTICAL)
169                sizer.Add(top_row_sizer)
170                sizer.Add(ok_button, flag=wx.ALIGN_CENTER | wx.ALL, border=5)
171                panel.SetSizer(sizer)
172
173            def on_ok(self, event):
174                self.Destroy()
175
176        logger = logging.getLogger(__name__)
177        try:
178            subprocess.check_output(["cc","--version"], stderr=subprocess.STDOUT)
179        except subprocess.CalledProcessError as exc:
180            dlg = GenericMessageBox(parent=None,
181            text='No compiler installed. Please install command line\n'
182                'developers tools by clicking \"Install\" in another winodw\n\n'
183                'Alternatively click \"Not Now\" and use OpenCL\n'
184                 'compiler, which can be set up from menu Fitting->OpenCL Options\n\n',
185            title = 'Compiler Info')
186            dlg.Show()
187            logger.error("No compiler installed. %s\n"%(exc))
188            logger.error(traceback.format_exc())
189
190def setup_logging():
191    from sas.logger_config import SetupLogger
192
193    logger = SetupLogger(__name__).config_production()
194    # Log the start of the session
195    logger.info(" --- SasView session started ---")
196    # Log the python version
197    logger.info("Python: %s" % sys.version)
198    return logger
199
200
201def setup_wx():
202    # Allow the dynamic selection of wxPython via an environment variable, when devs
203    # who have multiple versions of the module installed want to pick between them.
204    # This variable does not have to be set of course, and through normal usage will
205    # probably not be, but this can make things a little easier when upgrading to a
206    # new version of wx.
207    logger = logging.getLogger(__name__)
208    WX_ENV_VAR = "SASVIEW_WX_VERSION"
209    if WX_ENV_VAR in os.environ:
210        logger.info("You have set the %s environment variable to %s.",
211                    WX_ENV_VAR, os.environ[WX_ENV_VAR])
212        import wxversion
213        if wxversion.checkInstalled(os.environ[WX_ENV_VAR]):
214            logger.info("Version %s of wxPython is installed, so using that version.",
215                        os.environ[WX_ENV_VAR])
216            wxversion.select(os.environ[WX_ENV_VAR])
217        else:
218            logger.error("Version %s of wxPython is not installed, so using default version.",
219                         os.environ[WX_ENV_VAR])
220    else:
221        logger.info("You have not set the %s environment variable, so using default version of wxPython.",
222                    WX_ENV_VAR)
223
224    import wx
225
226    try:
227        logger.info("Wx version: %s", wx.__version__)
228    except AttributeError:
229        logger.error("Wx version: error reading version")
230
231    from . import wxcruft
232    wxcruft.call_later_fix()
233    #wxcruft.trace_new_id()
234    #Always use private .matplotlib setup to avoid conflicts with other
235    #uses of matplotlib
236
237
238def setup_mpl(backend=None):
239    # Always use private .matplotlib setup to avoid conflicts with other
240    mplconfigdir = os.path.join(sas.get_user_dir(), '.matplotlib')
241    if not os.path.exists(mplconfigdir):
242        os.mkdir(mplconfigdir)
243    os.environ['MPLCONFIGDIR'] = mplconfigdir
244    # Set backend to WXAgg; this overrides matplotlibrc, but shouldn't override
245    # mpl.use().  Note: Don't import matplotlib here since the script that
246    # we are running may not actually need it; also, putting as little on the
247    # path as we can
248    if backend:
249        os.environ['MPLBACKEND'] = backend
250
251    # TODO: ... so much for not importing matplotlib unless we need it...
252    from matplotlib import backend_bases
253    backend_bases.FigureCanvasBase.filetypes.pop('pgf', None)
254
255def setup_sasmodels():
256    """
257    Prepare sasmodels for running within sasview.
258    """
259    # Set SAS_MODELPATH so sasmodels can find our custom models
260    plugin_dir = os.path.join(sas.get_user_dir(), PLUGIN_MODEL_DIR)
261    os.environ['SAS_MODELPATH'] = plugin_dir
262    #Initialize environment variable with custom setting but only if variable not set
263    SAS_OPENCL = sas.get_custom_config().SAS_OPENCL
264    if SAS_OPENCL and "SAS_OPENCL" not in os.environ:
265        os.environ["SAS_OPENCL"] = SAS_OPENCL
266
267
268def run_gui(threaded=False):
269    """
270    __main__ method for loading and running SasView
271    """
272    from multiprocessing import freeze_support
273    freeze_support()
274    setup_logging()
275    setup_mpl(backend='WXAgg')
276    setup_sasmodels()
277    setup_wx()
278    app = SasView(threaded=threaded)
279    return app
280
281
282def run_cli():
283    from multiprocessing import freeze_support
284    freeze_support()
285    setup_logging()
286    # Use default matplotlib backend on mac/linux, but wx on windows.
287    # The problem on mac is that the wx backend requires pythonw.  On windows
288    # we are sure to wx since it is the shipped with the app.
289    setup_mpl(backend='WXAgg' if os.name == 'nt' else None)
290    setup_sasmodels()
291    if len(sys.argv) == 1 or sys.argv[1] == '-i':
292        # Run sasview as an interactive python interpreter
293        try:
294            from IPython import start_ipython
295            sys.argv = ["ipython", "--pylab"]
296            sys.exit(start_ipython())
297        except ImportError:
298            import code
299            code.interact(local={'exit': sys.exit})
300    elif sys.argv[1] == '-c':
301        exec(sys.argv[2])
302    else:
303        thing_to_run = sys.argv[1]
304        sys.argv = sys.argv[1:]
305        import runpy
306        if os.path.exists(thing_to_run):
307            runpy.run_path(thing_to_run, run_name="__main__")
308        else:
309            runpy.run_module(thing_to_run, run_name="__main__")
310
311
312if __name__ == "__main__":
313    run_gui()
Note: See TracBrowser for help on using the repository browser.