Coverage for larch/wxxas/exafs_panel.py: 0%
496 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"""
3Linear Combination panel
4"""
5import os
6import time
7import copy
8import wx
9import numpy as np
11from functools import partial
13from larch.math import index_of
14from larch.wxlib import (BitmapButton, FloatCtrl, FloatSpin, ToggleButton,
15 get_icon, SimpleText, pack, Button, HLine, Choice,
16 TextCtrl, plotlabels, Check, CEN, RIGHT, LEFT)
18from larch.xafs.xafsutils import etok, ktoe, FT_WINDOWS
19from larch.xafs.pre_edge import find_e0
21from .xas_dialogs import EnergyUnitsDialog
22from .taskpanel import TaskPanel, update_confval
23from .config import ATHENA_CLAMPNAMES, PlotWindowChoices
25np.seterr(all='ignore')
27# plot options:
28mu_bkg = '\u03bC(E) + \u03bc0(E)'
29chie = '\u03c7(E)'
30chik = '\u03c7(k)'
31chikwin = '\u03c7(k) + Window(k)'
32chirmag = '|\u03c7(R)|'
33chirre = 'Re[\u03c7(R)]'
34chirmr = '|\u03c7(R)| + Re[\u03c7(R)]'
35wavelet = 'EXAFS wavelet'
36chir_w = '\u03c7(R) + Window(R)'
37chiq = 'Filtered \u03c7(k)'
38chikq = '\u03c7(k) + Filtered \u03c7(k)'
39noplot = '<no plot>'
41PlotOne_Choices = [mu_bkg, chie, chik, chikwin, chirmag, chirre, chirmr, wavelet,
42 chir_w, chiq, chikq]
43PlotAlt_Choices = [noplot] + PlotOne_Choices
44PlotSel_Choices = [chie, chik, chirmag, chirre, chiq]
47PlotCmds = {mu_bkg: "plot_bkg({group:s}, show_ek0={show_ek0}",
48 chie: "plot_chie({group:s}",
49 chik: "plot_chik({group:s}, show_window=False, kweight={plot_kweight:.0f}",
50 chikwin: "plot_chik({group:s}, show_window=True, kweight={plot_kweight:.0f}",
51 chirmag: "plot_chir({group:s}, show_mag=True, show_real=False, rmax={plot_rmax:.1f}",
52 chirre: "plot_chir({group:s}, show_mag=False, show_real=True, rmax={plot_rmax:.1f}",
53 chirmr: "plot_chir({group:s}, show_mag=True, show_real=True, rmax={plot_rmax:.1f}",
54 chir_w: "plot_chir({group:s}, show_mag=True, show_real=True, show_window=True, rmax={plot_rmax:.1f}",
55 chiq: "plot_chiq({group:s}, show_chik=False",
56 chikq: "plot_chiq({group:s}, show_chik=True",
57 wavelet: "plot_wavelet({group:s}, rmax={plot_rmax:.1f}",
58 noplot: None}
61CLAMPLIST = ('0', '1', '2', '5', '10', '20', '50', '100', '200', '500', '1000',
62 '2000', '5000', '10000')
64autobk_cmd = """autobk({group:s}, rbkg={rbkg: .3f}, ek0={ek0: .4f},
65 kmin={bkg_kmin: .3f}, kmax={bkg_kmax: .3f}, kweight={bkg_kweight: .1f},
66 clamp_lo={bkg_clamplo: .1f}, clamp_hi={bkg_clamphi: .1f})"""
68xftf_cmd = """xftf({group:s}, kmin={fft_kmin: .3f}, kmax={fft_kmax: .3f}, dk={fft_dk: .3f},
69 kweight={fft_kweight: .3f}, window='{fft_kwindow:s}', rmax_out={fft_rmaxout:.3f})"""
71xftr_cmd = """xftr({group:s}, rmin={fft_rmin: .3f}, rmax={fft_rmax: .3f},
72 dr={fft_dr: .3f}, window='{fft_rwindow:s}')"""
75class EXAFSPanel(TaskPanel):
76 """EXAFS Panel"""
77 def __init__(self, parent, controller, **kws):
78 TaskPanel.__init__(self, parent, controller, panel='exafs', **kws)
80 self.skip_process = False
81 self.last_plot = 'one'
82 self.last_process_bkg = {}
83 self.last_process_fft = {}
84 self.last_process_time = time.time() - 5000
86 def build_display(self):
87 panel = self.panel
88 wids = self.wids
89 self.skip_process = True
91 wids['plotone_op'] = Choice(panel, choices=PlotOne_Choices,
92 action=self.onPlotOne, size=(175, -1))
93 wids['plotalt_op'] = Choice(panel, choices=PlotAlt_Choices,
94 action=self.onPlotOne, size=(175, -1))
95 wids['plotsel_op'] = Choice(panel, choices=PlotSel_Choices,
96 action=self.onPlotSel, size=(175, -1))
98 wids['plotone_op'].SetStringSelection(chik)
99 wids['plotsel_op'].SetStringSelection(chik)
100 wids['plotalt_op'].SetStringSelection(noplot)
102 plot_one = Button(panel, 'Plot Current Group', size=(175, -1),
103 action=self.onPlotOne)
105 plot_sel = Button(panel, 'Plot Selected Groups', size=(175, -1),
106 action=self.onPlotSel)
108 ## saveconf = Button(panel, 'Save as Default Settings', size=(200, -1),
109 # action=self.onSaveConfigBtn)
111 wids['plot_voffset'] = FloatSpin(panel, value=0, digits=2, increment=0.25,
112 action=self.onProcess)
113 wids['plot_kweight'] = FloatSpin(panel, value=2, digits=1, increment=1,
114 action=self.onProcess,
115 min_val=0, max_val=5)
116 wids['plot_kweight_alt'] = FloatSpin(panel, value=2, digits=1, increment=1,
117 action=self.onProcess,
118 min_val=0, max_val=5)
120 wids['plot_rmax'] = FloatSpin(panel, value=8, digits=1, increment=0.5,
121 action=self.onProcess,
122 min_val=2, max_val=20)
123 wids['plot_win'] = Choice(panel, size=(60, -1), choices=PlotWindowChoices,
124 action=self.onProcess)
125 wids['plot_win'].SetStringSelection('2')
127 ek0_panel = wx.Panel(panel)
128 opts = dict(digits=2, increment=0.1, min_val=0, action=self.onProcess)
129 wids['ek0'] = FloatSpin(ek0_panel, **opts)
130 wids['show_ek0'] = Check(ek0_panel, default=True, label='show?',
131 action=self.onShowEk0)
132 sx = wx.BoxSizer(wx.HORIZONTAL)
133 sx.Add(self.wids['ek0'], 0, LEFT, 4)
134 sx.Add(self.wids['show_ek0'], 0, LEFT, 4)
135 pack(ek0_panel, sx)
137 wids['push_e0'] = Button(panel, 'Use as Normalization E0', size=(190, -1),
138 action=self.onPushE0)
139 wids['push_e0'].SetToolTip('Use this value for E0 in the Normalization Tab')
142 #
143 wids['plotopt_name'] = TextCtrl(panel, 'kspace, kw=2', size=(150, -1),
144 action=self.onPlotOptSave,
145 act_on_losefocus=False)
146 wids['plotopt_name'].SetToolTip('Name this set of Plot Choices')
148 self.plotopt_saves = {'kspace, kw=2': {'plotone_op': chik, 'plotsel_op': chik,
149 'plotalt_op': noplot, 'plot_voffset': 0.0,
150 'plot_kweight': 2, 'plot_kweight_alt': 2,
151 'plot_rmax': 8}}
153 wids['plotopt_sel'] = Choice(panel, size=(150, -1),
154 choices=list(self.plotopt_saves.keys()),
155 action=self.onPlotOptSel)
158 opts['max_val'] = 6
159 opts['action'] = self.onRbkg
160 wids['rbkg'] = FloatSpin(panel, value=1.0, **opts)
162 opts['action'] = self.onProcess
163 opts['max_val'] = 125
164 bkg_kmin = self.add_floatspin('bkg_kmin', value=0, with_pin=True, **opts)
165 bkg_kmax = self.add_floatspin('bkg_kmax', value=20, with_pin=True, **opts)
166 fft_kmin = self.add_floatspin('fft_kmin', value=0, with_pin=True, **opts)
167 fft_kmax = self.add_floatspin('fft_kmax', value=20, with_pin=True, **opts)
169 wids['fft_dk'] = FloatSpin(panel, value=3, **opts)
171 opts.update({'increment': 0.1, 'digits': 2, 'max_val': 20})
172 fft_rmin = self.add_floatspin('fft_rmin', value=1, with_pin=True, **opts)
173 fft_rmax = self.add_floatspin('fft_rmax', value=6, with_pin=True, **opts)
175 wids['fft_dr'] = FloatSpin(panel, value=0.5, **opts)
176 wids['fft_rmaxout'] = FloatSpin(panel, value=12, min_val=2,
177 increment=0.5, digits=1, max_val=20)
179 opts.update({'increment': 1, 'digits': 1, 'max_val': 5})
180 wids['bkg_kweight'] = FloatSpin(panel, value=2, **opts)
181 wids['fft_kweight'] = FloatSpin(panel, value=2, **opts)
183 opts = dict(choices=CLAMPLIST, size=(80, -1), action=self.onProcess)
184 wids['bkg_clamplo'] = Choice(panel, **opts)
185 wids['bkg_clamphi'] = Choice(panel, **opts)
187 wids['fft_kwindow'] = Choice(panel, choices=list(FT_WINDOWS),
188 action=self.onProcess, size=(125, -1))
191 wids['fft_rwindow'] = Choice(panel, choices=list(FT_WINDOWS),
192 action=self.onProcess, size=(125, -1))
193 wids['fft_rwindow'].SetStringSelection('Hanning')
196 self.wids['is_frozen'] = Check(panel, default=False, label='Freeze Group',
197 action=self.onFreezeGroup)
199 def add_text(text, dcol=1, newrow=True):
200 panel.Add(SimpleText(panel, text), dcol=dcol, newrow=newrow)
202 def CopyBtn(name):
203 return Button(panel, 'Copy', size=(60, -1),
204 action=partial(self.onCopyParam, name))
205 copy_all = Button(panel, 'Copy All Parameters', size=(175, -1),
206 action=partial(self.onCopyParam, 'all'))
209 panel.Add(SimpleText(panel, 'EXAFS Data Reduction and Fourier Transforms',
210 size=(350, -1), **self.titleopts), style=LEFT, dcol=6)
212 panel.Add(plot_sel, newrow=True)
213 panel.Add(self.wids['plotsel_op'], dcol=2)
215 add_text('Vertical offset: ', newrow=False)
216 panel.Add(wids['plot_voffset'], style=RIGHT)
218 panel.Add(plot_one, newrow=True)
219 panel.Add(self.wids['plotone_op'], dcol=2)
221 add_text('Plot k weight: ', newrow=False)
222 panel.Add(wids['plot_kweight'], style=RIGHT)
224 add_text('Add Second Plot: ', newrow=True)
225 panel.Add(self.wids['plotalt_op'], dcol=2)
226 add_text('Plot2 k weight: ', newrow=False)
227 panel.Add(wids['plot_kweight_alt'], style=RIGHT)
228 add_text('Window for Second Plot: ', newrow=True)
229 panel.Add(self.wids['plot_win'], dcol=2)
230 add_text('Plot R max: ', newrow=False)
231 panel.Add(wids['plot_rmax'], style=RIGHT)
233 add_text('Save Plot Options as: ', newrow=True)
234 panel.Add(self.wids['plotopt_name'], dcol=2)
236 add_text('Use Saved Plot Options: ', dcol=1, newrow=False)
237 panel.Add(self.wids['plotopt_sel'], dcol=1)
240 panel.Add(HLine(panel, size=(500, 3)), dcol=6, newrow=True)
242 panel.Add(SimpleText(panel, ' Background subtraction', size=(200, -1),
243 **self.titleopts), dcol=2, style=LEFT, newrow=True)
244 panel.Add(SimpleText(panel, 'Copy To Selected Groups:'),
245 style=RIGHT, dcol=3)
248 add_text('E k=0: ')
249 panel.Add(ek0_panel, dcol=2)
250 panel.Add(wids['push_e0'], dcol=1)
251 panel.Add(CopyBtn('ek0'), style=RIGHT)
253 add_text('R bkg: ')
254 panel.Add(wids['rbkg'])
255 panel.Add((10, 10), dcol=2)
256 panel.Add(CopyBtn('rbkg'), style=RIGHT)
258 add_text('k min: ')
259 panel.Add(bkg_kmin)
260 panel.Add(SimpleText(panel, 'k max:'), style=LEFT)
261 panel.Add(bkg_kmax)
262 panel.Add(CopyBtn('bkg_krange'), style=RIGHT)
264 add_text('kweight: ', newrow=True)
265 panel.Add(wids['bkg_kweight'])
266 panel.Add((10, 10), dcol=2)
267 panel.Add(CopyBtn('bkg_kweight'), style=RIGHT)
269 add_text('Clamps Low E: ', newrow=True)
270 panel.Add( wids['bkg_clamplo'])
271 add_text('high E: ', newrow=False)
272 panel.Add( wids['bkg_clamphi'])
273 panel.Add(CopyBtn('bkg_clamp'), style=RIGHT)
275 panel.Add(HLine(panel, size=(500, 3)), dcol=6, newrow=True)
277 panel.Add(SimpleText(panel, ' Fourier transform (k->R) ', size=(275, -1),
278 **self.titleopts), dcol=2, style=LEFT, newrow=True)
279 panel.Add(SimpleText(panel, 'Copy To Selected Groups:'),
280 style=RIGHT, dcol=3)
282 panel.Add(SimpleText(panel, 'k min: '), newrow=True)
283 panel.Add(fft_kmin)
284 panel.Add(SimpleText(panel, 'k max:'), style=LEFT)
285 panel.Add(fft_kmax)
286 panel.Add(CopyBtn('fft_krange'), style=RIGHT)
288 panel.Add(SimpleText(panel, 'k weight : '), newrow=True)
289 panel.Add(wids['fft_kweight'])
290 panel.Add((10, 10), dcol=2)
291 panel.Add(CopyBtn('fft_kweight'), style=RIGHT)
293 panel.Add(SimpleText(panel, 'k window : '), newrow=True)
294 panel.Add(wids['fft_kwindow'])
295 panel.Add(SimpleText(panel, 'dk : '))
296 panel.Add(wids['fft_dk'])
297 panel.Add(CopyBtn('fft_kwindow'), style=RIGHT)
299 panel.Add(SimpleText(panel, 'R max output: '), newrow=True)
300 panel.Add(wids['fft_rmaxout'])
301 panel.Add((10, 10), dcol=2)
302 panel.Add(CopyBtn('fft_rmaxout'), style=RIGHT)
304 panel.Add(HLine(panel, size=(500, 3)), dcol=6, newrow=True)
306 panel.Add(SimpleText(panel, ' Back Fourier transform (R->q) ', size=(275, -1),
307 **self.titleopts), dcol=2, style=LEFT, newrow=True)
308 panel.Add(SimpleText(panel, 'Copy To Selected Groups:'),
309 style=RIGHT, dcol=3)
311 panel.Add(SimpleText(panel, 'R min: '), newrow=True)
312 panel.Add(fft_rmin)
314 panel.Add(SimpleText(panel, 'R max:'), style=LEFT)
315 panel.Add(fft_rmax)
316 panel.Add(CopyBtn('fft_rrange'), style=RIGHT)
318 panel.Add(SimpleText(panel, 'R window : '), newrow=True)
319 panel.Add(wids['fft_rwindow'])
320 panel.Add(SimpleText(panel, 'dR : '))
321 panel.Add(wids['fft_dr'])
323 panel.Add(CopyBtn('fft_rwindow'), style=RIGHT)
324 panel.Add((10, 10), newrow=True)
325 panel.Add(self.wids['is_frozen'], dcol=1, newrow=True)
326 panel.Add(copy_all, dcol=5, style=RIGHT)
328 panel.pack()
330 sizer = wx.BoxSizer(wx.VERTICAL)
331 sizer.Add((10, 10), 0, LEFT, 3)
332 sizer.Add(panel, 1, LEFT, 3)
333 pack(self, sizer)
334 self.skip_process = False
336 def get_config(self, dgroup=None):
337 """get and set processing configuration for a group"""
338 if dgroup is None:
339 dgroup = self.controller.get_group()
340 if dgroup is None:
341 return self.get_defaultconfig()
343 conf = getattr(dgroup.config, self.configname,
344 self.get_defaultconfig())
346 # update config from callargs - last call arguments
347 callargs = getattr(dgroup, 'callargs', None)
348 if callargs is not None:
349 bkg_callargs = getattr(callargs, 'autobk', None)
350 if bkg_callargs is not None:
351 for attr in ('rbkg', 'ek0'):
352 update_confval(conf, bkg_callargs, attr)
353 for attr in ('kmin', 'kmax', 'kweight'):
354 update_confval(conf, bkg_callargs, attr, pref='bkg_')
355 conf['bkg_clamplo'] = bkg_callargs.get('clamp_lo', 1)
356 conf['bkg_clamphi'] = bkg_callargs.get('clamp_hi', 20)
358 ftf_callargs = getattr(callargs, 'xftf', None)
359 if ftf_callargs is not None:
360 conf['fft_kwindow'] = ftf_callargs.get('window', 'Hanning')
361 conf['fft_rmaxout'] = ftf_callargs.get('rmax_out', 12)
362 for attr in ('kmin', 'kmax', 'dk', 'kweight'):
363 update_confval(conf, ftf_callargs, attr, pref='fft_')
365 ftr_callargs = getattr(callargs, 'xftr', None)
366 if ftr_callargs is not None:
367 conf['fft_rwindow'] = ftr_callargs.get('window', 'Hanning')
368 for attr in ('rmin', 'rmax', 'dr'):
369 update_confval(conf, ftr_callargs, attr, pref='fft_')
371 ek0 = getattr(dgroup, 'ek0', conf.get('ek0', None))
372 if ek0 is None:
373 nconf = getattr(dgroup.config, 'xasnorm', {'e0': None})
374 ek0 = nconf.get('e0', getattr(dgroup, 'e0', None))
375 if ek0 is None:
376 ek0 = min(dgroup.energy)
378 if getattr(dgroup, 'ek0', None) is None:
379 dgroup.ek0 = ek0
381 kmax = etok(max(dgroup.energy) - ek0)
383 bkg_kmax = conf.get('bkg_kmax', -1)
384 if bkg_kmax < 0 or bkg_kmax > kmax:
385 conf['bkg_kmax'] = 0.25*int(kmax*4.0 + 1.0)
387 fft_kmax = conf.get('fft_kmax', -1)
388 if fft_kmax < 0 or fft_kmax > kmax:
389 conf['fft_kmax'] = 0.25*int(kmax*4.0 - 1.0)
391 fft_rmin = conf.get('fft_rmin', -1)
392 if fft_rmin:
393 conf['fft_rmin'] = conf['rbkg']
395 setattr(dgroup.config, self.configname, conf)
396 return conf
398 def fill_form(self, dgroup):
399 """fill in form from a data group"""
400 opts = self.get_config(dgroup)
401 self.dgroup = dgroup
402 if not (hasattr(dgroup, 'norm') and hasattr(dgroup, 'e0')):
403 self.parent.process_normalization(dgroup)
405 self.skip_process = True
406 wids = self.wids
407 ek0 = getattr(dgroup, 'ek0', None)
408 if ek0 is None:
409 ek0 = dgroup.ek0 = getattr(dgroup, 'e0', None)
410 if ek0 is None:
411 ek0 = dgroup.ek0 = dgroup.e0 = find_e0(dgroup)
412 if ek0 is None:
413 print("cannot determine E0 for this group")
414 return
416 rbkg = getattr(dgroup, 'rbkg', None)
417 if rbkg is None:
418 rkbg = dgroup.rbkg = opts.get('rbkg', 1.0)
420 for attr in ('ek0', 'rbkg'):
421 wids[attr].SetValue(getattr(dgroup, attr))
423 for attr in ('bkg_kmin', 'bkg_kmax', 'bkg_kweight', 'fft_kmin',
424 'fft_kmax', 'fft_kweight', 'fft_dk', 'fft_rmaxout',
425 ):
426 try:
427 wids[attr].SetValue(float(opts.get(attr)))
428 except:
429 pass
430 for attr in ('fft_kwindow',):
431 if attr in opts:
432 wids[attr].SetStringSelection(opts[attr])
435 for attr in ('bkg_clamplo', 'bkg_clamphi'):
436 val = opts.get(attr, 0)
437 try:
438 val = float(val)
439 except:
440 if isinstance(val, str):
441 val = ATHENA_CLAMPNAMES.get(val.lower(), 0)
442 try:
443 wids[attr].SetStringSelection("%d" % int(val))
444 except:
445 pass
447 frozen = opts.get('is_frozen', False)
448 if hasattr(dgroup, 'is_frozen'):
449 frozen = dgroup.is_frozen
451 self.wids['is_frozen'].SetValue(frozen)
452 self._set_frozen(frozen)
454 self.skip_process = False
456 def read_form(self, dgroup=None, as_copy=False):
457 "read form, return dict of values"
458 skip_save = self.skip_process
459 self.skip_process = True
460 if dgroup is None:
461 dgroup = self.controller.get_group()
462 self.dgroup = dgroup
464 conf = self.get_config()
465 if dgroup is not None:
466 conf['group'] = dgroup.groupname
468 wids = self.wids
469 for attr in ('ek0', 'rbkg', 'bkg_kmin', 'bkg_kmax',
470 'bkg_kweight', 'fft_kmin', 'fft_kmax',
471 'fft_kweight', 'fft_dk', 'fft_rmaxout',
472 'fft_rmin', 'fft_rmax', 'fft_dr',
473 'plot_kweight', 'plot_rmax',
474 'plot_kweight_alt', 'plot_voffset'):
475 conf[attr] = wids[attr].GetValue()
477 for attr in ('bkg_clamplo', 'bkg_clamphi', 'plot_win'):
478 conf[attr] = int(wids[attr].GetStringSelection())
480 for attr in ('fft_kwindow', 'fft_rwindow', 'plotone_op',
481 'plotsel_op', 'plotalt_op'):
482 conf[attr] = wids[attr].GetStringSelection()
483 conf['show_ek0'] = wids['show_ek0'].IsChecked()
485 time.sleep(0.001)
486 self.skip_process = skip_save
487 if as_copy:
488 conf = copy.deepcopy(conf)
489 if dgroup is not None:
490 setattr(dgroup.config, self.configname, conf)
491 return conf
493 def onSaveConfigBtn(self, evt=None):
494 self.set_defaultconfig(self.read_form())
496 def onShowEk0(self, evt=None):
497 print("show ek0 ", evt)
500 def onPushE0(self, evt=None):
501 conf = self.read_form()
502 dgroup = self.controller.get_group()
503 if dgroup is not None:
504 nconf = getattr(dgroup.config, 'xasnorm', {'e0': None})
505 nconf['auto_e0'] = False
506 nconf['e0'] = dgroup.e0 = conf['ek0']
508 def onCopyParam(self, name=None, evt=None):
509 conf = self.read_form()
510 opts = {}
511 def copy_attrs(*args):
512 return {a: conf[a] for a in args}
513 name = str(name)
514 set_ek0 = set_rbkg = False
515 if name == 'all':
516 opts = copy_attrs( 'ek0', 'rbkg', 'bkg_kweight', 'fft_kweight',
517 'bkg_kmin', 'bkg_kmax', 'bkg_clamplo',
518 'bkg_clamphi', 'fft_kmin', 'fft_kmax',
519 'fft_kwindow', 'fft_dk', 'fft_rmin',
520 'fft_rmax', 'fft_rmaxout', 'fft_rwindow',
521 'fft_dr')
522 set_ek0 = True
523 set_rbkg = True
525 elif name in ('ek0', 'rbkg', 'bkg_kweight', 'fft_kweight'):
526 opts = copy_attrs(name)
527 if name == 'ek0':
528 set_ek0 = True
529 elif name == 'rbkg':
530 set_rbkg = True
531 elif name == 'bkg_krange':
532 opts = copy_attrs('bkg_kmin', 'bkg_kmax')
533 elif name == 'bkg_clamp':
534 opts = copy_attrs('bkg_clamplo', 'bkg_clamphi')
535 elif name == 'fft_krange':
536 opts = copy_attrs('fft_kmin', 'fft_kmax')
537 elif name == 'fft_kwindow':
538 opts = copy_attrs('fft_kwindow', 'fft_dk')
539 elif name == 'fft_rrange':
540 opts = copy_attrs('fft_rmin', 'fft_rmax')
541 elif name == 'fft_rmaxout':
542 opts = copy_attrs('fft_rmaxout',)
543 elif name == 'fft_rwindow':
544 opts = copy_attrs('fft_rwindow', 'fft_dr')
546 for checked in self.controller.filelist.GetCheckedStrings():
547 groupname = self.controller.file_groups[str(checked)]
548 grp = self.controller.get_group(groupname)
549 if grp != self.controller.group and not grp.is_frozen:
550 self.update_config(opts, dgroup=grp)
551 if set_ek0:
552 grp.ek0 = opts['ek0']
553 if set_rbkg:
554 grp.rbkg = opts['rbkg']
555 self.process(dgroup=grp, read_form=False)
558 def _set_frozen(self, frozen):
559 try:
560 dgroup = self.controller.get_group()
561 dgroup.is_frozen = frozen
562 except:
563 pass
565 for attr in ('ek0', 'rbkg', 'bkg_kmin', 'bkg_kmax', 'bkg_kweight',
566 'fft_kmin', 'fft_kmax', 'fft_kweight', 'fft_dk',
567 'fft_rmin', 'fft_rmax', 'fft_dr',
568 'bkg_clamplo', 'bkg_clamphi', 'fft_kwindow'):
569 self.wids[attr].Enable(not frozen)
571 def onFreezeGroup(self, evt=None):
572 self._set_frozen(evt.IsChecked())
575 def onRbkg(self, event=None):
576 self.wids['fft_rmin'].SetValue(self.wids['rbkg'].GetValue())
577 self.onProcess(event=event)
579 def onProcess(self, event=None):
580 """ handle process events"""
581 if self.skip_process or ((time.time() - self.last_process_time) < 0.5):
582 return
583 self.last_process_time = time.time()
584 self.skip_process = True
585 self.process(dgroup=self.dgroup, read_form=True)
586 self.skip_process = False
587 plotter = self.onPlotSel if self.last_plot=='selected' else self.onPlotOne
588 wx.CallAfter(plotter)
590 def process(self, dgroup=None, read_form=True, force=False, **kws):
591 conf = {}
592 if dgroup is not None:
593 self.dgroup = dgroup
594 conf = getattr(dgroup.config, self.configname, None)
595 if conf is None:
596 conf = self.get_config(dgroup=dgroup)
597 if 'ek0' not in conf:
598 conf['ek0'] = conf.get('e0', getattr(dgroup, 'e0', -1))
600 if read_form:
601 conf.update(self.read_form())
603 conf.update(kws)
604 if dgroup is None or 'fft_kwindow' not in conf:
605 return
607 conf['group'] = dgroup.groupname
609 try:
610 txt = autobk_cmd.format(**conf)
611 except:
612 conf.update(self.read_form())
613 txt = autobk_cmd.format(**conf)
615 bkgpars = []
616 for attr in ('ek0', 'rbkg', 'bkg_kmin', 'bkg_kmax',
617 'bkg_kweight', 'bkg_clamplo', 'bkg_clamphi'):
618 val = conf.get(attr, 0.0)
619 if val is None:
620 val = -1.0
621 bkgpars.append("%.3f" % val)
622 bkgpars = ':'.join(bkgpars)
623 lastpars = self.last_process_bkg.get(self.dgroup.groupname, '')
624 if force or (bkgpars != lastpars):
625 self.larch_eval(autobk_cmd.format(**conf))
626 self.last_process_bkg[self.dgroup.groupname] = bkgpars
627 self.last_process_fft[self.dgroup.groupname] = ''
629 fftpars = [conf['fft_kwindow'], conf['fft_rwindow']]
630 for attr in ('fft_kmin', 'fft_kmax', 'fft_kweight', 'fft_dk',
631 'fft_rmin', 'fft_rmax', 'fft_dr', 'fft_rmaxout'):
632 fftpars.append("%.3f" % conf.get(attr, 0.0))
633 fftpars = ':'.join(fftpars)
634 if fftpars != self.last_process_fft.get(self.dgroup.groupname, ''):
635 self.larch_eval(xftf_cmd.format(**conf))
636 self.larch_eval(xftr_cmd.format(**conf))
637 self.last_process_fft[self.dgroup.groupname] = fftpars
639 setattr(dgroup.config, self.configname, conf)
641 def plot(self, dgroup=None):
642 if self.skip_plotting:
643 return
644 self.onPlotOne(dgroup=dgroup)
647 def onPlotOptSave(self, name=None, event=None):
648 data = {}
649 if name is None or len(name) < 1:
650 name = f"view {len(self.plotopt_saves)+1}"
652 name = name.strip()
653 for attr in ('plot_voffset', 'plot_kweight',
654 'plot_kweight_alt', 'plot_rmax'):
655 data[attr] = self.wids[attr].GetValue()
657 for attr in ('plotone_op', 'plotsel_op', 'plotalt_op'):
658 data[attr] = self.wids[attr].GetStringSelection()
659 self.plotopt_saves[name] = data
661 choices = list(reversed(self.plotopt_saves.keys()))
662 self.wids['plotopt_sel'].SetChoices(choices)
663 self.wids['plotopt_sel'].SetSelection(0)
666 def onPlotOptSel(self, event=None):
667 name = event.GetString()
668 data = self.plotopt_saves.get(name, None)
669 if data is not None:
670 for attr in ('plot_voffset', 'plot_kweight',
671 'plot_kweight_alt', 'plot_rmax'):
672 self.wids[attr].SetValue(data[attr])
674 for attr in ('plotone_op', 'plotsel_op', 'plotalt_op'):
675 self.wids[attr].SetStringSelection(data[attr])
677 self.plot()
680 def onPlotOne(self, evt=None, dgroup=None):
681 if self.skip_plotting:
682 return
683 conf = self.read_form(as_copy=True)
684 if dgroup is not None:
685 self.dgroup = dgroup
686 conf['group'] = dgroup.groupname
687 self.process(dgroup=self.dgroup)
688 conf['title'] = '"%s"' % self.dgroup.filename
690 # print(" onPlotOne ", conf['plotone_op'])
691 cmd = PlotCmds[conf['plotone_op']] + ", win=1, title={title:s})"
692 # 2nd plot
693 cmd2 = PlotCmds[conf['plotalt_op']]
694 if cmd2 is not None:
695 cmd2 = cmd2.replace('plot_kweight', 'plot_kweight_alt')
696 cmd2 = cmd2 + ", win={plot_win:d}, title={title:s})"
697 cmd = "%s\n%s" % (cmd, cmd2)
698 self.controller.get_display(win=2)
700 # print(" onPlotOne ", cmd.format(**conf))
701 self.larch_eval(cmd.format(**conf))
702 self.last_plot = 'one'
704 self.controller.set_focus()
707 def onPlotSel(self, evt=None):
708 if self.skip_plotting:
709 return
710 group_ids = self.controller.filelist.GetCheckedStrings()
711 if len(group_ids) < 1:
712 return
714 conf = self.read_form(as_copy=True)
715 bcmd = PlotCmds[conf['plotsel_op']]
716 conf['new'] = 'True'
717 conf.pop('ek0') # don't copy ek0 to all groups
718 offset = conf['plot_voffset']
719 for i, checked in enumerate(group_ids):
720 groupname = self.controller.file_groups[str(checked)]
721 dgroup = self.controller.get_group(groupname)
722 if dgroup is not None:
723 conf['group'] = dgroup.groupname
724 conf['label'] = dgroup.filename
725 conf['offset'] = offset * i
726 if not hasattr(dgroup, 'chir_mag'):
727 self.process(dgroup=dgroup, force=True, read_form=False, **conf)
729 extra = """, offset={offset:.3f}, win=1, delay_draw=True,
730 label='{label:s}', new={new:s})"""
731 cmd = "%s%s" % (bcmd, extra)
732 self.larch_eval(cmd.format(**conf))
733 conf['new'] = 'False'
735 self.larch_eval("redraw(win=1, show_legend=True)")
736 self.last_plot = 'selected'
738 self.controller.set_focus()