Coverage for /Users/Newville/Codes/xraylarch/larch/wxxas/xasnorm_panel.py: 7%

860 statements  

« prev     ^ index     » next       coverage.py v7.3.2, created at 2023-11-09 10:08 -0600

1#!/usr/bin/env python 

2""" 

3XANES Normalization panel 

4""" 

5import os 

6import time 

7import wx 

8import numpy as np 

9 

10from functools import partial 

11 

12from xraydb import guess_edge, atomic_number 

13 

14from larch.utils import gformat 

15from larch.math import index_of 

16from larch.xafs.xafsutils import guess_energy_units 

17from larch.xafs.pre_edge import find_e0 

18 

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

20 SimpleText, pack, Button, HLine, Choice, Check, 

21 GridPanel, CEN, RIGHT, LEFT, plotlabels, 

22 get_zoomlimits, set_zoomlimits) 

23 

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

25 

26from larch.utils.physical_constants import ATOM_NAMES 

27from larch.wxlib.plotter import last_cursor_pos 

28from .xas_dialogs import EnergyUnitsDialog 

29from .taskpanel import TaskPanel, autoset_fs_increment 

30from .config import make_array_choice, EDGES, ATSYMS, NNORM_CHOICES, 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 

53PlotOne_Choices_nonxas = {'Raw Data': 'mu', 

54 'Scaled Data': 'norm', 

55 'Derivative': 'dmude', 

56 'Data + Derivative': 'norm+dmude'} 

57 

58PlotSel_Choices_nonxas = {'Raw Data': 'mu', 

59 'Scaled Data': 'norm', 

60 'Derivative': 'dmude'} 

61 

62FSIZE = 120 

63FSIZEBIG = 175 

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 

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

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

157 

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

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

160 default=0) 

161 

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

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

164 default=0) 

165 

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

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

168 defaults = self.get_defaultconfig() 

169 

170 pre_panel = wx.Panel(panel) 

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

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

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

174 action=self.onSet_XASE0) 

175 

176 sx = wx.BoxSizer(wx.HORIZONTAL) 

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

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

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

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

181 pack(pre_panel, sx) 

182 

183 nor_panel = wx.Panel(panel) 

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

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

186 

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

188 action=self.onSet_XASE0) 

189 sx = wx.BoxSizer(wx.HORIZONTAL) 

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

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

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

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

194 pack(nor_panel, sx) 

195 

196 

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

198 

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

200 scale = self.add_floatspin('scale', action=self.onSet_Scale, **opts) 

201 

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

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

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

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

206 min_val=-99000, max_val=99000, 

207 action=self.onSet_EnergyShift, 

208 size=(FSIZEBIG, -1)) 

209 

210 

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

212 action=self.onFreezeGroup) 

213 

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

215 action=self.onAutoNorm) 

216 copy_auto = Button(panel, 'Copy', size=(60, -1), 

217 action=self.onCopyAuto) 

218 

219 def CopyBtn(name): 

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

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

222 

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

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

225 

226 add_text = self.add_text 

227 HLINEWID = 700 

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

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

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

231 

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

233 add_text('Non-XAS Data Scale:') 

234 panel.Add(scale) 

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

236 

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

238 add_text('XAS Data:') 

239 panel.Add(use_auto, dcol=2) 

240 panel.Add(copy_auto, dcol=1, style=RIGHT) 

241 

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

243 panel.Add(atpanel, dcol=2) 

244 

245 add_text('Energy Reference : ') 

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

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

248 

249 add_text('Energy Shift : ') 

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

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

252 

253 add_text('E0 : ') 

254 panel.Add(e0_panel, dcol=2) 

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

256 

257 add_text('Edge Step: ') 

258 panel.Add(step_panel, dcol=2) 

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

260 

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

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

263 

264 add_text('Pre-edge range: ') 

265 panel.Add(pre_panel, dcol=2) 

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

267 

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

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

270 

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

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

273 

274 add_text('Normalization : ') 

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

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

277 

278 add_text('Norm Energy range: ') 

279 panel.Add(nor_panel, dcol=2) 

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

281 panel.Add(self.wids['nnorm'], dcol=3) 

282 

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

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

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

286 

287 panel.pack() 

288 

289 sizer = wx.BoxSizer(wx.VERTICAL) 

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

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

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

293 pack(self, sizer) 

294 

295 def get_config(self, dgroup=None): 

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

297 if dgroup is None: 

298 dgroup = self.controller.get_group() 

299 if dgroup is None: 

300 return self.get_defaultconfig() 

301 self.read_form() 

302 

303 defconf = self.get_defaultconfig() 

304 conf = getattr(dgroup.config, self.configname, None) 

305 if conf is None: 

306 conf = defconf 

307 

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

309 if k not in conf: 

310 conf[k] = v 

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

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

313 

314 atsym = '?' 

315 if hasattr(dgroup, 'element'): 

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

317 try: 

318 z = int(elem) 

319 atsym = ATSYMS[z] 

320 except: 

321 pass 

322 if elem in ATSYMS[1:]: 

323 atsym = elem 

324 else: 

325 try: 

326 if elem.lower() in ATOM_NAMES: 

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

328 atsym = ATSYMS[z] 

329 except: 

330 pass 

331 

332 conf['atsym'] = atsym 

333 if atsym == '?': 

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

335 

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 if hasattr(dgroup, 'mback_params'): 

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

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

362 

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

364 return conf 

365 

366 def fill_form(self, dgroup): 

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

368 opts = self.get_config(dgroup) 

369 self.skip_process = True 

370 if self.is_xasgroup(dgroup): 

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

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

373 self.plotone_op.SetSelection(1) 

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

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

376 self.plotsel_op.SetSelection(1) 

377 

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

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

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

381 

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

383 if eref in (val, key): 

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

385 

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

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

388 

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

390 atsym, edge = guess_edge(dgroup.e0) 

391 opts['atsym'] = atsym 

392 opts['edge'] = edge 

393 

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

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

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

397 val = opts.get(attr, None) 

398 if val is not None: 

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

400 

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_step'].SetValue(opts['auto_step']) 

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

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

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

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

412 'atsym', 'step', 'norm_method'): 

413 self.wids[attr].Enable() 

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

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

416 

417 self.wids['scale'].Disable() 

418 

419 else: 

420 self.plotone_op.SetChoices(list(PlotOne_Choices_nonxas.keys())) 

421 self.plotsel_op.SetChoices(list(PlotSel_Choices_nonxas.keys())) 

422 

423 self.wids['scale'].SetValue(opts['scale']) 

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

425 'atsym', 'step', 'norm_method'): 

426 self.wids[attr].Disable() 

427 self.wids['scale'].Enable() 

428 

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

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

431 

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

433 self._set_frozen(frozen) 

434 wx.CallAfter(self.unset_skip_process) 

435 

436 def set_nnorm_widget(self, nnorm=None): 

437 nnorm_str = 'auto' 

438 if nnorm is not None: 

439 try: 

440 nnorm = int(nnorm) 

441 except ValueError: 

442 nnorm = None 

443 

444 for k, v in NNORM_CHOICES.items(): 

445 if v == nnorm: 

446 nnorm_str = k 

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

448 

449 def unset_skip_process(self): 

450 self.skip_process = False 

451 

452 def read_form(self): 

453 "read form, return dict of values" 

454 form_opts = {} 

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

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

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

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

459 if val == 0: val = None 

460 form_opts[attr] = val 

461 

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

463 

464 form_opts['nnorm'] = NNORM_CHOICES.get(self.wids['nnorm'].GetStringSelection(), None) 

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

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

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

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

469 for ch in ('show_e0', 'show_pre', 'show_norm', 'auto_e0', 'auto_step'): 

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

471 

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

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

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

475 form_opts['scale'] = self.wids['scale'].GetValue() 

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

477 return form_opts 

478 

479 def onNormMethod(self, evt=None): 

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

481 nnorm = NNORM_CHOICES.get(self.wids['nnorm'].GetStringSelection(), None) 

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

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

484 if method.startswith('mback'): 

485 dgroup = self.controller.get_group() 

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

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

488 atsym, edge = guess_edge(dgroup.e0) 

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

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

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

492 time.sleep(0.002) 

493 wx.CallAfter(self.onReprocess) 

494 

495 def _set_frozen(self, frozen): 

496 try: 

497 dgroup = self.controller.get_group() 

498 dgroup.is_frozen = frozen 

499 except: 

500 pass 

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

502 'nvict', 'nnorm', 'show_e0', 'auto_e0', 'auto_step', 

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

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

505 

506 def onFreezeGroup(self, evt=None): 

507 self._set_frozen(evt.IsChecked()) 

508 

509 def onEnergyRef(self, evt=None): 

510 dgroup = self.controller.get_group() 

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

512 gname = self.controller.file_groups[eref] 

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

514 dgroup.energy_ref = eref 

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

516 

517 def onPlotEither(self, evt=None): 

518 if self.last_plot_type == 'multi': 

519 self.onPlotSel(evt=evt) 

520 else: 

521 self.onPlotOne(evt=evt) 

522 

523 def onPlotOne(self, evt=None): 

524 self.last_plot_type = 'one' 

525 self.plot(self.controller.get_group()) 

526 wx.CallAfter(self.controller.set_focus) 

527 

528 def onVoffset(self, evt=None): 

529 time.sleep(0.002) 

530 wx.CallAfter(self.onPlotSel) 

531 

532 def onPlotSel(self, evt=None): 

533 newplot = True 

534 self.last_plot_type = 'multi' 

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

536 if len(group_ids) < 1: 

537 return 

538 last_id = group_ids[-1] 

539 

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

541 dgroup = self.controller.get_group(groupname) 

542 

543 plot_choices = PlotSel_Choices 

544 if not self.is_xasgroup(dgroup): 

545 plot_choices = PlotSel_Choices_nonxas 

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[ytitle] 

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 voff = self.wids['plot_voff'].GetValue() 

564 plot_traces = [] 

565 newplot = True 

566 plotopts = self.controller.get_plot_conf() 

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

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

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

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

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

572 

573 for ix, checked in enumerate(group_ids): 

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

575 dgroup = self.controller.get_group(groupname) 

576 if dgroup is None: 

577 continue 

578 self.ensure_xas_processed(dgroup) 

579 

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

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

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

583 

584 trace = {'xdata': dgroup.xdat, 

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

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

587 trace.update(popts) 

588 plot_traces.append(trace) 

589 newplot = False 

590 

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

592 zoom_limits = get_zoomlimits(ppanel, dgroup) 

593 

594 nplot_traces = len(ppanel.conf.traces) 

595 nplot_request = len(plot_traces) 

596 if nplot_request > nplot_traces: 

597 linecolors = ppanel.conf.linecolors 

598 ncols = len(linecolors) 

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

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

601 

602 # 

603 

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

605 zoom_limits=zoom_limits, show_legend=True) 

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

607 ppanel.canvas.draw() 

608 

609 wx.CallAfter(self.controller.set_focus) 

610 

611 def onAutoNorm(self, evt=None): 

612 defaults = self.get_defaultconfig() 

613 norm1 = defaults['norm1'] 

614 norm2 = defaults['norm2'] 

615 nnorm = 2 

616 if (norm2-norm1 < 350): nnorm = 1 

617 if (norm2-norm1 < 50): nnorm = 0 

618 

619 self.set_nnorm_widget(nnorm) 

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

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

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

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

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

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

626 self.onReprocess() 

627 

628 def onCopyAuto(self, evt=None): 

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

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

631 auto_step=1) 

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

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

634 grp = self.controller.get_group(groupname) 

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

636 self.update_config(opts, dgroup=grp) 

637 self.fill_form(grp) 

638 self.process(grp, force=True) 

639 

640 

641 def onSaveConfigBtn(self, evt=None): 

642 conf = self.get_config() 

643 conf.update(self.read_form()) 

644 # self.set_defaultconfig(conf) 

645 

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

647 conf = self.get_config() 

648 form = self.read_form() 

649 conf.update(form) 

650 dgroup = self.controller.get_group() 

651 self.update_config(conf) 

652 self.fill_form(dgroup) 

653 opts = {} 

654 name = str(name) 

655 def copy_attrs(*args): 

656 for a in args: 

657 opts[a] = conf[a] 

658 if name == 'all': 

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

660 'auto_step', 'energy_shift', 'pre1', 'pre2', 

661 'nvict', 'atsym', 'edge', 'norm_method', 'nnorm', 

662 'norm1', 'norm2', 'energy_ref') 

663 elif name == 'xas_e0': 

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

665 elif name == 'xas_step': 

666 copy_attrs('edge_step', 'auto_step') 

667 elif name == 'energy_shift': 

668 copy_attrs('energy_shift') 

669 elif name == 'xas_pre': 

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

671 elif name == 'atsym': 

672 copy_attrs('atsym', 'edge') 

673 elif name == 'xas_norm': 

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

675 elif name == 'energy_ref': 

676 copy_attrs('energy_ref') 

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

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

679 grp = self.controller.get_group(groupname) 

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

681 self.update_config(opts, dgroup=grp) 

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

683 if hasattr(grp, key): 

684 setattr(grp, key, val) 

685 self.fill_form(grp) 

686 self.process(grp, force=True) 

687 

688 def onAuto_XASE0(self, evt=None): 

689 if evt.IsChecked(): 

690 dgroup = self.controller.get_group() 

691 find_e0(dgroup) 

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

693 time.sleep(0.002) 

694 wx.CallAfter(self.onReprocess) 

695 

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

697 "handle setting auto e0 / show e0" 

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

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

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

701 time.sleep(0.002) 

702 wx.CallAfter(self.onReprocess) 

703 

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

705 "handle setting e0" 

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

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

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

709 time.sleep(0.002) 

710 wx.CallAfter(self.onReprocess) 

711 

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

713 conf = self.get_config() 

714 if conf['auto_energy_shift']: 

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

716 dgroup = self.controller.get_group() 

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

718 _gname = dgroup.groupname 

719 self.stale_groups = [] 

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

721 this = self.controller.get_group(gname) 

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

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

724 self.stale_groups.append(this) 

725 

726 wx.CallAfter(self.onReprocess) 

727 

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

729 "handle setting edge step" 

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

731 if edge_step < 0: 

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

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

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

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

736 time.sleep(0.01) 

737 wx.CallAfter(self.onReprocess) 

738 

739 def onSet_Scale(self, evt=None, value=None): 

740 "handle setting non-XAFS scale value" 

741 scale = self.wids['scale'].GetValue() 

742 if scale < 0: 

743 self.wids['scale'].SetValue(abs(scale)) 

744 self.update_config({'scale': self.wids['scale'].GetValue()}) 

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

746 time.sleep(0.01) 

747 wx.CallAfter(self.onReprocess) 

748 

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

750 conf = {} 

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

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

753 self.update_config(conf) 

754 time.sleep(0.01) 

755 wx.CallAfter(self.onReprocess) 

756 

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

758 """ 

759 get last selected point from a specified plot window 

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

761 

762 by default it finds the latest cursor position from the 

763 cursor history of the first 20 plot windows. 

764 """ 

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

766 return 

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

768 if opt == 'e0': 

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

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

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

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

773 time.sleep(0.01) 

774 wx.CallAfter(self.onReprocess) 

775 

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

777 "handle request reprocess" 

778 if self.skip_process: 

779 return 

780 try: 

781 dgroup = self.controller.get_group() 

782 except TypeError: 

783 return 

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

785 return 

786 form = self.read_form() 

787 self.process(dgroup=dgroup) 

788 if self.stale_groups is not None: 

789 for g in self.stale_groups: 

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

791 self.stale_groups = None 

792 self.onPlotEither() 

793 

794 

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

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

797 """ 

798 

799 if self.skip_process and not force: 

800 return 

801 if dgroup is None: 

802 dgroup = self.controller.get_group() 

803 if dgroup is None: 

804 return 

805 

806 self.skip_process = True 

807 

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 if not self.is_xasgroup(dgroup): 

822 self.skip_process = False 

823 dgroup.mu = dgroup.ydat * 1.0 

824 opts = {'group': dgroup.groupname, 'scale': conf.get('scale', 1.0)} 

825 self.larch_eval("{group:s}.scale = {scale:.8f}".format(**opts)) 

826 self.larch_eval("{group:s}.norm = {scale:.8f}*{group:s}.ydat".format(**opts)) 

827 return 

828 

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

830 if en_units is None: 

831 en_units = guess_energy_units(dgroup.energy) 

832 

833 if en_units != 'eV': 

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

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

836 unitname=en_units, 

837 dspace=mono_dspace) 

838 res = dlg.GetResponse() 

839 dlg.Destroy() 

840 if res.ok: 

841 en_units = res.units 

842 dgroup.mono_dspace = res.dspace 

843 dgroup.xdat = dgroup.energy = res.energy 

844 dgroup.energy_units = en_units 

845 

846 if hasattr(dgroup, 'e0') and form['atsym'] == '?': 

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

848 

849 dgroup.atsym = form['atsym'] 

850 dgroup.edge = form['edge'] 

851 

852 cmds = [] 

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

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

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

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

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

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

859 

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

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

862 

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

864 len(e1) == len(e2)): 

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

866 

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

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

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

870 "{group:s}.energy = {group:s}.xdat = {group:s}.energy_orig + {group:s}.energy_shift"]) 

871 

872 if len(cmds) > 0: 

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

874 

875 e0 = form['e0'] 

876 edge_step = form['edge_step'] 

877 

878 copts = [dgroup.groupname] 

879 if not form['auto_e0']: 

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

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

882 

883 if not form['auto_step']: 

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

885 

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

887 if form[attr] is None or form[attr] == 'auto': 

888 copts.append("%s=None" % attr) 

889 else: 

890 fmt = "%s=%d" if attr in ('nvict', 'nnorm') else "%s=%.2f" 

891 copts.append(fmt % (attr, form[attr])) 

892 

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

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

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

896 self.skip_process = False 

897 dgroup.mu = dgroup.ydat * 1.0 

898 opts = {'group': dgroup.groupname, 'scale': conf.get('scale', 1.0)} 

899 return 

900 

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

902 form['normmeth'] = 'poly' 

903 

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

905 

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

907 form['normmeth'] = 'mback' 

908 copts = [dgroup.groupname] 

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

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

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

912 if form[attr] is None: 

913 copts.append("%s=None" % attr) 

914 else: 

915 copts.append("%s=%.2f" % (attr, form[attr])) 

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

917 

918 if form['auto_step']: 

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

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

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

922 else: 

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

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

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

926 

927 if norm_method.startswith('area'): 

928 form['normmeth'] = 'area' 

929 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(expr.format(**form)) 

932 

933 

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

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

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

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

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

939 

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

941 atsym, edge = guess_edge(dgroup.e0) 

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

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

944 

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

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

947 

948 self.set_nnorm_widget(dgroup.pre_edge_details.nnorm) 

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

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

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

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

953 if val is not None: 

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

955 

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

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

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

959 self.update_config(conf, dgroup=dgroup) 

960 wx.CallAfter(self.unset_skip_process) 

961 

962 def get_plot_arrays(self, dgroup): 

963 lab = plotlabels.norm 

964 if dgroup is None: 

965 return 

966 

967 dgroup.plot_y2label = None 

968 dgroup.plot_xlabel = plotlabels.energy 

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

970 

971 if not self.is_xasgroup(dgroup): 

972 pchoice = PlotOne_Choices_nonxas[self.plotone_op.GetStringSelection()] 

973 dgroup.plot_xlabel = 'x' 

974 dgroup.plot_ylabel = 'y' 

975 dgroup.plot_yarrays = [('ydat', PLOTOPTS_1, 'ydat')] 

976 dgroup.dmude = np.gradient(dgroup.ydat)/np.gradient(dgroup.xdat) 

977 dgroup.d2mude = np.gradient(dgroup.dmude)/np.gradient(dgroup.xdat) 

978 if not hasattr(dgroup, 'scale'): 

979 dgroup.scale = 1.0 

980 

981 dgroup.norm = dgroup.ydat*dgroup.scale 

982 if pchoice == 'dmude': 

983 dgroup.plot_ylabel = 'dy/dx' 

984 dgroup.plot_yarrays = [('dmude', PLOTOPTS_1, 'dy/dx')] 

985 elif pchoice == 'd2mude': 

986 dgroup.plot_ylabel = 'd2y/dx2' 

987 dgroup.plot_yarrays = [('d2mude', PLOTOPTS_1, 'd2y/dx')] 

988 elif pchoice == 'norm': 

989 dgroup.plot_ylabel = 'scaled y' 

990 dgroup.plot_yarrays = [('norm', PLOTOPTS_1, 'y/scale')] 

991 elif pchoice == 'norm+dmude': 

992 lab = plotlabels.norm 

993 dgroup.plot_y2label = 'dy/dx' 

994 dgroup.plot_yarrays = [('ydat', PLOTOPTS_1, 'y'), 

995 ('dmude', PLOTOPTS_D, 'dy/dx')] 

996 elif pchoice == 'norm+d2mude': 

997 lab = plotlabels.norm 

998 dgroup.plot_y2label = 'd2y/dx2' 

999 dgroup.plot_yarrays = [('ydat', PLOTOPTS_1, 'y'), 

1000 ('d2normde', PLOTOPTS_D, 'd2y/dx2')] 

1001 return 

1002 

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

1004 

1005 pchoice = PlotOne_Choices[self.plotone_op.GetStringSelection()] 

1006 

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

1008 lab = getattr(plotlabels, pchoice) 

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

1010 

1011 elif pchoice == 'prelines': 

1012 lab = plotlabels.mu 

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

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

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

1016 

1017 elif pchoice == 'norm+d2mude': 

1018 lab = plotlabels.norm 

1019 dgroup.plot_y2label = lab2 = plotlabels.d2mude 

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

1021 ('d2mude', PLOTOPTS_D, lab2)] 

1022 

1023 elif pchoice == 'norm+dmude': 

1024 lab = plotlabels.norm 

1025 dgroup.plot_y2label = lab2 = plotlabels.dmude 

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

1027 ('dmude', PLOTOPTS_D, lab2)] 

1028 elif pchoice == 'norm+i0': 

1029 lab = plotlabels.norm 

1030 dgroup.plot_y2label = lab2 = plotlabels.i0 

1031 dgroup.plot_yarrays = [('ydat', PLOTOPTS_1, lab), 

1032 ('i0', PLOTOPTS_D, lab2)] 

1033 elif pchoice == 'norm+flat': 

1034 lab = plotlabels.norm 

1035 dgroup.plot_y2label = lab2 = plotlabels.flat 

1036 dgroup.plot_yarrays = [('ydat', PLOTOPTS_1, lab), 

1037 ('flat', PLOTOPTS_D, lab2)] 

1038 elif pchoice == 'mback_norm': 

1039 req_attrs.append('mback_norm') 

1040 lab = plotlabels.mu 

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

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

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

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

1045 

1046 elif pchoice == 'mback_poly': 

1047 req_attrs.append('mback_norm') 

1048 lab = plotlabels.norm 

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

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

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

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

1053 

1054 elif pchoice == 'area_norm': 

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

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

1057 

1058 dgroup.plot_ylabel = lab 

1059 needs_proc = False 

1060 for attr in req_attrs: 

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

1062 

1063 if needs_proc: 

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

1065 

1066 y4e0 = dgroup.ydat = getattr(dgroup, dgroup.plot_yarrays[0][0], dgroup.mu) 

1067 dgroup.plot_extras = [] 

1068 

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

1070 'label': '_nolegend_', 

1071 'markerfacecolor': '#888', 

1072 'markeredgecolor': '#A00'} 

1073 

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

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

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

1077 

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

1079 popts['markersize'] = 4 

1080 wids = [] 

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

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

1083 for wid in wids: 

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

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

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

1087 

1088 

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

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

1091 

1092 if self.skip_plotting: 

1093 return 

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

1095 

1096 plotcmd = ppanel.oplot 

1097 if new: 

1098 plotcmd = ppanel.plot 

1099 

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

1101 self.controller.set_plot_erange(erange) 

1102 

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

1104 if groupname is None: 

1105 return 

1106 

1107 if not hasattr(dgroup, 'xdat'): 

1108 print("Cannot plot group ", groupname) 

1109 

1110 if ((getattr(dgroup, 'plot_yarrays', None) is None or 

1111 getattr(dgroup, 'energy', None) is None or 

1112 getattr(dgroup, 'mu', None) is None or 

1113 getattr(dgroup, 'e0', None) is None or 

1114 getattr(dgroup, 'dmude', None) is None or 

1115 getattr(dgroup, 'd2mude', None) is None or 

1116 getattr(dgroup, 'norm', None) is None)): 

1117 self.process(dgroup=dgroup) 

1118 self.get_plot_arrays(dgroup) 

1119 

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

1121 plot_yarrays = dgroup.plot_yarrays 

1122 

1123 popts = self.controller.get_plot_conf() 

1124 popts.update(kws) 

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

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

1127 

1128 path, fname = os.path.split(dgroup.filename) 

1129 if 'label' not in popts: 

1130 popts['label'] = dgroup.plot_ylabel 

1131 

1132 zoom_limits = get_zoomlimits(ppanel, dgroup) 

1133 

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

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

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

1137 

1138 popts['xlabel'] = dgroup.plot_xlabel 

1139 popts['ylabel'] = dgroup.plot_ylabel 

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

1141 popts['y2label'] = dgroup.plot_y2label 

1142 

1143 plot_choices = PlotSel_Choices 

1144 if not self.is_xasgroup(dgroup): 

1145 plot_choices = PlotSel_Choices_nonxas 

1146 

1147 if multi: 

1148 ylabel = self.plotsel_op.GetStringSelection() 

1149 yarray_name = plot_choices[ylabel] 

1150 

1151 if self.is_xasgroup(dgroup): 

1152 ylabel = getattr(plotlabels, yarray_name, ylabel) 

1153 popts['ylabel'] = ylabel 

1154 

1155 plot_extras = None 

1156 if new: 

1157 if title is None: 

1158 title = fname 

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

1160 

1161 popts['title'] = title 

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

1163 narr = len(plot_yarrays) - 1 

1164 

1165 _linewidth = popts['linewidth'] 

1166 

1167 for i, pydat in enumerate(plot_yarrays): 

1168 yaname, yopts, yalabel = pydat 

1169 popts.update(yopts) 

1170 if yalabel is not None: 

1171 popts['label'] = yalabel 

1172 linewidht = _linewidth 

1173 if 'linewidth' in popts: 

1174 linewidth = popts.pop('linewidth') 

1175 popts['delay_draw'] = delay_draw 

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

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

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

1179 dgroup.i0 = np.ones(len(dgroup.xdat)) 

1180 plotcmd(dgroup.xdat, getattr(dgroup, yaname)+yoff, linewidth=linewidth, **popts) 

1181 plotcmd = ppanel.oplot 

1182 

1183 if with_extras and plot_extras is not None: 

1184 axes = ppanel.axes 

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

1186 if etype == 'marker': 

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

1188 'label': '_nolegend_', 

1189 'markerfacecolor': 'red', 

1190 'markeredgecolor': '#884444'} 

1191 xpopts.update(opts) 

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

1193 elif etype == 'vline': 

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

1195 'label': '_nolegend_', 

1196 'color': '#888888'} 

1197 xpopts.update(opts) 

1198 axes.axvline(x, **xpopts) 

1199 

1200 # set_zoomlimits(ppanel, zoom_limits) 

1201 ppanel.reset_formats() 

1202 set_zoomlimits(ppanel, zoom_limits) 

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