Coverage for larch/wxmap/mapmathpanel.py: 18%

241 statements  

« prev     ^ index     » next       coverage.py v7.6.0, created at 2024-10-16 21:04 +0000

1#!/usr/bin/env python 

2""" 

3GUI for displaying maps from HDF5 files 

4 

5""" 

6 

7import os 

8import platform 

9import sys 

10import time 

11import json 

12import socket 

13import datetime 

14from functools import partial 

15from threading import Thread 

16 

17import wx 

18import wx.lib.scrolledpanel as scrolled 

19import wx.lib.mixins.inspection 

20try: 

21 from wx._core import PyDeadObjectError 

22except: 

23 PyDeadObjectError = Exception 

24 

25import numpy as np 

26 

27from ..wxlib import (LarchPanel, LarchFrame, EditableListBox, SimpleText, 

28 FloatCtrl, Font, pack, Popup, Button, MenuItem, 

29 Choice, Check, GridPanel, FileSave, HLine) 

30from ..utils.strutils import bytes2str, version_ge 

31 

32from ..xrmmap import GSEXRM_MapFile, GSEXRM_FileStatus, h5str, ensure_subgroup 

33 

34CEN = wx.ALIGN_CENTER 

35LEFT = wx.ALIGN_LEFT 

36RIGHT = wx.ALIGN_RIGHT 

37ALL_CEN = wx.ALL|CEN 

38ALL_LEFT = wx.ALL|LEFT 

39 

40VARNAMES = ('a', 'b', 'c', 'd', 'e', 'f') 

41 

42class MapMathPanel(scrolled.ScrolledPanel): 

43 """Panel of Controls for doing math on arrays from Map data""" 

44 label = 'Map Math' 

45 def __init__(self, parent, owner=None, **kws): 

46 

47 self.map = None 

48 self.cfile = None 

49 

50 scrolled.ScrolledPanel.__init__(self, parent, -1, 

51 style=wx.GROW|wx.TAB_TRAVERSAL, **kws) 

52 self.owner = owner 

53 sizer = wx.GridBagSizer(3, 3) 

54 bpanel = wx.Panel(self) 

55 show_new = Button(bpanel, 'Show New Map', size=(125, -1), 

56 action=partial(self.onShowMap, new=True)) 

57 show_old = Button(bpanel, 'Replace Last Map', size=(125, -1), 

58 action=partial(self.onShowMap, new=False)) 

59 bsizer = wx.BoxSizer(wx.HORIZONTAL) 

60 bsizer.Add(show_new, 0, 3) 

61 bsizer.Add(show_old, 0, 3) 

62 pack(bpanel, bsizer) 

63 

64 save_arr = Button(self, 'Save Array', size=(120, -1), 

65 action=self.onSaveArray) 

66 

67 self.expr_in = wx.TextCtrl(self, -1, '', size=(180, -1)) 

68 self.name_in = wx.TextCtrl(self, -1, '', size=(180, -1)) 

69 

70 ir = 0 

71 txt = """Enter Math Expressions for Map: a+b, (a-b)/c, log10(a+0.1), etc""" 

72 sizer.Add(SimpleText(self, txt), (ir, 0), (1, 6), ALL_LEFT, 2) 

73 

74 ir += 1 

75 sizer.Add(SimpleText(self, 'Expression:'), (ir, 0), (1, 1), ALL_CEN, 2) 

76 sizer.Add(self.expr_in, (ir, 1), (1, 1), ALL_LEFT, 2) 

77 sizer.Add(bpanel, (ir, 2), (1, 3), ALL_LEFT, 2) 

78 

79 ir += 1 

80 sizer.Add(SimpleText(self, 'Array Name:'), (ir, 0), (1, 1), ALL_CEN, 2) 

81 sizer.Add(self.name_in, (ir, 1), (1, 1), ALL_LEFT, 2) 

82 sizer.Add(save_arr, (ir, 2), (1, 1), ALL_LEFT, 2) 

83 

84 ir += 1 

85 sizer.Add(SimpleText(self, 'Array'), (ir, 0), (1, 1), ALL_CEN, 2) 

86 sizer.Add(SimpleText(self, 'File'), (ir, 1), (1, 1), ALL_CEN, 2) 

87 sizer.Add(SimpleText(self, 'Detector'), (ir, 2), (1, 1), ALL_CEN, 2) 

88 sizer.Add(SimpleText(self, 'ROI'), (ir, 3), (1, 1), ALL_CEN, 2) 

89 sizer.Add(SimpleText(self, 'DT Correct?'), (ir, 4), (1, 1), ALL_CEN, 2) 

90 sizer.Add(SimpleText(self, 'Array Shape'), (ir, 5), (1, 1), ALL_CEN, 2) 

91 

92 self.varfile = {} 

93 self.varroi = {} 

94 self.varshape = {} 

95 self.vardet = {} 

96 self.varcor = {} 

97 for varname in VARNAMES: 

98 self.varfile[varname] = vfile = Choice(self, size=(250, -1), 

99 action=partial(self.onFILE, varname=varname)) 

100 self.varroi[varname] = vroi = Choice(self, size=(125, -1), 

101 action=partial(self.onROI, varname=varname)) 

102 self.vardet[varname] = vdet = Choice(self, size=(100, -1), 

103 action=partial(self.onDET, varname=varname)) 

104 self.varcor[varname] = vcor = wx.CheckBox(self, -1, ' ') 

105 self.varshape[varname] = vshape = SimpleText(self, '(, )', 

106 size=(125, -1)) 

107 vcor.SetValue(self.owner.dtcor) 

108 vdet.SetSelection(0) 

109 

110 ir += 1 

111 sizer.Add(SimpleText(self, '%s = ' % varname), (ir, 0), (1, 1), ALL_CEN, 2) 

112 sizer.Add(vfile, (ir, 1), (1, 1), ALL_CEN, 2) 

113 sizer.Add(vdet, (ir, 2), (1, 1), ALL_CEN, 2) 

114 sizer.Add(vroi, (ir, 3), (1, 1), ALL_CEN, 2) 

115 sizer.Add(vcor, (ir, 4), (1, 1), ALL_CEN, 2) 

116 sizer.Add(vshape, (ir, 5), (1, 1), ALL_LEFT, 2) 

117 

118 ir += 1 

119 sizer.Add(HLine(self, size=(350, 4)), (ir, 0), (1, 5), ALL_LEFT, 2) 

120 

121 ir += 1 

122 sizer.Add(SimpleText(self, 'Work Arrays: '), (ir, 0), (1, 1), ALL_LEFT, 2) 

123 

124 self.workarray_choice = Choice(self, size=(200, -1), 

125 action=self.onSelectArray) 

126 btn_delete = Button(self, 'Delete Array', size=(90, -1), 

127 action=self.onDeleteArray) 

128 self.info1 = wx.StaticText(self, -1, '', size=(250, -1)) 

129 self.info2 = wx.StaticText(self, -1, '', size=(250, -1)) 

130 

131 

132 sizer.Add(self.workarray_choice, (ir, 1), (1, 1), ALL_LEFT, 2) 

133 sizer.Add(btn_delete, (ir, 2), (1, 1), ALL_LEFT, 2) 

134 sizer.Add(self.info1, (ir+1, 0), (1, 3), ALL_LEFT, 2) 

135 sizer.Add(self.info2, (ir+2, 0), (3, 3), ALL_LEFT, 2) 

136 

137 pack(self, sizer) 

138 self.SetupScrolling() 

139 

140 def on_select(self): 

141 for v in VARNAMES: 

142 self.onFILE(evt=None, varname=v) 

143 

144 

145 def onSelectArray(self, evt=None): 

146 xrmfile = self.owner.current_file 

147 name = self.workarray_choice.GetStringSelection() 

148 dset = xrmfile.get_work_array(h5str(name)) 

149 expr = bytes2str(dset.attrs.get('expression', '<unknonwn>')) 

150 self.info1.SetLabel("Expression: %s" % expr) 

151 

152 info = json.loads(bytes2str(dset.attrs.get('info', []))) 

153 buff = [] 

154 for var, dat in info: 

155 fname, aname, det, dtc = dat 

156 if dat[1] != '1': 

157 buff.append("%s= %s('%s', det=%s, dtcorr=%s)" % (var, fname, aname, det, dtc)) 

158 self.info2.SetLabel('\n'.join(buff)) 

159 

160 def onDeleteArray(self, evt=None): 

161 name = self.workarray_choice.GetStringSelection() 

162 xrmfile = self.owner.current_file 

163 

164 if (wx.ID_YES == Popup(self.owner, """Delete Array '%s' for %s? 

165 WARNING: This cannot be undone 

166 """ % (name, xrmfile.filename), 

167 'Delete Array?', style=wx.YES_NO)): 

168 xrmfile.del_work_array(h5str(name)) 

169 self.update_xrmmap(xrmfile) 

170 

171 def onSaveArray(self, evt=None): 

172 name = self.name_in.GetValue() 

173 expr = self.expr_in.GetValue() 

174 xrmfile = self.owner.current_file 

175 info = [] 

176 for varname in sorted(self.varfile.keys()): 

177 fname = self.varfile[varname].GetStringSelection() 

178 roiname = self.varroi[varname].GetStringSelection() 

179 dname = self.vardet[varname].GetStringSelection() 

180 dtcorr = self.varcor[varname].IsChecked() 

181 info.append((varname, (fname, roiname, dname, dtcorr))) 

182 

183 if self.map is None: 

184 self.onShowMap() 

185 

186 if name in xrmfile.work_array_names(): 

187 if (wx.ID_YES == Popup(self.owner, """Overwrite Array '%s' for %s? 

188 WARNING: This cannot be undone 

189 """ % (name, xrmfile.filename), 

190 'Overwrite Array?', style=wx.YES_NO)): 

191 xrmfile.del_work_array(h5str(name)) 

192 else: 

193 return 

194 xrmfile.add_work_array(self.map, h5str(name), 

195 expression=h5str(expr), 

196 info=json.dumps(info)) 

197 

198 for p in self.owner.nb.pagelist: 

199 if hasattr(p, 'update_xrmmap'): 

200 p.update_xrmmap(xrmfile=xrmfile, set_detectors=True) 

201 

202 def onFILE(self, evt=None, varname='a'): 

203 

204 fname = self.varfile[varname].GetStringSelection() 

205 if fname not in (None, 'None', ''): 

206 shape = self.owner.filemap[fname].get_shape() 

207 self.varshape[varname].SetLabel('%s' % repr(shape)) 

208 

209 def onDET(self, evt, varname='a'): 

210 self.set_roi_choices(varname=varname) 

211 

212 def onROI(self, evt, varname='a'): 

213 fname = self.varfile[varname].GetStringSelection() 

214 roiname = self.varroi[varname].GetStringSelection() 

215 dname = self.vardet[varname].GetStringSelection() 

216 dtcorr = self.varcor[varname].IsChecked() 

217 

218 shape = self.owner.filemap[fname].get_shape() 

219 self.varshape[varname].SetLabel('%s' % repr(shape)) 

220 map = self.owner.filemap[fname].get_roimap(roiname, det=dname, dtcorrect=dtcorr) 

221 

222 def update_xrmmap(self, xrmfile=None, set_detectors=None): 

223 if xrmfile is None: 

224 xrmfile = self.owner.current_file 

225 

226 self.cfile = xrmfile 

227 self.xrmmap = xrmfile.xrmmap 

228 self.set_file_choices(self.owner.filelist.GetItems()) 

229 self.set_det_choices() 

230 self.set_workarray_choices(self.xrmmap) 

231 

232 for vfile in self.varfile.values(): 

233 vfile.SetSelection(-1) 

234 self.info1.SetLabel('') 

235 self.info2.SetLabel('') 

236 

237 def set_det_choices(self, varname=None): 

238 

239 det_list = self.cfile.get_detector_list() 

240 if varname is None: 

241 for wid in self.vardet.values(): 

242 wid.SetChoices(det_list) 

243 else: 

244 self.vardet[varname].SetChoices(det_list) 

245 self.set_roi_choices(varname=varname) 

246 

247 

248 def set_roi_choices(self, varname=None): 

249 if varname is None: 

250 for varname in self.vardet.keys(): 

251 dname = self.vardet[varname].GetStringSelection() 

252 rois = self.update_roi(dname) 

253 self.varroi[varname].SetChoices(rois) 

254 else: 

255 dname = self.vardet[varname].GetStringSelection() 

256 rois = self.update_roi(dname) 

257 self.varroi[varname].SetChoices(rois) 

258 

259 

260 def update_roi(self, detname): 

261 return self.cfile.get_roi_list(detname) 

262 

263 def set_workarray_choices(self, xrmmap): 

264 

265 c = self.workarray_choice 

266 c.Clear() 

267 if 'work' in xrmmap: 

268 choices = [a for a in xrmmap['work']] 

269 c.AppendItems(choices) 

270 c.SetSelection(len(choices)-1) 

271 

272 def set_file_choices(self, fnames): 

273 for wid in self.varfile.values(): 

274 wid.SetChoices(fnames) 

275 

276 for varname in VARNAMES: 

277 fname = self.varfile[varname].GetStringSelection() 

278 if fname in (None, 'None', ''): 

279 self.varfile[varname].SetSelection(0) 

280 

281 

282 def onShowMap(self, event=None, new=True): 

283 def get_expr(wid): 

284 val = str(wid.Value) 

285 if len(val) == 0: 

286 val = '1' 

287 return val 

288 expr_in = get_expr(self.expr_in) 

289 

290 files = [] 

291 _larch = self.owner.larch 

292 filemap = self.owner.filemap 

293 

294 for varname in self.varfile.keys(): 

295 try: 

296 _larch.symtable.get_symbol(varname) 

297 _larch.symtable.del_symbol(str(varname)) 

298 except: 

299 pass 

300 fname = self.varfile[varname].GetStringSelection() 

301 if fname in filemap: 

302 if fname not in files: 

303 files.append(fname) 

304 roiname = self.varroi[varname].GetStringSelection() 

305 dname = self.vardet[varname].GetStringSelection() 

306 dtcorr = self.varcor[varname].IsChecked() 

307 

308 map = filemap[fname].get_roimap(roiname, det=dname, dtcorrect=dtcorr) 

309 _larch.symtable.set_symbol(str(varname), map) 

310 

311 _larch.eval("_mapcalc = %s" % expr_in) 

312 self.map = _larch.symtable._mapcalc 

313 omap = self.map[:, 1:-1] 

314 info = 'Intensity: [%g, %g]' %(omap.min(), omap.max()) 

315 title = '%se: %s' % (fname, expr_in) 

316 subtitles = None 

317 

318 main_file = filemap[files[0]] 

319 try: 

320 x = main_file.get_pos(0, mean=True) 

321 except: 

322 x = None 

323 try: 

324 y = main_file.get_pos(1, mean=True) 

325 except: 

326 y = None 

327 

328 if len(self.owner.im_displays) == 0 or new: 

329 iframe = self.owner.add_imdisplay(title) 

330 

331 self.owner.display_map(omap, title=title, subtitles=subtitles, 

332 info=info, x=x, y=y, xrmfile=main_file, 

333 with_savepos=(len(files)==1))