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
« 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
5"""
7import os
8import platform
9import sys
10import time
11import json
12import socket
13import datetime
14from functools import partial
15from threading import Thread
17import wx
18import wx.lib.scrolledpanel as scrolled
19import wx.lib.mixins.inspection
20try:
21 from wx._core import PyDeadObjectError
22except:
23 PyDeadObjectError = Exception
25import numpy as np
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
32from ..xrmmap import GSEXRM_MapFile, GSEXRM_FileStatus, h5str, ensure_subgroup
34CEN = wx.ALIGN_CENTER
35LEFT = wx.ALIGN_LEFT
36RIGHT = wx.ALIGN_RIGHT
37ALL_CEN = wx.ALL|CEN
38ALL_LEFT = wx.ALL|LEFT
40VARNAMES = ('a', 'b', 'c', 'd', 'e', 'f')
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):
47 self.map = None
48 self.cfile = None
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)
64 save_arr = Button(self, 'Save Array', size=(120, -1),
65 action=self.onSaveArray)
67 self.expr_in = wx.TextCtrl(self, -1, '', size=(180, -1))
68 self.name_in = wx.TextCtrl(self, -1, '', size=(180, -1))
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)
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)
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)
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)
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)
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)
118 ir += 1
119 sizer.Add(HLine(self, size=(350, 4)), (ir, 0), (1, 5), ALL_LEFT, 2)
121 ir += 1
122 sizer.Add(SimpleText(self, 'Work Arrays: '), (ir, 0), (1, 1), ALL_LEFT, 2)
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))
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)
137 pack(self, sizer)
138 self.SetupScrolling()
140 def on_select(self):
141 for v in VARNAMES:
142 self.onFILE(evt=None, varname=v)
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)
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))
160 def onDeleteArray(self, evt=None):
161 name = self.workarray_choice.GetStringSelection()
162 xrmfile = self.owner.current_file
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)
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)))
183 if self.map is None:
184 self.onShowMap()
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))
198 for p in self.owner.nb.pagelist:
199 if hasattr(p, 'update_xrmmap'):
200 p.update_xrmmap(xrmfile=xrmfile, set_detectors=True)
202 def onFILE(self, evt=None, varname='a'):
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))
209 def onDET(self, evt, varname='a'):
210 self.set_roi_choices(varname=varname)
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()
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)
222 def update_xrmmap(self, xrmfile=None, set_detectors=None):
223 if xrmfile is None:
224 xrmfile = self.owner.current_file
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)
232 for vfile in self.varfile.values():
233 vfile.SetSelection(-1)
234 self.info1.SetLabel('')
235 self.info2.SetLabel('')
237 def set_det_choices(self, varname=None):
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)
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)
260 def update_roi(self, detname):
261 return self.cfile.get_roi_list(detname)
263 def set_workarray_choices(self, xrmmap):
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)
272 def set_file_choices(self, fnames):
273 for wid in self.varfile.values():
274 wid.SetChoices(fnames)
276 for varname in VARNAMES:
277 fname = self.varfile[varname].GetStringSelection()
278 if fname in (None, 'None', ''):
279 self.varfile[varname].SetSelection(0)
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)
290 files = []
291 _larch = self.owner.larch
292 filemap = self.owner.filemap
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()
308 map = filemap[fname].get_roimap(roiname, det=dname, dtcorrect=dtcorr)
309 _larch.symtable.set_symbol(str(varname), map)
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
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
328 if len(self.owner.im_displays) == 0 or new:
329 iframe = self.owner.add_imdisplay(title)
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))