Coverage for larch/apps.py: 26%
156 statements
« prev ^ index » next coverage.py v7.6.0, created at 2024-10-16 21:04 +0000
« prev ^ index » next coverage.py v7.6.0, created at 2024-10-16 21:04 +0000
1"""
2main Larch Applications
3"""
4import sys
5import locale
6import inspect
7import shutil
8from argparse import ArgumentParser
9from pathlib import Path
11import matplotlib
13from .site_config import icondir, uname, update_larch
14from .version import __date__, make_banner, check_larchversion
16HAS_WXPYTHON = False
17try:
18 import wx
19 HAS_WXPYTHON = True
20except ImportError:
21 pass
23if HAS_WXPYTHON:
24 # note: this will be needed for some macOS builds until wxPython 4.2.1 is released.
25 if uname == 'darwin':
26 wx.PyApp.IsDisplayAvailable = lambda _: True
28def use_mpl_wxagg():
29 """import matplotlib, set backend to wxAgg"""
30 if HAS_WXPYTHON:
31 try:
32 matplotlib.use('WXAgg', force=True)
33 except ImportError:
34 pass
36def set_locale():
37 """set locale to 'C' for these applications"""
38 locale.setlocale(locale.LC_ALL, 'C')
40class LarchApp(object):
41 """wrapper for Larh application"""
42 def __init__(self, name, script, icon=None, description=None,
43 is_wxapp=True, filetype=None):
44 self.name = name
45 self.script = script
46 self.is_wxapp = is_wxapp
47 self.description = description or name
48 self.icon = icon or 'larch'
49 self.filetype = filetype or 'data file'
51 def make_desktop_shortcut(self, folder='Larch'):
52 pass
54 def prep_cli(self):
55 parser = ArgumentParser(description=self.description)
56 parser.add_argument('filename', nargs='?', help=self.filetype)
58 parser.add_argument('-m', '-mode', dest='run_mode', action='store_true',
59 default='xas', help='set startup mode')
60 parser.add_argument('-w', '-wx_inspect', dest='wx_inspect', action='store_true',
61 default=False, help='enable wxPython inspection and debugging')
63 args = parser.parse_args()
64 self.filename = None
65 if 'filename' in args and args.filename is not None:
66 self.filename = Path(args.filename).absolute()
67 self.wx_inspect = args.wx_inspect
68 self.run_mode = args.run_mode
69 if self.is_wxapp:
70 set_locale()
71 use_mpl_wxagg()
74# # App Name, icon, terminal, Script / pyshortcuts command, Description
75# MainApps = (('Larch CLI', 'larch', True, 'larch', 'Basic Command-line interface for Larch'),
76# ('Larch Updater', 'larch', True, '_ -m pip install --upgrade xraylarch', 'Larch Updatar'),
77# ('Larch GUI', 'larch', False, 'larch --wxgui', 'Enhanced Command-line interface for Larch'),
78# ('XAS Viewer', 'onecone', False, 'larix', 'XANES and EXAFS Analysis GUI for Larch'),
79# ('Larix', 'onecone', False, 'larix', 'XANES and EXAFS Analysis GUI for Larch'),
80# ('GSE MapViewer', 'gse_xrfmap', False, 'gse_mapviewer', 'XRF Map Viewing and Analysis'),
81# ('XRF Viewer', 'ptable', False, 'larch_xrf', 'X-ray FluorescenceData Viewing and Analysis'),
82# ('XRD1D Viewer', 'larch', False, 'larch_xrd1d', 'X-ray Diffraction Data Viewing'),
83# )
84#
87LarchApps = {
88 'larch': LarchApp(name='Larch CLI', script='larch', icon='larch',
89 description='Basic Command-line interface for Larch'),
90 'Larch GUI': LarchApp(name='Larch GUI', script='larch --wxgui', icon='larch',
91 description='Enhanced Command-line interface for Larch'),
92 'Larch Updater': LarchApp(name='Update Larch',
93 script='_ -m pip install --upgrade xraylarch',
94 icon='larch',
95 description='Larch Updater', is_wxapp=False),
97 'Larix': LarchApp(name='Larix', script='larix', icon='onecone',
98 description='XANES and EXAFS Analysis GUI for Larch'),
99 'XRFMap Viewer': LarchApp(name='XRFMap Viewer', script='gse_mapviewer',
100 icon='gse_xrfmap', filetype='XRM Map File (.h5)',
101 description='XRFMap Viewing and Analysis'),
102 'XRF Viewer': LarchApp(name='XRF Viewer', script='larch_xrf', icon='ptable',
103 description='X-ray FluorescenceData Viewing and Analysis'),
104 'XRD1D Viewer': LarchApp(name='XRD1D Viewer', script='larch_xrd1d', icon='larch',
105 description='X-ray Diffraction Data Viewing'),
106 }
109# entry points:
110def run_gse_mapviewer():
111 "XRFMap Viewer"
112 app = LarchApps['XRFMap Viewer']
113 app.prep_cli()
114 from .wxmap import MapViewer
115 MapViewer(check_version=True, title=app.description,
116 filename=app.filename).MainLoop()
119def run_larix():
120 """XANES and EXAFS Analysis GUI for Larch"""
121 app = LarchApps['Larix']
122 app.prep_cli()
123 from .wxxas import LarixApp
124 LarixApp(check_version=True, filename=app.filename,
125 mode=app.run_mode, with_wx_inspect=app.wx_inspect).MainLoop()
127run_xas_viewer = run_larix
129def run_larch_xrf():
130 """X-ray FluorescenceData Viewing and Analysis"""
131 app = LarchApps['XRF Viewer']
132 app.prep_cli()
133 from .wxlib.xrfdisplay import XRFApp
134 XRFApp(filename=app.filename).MainLoop()
136def run_epics_xrf():
137 """XRF Viewing and Control for Epics XRF Detectors"""
138 app = LarchApps['XRF Viewer']
139 app.prep_cli()
140 try:
141 from .epics import EpicsXRFApp
142 EpicsXRFApp().MainLoop()
143 except ImportError:
144 print('cannot import EpicsXRFApp: try `pip install "xraylarch[epics]"`')
146def run_larch_xrd1d():
147 """X-ray Diffraction Data Display"""
148 app = LarchApps['XRD1D Viewer']
149 app.prep_cli()
150 from .wxxrd import XRD1DApp
151 XRD1DApp().MainLoop()
153def run_xrd2d_viewer():
154 """XRD Display for 2D patternss"""
155 set_locale()
156 use_mpl_wxagg()
157 from .wxxrd import XRD2DViewer
158 XRD2DViewer().MainLoop()
160def run_gse_dtcorrect():
161 """GSE DT Correct """
162 set_locale()
163 use_mpl_wxagg()
164 from .wxmap import DTViewer
165 DTViewer().MainLoop()
168def run_feff6l():
169 "run feff6l"
170 from .xafs.feffrunner import feff6l_cli
171 feff6l_cli()
173def run_feff8l():
174 "run feff8l"
175 from .xafs.feffrunner import feff8l_cli
176 feff8l_cli()
178def run_larch_server():
179 "run larch XMLRPC server"
180 from .xmlrpc_server import larch_server_cli
181 larch_server_cli()
184## main larch cli or wxgui
185def run_larch():
186 """
187 main larch application launcher, running either
188 commandline repl program or wxgui
189 """
190 parser = ArgumentParser(description='run main larch program')
191 sargs = (("-v", "--version", "version", False, "show version"),
192 ("-e", "--exec", "noshell", False, "execute script only"),
193 ("-q", "--quiet", "quiet", False, "set quiet mode"),
194 ("-x", "--nowx", "nowx", False, "set no wx graphics mode"),
195 ("-w", "--wxgui", "wxgui", False, "run Larch GUI"),
196 ("-m", "--makeicons", "makeicons", False, "create desktop icons"),
197 ("-u", "--update", "update", False, "update larch to the latest version"),
198 ("-r", "--remote", "server_mode", False, "run in remote server mode"),
199 ("-p", "--port", "port", "4966", "port number for remote server"))
201 for opt, longopt, dest, default, help in sargs:
202 parser.add_argument(opt, longopt, dest=dest, action='store_true',
203 default=default, help=help)
205 parser.add_argument('scripts', nargs='*',
206 help='larch or python scripts to run on startup')
208 args = parser.parse_args()
209 if args.version:
210 print(make_banner(with_libraries=True))
211 vinfo = check_larchversion()
212 if vinfo.update_available:
213 print(vinfo.message)
214 return
216 with_wx = HAS_WXPYTHON and (not args.nowx)
218 # create desktop icons
219 if args.makeicons:
220 larchdir = Path(get_desktop(), 'Larch').absolute()
221 if Path(larchdir).exists():
222 shutil.rmtree(larchdir)
224 for n, app in LarchApps.items():
225 app.make_desktop_shortcut()
226 return
228 # run updates
229 if args.update:
230 update_larch()
231 return
233 # run in server mode
234 if args.server_mode:
235 if with_wx:
236 use_mpl_wxagg()
237 vinfo = check_larchversion()
238 if vinfo.update_available:
239 print(vinfo.message)
240 from .xmlrpc_server import LarchServer
241 server = LarchServer(host='localhost', port=int(args.port))
242 server.run()
244 # run wx Larch GUI
245 elif args.wxgui:
246 set_locale()
247 use_mpl_wxagg()
248 from .wxlib.larchframe import LarchApp
249 LarchApp(with_inspection=True).MainLoop()
251 # run wx Larch CLI
252 else:
253 if with_wx:
254 set_locale()
255 use_mpl_wxagg()
256 vinfo = check_larchversion()
257 if vinfo.update_available:
258 print(vinfo.message)
260 from .shell import Shell
261 cli = Shell(quiet=args.quiet, with_wx=with_wx)
262 # execute scripts listed on command-line
263 if args.scripts is not None:
264 for script in args.scripts:
265 if script.endswith('.py'):
266 cmd = f"import {script[:-3]}"
267 else:
268 cmd = f"run('{script}')"
269 cli.default(cmd)
270 # if interactive, start command loop
271 if not args.noshell:
272 try:
273 cli.cmdloop()
274 except ValueError:
275 pass