Coverage for larch/wxxas/xasnorm_panel.py: 0%

833 statements  

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

1#!/usr/bin/env python 

2""" 

3XANES Normalization panel 

4""" 

5import time 

6import wx 

7from copy import deepcopy 

8import numpy as np 

9 

10from functools import partial 

11from xraydb import guess_edge, atomic_number 

12 

13from larch.utils import gformat, path_split 

14from larch.math import index_of 

15from larch.xafs.xafsutils import guess_energy_units 

16from larch.xafs.pre_edge import find_e0 

17 

18from larch.wxlib import (BitmapButton, FloatCtrl, FloatSpin, get_icon, 

19 SimpleText, pack, Button, HLine, Choice, Check, 

20 GridPanel, CEN, RIGHT, LEFT, plotlabels, 

21 get_zoomlimits, set_zoomlimits) 

22 

23from larch.utils.strutils import fix_varname, fix_filename, file2groupname 

24 

25from larch.utils.physical_constants import ATOM_NAMES 

26from larch.wxlib.plotter import last_cursor_pos 

27from .xas_dialogs import EnergyUnitsDialog 

28from .taskpanel import TaskPanel, autoset_fs_increment, update_confval 

29from .config import (make_array_choice, EDGES, ATSYMS, 

30 NNORM_CHOICES, NNORM_STRINGS, NORM_METHODS) 

31 

32np.seterr(all='ignore') 

33 

34PLOTOPTS_1 = dict(style='solid', marker='None') 

35PLOTOPTS_2 = dict(style='short dashed', zorder=3, marker='None') 

36PLOTOPTS_D = dict(style='solid', zorder=2, side='right', marker='None') 

37 

38PlotOne_Choices = make_array_choice(['mu','norm', 'flat', 'prelines', 

39 'norm+flat', 'mback_norm', 'mback_poly', 

40 'i0', 'norm+i0', 'dmude', 'norm+dmude', 

41 'd2mude', 'norm+d2mude']) 

42 

43 

44PlotSel_Choices = make_array_choice(['mu', 'norm', 'flat', 'dmude', 'd2mude']) 

45 

46Plot_EnergyRanges = {'full E range': None, 

47 'E0 -20:+80eV': (-20, 80), 

48 'E0 -30:+120eV': (-30, 120), 

49 'E0 -50:+250eV': (-50, 250), 

50 'E0 -100:+500eV': (-100, 500)} 

51 

52 

53 

54FSIZE = 120 

55FSIZEBIG = 175 

56 

57def get_auto_nnorm(norm1, norm2): 

58 "autoamatically set nnorm from range" 

59 nrange = abs(norm2 - norm1) 

60 nnorm = 2 

61 if nrange < 300: nnorm = 1 

62 if nrange < 30: nnorm = 0 

63 return nnorm 

64 

65class XASNormPanel(TaskPanel): 

66 """XAS normalization Panel""" 

67 def __init__(self, parent, controller=None, **kws): 

68 TaskPanel.__init__(self, parent, controller, panel='xasnorm', **kws) 

69 

70 def build_display(self): 

71 panel = self.panel 

72 self.wids = {} 

73 self.last_plot_type = 'one' 

74 

75 trow = wx.Panel(panel) 

76 plot_sel = Button(trow, 'Plot Selected Groups', size=(175, -1), 

77 action=self.onPlotSel) 

78 plot_one = Button(trow, 'Plot Current Group', size=(175, -1), 

79 action=self.onPlotOne) 

80 

81 self.plotsel_op = Choice(trow, choices=list(PlotSel_Choices.keys()), 

82 action=self.onPlotSel, size=(300, -1)) 

83 self.plotone_op = Choice(trow, choices=list(PlotOne_Choices.keys()), 

84 action=self.onPlotOne, size=(300, -1)) 

85 

86 self.plot_erange = Choice(trow, choices=list(Plot_EnergyRanges.keys()), 

87 action=self.onPlotEither, size=(175, -1)) 

88 

89 opts = {'digits': 2, 'increment': 0.05, 'value': 0, 'size': (FSIZE, -1)} 

90 plot_voff = self.add_floatspin('plot_voff', with_pin=False, 

91 parent=trow, 

92 action=self.onVoffset, 

93 max_val=10000, min_val=-10000, 

94 **opts) 

95 

96 vysize, vxsize = plot_sel.GetBestSize() 

97 voff_lab = wx.StaticText(parent=trow, label=' Y Offset:', size=(80, vxsize), 

98 style=wx.RIGHT|wx.ALIGN_CENTRE_HORIZONTAL|wx.ST_NO_AUTORESIZE) 

99 

100 self.plot_erange.SetSelection(0) 

101 self.plotone_op.SetSelection(1) 

102 self.plotsel_op.SetSelection(1) 

103 

104 tsizer = wx.GridBagSizer(3, 3) 

105 tsizer.Add(plot_sel, (0, 0), (1, 1), LEFT, 2) 

106 tsizer.Add(self.plotsel_op, (0, 1), (1, 1), LEFT, 2) 

107 tsizer.Add(voff_lab, (0, 2), (1, 1), RIGHT, 2) 

108 tsizer.Add(plot_voff, (0, 3), (1, 1), RIGHT, 2) 

109 tsizer.Add(plot_one, (1, 0), (1, 1), LEFT, 2) 

110 tsizer.Add(self.plotone_op, (1, 1), (1, 1), LEFT, 2) 

111 tsizer.Add(self.plot_erange, (1, 2), (1, 2), RIGHT, 2) 

112 

113 pack(trow, tsizer) 

114 

115 # atom row 

116 atpanel = wx.Panel(panel) 

117 self.wids['atsym'] = Choice(atpanel, choices=ATSYMS, size=(100, -1)) 

118 self.wids['edge'] = Choice(atpanel, choices=EDGES, size=(100, -1)) 

119 sat = wx.BoxSizer(wx.HORIZONTAL) 

120 sat.Add(self.wids['atsym'], 0, LEFT, 4) 

121 sat.Add(self.wids['edge'], 0, LEFT, 4) 

122 pack(atpanel, sat) 

123 

124 # e0 row 

125 e0_panel = wx.Panel(panel) 

126 xas_e0 = self.add_floatspin('e0', action=self.onSet_XASE0Val, 

127 min_val=-1000, max_val=1e7, digits=3, 

128 increment=0.05, value=0, size=(FSIZEBIG, -1), 

129 parent=e0_panel) 

130 

131 self.wids['auto_e0'] = Check(e0_panel, default=True, label='auto?', 

132 action=self.onAuto_XASE0) 

133 self.wids['show_e0'] = Check(e0_panel, default=True, label='show?', 

134 action=self.onSet_XASE0) 

135 

136 sx = wx.BoxSizer(wx.HORIZONTAL) 

137 sx.Add(xas_e0, 0, LEFT, 4) 

138 sx.Add(self.wids['auto_e0'], 0, LEFT, 4) 

139 sx.Add(self.wids['show_e0'], 0, LEFT, 4) 

140 pack(e0_panel, sx) 

141 

142 # step row 

143 step_panel = wx.Panel(panel) 

144 xas_step = self.add_floatspin('step', action=self.onSet_XASStep, with_pin=False, 

145 min_val=-1000.0, max_val=1e7, digits=4, increment=0.05, 

146 value=0.1, size=(FSIZEBIG, -1), parent=step_panel) 

147 self.wids['auto_step'] = Check(step_panel, default=True, label='auto?', 

148 action=self.onNormMethod) 

149 sx = wx.BoxSizer(wx.HORIZONTAL) 

150 sx.Add(xas_step, 0, LEFT, 4) 

151 sx.Add(self.wids['auto_step'], 0, LEFT, 4) 

152 pack(step_panel, sx) 

153 

154 # step rows 

155 nnorm_panel = wx.Panel(panel) 

156 self.wids['nnorm'] = Choice(nnorm_panel, choices=list(NNORM_CHOICES.keys()), 

157 size=(150, -1), action=self.onNNormChoice, 

158 default=2) 

159 self.wids['auto_nnorm'] = Check(nnorm_panel, default=True, label='auto?', 

160 action=self.onAuto_NNORM) 

161 

162 sx = wx.BoxSizer(wx.HORIZONTAL) 

163 sx.Add(self.wids['nnorm'], 0, LEFT, 4) 

164 sx.Add(self.wids['auto_nnorm'], 0, LEFT, 4) 

165 pack(nnorm_panel, sx) 

166 

167 self.wids['energy_ref'] = Choice(panel, choices=['None'], 

168 action=self.onEnergyRef, size=(300, -1)) 

169 

170 self.wids['nvict'] = Choice(panel, choices=('0', '1', '2', '3'), 

171 size=(100, -1), action=self.onNormMethod, 

172 default=0) 

173 

174 

175 opts = {'size': (FSIZE, -1), 'digits': 2, 'increment': 5.0, 'action': self.onSet_Ranges, 

176 'min_val':-99000, 'max_val':99000} 

177 defaults = self.get_defaultconfig() 

178 

179 pre_panel = wx.Panel(panel) 

180 xas_pre1 = self.add_floatspin('pre1', value=defaults['pre1'], parent=pre_panel, **opts) 

181 xas_pre2 = self.add_floatspin('pre2', value=defaults['pre2'], parent=pre_panel, **opts) 

182 self.wids['show_pre'] = Check(pre_panel, default=False, label='show?', 

183 action=self.onSet_XASE0) 

184 

185 sx = wx.BoxSizer(wx.HORIZONTAL) 

186 sx.Add(xas_pre1, 0, LEFT, 4) 

187 sx.Add(SimpleText(pre_panel, ' : '), 0, LEFT, 4) 

188 sx.Add(xas_pre2, 0, LEFT, 4) 

189 sx.Add(self.wids['show_pre'], 0, LEFT, 4) 

190 pack(pre_panel, sx) 

191 

192 nor_panel = wx.Panel(panel) 

193 xas_norm1 = self.add_floatspin('norm1', value=defaults['norm1'], parent=nor_panel, **opts) 

194 xas_norm2 = self.add_floatspin('norm2', value=defaults['norm2'], parent=nor_panel, **opts) 

195 

196 self.wids['show_norm'] = Check(nor_panel, default=False, label='show?', 

197 action=self.onSet_XASE0) 

198 sx = wx.BoxSizer(wx.HORIZONTAL) 

199 sx.Add(xas_norm1, 0, LEFT, 4) 

200 sx.Add(SimpleText(nor_panel, ' : '), 0, LEFT, 4) 

201 sx.Add(xas_norm2, 0, LEFT, 4) 

202 sx.Add(self.wids['show_norm'], 0, LEFT, 4) 

203 pack(nor_panel, sx) 

204 

205 

206 opts = {'digits': 3, 'increment': 0.05, 'value': 0, 'size': (FSIZEBIG, -1)} 

207 

208 opts.update({'value': 1.0, 'digits': 3}) 

209 

210 self.wids['norm_method'] = Choice(panel, choices=NORM_METHODS, 

211 size=(150, -1), action=self.onNormMethod) 

212 self.wids['norm_method'].SetSelection(0) 

213 self.wids['energy_shift'] = FloatSpin(panel, value=0, digits=3, increment=0.05, 

214 min_val=-99000, max_val=99000, 

215 action=self.onSet_EnergyShift, 

216 size=(FSIZEBIG, -1)) 

217 

218 

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

220 action=self.onFreezeGroup) 

221 

222 use_auto = Button(panel, 'Use Default Settings', size=(200, -1), 

223 action=self.onResetNorm) 

224 

225 def CopyBtn(name): 

226 return Button(panel, 'Copy', size=(60, -1), 

227 action=partial(self.onCopyParam, name)) 

228 

229 copy_all = Button(panel, 'Copy All Parameters', size=(200, -1), 

230 action=partial(self.onCopyParam, 'all')) 

231 

232 add_text = self.add_text 

233 HLINEWID = 700 

234 panel.Add(SimpleText(panel, 'XAS Pre-edge subtraction and Normalization', 

235 size=(650, -1), **self.titleopts), style=LEFT, dcol=4) 

236 panel.Add(trow, dcol=4, newrow=True) 

237 

238 panel.Add(HLine(panel, size=(HLINEWID, 3)), dcol=4, newrow=True) 

239 add_text('XAS Data:') 

240 panel.Add(use_auto, dcol=1) 

241 panel.Add(SimpleText(panel, 'Copy to Selected Groups:'), style=RIGHT, dcol=2) 

242 

243 add_text('Element and Edge: ', newrow=True) 

244 panel.Add(atpanel, dcol=2) 

245 panel.Add(CopyBtn('atsym'), dcol=1, style=RIGHT) 

246 

247 add_text('Energy Reference : ') 

248 panel.Add(self.wids['energy_ref'], dcol=2) 

249 panel.Add(CopyBtn('energy_ref'), dcol=1, style=RIGHT) 

250 

251 add_text('Energy Shift : ') 

252 panel.Add(self.wids['energy_shift'], dcol=2) 

253 panel.Add(CopyBtn('energy_shift'), dcol=1, style=RIGHT) 

254 

255 add_text('E0 : ') 

256 panel.Add(e0_panel, dcol=2) 

257 panel.Add(CopyBtn('xas_e0'), dcol=1, style=RIGHT) 

258 

259 add_text('Edge Step: ') 

260 panel.Add(step_panel, dcol=2) 

261 panel.Add(CopyBtn('xas_step'), dcol=1, style=RIGHT) 

262 

263 panel.Add((5, 5), newrow=True) 

264 panel.Add(HLine(panel, size=(HLINEWID, 3)), dcol=4, newrow=True) 

265 

266 add_text('Pre-edge range: ') 

267 panel.Add(pre_panel, dcol=2) 

268 panel.Add(CopyBtn('xas_pre'), dcol=1, style=RIGHT) 

269 

270 panel.Add(SimpleText(panel, 'Victoreen order:'), newrow=True) 

271 panel.Add(self.wids['nvict'], dcol=2) 

272 

273 panel.Add((5, 5), newrow=True) 

274 panel.Add(HLine(panel, size=(HLINEWID, 3)), dcol=4, newrow=True) 

275 

276 add_text('Normalization : ') 

277 panel.Add(self.wids['norm_method'], dcol=2) 

278 panel.Add(CopyBtn('xas_norm'), dcol=1, style=RIGHT) 

279 

280 add_text('Norm Energy range: ') 

281 panel.Add(nor_panel, dcol=2) 

282 panel.Add(SimpleText(panel, 'Polynomial Type:'), newrow=True) 

283 panel.Add(nnorm_panel, dcol=3) 

284 

285 panel.Add(HLine(panel, size=(HLINEWID, 3)), dcol=4, newrow=True) 

286 panel.Add(self.wids['is_frozen'], newrow=True) 

287 panel.Add(copy_all, dcol=3, style=RIGHT) 

288 

289 panel.pack() 

290 

291 sizer = wx.BoxSizer(wx.VERTICAL) 

292 sizer.Add((5, 5), 0, LEFT, 3) 

293 sizer.Add(panel, 0, LEFT, 3) 

294 sizer.Add((5, 5), 0, LEFT, 3) 

295 pack(self, sizer) 

296 

297 def get_config(self, dgroup=None): 

298 """custom get_config to possibly inherit from Athena settings""" 

299 if dgroup is None: 

300 dgroup = self.controller.get_group() 

301 if dgroup is None: 

302 return self.get_defaultconfig() 

303 self.read_form() 

304 

305 

306 defconf = self.get_defaultconfig() 

307 conf = getattr(dgroup.config, self.configname, defconf) 

308 

309 for k, v in defconf.items(): 

310 if k not in conf: 

311 conf[k] = v 

312 if conf.get('edge_step', None) is None: 

313 conf['edge_step'] = getattr(dgroup, 'edge_step', 1) 

314 

315 atsym = '?' 

316 if hasattr(dgroup, 'element'): 

317 elem = getattr(dgroup, 'element', '?') 

318 try: 

319 z = int(elem) 

320 atsym = ATSYMS[z] 

321 except: 

322 pass 

323 if elem in ATSYMS[1:]: 

324 atsym = elem 

325 else: 

326 try: 

327 if elem.lower() in ATOM_NAMES: 

328 z = 1 + ATOM_NAMES.index(eleme.lower()) 

329 atsym = ATSYMS[z] 

330 except: 

331 pass 

332 

333 conf['atsym'] = atsym 

334 if atsym == '?': 

335 conf['atsym'] = getattr(dgroup, 'atsym', atsym) 

336 conf['edge'] = getattr(dgroup,'edge', conf['edge']) 

337 

338 xeref = getattr(dgroup, 'energy_ref', '') 

339 fname = getattr(dgroup, 'filename', None) 

340 if fname is None: 

341 fname = getattr(dgroup, 'groupname', None) 

342 if fname is None: 

343 fname =file2groupname('unknown_group', 

344 symtable=self._larch.symtable) 

345 

346 conf['energy_ref'] = getattr(dgroup, 'energy_ref', fname) 

347 

348 if conf['energy_ref'] in (None, 'None'): 

349 conf['energy_ref'] = fname 

350 

351 

352 conf['energy_shift'] = getattr(dgroup,'energy_shift', conf['energy_shift']) 

353 

354 if hasattr(dgroup, 'e0') and conf['atsym'] == '?': 

355 atsym, edge = guess_edge(dgroup.e0) 

356 conf['atsym'] = atsym 

357 conf['edge'] = edge 

358 

359 

360 if hasattr(dgroup, 'mback_params'): 

361 conf['atsym'] = getattr(dgroup.mback_params, 'atsym', conf['atsym']) 

362 conf['edge'] = getattr(dgroup.mback_params, 'edge', conf['edge']) 

363 

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

365 return conf 

366 

367 def fill_form(self, dgroup): 

368 """fill in form from a data group""" 

369 opts = self.get_config(dgroup) 

370 self.skip_process = True 

371 if self.is_xasgroup(dgroup): 

372 if self.plotone_op.GetCount() != len(PlotOne_Choices.keys()): 

373 self.plotone_op.SetChoices(list(PlotOne_Choices.keys())) 

374 self.plotone_op.SetSelection(1) 

375 if self.plotsel_op.GetCount() != len(PlotSel_Choices.keys()): 

376 self.plotsel_op.SetChoices(list(PlotSel_Choices.keys())) 

377 self.plotsel_op.SetSelection(1) 

378 

379 groupnames = list(self.controller.file_groups.keys()) 

380 self.wids['energy_ref'].SetChoices(groupnames) 

381 eref = opts.get('energy_ref', 'no_energy_ref') 

382 

383 for key, val in self.controller.file_groups.items(): 

384 if eref in (val, key): 

385 self.wids['energy_ref'].SetStringSelection(key) 

386 

387 self.wids['e0'].SetValue(opts.get('e0', -1)) 

388 edge_step = opts.get('edge_step', 1.0) 

389 

390 if hasattr(dgroup, 'e0') and opts['atsym'] == '?': 

391 atsym, edge = guess_edge(dgroup.e0) 

392 opts['atsym'] = atsym 

393 opts['edge'] = edge 

394 

395 self.wids['step'].SetValue(edge_step) 

396 autoset_fs_increment(self.wids['step'], edge_step) 

397 for attr in ('pre1', 'pre2', 'norm1', 'norm2'): 

398 val = opts.get(attr, None) 

399 if val is not None: 

400 self.wids[attr].SetValue(val) 

401 self.set_nnorm_widget(opts.get('nnorm')) 

402 

403 self.wids['energy_shift'].SetValue(opts['energy_shift']) 

404 self.wids['nvict'].SetStringSelection("%d" % opts['nvict']) 

405 self.wids['show_e0'].SetValue(opts['show_e0']) 

406 self.wids['auto_e0'].SetValue(opts['auto_e0']) 

407 self.wids['auto_nnorm'].SetValue(opts.get('auto_nnorm', 0)) 

408 self.wids['auto_step'].SetValue(opts['auto_step']) 

409 

410 self.wids['edge'].SetStringSelection(opts['edge'].title()) 

411 self.wids['atsym'].SetStringSelection(opts['atsym'].title()) 

412 self.wids['norm_method'].SetStringSelection(opts['norm_method'].lower()) 

413 for attr in ('pre1', 'pre2', 'norm1', 'norm2', 'nnorm', 'edge', 

414 'atsym', 'step', 'norm_method'): 

415 self.wids[attr].Enable() 

416 self.wids['show_pre'].SetValue(opts['show_pre']) 

417 self.wids['show_norm'].SetValue(opts['show_norm']) 

418 

419 

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

421 frozen = getattr(dgroup, 'is_frozen', frozen) 

422 

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

424 self._set_frozen(frozen) 

425 wx.CallAfter(self.unset_skip_process) 

426 

427 def set_nnorm_widget(self, nnorm=None): 

428 conf = self.get_config() 

429 nnorm_default = get_auto_nnorm(conf['norm1'], conf['norm2']) 

430 if nnorm in (None, 'auto'): 

431 nnorm = nnorm_default 

432 elif nnorm in NNORM_CHOICES: 

433 nnorm = int(NNORM_CHOICES[nnorm]) 

434 nnorm_str = NNORM_STRINGS.get(nnorm, None) 

435 if nnorm_str is None: 

436 nnorm_str = NNORM_STRINGS.get(nnorm_default, '1') 

437 self.wids['nnorm'].SetStringSelection(nnorm_str) 

438 self.wids['auto_nnorm'].SetValue(0) 

439 

440 def unset_skip_process(self): 

441 self.skip_process = False 

442 

443 def read_form(self): 

444 "read form, return dict of values" 

445 form_opts = {} 

446 form_opts['e0'] = self.wids['e0'].GetValue() 

447 form_opts['edge_step'] = self.wids['step'].GetValue() 

448 for attr in ('pre1', 'pre2', 'norm1', 'norm2'): 

449 val = self.wids[attr].GetValue() 

450 if val == 0: val = None 

451 form_opts[attr] = val 

452 

453 form_opts['energy_shift'] = self.wids['energy_shift'].GetValue() 

454 

455 form_opts['nnorm'] = NNORM_CHOICES.get(self.wids['nnorm'].GetStringSelection(), 1) 

456 form_opts['nvict'] = int(self.wids['nvict'].GetStringSelection()) 

457 form_opts['plotone_op'] = self.plotone_op.GetStringSelection() 

458 form_opts['plotsel_op'] = self.plotsel_op.GetStringSelection() 

459 form_opts['plot_voff'] = self.wids['plot_voff'].GetValue() 

460 for ch in ('show_e0', 'show_pre', 'show_norm', 'auto_e0', 

461 'auto_step', 'auto_nnorm'): 

462 form_opts[ch] = self.wids[ch].IsChecked() 

463 

464 form_opts['norm_method'] = self.wids['norm_method'].GetStringSelection().lower() 

465 form_opts['edge'] = self.wids['edge'].GetStringSelection().title() 

466 form_opts['atsym'] = self.wids['atsym'].GetStringSelection().title() 

467 form_opts['energy_ref'] = self.wids['energy_ref'].GetStringSelection() 

468 return form_opts 

469 

470 def onNNormChoice(self, evt=None): 

471 auto_nnorm = self.wids['auto_nnorm'].SetValue(0) 

472 self.onNormMethod() 

473 

474 def onNormMethod(self, evt=None): 

475 method = self.wids['norm_method'].GetStringSelection().lower() 

476 auto_nnorm = self.wids['auto_nnorm'].GetValue() 

477 

478 nnorm = NNORM_CHOICES.get(self.wids['nnorm'].GetStringSelection(), 1) 

479 if nnorm is None: 

480 nnorm = get_auto_nnorm(self.wids['norm1'].GetValue(), 

481 self.wids['norm2'].GetValue()) 

482 

483 nvict = int(self.wids['nvict'].GetStringSelection()) 

484 self.update_config({'norm_method': method, 'nnorm': nnorm, 'nvict': nvict}) 

485 if method.startswith('mback'): 

486 dgroup = self.controller.get_group() 

487 cur_elem = self.wids['atsym'].GetStringSelection() 

488 if hasattr(dgroup, 'e0') and cur_elem == 'H': 

489 atsym, edge = guess_edge(dgroup.e0) 

490 self.wids['edge'].SetStringSelection(edge) 

491 self.wids['atsym'].SetStringSelection(atsym) 

492 self.update_config({'edge': edge, 'atsym': atsym}) 

493 time.sleep(0.002) 

494 wx.CallAfter(self.onReprocess) 

495 

496 def _set_frozen(self, frozen): 

497 try: 

498 dgroup = self.controller.get_group() 

499 dgroup.is_frozen = frozen 

500 except: 

501 pass 

502 

503 for wattr in ('e0', 'step', 'pre1', 'pre2', 'norm1', 'norm2', 'nvict', 

504 'nnorm', 'show_e0', 'auto_e0', 'auto_step', 'auto_nnorm', 

505 'norm_method', 'edge', 'atsym', 'show_pre', 'show_norm'): 

506 self.wids[wattr].Enable(not frozen) 

507 

508 def onFreezeGroup(self, evt=None): 

509 self._set_frozen(evt.IsChecked()) 

510 

511 def onEnergyRef(self, evt=None): 

512 dgroup = self.controller.get_group() 

513 eref = self.wids['energy_ref'].GetStringSelection() 

514 gname = self.controller.file_groups[eref] 

515 dgroup.config.xasnorm['energy_ref'] = eref 

516 dgroup.energy_ref = eref 

517 self.update_config({'energy_ref': eref}, dgroup=dgroup) 

518 

519 def onPlotEither(self, evt=None): 

520 if self.last_plot_type == 'multi': 

521 self.onPlotSel(evt=evt) 

522 else: 

523 self.onPlotOne(evt=evt) 

524 

525 def onPlotOne(self, evt=None): 

526 self.last_plot_type = 'one' 

527 self.plot(self.controller.get_group()) 

528 wx.CallAfter(self.controller.set_focus) 

529 

530 def onVoffset(self, evt=None): 

531 time.sleep(0.002) 

532 wx.CallAfter(self.onPlotSel) 

533 

534 def onPlotSel(self, evt=None): 

535 newplot = True 

536 self.last_plot_type = 'multi' 

537 group_ids = self.controller.filelist.GetCheckedStrings() 

538 if len(group_ids) < 1: 

539 return 

540 last_id = group_ids[-1] 

541 

542 groupname = self.controller.file_groups[str(last_id)] 

543 dgroup = self.controller.get_group(groupname) 

544 

545 plot_choices = PlotSel_Choices 

546 

547 erange = Plot_EnergyRanges[self.plot_erange.GetStringSelection()] 

548 self.controller.set_plot_erange(erange) 

549 

550 ytitle = self.plotsel_op.GetStringSelection() 

551 yarray_name = plot_choices.get(ytitle, 'norm') 

552 ylabel = getattr(plotlabels, yarray_name, ytitle) 

553 xlabel = getattr(dgroup, 'plot_xlabel', getattr(plotlabels, 'energy')) 

554 

555 if yarray_name == 'norm': 

556 norm_method = self.wids['norm_method'].GetStringSelection().lower() 

557 if norm_method.startswith('mback'): 

558 yarray_name = 'norm_mback' 

559 ylabel = "%s (MBACK)" % ylabel 

560 elif norm_method.startswith('area'): 

561 yarray_name = 'norm_area' 

562 ylabel = "%s (Area)" % ylabel 

563 

564 voff = self.wids['plot_voff'].GetValue() 

565 plot_traces = [] 

566 newplot = True 

567 plotopts = self.controller.get_plot_conf() 

568 popts = {'style': 'solid', 'marker': None} 

569 popts['linewidth'] = plotopts.pop('linewidth') 

570 popts['marksize'] = plotopts.pop('markersize') 

571 popts['grid'] = plotopts.pop('show_grid') 

572 popts['fullbox'] = plotopts.pop('show_fullbox') 

573 

574 for ix, checked in enumerate(group_ids): 

575 groupname = self.controller.file_groups[str(checked)] 

576 dgroup = self.controller.get_group(groupname) 

577 if dgroup is None: 

578 continue 

579 self.ensure_xas_processed(dgroup, force_mback =('mback' in yarray_name)) 

580 

581 if erange is not None and hasattr(dgroup, 'e0') and 'xmin' not in popts: 

582 popts['xmin'] = dgroup.e0 + erange[0] 

583 popts['xmax'] = dgroup.e0 + erange[1] 

584 

585 trace = {'xdata': dgroup.xplot, 

586 'ydata': getattr(dgroup, yarray_name) + ix*voff, 

587 'label': dgroup.filename, 'new': newplot} 

588 trace.update(popts) 

589 plot_traces.append(trace) 

590 newplot = False 

591 

592 ppanel = self.controller.get_display(stacked=False).panel 

593 zoom_limits = get_zoomlimits(ppanel, dgroup) 

594 

595 nplot_traces = len(ppanel.conf.traces) 

596 nplot_request = len(plot_traces) 

597 if nplot_request > nplot_traces: 

598 linecolors = ppanel.conf.linecolors 

599 ncols = len(linecolors) 

600 for i in range(nplot_traces, nplot_request+5): 

601 ppanel.conf.init_trace(i, linecolors[i%ncols], 'dashed') 

602 

603 # 

604 

605 ppanel.plot_many(plot_traces, xlabel=plotlabels.energy, ylabel=ylabel, 

606 zoom_limits=zoom_limits, show_legend=True) 

607 set_zoomlimits(ppanel, zoom_limits) or ppanel.unzoom_all() 

608 ppanel.canvas.draw() 

609 

610 wx.CallAfter(self.controller.set_focus) 

611 

612 def onAuto_NNORM(self, evt=None): 

613 if evt.IsChecked(): 

614 nnorm = get_auto_nnorm(self.wids['norm1'].GetValue(), 

615 self.wids['norm2'].GetValue()) 

616 self.set_nnorm_widget(nnorm) 

617 self.wids['auto_nnorm'].SetValue(0) 

618 time.sleep(0.001) 

619 wx.CallAfter(self.onReprocess) 

620 

621 def onResetNorm(self, evt=None): 

622 auto_nnorm = self.wids['auto_nnorm'].GetValue() 

623 if auto_nnorm: 

624 nnorm = get_auto_nnorm(self.wids['norm1'].GetValue(), 

625 self.wids['norm2'].GetValue()) 

626 self.set_nnorm_widget(nnorm) 

627 

628 defaults = self.get_defaultconfig() 

629 

630 self.wids['auto_step'].SetValue(1) 

631 self.wids['auto_e0'].SetValue(1) 

632 self.wids['auto_e0'].SetValue(1) 

633 self.wids['nvict'].SetSelection(0) 

634 for attr in ('pre1', 'pre2', 'norm1', 'norm2'): 

635 self.wids[attr].SetValue(defaults[attr]) 

636 self.onReprocess() 

637 

638 def onCopyAuto(self, evt=None): 

639 opts = dict(pre1=0, pre2=0, nvict=0, norm1=0, norm2=0, 

640 norm_method='polynomial', nnorm=2, auto_e0=1, 

641 auto_step=1) 

642 for checked in self.controller.filelist.GetCheckedStrings(): 

643 groupname = self.controller.file_groups[str(checked)] 

644 grp = self.controller.get_group(groupname) 

645 if grp != self.controller.group and not getattr(grp, 'is_frozen', False): 

646 self.update_config(opts, dgroup=grp) 

647 self.fill_form(grp) 

648 self.process(grp, force=True) 

649 

650 

651 def onSaveConfigBtn(self, evt=None): 

652 conf = self.get_config() 

653 conf.update(self.read_form()) 

654 # self.set_defaultconfig(conf) 

655 

656 def onCopyParam(self, name=None, evt=None): 

657 conf = self.get_config() 

658 form = self.read_form() 

659 conf.update(form) 

660 dgroup = self.controller.get_group() 

661 self.update_config(conf) 

662 self.fill_form(dgroup) 

663 opts = {} 

664 name = str(name) 

665 def copy_attrs(*args): 

666 for a in args: 

667 opts[a] = conf[a] 

668 if name == 'all': 

669 copy_attrs('e0', 'show_e0', 'auto_e0', 'edge_step', 

670 'auto_step', 'energy_shift', 'pre1', 'pre2', 

671 'nvict', 'atsym', 'edge', 'norm_method', 'nnorm', 

672 'norm1', 'norm2', 'energy_ref') 

673 elif name == 'xas_e0': 

674 copy_attrs('e0', 'show_e0', 'auto_e0') 

675 elif name == 'xas_step': 

676 copy_attrs('edge_step', 'auto_step') 

677 elif name == 'energy_shift': 

678 copy_attrs('energy_shift') 

679 elif name == 'xas_pre': 

680 copy_attrs('pre1', 'pre2', 'nvict', 'show_pre') 

681 elif name == 'atsym': 

682 copy_attrs('atsym', 'edge') 

683 elif name == 'xas_norm': 

684 copy_attrs('norm_method', 'nnorm', 'norm1', 'norm2', 'show_norm') 

685 elif name == 'energy_ref': 

686 copy_attrs('energy_ref') 

687 for checked in self.controller.filelist.GetCheckedStrings(): 

688 groupname = self.controller.file_groups[str(checked)] 

689 grp = self.controller.get_group(groupname) 

690 if grp != self.controller.group and not getattr(grp, 'is_frozen', False): 

691 self.update_config(opts, dgroup=grp) 

692 for key, val in opts.items(): 

693 if hasattr(grp, key): 

694 setattr(grp, key, val) 

695 self.fill_form(grp) 

696 self.process(grp, force=True) 

697 

698 def onAuto_XASE0(self, evt=None): 

699 if evt.IsChecked(): 

700 dgroup = self.controller.get_group() 

701 find_e0(dgroup) 

702 self.update_config({'e0': dgroup.e0}) 

703 time.sleep(0.002) 

704 wx.CallAfter(self.onReprocess) 

705 

706 def onSet_XASE0(self, evt=None, value=None): 

707 "handle setting auto e0 / show e0" 

708 auto_e0 = self.wids['auto_e0'].GetValue() 

709 self.update_config({'e0': self.wids['e0'].GetValue(), 

710 'auto_e0':self.wids['auto_e0'].GetValue()}) 

711 time.sleep(0.002) 

712 wx.CallAfter(self.onReprocess) 

713 

714 def onSet_XASE0Val(self, evt=None, value=None): 

715 "handle setting e0" 

716 self.wids['auto_e0'].SetValue(0) 

717 self.update_config({'e0': self.wids['e0'].GetValue(), 

718 'auto_e0':self.wids['auto_e0'].GetValue()}) 

719 time.sleep(0.002) 

720 wx.CallAfter(self.onReprocess) 

721 

722 def onSet_EnergyShift(self, evt=None, value=None): 

723 conf = self.get_config() 

724 if conf['auto_energy_shift']: 

725 eshift = self.wids['energy_shift'].GetValue() 

726 dgroup = self.controller.get_group() 

727 _eref = getattr(dgroup, 'energy_ref', '<;no eref;>') 

728 _gname = dgroup.groupname 

729 self.stale_groups = [] 

730 for fname, gname in self.controller.file_groups.items(): 

731 this = self.controller.get_group(gname) 

732 if _gname != gname and _eref == getattr(this, 'energy_ref', None): 

733 this.energy_shift = this.config.xasnorm['energy_shift'] = eshift 

734 self.stale_groups.append(this) 

735 

736 wx.CallAfter(self.onReprocess) 

737 

738 def onSet_XASStep(self, evt=None, value=None): 

739 "handle setting edge step" 

740 edge_step = self.wids['step'].GetValue() 

741 if edge_step < 0: 

742 self.wids['step'].SetValue(abs(edge_step)) 

743 self.wids['auto_step'].SetValue(0) 

744 self.update_config({'edge_step': abs(edge_step), 'auto_step': False}) 

745 autoset_fs_increment(self.wids['step'], abs(edge_step)) 

746 time.sleep(0.01) 

747 wx.CallAfter(self.onReprocess) 

748 

749 

750 def onSet_Ranges(self, evt=None, **kws): 

751 conf = {} 

752 for attr in ('pre1', 'pre2', 'norm1', 'norm2'): 

753 conf[attr] = self.wids[attr].GetValue() 

754 self.update_config(conf) 

755 time.sleep(0.01) 

756 wx.CallAfter(self.onReprocess) 

757 

758 def pin_callback(self, opt='__', xsel=None, relative_e0=True, **kws): 

759 """ 

760 get last selected point from a specified plot window 

761 and fill in the value for the widget defined by `opt`. 

762 

763 by default it finds the latest cursor position from the 

764 cursor history of the first 20 plot windows. 

765 """ 

766 if xsel is None or opt not in self.wids: 

767 return 

768 

769 e0 = self.wids['e0'].GetValue() 

770 if opt == 'e0': 

771 self.wids['e0'].SetValue(xsel) 

772 self.wids['auto_e0'].SetValue(0) 

773 elif opt in ('pre1', 'pre2', 'norm1', 'norm2'): 

774 self.wids[opt].SetValue(xsel-e0) 

775 time.sleep(0.01) 

776 wx.CallAfter(self.onReprocess) 

777 

778 def onReprocess(self, evt=None, value=None, **kws): 

779 "handle request reprocess" 

780 if self.skip_process: 

781 return 

782 try: 

783 dgroup = self.controller.get_group() 

784 except TypeError: 

785 return 

786 if not hasattr(dgroup.config, self.configname): 

787 return 

788 form = self.read_form() 

789 self.process(dgroup=dgroup) 

790 if self.stale_groups is not None: 

791 for g in self.stale_groups: 

792 self.process(dgroup=g, force=True) 

793 self.stale_groups = None 

794 self.onPlotEither() 

795 

796 

797 def process(self, dgroup=None, force_mback=False, force=False, use_form=True, **kws): 

798 """ handle process (pre-edge/normalize) of XAS data from XAS form 

799 """ 

800 if self.skip_process and not force: 

801 return 

802 if dgroup is None: 

803 dgroup = self.controller.get_group() 

804 if dgroup is None: 

805 return 

806 

807 self.skip_process = True 

808 conf = self.get_config(dgroup) 

809 form = self.read_form() 

810 if not use_form: 

811 form.update(self.get_defaultconfig()) 

812 

813 form['group'] = dgroup.groupname 

814 groupnames = list(self.controller.file_groups.keys()) 

815 self.wids['energy_ref'].SetChoices(groupnames) 

816 eref_sel = self.wids['energy_ref'].GetStringSelection() 

817 for key, val in self.controller.file_groups.items(): 

818 if eref_sel in (val, key): 

819 self.wids['energy_ref'].SetStringSelection(key) 

820 

821 

822 en_units = getattr(dgroup, 'energy_units', None) 

823 if en_units is None: 

824 en_units = guess_energy_units(dgroup.energy) 

825 

826 if en_units != 'eV': 

827 mono_dspace = getattr(dgroup, 'mono_dspace', 1) 

828 dlg = EnergyUnitsDialog(self.parent, dgroup.energy, 

829 unitname=en_units, 

830 dspace=mono_dspace) 

831 res = dlg.GetResponse() 

832 dlg.Destroy() 

833 if res.ok: 

834 en_units = res.units 

835 dgroup.mono_dspace = res.dspace 

836 dgroup.xplot = dgroup.energy = res.energy 

837 dgroup.energy_units = en_units 

838 

839 if not hasattr(dgroup, 'e0'): 

840 e0 = find_e0(dgroup) 

841 if form['atsym'] == '?' and conf.get('atsym', '?') != '?': 

842 form['atsym'] = conf['atsym'] 

843 form['edge'] = conf.get('edge', 'K') 

844 

845 if form['atsym'] == '?': 

846 form['atsym'], form['edge'] = guess_edge(dgroup.e0) 

847 dgroup.atsym = form['atsym'] 

848 dgroup.edge = form['edge'] 

849 

850 

851 cmds = [] 

852 # test whether the energy shift is 0 or is different from the current energy shift: 

853 ediff = 8.42e14 # just a huge energy step/shift 

854 eshift_current = getattr(dgroup, 'energy_shift', ediff) 

855 eshift = form.get('energy_shift', ediff) 

856 e1 = getattr(dgroup, 'energy', [ediff]) 

857 e2 = getattr(dgroup, 'energy_orig', None) 

858 

859 if (not isinstance(e2, np.ndarray) or (len(e1) != len(e2))): 

860 cmds.append("{group:s}.energy_orig = {group:s}.energy[:]") 

861 

862 if (isinstance(e1, np.ndarray) and isinstance(e2, np.ndarray) and 

863 len(e1) == len(e2)): 

864 ediff = (e1-e2).min() 

865 

866 if abs(eshift-ediff) > 1.e-5 or abs(eshift-eshift_current) > 1.e-5: 

867 if abs(eshift) > 1e15: eshift = 0.0 

868 cmds.extend(["{group:s}.energy_shift = {eshift:.4f}", 

869 "{group:s}.energy = {group:s}.xplot = {group:s}.energy_orig + {group:s}.energy_shift"]) 

870 

871 if len(cmds) > 0: 

872 self.larch_eval(('\n'.join(cmds)).format(group=dgroup.groupname, eshift=eshift)) 

873 

874 e0 = form['e0'] 

875 edge_step = form['edge_step'] 

876 

877 copts = [dgroup.groupname] 

878 if not form['auto_e0']: 

879 if e0 < max(dgroup.energy) and e0 > min(dgroup.energy): 

880 copts.append("e0=%.4f" % float(e0)) 

881 

882 if not form['auto_step']: 

883 copts.append("step=%s" % gformat(float(edge_step))) 

884 

885 for attr in ('pre1', 'pre2', 'nvict', 'nnorm', 'norm1', 'norm2'): 

886 val = form[attr] 

887 if val is None or val == 'auto': 

888 val = 'None' 

889 elif attr in ('nvict', 'nnorm'): 

890 if val in NNORM_CHOICES: 

891 val = NNORM_CHOICES[val] 

892 val = int(val) 

893 else: 

894 val = f"{float(val):.2f}" 

895 copts.append(f"{attr}={val}") 

896 # print("process PreEdge ", copts) 

897 self.larch_eval("pre_edge(%s)" % (', '.join(copts))) 

898 self.larch_eval("{group:s}.norm_poly = 1.0*{group:s}.norm".format(**form)) 

899 if not hasattr(dgroup, 'e0'): 

900 self.skip_process = False 

901 dgroup.mu = dgroup.yplot * 1.0 

902 opts = {'group': dgroup.groupname} 

903 return 

904 

905 norm_method = form['norm_method'].lower() 

906 form['normmeth'] = 'poly' 

907 

908 dgroup.journal.add_ifnew('normalization_method', norm_method) 

909 

910 if force_mback or norm_method.startswith('mback'): 

911 form['normmeth'] = 'mback' 

912 copts = [dgroup.groupname] 

913 copts.append("z=%d" % atomic_number(form['atsym'])) 

914 copts.append("edge='%s'" % form['edge']) 

915 for attr in ('pre1', 'pre2', 'nvict', 'nnorm', 'norm1', 'norm2'): 

916 val = form[attr] 

917 if val is None or val == 'auto': 

918 val = 'None' 

919 elif attr in ('nvict', 'nnorm'): 

920 if val in NNORM_CHOICES: 

921 val = NNORM_CHOICES[val] 

922 val = int(val) 

923 else: 

924 val = f"{float(val):.2f}" 

925 copts.append(f"{attr}={val}") 

926 self.larch_eval("mback_norm(%s)" % (', '.join(copts))) 

927 

928 if form['auto_step']: 

929 norm_expr = """{group:s}.norm = 1.0*{group:s}.norm_{normmeth:s} 

930{group:s}.edge_step = 1.0*{group:s}.edge_step_{normmeth:s}""" 

931 self.larch_eval(norm_expr.format(**form)) 

932 else: 

933 norm_expr = """{group:s}.norm = 1.0*{group:s}.norm_{normmeth:s} 

934{group:s}.norm *= {group:s}.edge_step_{normmeth:s}/{edge_step:.8f}""" 

935 self.larch_eval(norm_expr.format(**form)) 

936 

937 if norm_method.startswith('area'): 

938 form['normmeth'] = 'area' 

939 expr = """{group:s}.norm = 1.0*{group:s}.norm_{normmeth:s} 

940{group:s}.edge_step = 1.0*{group:s}.edge_step_{normmeth:s}""" 

941 self.larch_eval(expr.format(**form)) 

942 

943 

944 if form['auto_e0'] and hasattr(dgroup, 'e0'): 

945 self.wids['e0'].SetValue(dgroup.e0) 

946 if form['auto_step'] and hasattr(dgroup, 'edge_step'): 

947 self.wids['step'].SetValue(dgroup.edge_step) 

948 autoset_fs_increment(self.wids['step'], dgroup.edge_step) 

949 

950 if hasattr(dgroup, 'e0') and (conf.get('atsym', '?') == '?'): 

951 atsym, edge = guess_edge(dgroup.e0) 

952 conf['atsym'] = dgroup.atsym = atsym 

953 conf['edge'] = dgroup.edge = edge 

954 self.wids['atsym'].SetStringSelection(dgroup.atsym) 

955 self.wids['edge'].SetStringSelection(dgroup.edge) 

956 

957 self.set_nnorm_widget(dgroup.pre_edge_details.nnorm) 

958 for attr in ('e0', 'edge_step'): 

959 conf[attr] = getattr(dgroup, attr) 

960 for attr in ('pre1', 'pre2', 'norm1', 'norm2'): 

961 conf[attr] = val = getattr(dgroup.pre_edge_details, attr, None) 

962 if val is not None: 

963 self.wids[attr].SetValue(val) 

964 

965 if hasattr(dgroup, 'mback_params'): # from mback 

966 conf['atsym'] = getattr(dgroup.mback_params, 'atsym') 

967 conf['edge'] = getattr(dgroup.mback_params, 'edge') 

968 self.update_config(conf, dgroup=dgroup) 

969 # print("process updated conf ", dgroup, conf) 

970 wx.CallAfter(self.unset_skip_process) 

971 

972 

973 def get_plot_arrays(self, dgroup): 

974 lab = plotlabels.norm 

975 if dgroup is None: 

976 return 

977 

978 dgroup.plot_y2label = None 

979 dgroup.plot_xlabel = plotlabels.energy 

980 dgroup.plot_yarrays = [('norm', PLOTOPTS_1, lab)] 

981 

982 req_attrs = ['e0', 'norm', 'dmude', 'd2mude', 'pre_edge'] 

983 

984 pchoice = PlotOne_Choices.get(self.plotone_op.GetStringSelection(), 'norm') 

985 

986 if pchoice in ('mu', 'norm', 'i0', 'flat', 'dmude', 'd2mude'): 

987 lab = getattr(plotlabels, pchoice) 

988 dgroup.plot_yarrays = [(pchoice, PLOTOPTS_1, lab)] 

989 

990 elif pchoice == 'prelines': 

991 lab = plotlabels.mu 

992 dgroup.plot_yarrays = [('mu', PLOTOPTS_1, plotlabels.mu), 

993 ('pre_edge', PLOTOPTS_2, 'pre edge'), 

994 ('post_edge', PLOTOPTS_2, 'post edge')] 

995 

996 elif pchoice == 'norm+d2mude': 

997 lab = plotlabels.norm 

998 dgroup.plot_y2label = lab2 = plotlabels.d2mude 

999 dgroup.plot_yarrays = [('norm', PLOTOPTS_1, lab), 

1000 ('d2mude', PLOTOPTS_D, lab2)] 

1001 

1002 elif pchoice == 'norm+dmude': 

1003 lab = plotlabels.norm 

1004 dgroup.plot_y2label = lab2 = plotlabels.dmude 

1005 dgroup.plot_yarrays = [('norm', PLOTOPTS_1, lab), 

1006 ('dmude', PLOTOPTS_D, lab2)] 

1007 elif pchoice == 'norm+i0': 

1008 lab = plotlabels.norm 

1009 dgroup.plot_y2label = lab2 = plotlabels.i0 

1010 dgroup.plot_yarrays = [('norm', PLOTOPTS_1, lab), 

1011 ('i0', PLOTOPTS_D, lab2)] 

1012 elif pchoice == 'norm+flat': 

1013 lab = plotlabels.norm 

1014 dgroup.plot_y2label = lab2 = plotlabels.flat 

1015 dgroup.plot_yarrays = [('norm', PLOTOPTS_1, lab), 

1016 ('flat', PLOTOPTS_D, lab2)] 

1017 elif pchoice == 'mback_norm': 

1018 req_attrs.append('mback_norm') 

1019 lab = plotlabels.mu 

1020 if not hasattr(dgroup, 'mback_mu'): 

1021 self.process(dgroup=dgroup, force_mback=True) 

1022 dgroup.plot_yarrays = [('mu', PLOTOPTS_1, lab), 

1023 ('mback_mu', PLOTOPTS_2, r'tabulated $\mu(E)$')] 

1024 

1025 elif pchoice == 'mback_poly': 

1026 req_attrs.append('mback_norm') 

1027 lab = plotlabels.norm 

1028 if not hasattr(dgroup, 'mback_mu'): 

1029 self.process(dgroup=dgroup, force_mback=True) 

1030 dgroup.plot_yarrays = [('norm_mback', PLOTOPTS_1, 'mback'), 

1031 ('norm_poly', PLOTOPTS_2, 'polynomial')] 

1032 

1033 elif pchoice == 'area_norm': 

1034 dgroup.plot_yarrays = [('norm_area', PLOTOPTS_1, 'area'), 

1035 ('norm_poly', PLOTOPTS_2, 'polynomial')] 

1036 

1037 dgroup.plot_ylabel = lab 

1038 needs_proc = False 

1039 for attr in req_attrs: 

1040 needs_proc = needs_proc or (not hasattr(dgroup, attr)) 

1041 

1042 if needs_proc: 

1043 self.process(dgroup=dgroup, force=True) 

1044 

1045 y4e0 = dgroup.yplot = getattr(dgroup, dgroup.plot_yarrays[0][0], dgroup.mu) 

1046 dgroup.plot_extras = [] 

1047 

1048 popts = {'marker': 'o', 'markersize': 5, 

1049 'label': '_nolegend_', 

1050 'markerfacecolor': '#888', 

1051 'markeredgecolor': '#A00'} 

1052 

1053 if self.wids['show_e0'].IsChecked(): 

1054 ie0 = index_of(dgroup.energy, dgroup.e0) 

1055 dgroup.plot_extras.append(('marker', dgroup.e0, y4e0[ie0], popts)) 

1056 

1057 if self.wids['show_pre'].IsChecked() or self.wids['show_norm'].IsChecked(): 

1058 popts['markersize'] = 4 

1059 wids = [] 

1060 if self.wids['show_pre'].IsChecked(): wids.extend(['pre1', 'pre2']) 

1061 if self.wids['show_norm'].IsChecked(): wids.extend(['norm1', 'norm2']) 

1062 for wid in wids: 

1063 val = self.wids[wid].GetValue() 

1064 ival = min(len(y4e0)-1, index_of(dgroup.energy, dgroup.e0 + val)) 

1065 dgroup.plot_extras.append(('marker', dgroup.e0+val, y4e0[ival], popts)) 

1066 

1067 def plot(self, dgroup, title=None, plot_yarrays=None, yoff=0, 

1068 delay_draw=True, multi=False, new=True, with_extras=True, **kws): 

1069 

1070 if self.skip_plotting: 

1071 return 

1072 ppanel = self.controller.get_display(stacked=False).panel 

1073 

1074 plotcmd = ppanel.oplot 

1075 if new: 

1076 plotcmd = ppanel.plot 

1077 

1078 erange = Plot_EnergyRanges[self.plot_erange.GetStringSelection()] 

1079 self.controller.set_plot_erange(erange) 

1080 

1081 groupname = getattr(dgroup, 'groupname', None) 

1082 if groupname is None: 

1083 return 

1084 

1085 self.ensure_xas_processed(dgroup, force_mback=True) 

1086 self.get_plot_arrays(dgroup) 

1087 

1088 if plot_yarrays is None and hasattr(dgroup, 'plot_yarrays'): 

1089 plot_yarrays = dgroup.plot_yarrays 

1090 

1091 popts = self.controller.get_plot_conf() 

1092 popts.update(kws) 

1093 popts['grid'] = popts.pop('show_grid') 

1094 popts['fullbox'] = popts.pop('show_fullbox') 

1095 

1096 path, fname = path_split(dgroup.filename) 

1097 if 'label' not in popts: 

1098 popts['label'] = dgroup.plot_ylabel 

1099 

1100 zoom_limits = get_zoomlimits(ppanel, dgroup) 

1101 

1102 if erange is not None and hasattr(dgroup, 'e0'): 

1103 popts['xmin'] = dgroup.e0 + erange[0] 

1104 popts['xmax'] = dgroup.e0 + erange[1] 

1105 

1106 popts['xlabel'] = dgroup.plot_xlabel 

1107 popts['ylabel'] = dgroup.plot_ylabel 

1108 if getattr(dgroup, 'plot_y2label', None) is not None: 

1109 popts['y2label'] = dgroup.plot_y2label 

1110 

1111 plot_choices = PlotSel_Choices 

1112 if multi: 

1113 ylabel = self.plotsel_op.GetStringSelection() 

1114 yarray_name = plot_choices.get(ylabel, 'norm') 

1115 

1116 if self.is_xasgroup(dgroup): 

1117 ylabel = getattr(plotlabels, yarray_name, ylabel) 

1118 popts['ylabel'] = ylabel 

1119 

1120 plot_extras = None 

1121 if new: 

1122 if title is None: 

1123 title = fname 

1124 plot_extras = getattr(dgroup, 'plot_extras', None) 

1125 

1126 popts['title'] = title 

1127 popts['show_legend'] = len(plot_yarrays) > 1 

1128 narr = len(plot_yarrays) - 1 

1129 

1130 _linewidth = popts['linewidth'] 

1131 for i, pydat in enumerate(plot_yarrays): 

1132 yaname, yopts, yalabel = pydat 

1133 popts.update(yopts) 

1134 if yalabel is not None: 

1135 popts['label'] = yalabel 

1136 linewidht = _linewidth 

1137 if 'linewidth' in popts: 

1138 linewidth = popts.pop('linewidth') 

1139 popts['delay_draw'] = delay_draw 

1140 if yaname == 'norm_mback' and not hasattr(dgroup, yaname): 

1141 self.process(dgroup=dgroup, force=True, force_mback=True) 

1142 if yaname == 'i0' and not hasattr(dgroup, yaname): 

1143 dgroup.i0 = np.ones(len(dgroup.xplot)) 

1144 plotcmd(dgroup.xplot, getattr(dgroup, yaname)+yoff, linewidth=linewidth, **popts) 

1145 plotcmd = ppanel.oplot 

1146 

1147 if with_extras and plot_extras is not None: 

1148 axes = ppanel.axes 

1149 for etype, x, y, opts in plot_extras: 

1150 if etype == 'marker': 

1151 xpopts = {'marker': 'o', 'markersize': 5, 

1152 'label': '_nolegend_', 

1153 'markerfacecolor': 'red', 

1154 'markeredgecolor': '#884444'} 

1155 xpopts.update(opts) 

1156 axes.plot([x], [y], **xpopts) 

1157 elif etype == 'vline': 

1158 xpopts = {'ymin': 0, 'ymax': 1.0, 

1159 'label': '_nolegend_', 

1160 'color': '#888888'} 

1161 xpopts.update(opts) 

1162 axes.axvline(x, **xpopts) 

1163 

1164 # set_zoomlimits(ppanel, zoom_limits) 

1165 ppanel.reset_formats() 

1166 set_zoomlimits(ppanel, zoom_limits) 

1167 ppanel.conf.unzoom(full=True, delay_draw=False)