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

1#!/usr/bin/env python 

2""" 

3Linear Combination panel 

4""" 

5import os 

6import time 

7import copy 

8import wx 

9import numpy as np 

10 

11from functools import partial 

12 

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) 

17 

18from larch.xafs.xafsutils import etok, ktoe, FT_WINDOWS 

19from larch.xafs.pre_edge import find_e0 

20 

21from .xas_dialogs import EnergyUnitsDialog 

22from .taskpanel import TaskPanel, update_confval 

23from .config import ATHENA_CLAMPNAMES, PlotWindowChoices 

24 

25np.seterr(all='ignore') 

26 

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

40 

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] 

45 

46 

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} 

59 

60 

61CLAMPLIST = ('0', '1', '2', '5', '10', '20', '50', '100', '200', '500', '1000', 

62 '2000', '5000', '10000') 

63 

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

67 

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

70 

71xftr_cmd = """xftr({group:s}, rmin={fft_rmin: .3f}, rmax={fft_rmax: .3f}, 

72 dr={fft_dr: .3f}, window='{fft_rwindow:s}')""" 

73 

74 

75class EXAFSPanel(TaskPanel): 

76 """EXAFS Panel""" 

77 def __init__(self, parent, controller, **kws): 

78 TaskPanel.__init__(self, parent, controller, panel='exafs', **kws) 

79 

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 

85 

86 def build_display(self): 

87 panel = self.panel 

88 wids = self.wids 

89 self.skip_process = True 

90 

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

97 

98 wids['plotone_op'].SetStringSelection(chik) 

99 wids['plotsel_op'].SetStringSelection(chik) 

100 wids['plotalt_op'].SetStringSelection(noplot) 

101 

102 plot_one = Button(panel, 'Plot Current Group', size=(175, -1), 

103 action=self.onPlotOne) 

104 

105 plot_sel = Button(panel, 'Plot Selected Groups', size=(175, -1), 

106 action=self.onPlotSel) 

107 

108 ## saveconf = Button(panel, 'Save as Default Settings', size=(200, -1), 

109 # action=self.onSaveConfigBtn) 

110 

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) 

119 

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

126 

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) 

136 

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

140 

141 

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

147 

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}} 

152 

153 wids['plotopt_sel'] = Choice(panel, size=(150, -1), 

154 choices=list(self.plotopt_saves.keys()), 

155 action=self.onPlotOptSel) 

156 

157 

158 opts['max_val'] = 6 

159 opts['action'] = self.onRbkg 

160 wids['rbkg'] = FloatSpin(panel, value=1.0, **opts) 

161 

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) 

168 

169 wids['fft_dk'] = FloatSpin(panel, value=3, **opts) 

170 

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) 

174 

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) 

178 

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) 

182 

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) 

186 

187 wids['fft_kwindow'] = Choice(panel, choices=list(FT_WINDOWS), 

188 action=self.onProcess, size=(125, -1)) 

189 

190 

191 wids['fft_rwindow'] = Choice(panel, choices=list(FT_WINDOWS), 

192 action=self.onProcess, size=(125, -1)) 

193 wids['fft_rwindow'].SetStringSelection('Hanning') 

194 

195 

196 self.wids['is_frozen'] = Check(panel, default=False, label='Freeze Group', 

197 action=self.onFreezeGroup) 

198 

199 def add_text(text, dcol=1, newrow=True): 

200 panel.Add(SimpleText(panel, text), dcol=dcol, newrow=newrow) 

201 

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

207 

208 

209 panel.Add(SimpleText(panel, 'EXAFS Data Reduction and Fourier Transforms', 

210 size=(350, -1), **self.titleopts), style=LEFT, dcol=6) 

211 

212 panel.Add(plot_sel, newrow=True) 

213 panel.Add(self.wids['plotsel_op'], dcol=2) 

214 

215 add_text('Vertical offset: ', newrow=False) 

216 panel.Add(wids['plot_voffset'], style=RIGHT) 

217 

218 panel.Add(plot_one, newrow=True) 

219 panel.Add(self.wids['plotone_op'], dcol=2) 

220 

221 add_text('Plot k weight: ', newrow=False) 

222 panel.Add(wids['plot_kweight'], style=RIGHT) 

223 

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) 

232 

233 add_text('Save Plot Options as: ', newrow=True) 

234 panel.Add(self.wids['plotopt_name'], dcol=2) 

235 

236 add_text('Use Saved Plot Options: ', dcol=1, newrow=False) 

237 panel.Add(self.wids['plotopt_sel'], dcol=1) 

238 

239 

240 panel.Add(HLine(panel, size=(500, 3)), dcol=6, newrow=True) 

241 

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) 

246 

247 

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) 

252 

253 add_text('R bkg: ') 

254 panel.Add(wids['rbkg']) 

255 panel.Add((10, 10), dcol=2) 

256 panel.Add(CopyBtn('rbkg'), style=RIGHT) 

257 

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) 

263 

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) 

268 

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) 

274 

275 panel.Add(HLine(panel, size=(500, 3)), dcol=6, newrow=True) 

276 

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) 

281 

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) 

287 

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) 

292 

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) 

298 

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) 

303 

304 panel.Add(HLine(panel, size=(500, 3)), dcol=6, newrow=True) 

305 

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) 

310 

311 panel.Add(SimpleText(panel, 'R min: '), newrow=True) 

312 panel.Add(fft_rmin) 

313 

314 panel.Add(SimpleText(panel, 'R max:'), style=LEFT) 

315 panel.Add(fft_rmax) 

316 panel.Add(CopyBtn('fft_rrange'), style=RIGHT) 

317 

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

322 

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) 

327 

328 panel.pack() 

329 

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 

335 

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

342 

343 conf = getattr(dgroup.config, self.configname, 

344 self.get_defaultconfig()) 

345 

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) 

357 

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

364 

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

370 

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) 

377 

378 if getattr(dgroup, 'ek0', None) is None: 

379 dgroup.ek0 = ek0 

380 

381 kmax = etok(max(dgroup.energy) - ek0) 

382 

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) 

386 

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) 

390 

391 fft_rmin = conf.get('fft_rmin', -1) 

392 if fft_rmin: 

393 conf['fft_rmin'] = conf['rbkg'] 

394 

395 setattr(dgroup.config, self.configname, conf) 

396 return conf 

397 

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) 

404 

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 

415 

416 rbkg = getattr(dgroup, 'rbkg', None) 

417 if rbkg is None: 

418 rkbg = dgroup.rbkg = opts.get('rbkg', 1.0) 

419 

420 for attr in ('ek0', 'rbkg'): 

421 wids[attr].SetValue(getattr(dgroup, attr)) 

422 

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

433 

434 

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 

446 

447 frozen = opts.get('is_frozen', False) 

448 if hasattr(dgroup, 'is_frozen'): 

449 frozen = dgroup.is_frozen 

450 

451 self.wids['is_frozen'].SetValue(frozen) 

452 self._set_frozen(frozen) 

453 

454 self.skip_process = False 

455 

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 

463 

464 conf = self.get_config() 

465 if dgroup is not None: 

466 conf['group'] = dgroup.groupname 

467 

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

476 

477 for attr in ('bkg_clamplo', 'bkg_clamphi', 'plot_win'): 

478 conf[attr] = int(wids[attr].GetStringSelection()) 

479 

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

484 

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 

492 

493 def onSaveConfigBtn(self, evt=None): 

494 self.set_defaultconfig(self.read_form()) 

495 

496 def onShowEk0(self, evt=None): 

497 print("show ek0 ", evt) 

498 

499 

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

507 

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 

524 

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

545 

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) 

556 

557 

558 def _set_frozen(self, frozen): 

559 try: 

560 dgroup = self.controller.get_group() 

561 dgroup.is_frozen = frozen 

562 except: 

563 pass 

564 

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) 

570 

571 def onFreezeGroup(self, evt=None): 

572 self._set_frozen(evt.IsChecked()) 

573 

574 

575 def onRbkg(self, event=None): 

576 self.wids['fft_rmin'].SetValue(self.wids['rbkg'].GetValue()) 

577 self.onProcess(event=event) 

578 

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) 

589 

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

599 

600 if read_form: 

601 conf.update(self.read_form()) 

602 

603 conf.update(kws) 

604 if dgroup is None or 'fft_kwindow' not in conf: 

605 return 

606 

607 conf['group'] = dgroup.groupname 

608 

609 try: 

610 txt = autobk_cmd.format(**conf) 

611 except: 

612 conf.update(self.read_form()) 

613 txt = autobk_cmd.format(**conf) 

614 

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] = '' 

628 

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 

638 

639 setattr(dgroup.config, self.configname, conf) 

640 

641 def plot(self, dgroup=None): 

642 if self.skip_plotting: 

643 return 

644 self.onPlotOne(dgroup=dgroup) 

645 

646 

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

651 

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

656 

657 for attr in ('plotone_op', 'plotsel_op', 'plotalt_op'): 

658 data[attr] = self.wids[attr].GetStringSelection() 

659 self.plotopt_saves[name] = data 

660 

661 choices = list(reversed(self.plotopt_saves.keys())) 

662 self.wids['plotopt_sel'].SetChoices(choices) 

663 self.wids['plotopt_sel'].SetSelection(0) 

664 

665 

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

673 

674 for attr in ('plotone_op', 'plotsel_op', 'plotalt_op'): 

675 self.wids[attr].SetStringSelection(data[attr]) 

676 

677 self.plot() 

678 

679 

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 

689 

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) 

699 

700 # print(" onPlotOne ", cmd.format(**conf)) 

701 self.larch_eval(cmd.format(**conf)) 

702 self.last_plot = 'one' 

703 

704 self.controller.set_focus() 

705 

706 

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 

713 

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) 

728 

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' 

734 

735 self.larch_eval("redraw(win=1, show_legend=True)") 

736 self.last_plot = 'selected' 

737 

738 self.controller.set_focus()