source: sasview/src/sas/sasview/sasview.py @ 5251ec6

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

improved support for py37 in sasgui

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