Coverage for larch/apps.py: 26%

156 statements  

« 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 

10 

11import matplotlib 

12 

13from .site_config import icondir, uname, update_larch 

14from .version import __date__, make_banner, check_larchversion 

15 

16HAS_WXPYTHON = False 

17try: 

18 import wx 

19 HAS_WXPYTHON = True 

20except ImportError: 

21 pass 

22 

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 

27 

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 

35 

36def set_locale(): 

37 """set locale to 'C' for these applications""" 

38 locale.setlocale(locale.LC_ALL, 'C') 

39 

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' 

50 

51 def make_desktop_shortcut(self, folder='Larch'): 

52 pass 

53 

54 def prep_cli(self): 

55 parser = ArgumentParser(description=self.description) 

56 parser.add_argument('filename', nargs='?', help=self.filetype) 

57 

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') 

62 

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() 

72 

73 

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# 

85 

86 

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), 

96 

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 } 

107 

108 

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() 

117 

118 

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() 

126 

127run_xas_viewer = run_larix 

128 

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() 

135 

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]"`') 

145 

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() 

152 

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() 

159 

160def run_gse_dtcorrect(): 

161 """GSE DT Correct """ 

162 set_locale() 

163 use_mpl_wxagg() 

164 from .wxmap import DTViewer 

165 DTViewer().MainLoop() 

166 

167 

168def run_feff6l(): 

169 "run feff6l" 

170 from .xafs.feffrunner import feff6l_cli 

171 feff6l_cli() 

172 

173def run_feff8l(): 

174 "run feff8l" 

175 from .xafs.feffrunner import feff8l_cli 

176 feff8l_cli() 

177 

178def run_larch_server(): 

179 "run larch XMLRPC server" 

180 from .xmlrpc_server import larch_server_cli 

181 larch_server_cli() 

182 

183 

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")) 

200 

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) 

204 

205 parser.add_argument('scripts', nargs='*', 

206 help='larch or python scripts to run on startup') 

207 

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 

215 

216 with_wx = HAS_WXPYTHON and (not args.nowx) 

217 

218 # create desktop icons 

219 if args.makeicons: 

220 larchdir = Path(get_desktop(), 'Larch').absolute() 

221 if Path(larchdir).exists(): 

222 shutil.rmtree(larchdir) 

223 

224 for n, app in LarchApps.items(): 

225 app.make_desktop_shortcut() 

226 return 

227 

228 # run updates 

229 if args.update: 

230 update_larch() 

231 return 

232 

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() 

243 

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() 

250 

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) 

259 

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