source: sasview/src/sas/sasview/sasview.py @ 316b9c1

magnetic_scattrelease-4.2.2ticket-1009ticket-1094-headlessticket-1242-2d-resolutionticket-1243ticket-1249unittest-saveload
Last change on this file since 316b9c1 was 1270e3c, checked in by wojciech, 6 years ago

Improved message text

  • Property mode set to 100644
File size: 11.4 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        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        # Start the main loop
132        self.gui.MainLoop()
133
134    def check_sasmodels_compiler(self):
135        """
136        Checking c compiler for sasmodels and raises xcode command line
137        tools for installation
138        """
139        #wx should be importable at this stage
140        import wx
141        import subprocess
142        #Generic message box created becuase standard MessageBox is not moveable
143        class GenericMessageBox(wx.Dialog):
144            def __init__(self, parent, text, title = ''):
145
146                wx.Dialog.__init__(self, parent, -1, title = title,
147                               size = (360,200), pos=(20,60),
148                               style = wx.STAY_ON_TOP | wx.DEFAULT_DIALOG_STYLE)
149                panel = wx.Panel(self, -1)
150                top_row_sizer = wx.BoxSizer(wx.HORIZONTAL)
151
152                error_bitmap = wx.ArtProvider.GetBitmap(
153                    wx.ART_ERROR, wx.ART_MESSAGE_BOX
154                )
155                error_bitmap_ctrl = wx.StaticBitmap(panel, -1)
156                error_bitmap_ctrl.SetBitmap(error_bitmap)
157                label = wx.StaticText(panel, -1, text)
158                top_row_sizer.Add(error_bitmap_ctrl, flag=wx.ALL, border=10)
159                top_row_sizer.Add(label, flag=wx.ALIGN_CENTER_VERTICAL)
160
161                #Create the OK button in the bottom row.
162                ok_button = wx.Button(panel, wx.ID_OK )
163                self.Bind(wx.EVT_BUTTON, self.on_ok, source=ok_button)
164                ok_button.SetFocus()
165                ok_button.SetDefault()
166
167                sizer = wx.BoxSizer(wx.VERTICAL)
168                sizer.Add(top_row_sizer)
169                sizer.Add(ok_button, flag=wx.ALIGN_CENTER | wx.ALL, border=5)
170                panel.SetSizer(sizer)
171
172            def on_ok(self, event):
173                self.Destroy()
174
175        logger = logging.getLogger(__name__)
176        try:
177            subprocess.check_output(["cc","--version"], stderr=subprocess.STDOUT)
178        except subprocess.CalledProcessError as exc:
179            dlg = GenericMessageBox(parent=None,
180            text='No compiler installed. Please install command line\n'
181                'developers tools by clicking \"Install\" in another winodw\n\n'
182                'Alternatively click \"Not Now\" and use OpenCL\n'
183                 'compiler, which can be set up from menu Fitting->OpenCL Options\n\n',
184            title = 'Compiler Info')
185            dlg.Show()
186            logger.error("No compiler installed. %s\n"%(exc))
187            logger.error(traceback.format_exc())
188
189def setup_logging():
190    from sas.logger_config import SetupLogger
191
192    logger = SetupLogger(__name__).config_production()
193    # Log the start of the session
194    logger.info(" --- SasView session started ---")
195    # Log the python version
196    logger.info("Python: %s" % sys.version)
197    return logger
198
199
200def setup_wx():
201    # Allow the dynamic selection of wxPython via an environment variable, when devs
202    # who have multiple versions of the module installed want to pick between them.
203    # This variable does not have to be set of course, and through normal usage will
204    # probably not be, but this can make things a little easier when upgrading to a
205    # new version of wx.
206    logger = logging.getLogger(__name__)
207    WX_ENV_VAR = "SASVIEW_WX_VERSION"
208    if WX_ENV_VAR in os.environ:
209        logger.info("You have set the %s environment variable to %s.",
210                    WX_ENV_VAR, os.environ[WX_ENV_VAR])
211        import wxversion
212        if wxversion.checkInstalled(os.environ[WX_ENV_VAR]):
213            logger.info("Version %s of wxPython is installed, so using that version.",
214                        os.environ[WX_ENV_VAR])
215            wxversion.select(os.environ[WX_ENV_VAR])
216        else:
217            logger.error("Version %s of wxPython is not installed, so using default version.",
218                         os.environ[WX_ENV_VAR])
219    else:
220        logger.info("You have not set the %s environment variable, so using default version of wxPython.",
221                    WX_ENV_VAR)
222
223    import wx
224
225    try:
226        logger.info("Wx version: %s", wx.__version__)
227    except AttributeError:
228        logger.error("Wx version: error reading version")
229
230    from . import wxcruft
231    wxcruft.call_later_fix()
232    #wxcruft.trace_new_id()
233    #Always use private .matplotlib setup to avoid conflicts with other
234    #uses of matplotlib
235
236
237def setup_mpl(backend=None):
238    # Always use private .matplotlib setup to avoid conflicts with other
239    mplconfigdir = os.path.join(sas.get_user_dir(), '.matplotlib')
240    if not os.path.exists(mplconfigdir):
241        os.mkdir(mplconfigdir)
242    os.environ['MPLCONFIGDIR'] = mplconfigdir
243    # Set backend to WXAgg; this overrides matplotlibrc, but shouldn't override
244    # mpl.use().  Note: Don't import matplotlib here since the script that
245    # we are running may not actually need it; also, putting as little on the
246    # path as we can
247    if backend:
248        os.environ['MPLBACKEND'] = backend
249
250    # TODO: ... so much for not importing matplotlib unless we need it...
251    from matplotlib import backend_bases
252    backend_bases.FigureCanvasBase.filetypes.pop('pgf', None)
253
254def setup_sasmodels():
255    """
256    Prepare sasmodels for running within sasview.
257    """
258    # Set SAS_MODELPATH so sasmodels can find our custom models
259    plugin_dir = os.path.join(sas.get_user_dir(), PLUGIN_MODEL_DIR)
260    os.environ['SAS_MODELPATH'] = plugin_dir
261    #Initialize environment variable with custom setting but only if variable not set
262    SAS_OPENCL = sas.get_custom_config().SAS_OPENCL
263    if SAS_OPENCL and "SAS_OPENCL" not in os.environ:
264        os.environ["SAS_OPENCL"] = SAS_OPENCL
265
266def run_gui():
267    """
268    __main__ method for loading and running SasView
269    """
270    from multiprocessing import freeze_support
271    freeze_support()
272    setup_logging()
273    setup_mpl(backend='WXAgg')
274    setup_sasmodels()
275    setup_wx()
276    SasView()
277
278
279def run_cli():
280    from multiprocessing import freeze_support
281    freeze_support()
282    setup_logging()
283    # Use default matplotlib backend on mac/linux, but wx on windows.
284    # The problem on mac is that the wx backend requires pythonw.  On windows
285    # we are sure to wx since it is the shipped with the app.
286    setup_mpl(backend='WXAgg' if os.name == 'nt' else None)
287    setup_sasmodels()
288    if len(sys.argv) == 1 or sys.argv[1] == '-i':
289        # Run sasview as an interactive python interpreter
290        try:
291            from IPython import start_ipython
292            sys.argv = ["ipython", "--pylab"]
293            sys.exit(start_ipython())
294        except ImportError:
295            import code
296            code.interact(local={'exit': sys.exit})
297    elif sys.argv[1] == '-c':
298        exec(sys.argv[2])
299    else:
300        thing_to_run = sys.argv[1]
301        sys.argv = sys.argv[1:]
302        import runpy
303        if os.path.exists(thing_to_run):
304            runpy.run_path(thing_to_run, run_name="__main__")
305        else:
306            runpy.run_module(thing_to_run, run_name="__main__")
307
308
309if __name__ == "__main__":
310    run_gui()
Note: See TracBrowser for help on using the repository browser.