Coverage for larch/wxlib/specfile_importer.py: 9%
479 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"""
4"""
5from pathlib import Path
7import numpy as np
8np.seterr(all='ignore')
10from functools import partial
12import wx
13import wx.lib.scrolledpanel as scrolled
14import wx.lib.agw.flatnotebook as fnb
15from wxmplot import PlotPanel
17from wxutils import (SimpleText, FloatCtrl, GUIColors, Button, Choice,
18 FileCheckList, pack, Popup, Check, MenuItem, CEN,
19 RIGHT, LEFT, FRAMESTYLE, HLine, Font)
21import larch
22from larch import Group
23from larch.utils.strutils import fix_varname
24from larch.xafs.xafsutils import guess_energy_units
25from larch.io import look_for_nans, is_specfile, open_specfile
26from larch.utils.physical_constants import PLANCK_HC, DEG2RAD, PI
27from .columnframe import MultiColumnFrame, create_arrays, energy_may_need_rebinning
29CEN |= wx.ALL
30FNB_STYLE = fnb.FNB_NO_X_BUTTON|fnb.FNB_SMART_TABS
31FNB_STYLE |= fnb.FNB_NO_NAV_BUTTONS|fnb.FNB_NODRAG
33XPRE_OPS = ('', 'log(', '-log(')
34YPRE_OPS = ('', 'log(', '-log(')
35ARR_OPS = ('+', '-', '*', '/')
37YERR_OPS = ('Constant', 'Sqrt(Y)', 'Array')
38CONV_OPS = ('Lorenztian', 'Gaussian')
40XDATATYPES = ('xydata', 'xas')
41ENUNITS_TYPES = ('eV', 'keV', 'degrees', 'not energy')
44class SpecfileImporter(wx.Frame) :
45 """Column Data File, select columns"""
46 def __init__(self, parent, filename=None, config=None, _larch=None,
47 read_ok_cb=None):
48 if not is_specfile(filename):
49 title = "Not a Specfile: %s" % filename
50 message = "Error reading %s as a Specfile" % filename
51 r = Popup(parent, message, title)
52 return None
54 self.parent = parent
55 fpath = Path(filename).absolute()
56 self.path = fpath.as_posix()
57 self.filename = fpath.name
58 self._larch = _larch
59 self.specfile = open_specfile(self.path)
60 self.scans = []
61 curscan = None
62 for scandata in self.specfile.get_scans():
63 name, cmd, dtime = scandata
64 self.scans.append("%s | %s" % (name, cmd))
65 if curscan is None:
66 curscan = name
68 self.curscan = self.specfile.get_scan(curscan)
69 self.subframes = {}
70 self.workgroup = Group()
71 for attr in ('path', 'filename', 'datatype',
72 'array_labels', 'data'):
73 setattr(self.workgroup, attr, None)
75 self.array_labels = [l.lower() for l in self.curscan.array_labels]
77 if self.workgroup.datatype is None:
78 self.workgroup.datatype = 'xydata'
79 for arrlab in self.array_labels[:4]:
80 if 'ener' in arrlab.lower():
81 self.workgroup.datatype = 'xas'
83 self.read_ok_cb = read_ok_cb
85 self.config = dict(xarr=self.curscan.axis.lower(), yarr1=None,
86 yarr2=None, yop='/', ypop='',
87 monod=3.1355316, en_units='eV',
88 yerror=YERR_OPS[0], yerr_val=1,
89 yerr_arr=None, dtc_config={}, multicol_config={})
91 if config is not None:
92 self.config.update(config)
94 if self.config['yarr2'] is None and 'i0' in self.array_labels:
95 self.config['yarr2'] = 'i0'
97 if self.config['yarr1'] is None:
98 if 'itrans' in self.array_labels:
99 self.config['yarr1'] = 'itrans'
100 elif 'i1' in self.array_labels:
101 self.config['yarr1'] = 'i1'
103 wx.Frame.__init__(self, None, -1, f'Build Arrays for {filename:s}',
104 style=FRAMESTYLE)
106 self.SetMinSize((750, 550))
107 self.SetSize((850, 650))
108 self.colors = GUIColors()
110 x0, y0 = parent.GetPosition()
111 self.SetPosition((x0+60, y0+60))
112 self.SetFont(Font(10))
114 splitter = wx.SplitterWindow(self, style=wx.SP_LIVE_UPDATE)
115 splitter.SetMinimumPaneSize(200)
117 leftpanel = wx.Panel(splitter)
118 ltop = wx.Panel(leftpanel)
120 sel_none = Button(ltop, 'Select None', size=(100, 30), action=self.onSelNone)
121 sel_all = Button(ltop, 'Select All', size=(100, 30), action=self.onSelAll)
122 sel_imp = Button(ltop, 'Import Selected Scans', size=(200, -1), action=self.onOK)
124 self.scanlist = FileCheckList(leftpanel, select_action=self.onScanSelect)
125 self.scanlist.AppendItems(self.scans)
127 tsizer = wx.GridBagSizer(2, 2)
128 tsizer.Add(sel_all, (0, 0), (1, 1), LEFT, 0)
129 tsizer.Add(sel_none, (0, 1), (1, 1), LEFT, 0)
130 tsizer.Add(sel_imp, (1, 0), (1, 2), LEFT, 0)
131 pack(ltop, tsizer)
133 sizer = wx.BoxSizer(wx.VERTICAL)
134 sizer.Add(ltop, 0, LEFT|wx.GROW, 1)
135 sizer.Add(self.scanlist, 1, LEFT|wx.GROW|wx.ALL, 1)
136 pack(leftpanel, sizer)
138 # right hand side
139 rightpanel = wx.Panel(splitter)
141 panel = wx.Panel(rightpanel)
142 # title row
143 self.title = SimpleText(panel,
144 " %s, scan %s" % (self.path, self.curscan.scan_name),
145 font=Font(11), colour=self.colors.title, style=LEFT)
147 self.wid_scantitle = SimpleText(panel, " %s" % self.curscan.title,
148 font=Font(11), style=LEFT)
149 self.wid_scantime = SimpleText(panel, self.curscan.timestring,
150 font=Font(11), style=LEFT)
152 yarr_labels = self.yarr_labels = self.array_labels + ['1.0', '0.0', '']
153 xarr_labels = self.xarr_labels = self.array_labels + ['_index']
155 self.xarr = Choice(panel, choices=xarr_labels, action=self.onXSelect, size=(150, -1))
156 self.yarr1 = Choice(panel, choices=yarr_labels, action=self.onUpdate, size=(150, -1))
157 self.yarr2 = Choice(panel, choices=yarr_labels, action=self.onUpdate, size=(150, -1))
158 self.yerr_arr = Choice(panel, choices=yarr_labels, action=self.onUpdate, size=(150, -1))
159 self.yerr_arr.Disable()
161 self.datatype = Choice(panel, choices=XDATATYPES, action=self.onUpdate, size=(150, -1))
162 self.datatype.SetStringSelection(self.workgroup.datatype)
164 self.en_units = Choice(panel, choices=ENUNITS_TYPES, action=self.onEnUnitsSelect,
165 size=(150, -1))
167 self.ypop = Choice(panel, choices=YPRE_OPS, action=self.onUpdate, size=(150, -1))
168 self.yop = Choice(panel, choices=ARR_OPS, action=self.onUpdate, size=(50, -1))
169 self.yerr_op = Choice(panel, choices=YERR_OPS, action=self.onYerrChoice, size=(150, -1))
171 self.yerr_val = FloatCtrl(panel, value=1, precision=4, size=(90, -1))
172 self.monod_val = FloatCtrl(panel, value=3.1355316, precision=7, size=(90, -1))
174 xlab = SimpleText(panel, ' X array: ')
175 ylab = SimpleText(panel, ' Y array: ')
176 units_lab = SimpleText(panel, ' Units: ')
177 yerr_lab = SimpleText(panel, ' Yerror: ')
178 dtype_lab = SimpleText(panel, ' Data Type: ')
179 monod_lab = SimpleText(panel, ' Mono D spacing (Ang): ')
180 yerrval_lab = SimpleText(panel, ' Value:')
182 self.ysuf = SimpleText(panel, '')
183 self.message = SimpleText(panel, '-', font=Font(11),
184 colour=self.colors.title, style=LEFT)
186 self.ypop.SetStringSelection(self.config['ypop'])
187 self.yop.SetStringSelection(self.config['yop'])
188 self.monod_val.SetValue(self.config['monod'])
189 self.monod_val.SetAction(self.onUpdate)
191 self.monod_val.Enable(self.config['en_units'].startswith('deg'))
192 self.en_units.SetStringSelection(self.config['en_units'])
193 self.yerr_op.SetStringSelection(self.config['yerror'])
194 self.yerr_val.SetValue(self.config['yerr_val'])
195 if '(' in self.config['ypop']:
196 self.ysuf.SetLabel(')')
198 ixsel, iysel, iy2sel, iyesel = 0, 1, len(yarr_labels)-1, len(yarr_labels)-1
199 if self.config['xarr'] in xarr_labels:
200 ixsel = xarr_labels.index(self.config['xarr'])
201 if self.config['yarr1'] in self.array_labels:
202 iysel = self.array_labels.index(self.config['yarr1'])
203 if self.config['yarr2'] in yarr_labels:
204 iy2sel = yarr_labels.index(self.config['yarr2'])
205 if self.config['yerr_arr'] in yarr_labels:
206 iyesel = yarr_labels.index(self.config['yerr_arr'])
207 self.xarr.SetSelection(ixsel)
208 self.yarr1.SetSelection(iysel)
209 self.yarr2.SetSelection(iy2sel)
210 self.yerr_arr.SetSelection(iyesel)
212 bpanel = wx.Panel(panel)
213 bsizer = wx.BoxSizer(wx.HORIZONTAL)
214 self.multi_sel = Button(bpanel, 'Select Multilple Columns', action=self.onMultiColumn)
215 self.multi_clear = Button(bpanel, 'Clear Multiple Columns', action=self.onClearMultiColumn)
216 self.multi_clear.Disable()
217 self.multi_sel.SetToolTip('Select Multiple Columns to import as separate groups')
218 self.multi_clear.SetToolTip('Clear Multiple Column Selection')
219 bsizer.Add(self.multi_sel)
220 bsizer.Add(self.multi_clear)
221 pack(bpanel, bsizer)
223 sizer = wx.GridBagSizer(2, 2)
224 ir = 0
225 sizer.Add(self.title, (ir, 0), (1, 7), LEFT, 5)
227 ir += 1
228 sizer.Add(self.wid_scantitle, (ir, 0), (1, 3), LEFT, 0)
229 sizer.Add(self.wid_scantime, (ir, 3), (1, 2), LEFT, 0)
232 ir += 1
233 sizer.Add(xlab, (ir, 0), (1, 1), LEFT, 0)
234 sizer.Add(self.xarr, (ir, 1), (1, 1), LEFT, 0)
235 sizer.Add(units_lab, (ir, 2), (1, 2), RIGHT, 0)
236 sizer.Add(self.en_units, (ir, 4), (1, 2), LEFT, 0)
238 ir += 1
239 sizer.Add(dtype_lab, (ir, 0), (1, 1), LEFT, 0)
240 sizer.Add(self.datatype, (ir, 1), (1, 1), LEFT, 0)
241 sizer.Add(monod_lab, (ir, 2), (1, 2), RIGHT, 0)
242 sizer.Add(self.monod_val, (ir, 4), (1, 1), LEFT, 0)
244 ir += 1
245 sizer.Add(ylab, (ir, 0), (1, 1), LEFT, 0)
246 sizer.Add(self.ypop, (ir, 1), (1, 1), LEFT, 0)
247 sizer.Add(self.yarr1, (ir, 2), (1, 1), LEFT, 0)
248 sizer.Add(self.yop, (ir, 3), (1, 1), RIGHT, 0)
249 sizer.Add(self.yarr2, (ir, 4), (1, 1), LEFT, 0)
250 sizer.Add(self.ysuf, (ir, 5), (1, 1), LEFT, 0)
252 ir += 1
253 sizer.Add(yerr_lab, (ir, 0), (1, 1), LEFT, 0)
254 sizer.Add(self.yerr_op, (ir, 1), (1, 1), LEFT, 0)
255 sizer.Add(self.yerr_arr, (ir, 2), (1, 1), LEFT, 0)
256 sizer.Add(yerrval_lab, (ir, 3), (1, 1), RIGHT, 0)
257 sizer.Add(self.yerr_val, (ir, 4), (1, 2), LEFT, 0)
259 ir += 1
260 sizer.Add(self.message, (ir, 0), (1, 4), LEFT, 0)
261 ir +=1
262 sizer.Add(bpanel, (ir, 0), (1, 5), LEFT, 3)
264 pack(panel, sizer)
266 self.nb = fnb.FlatNotebook(rightpanel, -1, agwStyle=FNB_STYLE)
267 self.nb.SetTabAreaColour(wx.Colour(248,248,240))
268 self.nb.SetActiveTabColour(wx.Colour(254,254,195))
269 self.nb.SetNonActiveTabTextColour(wx.Colour(40,40,180))
270 self.nb.SetActiveTabTextColour(wx.Colour(80,0,0))
272 self.plotpanel = PlotPanel(rightpanel, messenger=self.plot_messages)
273 try:
274 plotopts = self._larch.symtable._sys.wx.plotopts
275 self.plotpanel.conf.set_theme(plotopts['theme'])
276 self.plotpanel.conf.enable_grid(plotopts['show_grid'])
277 except:
278 pass
280 self.plotpanel.SetMinSize((300, 250))
282 shead = wx.Panel(rightpanel)
283 self.scanheader = wx.TextCtrl(shead, style=wx.TE_MULTILINE|wx.TE_READONLY,
284 size=(400, 250))
285 self.scanheader.SetValue('\n'.join(self.curscan.scan_header))
286 self.scanheader.SetFont(Font(10))
287 textsizer = wx.BoxSizer(wx.VERTICAL)
288 textsizer.Add(self.scanheader, 1, LEFT|wx.GROW, 1)
289 pack(shead, textsizer)
292 fhead = wx.Panel(rightpanel)
293 self.fileheader = wx.TextCtrl(fhead, style=wx.TE_MULTILINE|wx.TE_READONLY,
294 size=(400, 250))
295 self.fileheader.SetValue('\n'.join(self.curscan.file_header))
296 self.fileheader.SetFont(Font(10))
297 textsizer = wx.BoxSizer(wx.VERTICAL)
298 textsizer.Add(self.fileheader, 1, LEFT|wx.GROW, 1)
299 pack(fhead, textsizer)
303 self.nb.AddPage(fhead, ' File Header ', True)
304 self.nb.AddPage(shead, ' Scan Header ', True)
305 self.nb.AddPage(self.plotpanel, ' Plot of Selected Arrays ', True)
307 sizer = wx.BoxSizer(wx.VERTICAL)
308 sizer.Add(panel, 0, LEFT|wx.GROW, 1)
309 sizer.Add(self.nb, 1, LEFT|wx.GROW|wx.ALL, 1)
310 pack(rightpanel, sizer)
312 splitter.SplitVertically(leftpanel, rightpanel, 1)
313 self.statusbar = self.CreateStatusBar(2, 0)
314 self.statusbar.SetStatusWidths([-1, -1])
315 statusbar_fields = [filename, ""]
316 for i in range(len(statusbar_fields)):
317 self.statusbar.SetStatusText(statusbar_fields[i], i)
319 self.set_energy_units()
320 csize = self.GetSize()
321 bsize = self.GetBestSize()
322 if bsize[0] > csize[0]: csize[0] = bsize[0]
323 if bsize[1] > csize[1]: csize[1] = bsize[1]
324 self.SetSize(csize)
325 self.Show()
326 self.Raise()
327 self.onUpdate(self)
329 def set_energy_units(self):
330 ix = self.xarr.GetSelection()
331 xname = self.xarr.GetStringSelection()
332 rdata = self.curscan.data
333 try:
334 ncol, npts = rdata.shape
335 except:
336 self.statusbar.SetStatusText(f"Warning: Could not read data for scan '{self.curscan.title:s}'")
338 workgroup = self.workgroup
339 if xname.startswith('_index') or ix >= ncol:
340 workgroup.xplot = 1.0*np.arange(npts)
341 else:
342 workgroup.xplot = 1.0*rdata[ix, :]
343 eguess = guess_energy_units(workgroup.xplot)
344 if eguess.startswith('eV'):
345 self.en_units.SetStringSelection('eV')
346 elif eguess.startswith('keV'):
347 self.en_units.SetStringSelection('keV')
349 def onScanSelect(self, event=None):
350 try:
351 scan_desc = event.GetString()
352 name = [s.strip() for s in scan_desc.split(' | ')][0]
353 self.curscan = self.specfile.get_scan(name)
354 except:
355 return
356 slist = list(self.scanlist.GetCheckedStrings())
357 if scan_desc not in slist:
358 slist.append(scan_desc)
359 self.scanlist.SetCheckedStrings(slist)
361 self.wid_scantitle.SetLabel(" %s" % self.curscan.title)
362 self.wid_scantime.SetLabel(self.curscan.timestring)
364 self.title.SetLabel(" %s, scan %s" % (self.path, self.curscan.scan_name))
365 self.array_labels = [l.lower() for l in self.curscan.array_labels]
366 self.workgroup.array_labels = self.array_labels
367 self.workgroup.data = self.curscan.data
369 yarr_labels = self.yarr_labels = self.array_labels + ['1.0', '0.0', '']
370 xarr_labels = self.xarr_labels = self.array_labels + ['_index']
372 xsel = self.xarr.GetStringSelection()
373 self.xarr.Clear()
374 self.xarr.AppendItems(xarr_labels)
375 if xsel in xarr_labels:
376 self.xarr.SetStringSelection(xsel)
377 else:
378 self.xarr.SetSelection(0)
380 y1sel = self.yarr1.GetStringSelection()
381 self.yarr1.Clear()
382 self.yarr1.AppendItems(yarr_labels)
383 if y1sel in yarr_labels:
384 self.yarr1.SetStringSelection(y1sel)
385 else:
386 self.yarr1.SetSelection(1)
388 y2sel = self.yarr2.GetStringSelection()
389 self.yarr2.Clear()
390 self.yarr2.AppendItems(yarr_labels)
391 if y2sel in yarr_labels:
392 self.yarr2.SetStringSelection(y2sel)
394 xsel = self.xarr.GetStringSelection()
395 self.workgroup.datatype = 'xas' if 'en' in xsel else 'xydata'
396 self.datatype.SetStringSelection(self.workgroup.datatype)
398 self.scanheader.SetValue('\n'.join(self.curscan.scan_header))
399 self.set_energy_units()
400 self.onUpdate()
402 def onClearMultiColumn(self, event=None):
403 self.config['multicol_config'] = {}
404 self.message.SetLabel(f" cleared reading of multiple columns")
405 self.multi_clear.Disable()
406 self.yarr1.Enable()
407 self.ypop.Enable()
408 self.yop.Enable()
409 self.onUpdate()
411 def onMultiColumn(self, event=None):
412 if 'multicol_config' not in self.config:
413 self.config['multicol_config'] = {}
415 if len(self.array_labels) < 1:
416 self.array_labels = [l.lower() for l in self.curscan.array_labels]
417 self.workgroup.array_labels = self.array_labels
418 self.workgroup.data = self.curscan.data
419 self.show_subframe('multicol', MultiColumnFrame,
420 config=self.config['multicol_config'],
421 group=self.workgroup,
422 on_ok=self.onMultiColumn_OK)
424 def onMultiColumn_OK(self, config, update=True, **kws):
425 chans = config.get('channels', [])
426 if len(chans) == 0:
427 self.config['multicol_config'] = {}
428 else:
429 self.config['multicol_config'] = config
430 self.yarr1.SetSelection(chans[0])
431 self.yarr2.SetSelection(config['i0'])
432 self.ypop.SetStringSelection('')
433 self.yarr1.Disable()
434 self.ypop.Disable()
435 self.yop.Disable()
436 y2 = self.yarr2.GetStringSelection()
437 msg = f" Will import {len(config['channels'])} Y arrays, divided by '{y2}'"
438 self.message.SetLabel(msg)
439 self.multi_clear.Enable()
440 if update:
441 self.onUpdate()
444 def show_subframe(self, name, frameclass, **opts):
445 shown = False
446 if name in self.subframes:
447 try:
448 self.subframes[name].Raise()
449 shown = True
450 except:
451 pass
452 if not shown:
453 self.subframes[name] = frameclass(self, **opts)
454 self.subframes[name].Show()
455 self.subframes[name].Raise()
457 def set_array_labels(self, arr_labels):
458 self.workgroup.array_labels = arr_labels
459 yarr_labels = self.yarr_labels = arr_labels + ['1.0', '0.0', '']
460 xarr_labels = self.xarr_labels = arr_labels + ['_index']
461 def update(wid, choices):
462 curstr = wid.GetStringSelection()
463 curind = wid.GetSelection()
464 wid.SetChoices(choices)
465 if curstr in choices:
466 wid.SetStringSelection(curstr)
467 else:
468 wid.SetSelection(curind)
469 update(self.xarr, xarr_labels)
470 update(self.yarr1, yarr_labels)
471 update(self.yarr2, yarr_labels)
472 update(self.yerr_arr, yarr_labels)
473 self.onUpdate()
475 def onSelAll(self, event=None):
476 self.scanlist.SetCheckedStrings(self.scans)
478 def onSelNone(self, event=None):
479 self.scanlist.SetCheckedStrings([])
481 def onOK(self, event=None):
482 """ build arrays according to selection """
484 scanlist = []
485 for s in self.scanlist.GetCheckedStrings():
486 words = [s.strip() for s in s.split('|')]
487 scanlist.append(words[0])
488 if len(scanlist) == 0:
489 cancel = Popup(self, """No scans selected.
490 Cancel import from this project?""", 'Cancel Import?',
491 style=wx.YES_NO)
492 if wx.ID_YES == cancel:
493 self.Destroy()
494 else:
495 return
497 self.read_form()
498 cout = create_arrays(self.workgroup, **self.config)
499 self.config.update(cout)
500 conf = self.config
501 conf['array_labels'] = self.workgroup.array_labels
503 if self.ypop.Enabled: #not using multicolumn mode
504 conf['multicol_config'] = {'channels': [], 'i0': conf['iy2']}
506 self.expressions = conf['expressions']
508 # generate script to pass back to calling program:
509 # read_cmd = "_specfile.get_scan(scan='{scan}')"
510 buff = ["{group} = {specfile}.get_scan(scan='{scan}')",
511 "{group}.path = '{path}'",
512 "{group}.is_frozen = False"]
514 for attr in ('datatype', 'plot_xlabel', 'plot_ylabel'):
515 val = getattr(self.workgroup, attr)
516 buff.append("{group}.%s = '%s'" % (attr, val))
518 xexpr = self.expressions['xplot']
519 en_units = conf['en_units']
520 if en_units.startswith('deg'):
521 buff.append(f"mono_dspace = {dspace:.9f}")
522 buff.append(f"{ group} .xplot = PLANCK_HC/(2*mono_dspace*sin(DEG2RAD*({expr:s})))")
523 elif en_units.startswith('keV'):
524 buff.append(f"{ group} .xplot = 1000.0*{xexpr:s}")
525 else:
526 buff.append(f"{ group} .xplot = {xexpr:s}")
528 for aname in ('yplot', 'yerr'):
529 expr = self.expressions[aname]
530 buff.append(f"{ group} .{aname} = {expr}")
532 dtype = getattr(self.workgroup, 'datatype', 'xytype')
533 if dtype == 'xas':
534 buff.append("{group}.energy = {group}.xplot"[:])
535 buff.append("{group}.mu = {group}.yplot[:]")
536 buff.append("sort_xafs({group}, overwrite=True, fix_repeats=True)")
537 elif dtype == 'xydata':
538 buff.append("{group}.x = {group}.xplot[:]")
539 buff.append("{group}.y = {group}.yplot[:]")
540 buff.append("{group}.scale = (ptp({group}.yplot)+1.e-15)")
541 buff.append("{group}.xshift = 0.0")
543 script = "\n".join(buff)
545 self.config['array_desc'] = dict(xplot=self.workgroup.plot_xlabel,
546 yplot=self.workgroup.plot_ylabel,
547 yerr=self.expressions['yerr'])
548 if self.read_ok_cb is not None:
549 self.read_ok_cb(script, self.path, scanlist,
550 config=self.config)
552 for f in self.subframes.values():
553 try:
554 f.Destroy()
555 except:
556 pass
557 self.Destroy()
559 def onCancel(self, event=None):
560 self.workgroup.import_ok = False
561 for f in self.subframes.values():
562 try:
563 f.Destroy()
564 except:
565 pass
566 self.Destroy()
568 def onYerrChoice(self, evt=None):
569 yerr_choice = evt.GetString()
570 self.yerr_arr.Disable()
571 self.yerr_val.Disable()
572 if 'const' in yerr_choice.lower():
573 self.yerr_val.Enable()
574 elif 'array' in yerr_choice.lower():
575 self.yerr_arr.Enable()
576 self.onUpdate()
578 def onXSelect(self, evt=None):
579 ix = self.xarr.GetSelection()
580 xname = self.xarr.GetStringSelection()
582 workgroup = self.workgroup
583 rdata = self.curscan.data
584 ncol, npts = rdata.shape
585 if xname.startswith('_index') or ix >= ncol:
586 workgroup.xplot = 1.0*np.arange(npts)
587 else:
588 workgroup.xplot = 1.0*rdata[ix, :]
590 self.monod_val.Disable()
591 if self.datatype.GetStringSelection().strip().lower() == 'xydata':
592 self.en_units.SetSelection(4)
593 else:
594 eguess = guess_energy_units(workgroup.xplot)
595 if eguess.startswith('keV'):
596 self.en_units.SetSelection(1)
597 elif eguess.startswith('deg'):
598 self.en_units.SetSelection(2)
599 self.monod_val.Enable()
600 else:
601 self.en_units.SetSelection(0)
603 self.onUpdate()
605 def onEnUnitsSelect(self, evt=None):
606 self.monod_val.Enable(self.en_units.GetStringSelection().startswith('deg'))
607 self.onUpdate()
609 def read_form(self, **kws):
610 """return form configuration"""
611 datatype = self.datatype.GetStringSelection().strip().lower()
612 if datatype == 'xydata':
613 self.en_units.SetStringSelection('not energy')
615 conf = {'datatype': datatype,
616 'ix': self.xarr.GetSelection(),
617 'xarr': self.xarr.GetStringSelection(),
618 'en_units': self.en_units.GetStringSelection(),
619 'monod': float(self.monod_val.GetValue()),
620 'yarr1': self.yarr1.GetStringSelection().strip(),
621 'yarr2': self.yarr2.GetStringSelection().strip(),
622 'iy1': self.yarr1.GetSelection(),
623 'iy2': self.yarr2.GetSelection(),
624 'yop': self.yop.GetStringSelection().strip(),
625 'ypop': self.ypop.GetStringSelection().strip(),
626 'iyerr': self.yerr_arr.GetSelection(),
627 'yerr_arr': self.yerr_arr.GetStringSelection(),
628 'yerr_op': self.yerr_op.GetStringSelection().lower(),
629 'yerr_val': self.yerr_val.GetValue(),
630 }
631 self.config.update(conf)
632 return conf
635 def onUpdate(self, value=None, evt=None):
636 """column selections changed calc xplot and yplot"""
637 workgroup = self.workgroup
638 workgroup.data = self.curscan.data
639 workgroup.filename = self.curscan.filename
641 conf = self.read_form()
642 cout = create_arrays(workgroup, **conf)
644 self.expression = cout.pop('expressions')
645 conf.update(cout)
647 if energy_may_need_rebinning(workgroup):
648 self.message.SetLabel("Warning: XAS data may need to be rebinned!")
650 popts = dict(marker='o', markersize=4, linewidth=1.5,
651 title=Path(workgroup.filename).name,
652 ylabel=workgroup.plot_ylabel,
653 xlabel=workgroup.plot_xlabel,
654 label=workgroup.plot_ylabel)
655 try:
656 self.plotpanel.plot(workgroup.xplot, workgroup.yplot, **popts)
657 except:
658 pass
661 def plot_messages(self, msg, panel=1):
662 self.statusbar.SetStatusText(msg, panel)