Coverage for /Users/Newville/Codes/xraylarch/larch/wxlib/xafsplots.py: 29%

541 statements  

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

1#!/usr/bin/env python 

2""" 

3Plotting macros for XAFS data sets and fits 

4 

5 Function Description of what is plotted 

6 ---------------- ----------------------------------------------------- 

7 plot_mu() mu(E) for XAFS data group in various forms 

8 plot_bkg() mu(E) and background mu0(E) for XAFS data group 

9 plot_chik() chi(k) for XAFS data group 

10 plot_chie() chi(E) for XAFS data group 

11 plot_chir() chi(R) for XAFS data group 

12 plot_chifit() chi(k) and chi(R) for fit to feffit dataset 

13 plot_path_k() chi(k) for a single path of a feffit dataset 

14 plot_path_r() chi(R) for a single path of a feffit dataset 

15 plot_paths_k() chi(k) for model and all paths of a feffit dataset 

16 plot_paths_r() chi(R) for model and all paths of a feffit dataset 

17 plot_diffkk() plots from DIFFKK 

18 ---------------- ----------------------------------------------------- 

19""" 

20 

21import os 

22from numpy import gradient, ndarray, diff, where, arange, argmin 

23from matplotlib.ticker import FuncFormatter 

24 

25from larch import Group 

26from larch.math import (index_of, index_nearest, interp) 

27from larch.xafs import cauchy_wavelet, etok, ktoe 

28 

29try: 

30 import wx 

31 HAS_WXPYTHON = True 

32except ImportError: 

33 HAS_WXPYTHON = False 

34 

35if HAS_WXPYTHON: 

36 from .plotter import (get_display, _plot, _oplot, _newplot, _fitplot, 

37 _plot_text, _plot_marker, _plot_arrow, 

38 _plot_axvline, _plot_axhline, _imshow) 

39else: 

40 def nullfunc(*args, **kws): pass 

41 

42 get_display = _plot = _oplot = _newplot = nullfunc 

43 _fitplot = _plot_text = _plot_marker = nullfunc 

44 _plot_arrow = _plot_axvline = _plot_axhline = nullfunc 

45 

46 

47 

48LineColors = ('#1f77b4', '#d62728', '#2ca02c', '#ff7f0e', '#9467bd', 

49 '#8c564b', '#e377c2', '#7f7f7f', '#bcbd22', '#17becf') 

50 

51# common XAFS plot labels 

52def chirlab(kweight, show_mag=True, show_real=False, show_imag=False): 

53 """generate chi(R) label for a kweight 

54 

55 Arguments 

56 ---------- 

57 kweight k-weight to use (required) 

58 show_mag bool whether to plot |chi(R)| [True] 

59 show_real bool whether to plot Re[chi(R)] [False] 

60 show_imag bool whether to plot Im[chi(R)] [False] 

61 """ 

62 ylab = [] 

63 if show_mag: ylab.append(plotlabels.chirmag) 

64 if show_real: ylab.append(plotlabels.chirre) 

65 if show_imag: ylab.append(plotlabels.chirim) 

66 if len(ylab) > 1: ylab = [plotlabels.chir] 

67 return ylab[0].format(kweight+1) 

68#enddef 

69 

70plotlabels = Group(k = r'$k \rm\,(\AA^{-1})$', 

71 r = r'$R \rm\,(\AA)$', 

72 energy = r'$E\rm\,(eV)$', 

73 ewithk = r'$E\rm\,(eV)$' + '\n' + r'$[k \rm\,(\AA^{-1})]$', 

74 i0 = r'$I_0(E)$', 

75 mu = r'$\mu(E)$', 

76 norm = r'normalized $\mu(E)$', 

77 flat = r'flattened $\mu(E)$', 

78 deconv = r'deconvolved $\mu(E)$', 

79 dmude = r'$d\mu_{\rm norm}(E)/dE$', 

80 d2mude = r'$d^2\mu_{\rm norm}(E)/dE^2$', 

81 chie = r'$\chi(E)$', 

82 chie0 = r'$\chi(E)$', 

83 chie1 = r'$E\chi(E) \rm\, (eV)$', 

84 chiew = r'$E^{{{0:g}}}\chi(E) \rm\,(eV^{{{0:g}}})$', 

85 chikw = r'$k^{{{0:g}}}\chi(k) \rm\,(\AA^{{-{0:g}}})$', 

86 chi0 = r'$\chi(k)$', 

87 chi1 = r'$k\chi(k) \rm\,(\AA^{-1})$', 

88 chi2 = r'$k^2\chi(k) \rm\,(\AA^{-2})$', 

89 chi3 = r'$k^3\chi(k) \rm\,(\AA^{-3})$', 

90 chir = r'$\chi(R) \rm\,(\AA^{{-{0:g}}})$', 

91 chirmag = r'$|\chi(R)| \rm\,(\AA^{{-{0:g}}})$', 

92 chirre = r'${{\rm Re}}[\chi(R)] \rm\,(\AA^{{-{0:g}}})$', 

93 chirim = r'${{\rm Im}}[\chi(R)] \rm\,(\AA^{{-{0:g}}})$', 

94 chirpha = r'${{\rm Phase}}[\chi(R)] \rm\,(\AA^{{-{0:g}}})$', 

95 e0color = '#B2B282', 

96 chirlab = chirlab) 

97 

98def safetitle(t): 

99 if "'" in t: 

100 t = t.replace("'", "\\'") 

101 return t 

102 

103def _get_title(dgroup, title=None): 

104 """get best title for group""" 

105 if title is not None: 

106 return safetitle(title) 

107 data_group = getattr(dgroup, 'data', None) 

108 

109 for attr in ('title', 'plot_title', 'filename', 'name', '__name__'): 

110 t = getattr(dgroup, attr, None) 

111 if t is not None: 

112 if attr == 'filename': 

113 folder, file = os.path.split(t) 

114 if folder == '': 

115 t = file 

116 else: 

117 top, folder = os.path.split(folder) 

118 t = '/'.join((folder, file)) 

119 return safetitle(t) 

120 if data_group is not None: 

121 t = getattr(data_group, attr, None) 

122 if t is not None: 

123 return t 

124 return safetitle(repr(dgroup)) 

125 

126 

127def _get_kweight(dgroup, kweight=None): 

128 if kweight is not None: 

129 return kweight 

130 callargs = getattr(dgroup, 'callargs', None) 

131 ftargs = getattr(callargs, 'xftf', {'kweight':0}) 

132 return ftargs['kweight'] 

133 

134 

135def _get_erange(dgroup, emin=None, emax=None): 

136 """get absolute emin/emax for data range, allowing using 

137 values relative to e0. 

138 """ 

139 dat_emin, dat_emax = min(dgroup.energy)-100, max(dgroup.energy)+100 

140 e0 = getattr(dgroup, 'e0', 0.0) 

141 if emin is not None: 

142 if not (emin > dat_emin and emin < dat_emax): 

143 if emin+e0 > dat_emin and emin+e0 < dat_emax: 

144 emin += e0 

145 if emax is not None: 

146 if not (emax > dat_emin and emax < dat_emax): 

147 if emax+e0 > dat_emin and emax+e0 < dat_emax: 

148 emax += e0 

149 return emin, emax 

150#enddef 

151 

152def redraw(win=1, xmin=None, xmax=None, ymin=None, ymax=None, 

153 dymin=None, dymax=None, 

154 show_legend=True, stacked=False, _larch=None): 

155 disp = get_display(win=win, stacked=stacked, _larch=_larch) 

156 if disp is None: 

157 return 

158 panel = disp.panel 

159 panel.conf.show_legend = show_legend 

160 if (xmin is not None or xmax is not None or 

161 ymin is not None or ymax is not None): 

162 panel.set_xylims((xmin, xmax, ymin, ymax)) 

163 if stacked: 

164 disp.panel_bot.set_xylims((xmin, xmax, dymin, dymax)) 

165 

166 panel.unzoom_all() 

167 panel.reset_formats() 

168 if stacked: 

169 disp.panel_bot.unzoom_all() 

170 disp.panel_bot.reset_formats() 

171 if show_legend: # note: draw_legend *will* redraw the canvas 

172 panel.conf.draw_legend() 

173 else: 

174 panel.canvas.draw() 

175 if stacked: 

176 disp.panel_bot.canvas.draw() 

177 

178 #endif 

179#enddef 

180 

181 

182def plot_mu(dgroup, show_norm=False, show_flat=False, show_deriv=False, 

183 show_pre=False, show_post=False, show_e0=False, with_deriv=False, 

184 emin=None, emax=None, label='mu', new=True, delay_draw=False, 

185 offset=0, title=None, win=1, _larch=None): 

186 """ 

187 plot_mu(dgroup, norm=False, deriv=False, show_pre=False, show_post=False, 

188 show_e0=False, show_deriv=False, emin=None, emax=None, label=None, 

189 new=True, win=1) 

190 

191 Plot mu(E) for an XAFS data group in various forms 

192 

193 Arguments 

194 ---------- 

195 dgroup group of XAFS data after pre_edge() results (see Note 1) 

196 show_norm bool whether to show normalized data [False] 

197 show_flat bool whether to show flattened, normalized data [False] 

198 show_deriv bool whether to show derivative of normalized data [False] 

199 show_pre bool whether to show pre-edge curve [False] 

200 show_post bool whether to show post-edge curve [False] 

201 show_e0 bool whether to show E0 [False] 

202 with_deriv bool whether to show deriv (dmu/de) together with mu [False] 

203 emin min energy to show, absolute or relative to E0 [None, start of data] 

204 emax max energy to show, absolute or relative to E0 [None, end of data] 

205 label string for label [None: 'mu', `dmu/dE', or 'mu norm'] 

206 title string for plot title [None, may use filename if available] 

207 new bool whether to start a new plot [True] 

208 delay_draw bool whether to delay draw until more traces are added [False] 

209 offset vertical offset to use for y-array [0] 

210 win integer plot window to use [1] 

211 

212 Notes 

213 ----- 

214 1. The input data group must have the following attributes: 

215 energy, mu, norm, e0, pre_edge, edge_step 

216 """ 

217 if hasattr(dgroup, 'mu'): 

218 mu = dgroup.mu 

219 elif hasattr(dgroup, 'mutrans'): 

220 mu = dgroup.mutrans 

221 elif hasattr(dgroup, 'mufluor'): 

222 mu = dgroup.mufluor 

223 else: 

224 raise ValueError("XAFS data group has no array for mu") 

225 #endif 

226 ylabel = plotlabels.mu 

227 if label is None: 

228 label = getattr(dgroup, 'filename', 'mu') 

229 #endif 

230 if show_deriv: 

231 mu = dgroup.dmude 

232 ylabel = "%s (deriv)" % ylabel 

233 dlabel = plotlabels.dmude 

234 elif show_norm: 

235 mu = dgroup.norm 

236 ylabel = "%s (norm)" % ylabel 

237 dlabel = plotlabels.norm 

238 #endif 

239 elif show_flat: 

240 mu = dgroup.flat 

241 ylabel = "%s (flat)" % ylabel 

242 dlabel = plotlabels.flat 

243 #endif 

244 emin, emax = _get_erange(dgroup, emin, emax) 

245 title = _get_title(dgroup, title=title) 

246 

247 opts = dict(win=win, show_legend=True, linewidth=3, 

248 title=title, xmin=emin, xmax=emax, 

249 delay_draw=True, _larch=_larch) 

250 

251 _plot(dgroup.energy, mu+offset, xlabel=plotlabels.energy, ylabel=ylabel, 

252 label=label, zorder=20, new=new, **opts) 

253 

254 if with_deriv: 

255 dmu = dgroup.dmude 

256 _plot(dgroup.energy, dmu+offset, ylabel=plotlabels.dmude, 

257 label='%s (deriv)' % label, zorder=18, side='right', **opts) 

258 #endif 

259 if (not show_norm and not show_deriv): 

260 if show_pre: 

261 _plot(dgroup.energy, dgroup.pre_edge+offset, label='pre_edge', 

262 zorder=18, **opts) 

263 #endif 

264 if show_post: 

265 _plot(dgroup.energy, dgroup.post_edge+offset, label='post_edge', 

266 zorder=18, **opts) 

267 if show_pre: 

268 i = index_of(dgroup.energy, dgroup.e0) 

269 ypre = dgroup.pre_edge[i] 

270 ypost = dgroup.post_edge[i] 

271 _plot_arrow(dgroup.e0, ypre, dgroup.e0+offset, ypost, 

272 color=plotlabels.e0color, width=0.25, 

273 head_width=0, zorder=3, win=win, _larch=_larch) 

274 #endif 

275 #endif 

276 #endif 

277 if show_e0: 

278 _plot_axvline(dgroup.e0, zorder=2, size=3, 

279 label='E0', color=plotlabels.e0color, win=win, 

280 _larch=_larch) 

281 disp = get_display(win=win, _larch=_larch) 

282 if disp is not None: 

283 disp.panel.conf.draw_legend() 

284 redraw(win=win, xmin=emin, xmax=emax, _larch=_larch) 

285#enddef 

286 

287def plot_bkg(dgroup, norm=True, emin=None, emax=None, show_e0=False, 

288 label=None, title=None, new=True, delay_draw=False, offset=0, 

289 win=1, _larch=None): 

290 """ 

291 plot_bkg(dgroup, norm=True, emin=None, emax=None, show_e0=False, label=None, new=True, win=1): 

292 

293 Plot mu(E) and background mu0(E) for XAFS data group 

294 

295 Arguments 

296 ---------- 

297 dgroup group of XAFS data after autobk() results (see Note 1) 

298 norm bool whether to show normalized data [True] 

299 emin min energy to show, absolute or relative to E0 [None, start of data] 

300 emax max energy to show, absolute or relative to E0 [None, end of data] 

301 show_e0 bool whether to show E0 [False] 

302 label string for label [``None``: 'mu'] 

303 title string for plot titlte [None, may use filename if available] 

304 new bool whether to start a new plot [True] 

305 delay_draw bool whether to delay draw until more traces are added [False] 

306 offset vertical offset to use for y-array [0] 

307 win integer plot window to use [1] 

308 

309 Notes 

310 ----- 

311 1. The input data group must have the following attributes: 

312 energy, mu, bkg, norm, e0, pre_edge, edge_step, filename 

313 """ 

314 if hasattr(dgroup, 'mu'): 

315 mu = dgroup.mu 

316 elif hasattr(dgroup, 'mutrans'): 

317 mu = dgroup.mutrans 

318 else: 

319 raise ValueError("XAFS data group has no array for mu") 

320 #endif 

321 

322 bkg = dgroup.bkg 

323 ylabel = plotlabels.mu 

324 if label is None: 

325 label = 'mu' 

326 #endif 

327 emin, emax = _get_erange(dgroup, emin, emax) 

328 if norm: 

329 mu = dgroup.norm 

330 bkg = (dgroup.bkg - dgroup.pre_edge) / dgroup.edge_step 

331 ylabel = "%s (norm)" % ylabel 

332 label = "%s (norm)" % label 

333 #endif 

334 title = _get_title(dgroup, title=title) 

335 opts = dict(win=win, show_legend=True, linewidth=3, 

336 delay_draw=True, _larch=_larch) 

337 _plot(dgroup.energy, mu+offset, xlabel=plotlabels.energy, ylabel=ylabel, 

338 title=title, label=label, zorder=20, new=new, xmin=emin, xmax=emax, 

339 **opts) 

340 ymin, ymax = None, None 

341 disp = get_display(win=win, _larch=_larch) 

342 if disp is not None: 

343 xylims = disp.panel.get_viewlimits() 

344 ymin, ymax = xylims[2], xylims[3] 

345 _plot(dgroup.energy, bkg+offset, zorder=18, label='bkg', **opts) 

346 

347 if show_e0: 

348 _plot_axvline(dgroup.e0, zorder=2, size=3, label='E0', 

349 color=plotlabels.e0color, win=win, _larch=_larch) 

350 if disp is not None: 

351 disp.panel.conf.draw_legend() 

352 #endif 

353 redraw(win=win, xmin=emin, xmax=emax, ymin=ymin, ymax=ymax, _larch=_larch) 

354#enddef 

355 

356def plot_chie(dgroup, emin=-5, emax=None, label=None, title=None, 

357 eweight=0, show_k=True, new=True, delay_draw=False, 

358 offset=0, win=1, _larch=None): 

359 """ 

360 plot_chie(dgroup, emin=None, emax=None, label=None, new=True, win=1): 

361 

362 Plot chi(E) for XAFS data group 

363 

364 Arguments 

365 ---------- 

366 dgroup group of XAFS data after autobk() results (see Note 1) 

367 emin min energy to show, absolute or relative to E0 [-25] 

368 emax max energy to show, absolute or relative to E0 [None, end of data] 

369 label string for label [``None``: 'mu'] 

370 title string for plot title [None, may use filename if available] 

371 new bool whether to start a new plot [True] 

372 eweight energy weightingn for energisdef es>e0 [0] 

373 show_k bool whether to show k values [True] 

374 delay_draw bool whether to delay draw until more traces are added [False] 

375 offset vertical offset to use for y-array [0] 

376 win integer plot window to use [1] 

377 

378 Notes 

379 ----- 

380 1. The input data group must have the following attributes: 

381 energy, mu, bkg, norm, e0, pre_edge, edge_step, filename 

382 """ 

383 if hasattr(dgroup, 'mu'): 

384 mu = dgroup.mu 

385 elif hasattr(dgroup, 'mutrans'): 

386 mu = dgroup.mutrans 

387 else: 

388 raise ValueError("XAFS data group has no array for mu") 

389 #endif 

390 e0 = dgroup.e0 

391 chie = (mu - dgroup.bkg) 

392 ylabel = plotlabels.chie 

393 if abs(eweight) > 1.e-2: 

394 chie *= (dgroup.energy-e0)**(eweight) 

395 ylabel = plotlabels.chiew.format(eweight) 

396 

397 xlabel = plotlabels.ewithk if show_k else plotlabels.energy 

398 

399 emin, emax = _get_erange(dgroup, emin, emax) 

400 if emin is not None: 

401 emin = emin - e0 

402 if emax is not None: 

403 emax = emax - e0 

404 

405 

406 title = _get_title(dgroup, title=title) 

407 

408 def ek_formatter(x, pos): 

409 ex = float(x) 

410 if ex < 0: 

411 s = '' 

412 else: 

413 s = '\n[%.2f]' % (etok(ex)) 

414 return r"%1.4g%s" % (x, s) 

415 

416 _plot(dgroup.energy-e0, chie+offset, xlabel=xlabel, ylabel=ylabel, 

417 title=title, label=label, zorder=20, new=new, xmin=emin, 

418 xmax=emax, win=win, show_legend=True, delay_draw=delay_draw, 

419 linewidth=3, _larch=_larch) 

420 

421 if show_k: 

422 disp = get_display(win=win, _larch=_larch) 

423 axes = disp.panel.axes 

424 axes.xaxis.set_major_formatter(FuncFormatter(ek_formatter)) 

425 

426 if not delay_draw: 

427 redraw(win=win, xmin=emin, xmax=emax, _larch=_larch) 

428 

429#enddef 

430 

431def plot_chik(dgroup, kweight=None, kmax=None, show_window=True, 

432 scale_window=True, label=None, title=None, new=True, 

433 delay_draw=False, offset=0, win=1, _larch=None): 

434 """ 

435 plot_chik(dgroup, kweight=None, kmax=None, show_window=True, label=None, 

436 new=True, win=1) 

437 

438 Plot k-weighted chi(k) for XAFS data group 

439 

440 Arguments 

441 ---------- 

442 dgroup group of XAFS data after autobk() results (see Note 1) 

443 kweight k-weighting for plot [read from last xftf(), or 0] 

444 kmax max k to show [None, end of data] 

445 show_window bool whether to also plot k-window [True] 

446 scale_window bool whether to scale k-window to max |chi(k)| [True] 

447 label string for label [``None`` to use 'chi'] 

448 title string for plot title [None, may use filename if available] 

449 new bool whether to start a new plot [True] 

450 delay_draw bool whether to delay draw until more traces are added [False] 

451 offset vertical offset to use for y-array [0] 

452 win integer plot window to use [1] 

453 

454 Notes 

455 ----- 

456 1. The input data group must have the following attributes: 

457 k, chi, kwin, filename 

458 """ 

459 kweight = _get_kweight(dgroup, kweight) 

460 

461 chi = dgroup.chi * dgroup.k ** kweight 

462 opts = dict(win=win, show_legend=True, delay_draw=True, linewidth=3, 

463 _larch=_larch) 

464 if label is None: 

465 label = 'chi' 

466 #endif 

467 if new: 

468 title = _get_title(dgroup, title=title) 

469 _plot(dgroup.k, chi+offset, xlabel=plotlabels.k, 

470 ylabel=plotlabels.chikw.format(kweight), title=title, 

471 label=label, zorder=20, new=new, xmax=kmax, **opts) 

472 

473 if show_window and hasattr(dgroup, 'kwin'): 

474 kwin = dgroup.kwin 

475 if scale_window: 

476 kwin = kwin*max(abs(chi)) 

477 _plot(dgroup.k, kwin+offset, zorder=12, label='window', **opts) 

478 #endif 

479 redraw(win=win, xmax=kmax, _larch=_larch) 

480#enddef 

481 

482def plot_chir(dgroup, show_mag=True, show_real=False, show_imag=False, 

483 show_window=False, rmax=None, label=None, title=None, 

484 new=True, delay_draw=False, offset=0, win=1, _larch=None): 

485 """ 

486 plot_chir(dgroup, show_mag=True, show_real=False, show_imag=False, 

487 rmax=None, label=None, new=True, win=1) 

488 

489 Plot chi(R) for XAFS data group 

490 

491 Arguments 

492 ---------- 

493 dgroup group of XAFS data after xftf() results (see Note 1) 

494 show_mag bool whether to plot |chi(R)| [True] 

495 show_real bool whether to plot Re[chi(R)] [False] 

496 show_imag bool whether to plot Im[chi(R)] [False] 

497 show_window bool whether to R-windw for back FT (will be scaled) [False] 

498 label string for label [``None`` to use 'chir'] 

499 title string for plot title [None, may use filename if available] 

500 rmax max R to show [None, end of data] 

501 new bool whether to start a new plot [True] 

502 delay_draw bool whether to delay draw until more traces are added [False] 

503 offset vertical offset to use for y-array [0] 

504 win integer plot window to use [1] 

505 

506 Notes 

507 ----- 

508 1. The input data group must have the following attributes: 

509 r, chir_mag, chir_im, chir_re, kweight, filename 

510 """ 

511 kweight = _get_kweight(dgroup, None) 

512 

513 if new: 

514 title = _get_title(dgroup, title=title) 

515 

516 opts = dict(win=win, show_legend=True, linewidth=3, title=title, 

517 zorder=20, xmax=rmax, xlabel=plotlabels.r, new=new, 

518 delay_draw=True, _larch=_larch) 

519 

520 ylabel = plotlabels.chirlab(kweight, show_mag=show_mag, 

521 show_real=show_real, show_imag=show_imag) 

522 opts['ylabel'] = ylabel 

523 if not hasattr(dgroup, 'r'): 

524 print("group does not have chi(R) data") 

525 return 

526 #endif 

527 if label is None: 

528 label = 'chir' 

529 #endif 

530 if show_mag: 

531 _plot(dgroup.r, dgroup.chir_mag+offset, label='%s (mag)' % label, **opts) 

532 opts['new'] = False 

533 #endif 

534 if show_real: 

535 _plot(dgroup.r, dgroup.chir_re+offset, label='%s (real)' % label, **opts) 

536 opts['new'] = False 

537 #endif 

538 if show_imag: 

539 _plot(dgroup.r, dgroup.chir_im+offset, label='%s (imag)' % label, **opts) 

540 #endif 

541 if show_window and hasattr(dgroup, 'rwin'): 

542 rwin = dgroup.rwin * max(dgroup.chir_mag) 

543 opts['zorder'] = 15 

544 _plot(dgroup.r, rwin+offset, label='window', **opts) 

545 #endif 

546 

547 if show_mag or show_real or show_imag or show_window: 

548 redraw(win=win, xmax=rmax, _larch=_larch) 

549 #endif 

550#enddef 

551 

552def plot_chiq(dgroup, kweight=None, kmax=None, show_chik=False, label=None, 

553 title=None, new=True, delay_draw=False, offset=0, win=1, 

554 show_window=False, scale_window=True, _larch=None): 

555 """ 

556 plot_chiq(dgroup, kweight=None, kmax=None, show_chik=False, label=None, 

557 new=True, win=1) 

558 

559 Plot Fourier filtered chi(k), optionally with k-weighted chi(k) for XAFS data group 

560 

561 Arguments 

562 ---------- 

563 dgroup group of XAFS data after autobk() results (see Note 1) 

564 kweight k-weighting for plot [read from last xftf(), or 0] 

565 kmax max k to show [None, end of data] 

566 show_chik bool whether to also plot k-weighted chi(k) [False] 

567 show_window bool whether to also plot FT k-window [False] 

568 scale_window bool whether to scale FT k-window to max |chi(q)| [True] 

569 label string for label [``None`` to use 'chi'] 

570 title string for plot title [None, may use filename if available] 

571 new bool whether to start a new plot [True] 

572 delay_draw bool whether to delay draw until more traces are added [False] 

573 offset vertical offset to use for y-array [0] 

574 win integer plot window to use [1] 

575 

576 Notes 

577 ----- 

578 1. The input data group must have the following attributes: 

579 k, chi, kwin, filename 

580 """ 

581 kweight = _get_kweight(dgroup, kweight) 

582 nk = len(dgroup.k) 

583 chiq = dgroup.chiq_re[:nk] 

584 opts = dict(win=win, show_legend=True, delay_draw=True, linewidth=3, _larch=_larch) 

585 if label is None: 

586 label = 'chi(q) (filtered)' 

587 #endif 

588 if new: 

589 title = _get_title(dgroup, title=title) 

590 

591 _plot(dgroup.k, chiq+offset, xlabel=plotlabels.k, 

592 ylabel=plotlabels.chikw.format(kweight), title=title, 

593 label=label, zorder=20, new=new, xmax=kmax, **opts) 

594 

595 if show_chik: 

596 chik = dgroup.chi * dgroup.k ** kweight 

597 _plot(dgroup.k, chik+offset, zorder=16, label='chi(k)', **opts) 

598 #endif 

599 if show_window and hasattr(dgroup, 'kwin'): 

600 kwin = dgroup.kwin 

601 if scale_window: 

602 kwin = kwin*max(abs(chiq)) 

603 _plot(dgroup.k, kwin+offset, zorder=12, label='window', **opts) 

604 #endif 

605 

606 redraw(win=win, xmax=kmax, _larch=_larch) 

607#enddef 

608 

609 

610def plot_wavelet(dgroup, show_mag=True, show_real=False, show_imag=False, 

611 rmax=None, kmax=None, kweight=None, title=None, win=1, _larch=None): 

612 """ 

613 plot_wavelet(dgroup, show_mag=True, show_real=False, show_imag=False, 

614 rmax=None, kmax=None, kweight=None, title=None, win=1) 

615 

616 Plot wavelet for XAFS data group 

617 

618 Arguments 

619 ---------- 

620 dgroup group of XAFS data after xftf() results (see Note 1) 

621 show_mag bool whether to plot wavelet magnitude [True] 

622 show_real bool whether to plot real part of wavelet [False] 

623 show_imag bool whether to plot imaginary part of wavelet [False] 

624 title string for plot title [None, may use filename if available] 

625 rmax max R to show [None, end of data] 

626 kmax max k to show [None, end of data] 

627 kweight k-weight to use to construct wavelet [None, take from group] 

628 win integer image window to use [1] 

629 

630 Notes 

631 ----- 

632 The wavelet will be performed 

633 """ 

634 kweight = _get_kweight(dgroup, kweight) 

635 cauchy_wavelet(dgroup, kweight=kweight, rmax_out=rmax) 

636 title = _get_title(dgroup, title=title) 

637 

638 opts = dict(win=win, title=title, x=dgroup.k, y=dgroup.wcauchy_r, xmax=kmax, 

639 ymax=rmax, xlabel=plotlabels.k, ylabel=plotlabels.r, 

640 show_axis=True, _larch=_larch) 

641 if show_mag: 

642 _imshow(dgroup.wcauchy_mag, **opts) 

643 elif show_real: 

644 _imshow(dgroup.wcauchy_real, **opts) 

645 elif show_imag: 

646 _imshow(dgroup.wcauchy_imag, **opts) 

647 #endif 

648#enddef 

649 

650def plot_chifit(dataset, kmin=0, kmax=None, kweight=None, rmax=None, 

651 show_mag=True, show_real=False, show_imag=False, 

652 title=None, new=True, delay_draw=False, offset=0, win=1, 

653 _larch=None): 

654 """ 

655 plot_chifit(dataset, kmin=0, kmax=None, rmax=None, 

656 show_mag=True, show_real=False, show_imag=False, 

657 new=True, win=1) 

658 

659 Plot k-weighted chi(k) and chi(R) for fit to feffit dataset 

660 

661 Arguments 

662 ---------- 

663 dataset feffit dataset, after running feffit() 

664 kmin min k to show [0] 

665 kmax max k to show [None, end of data] 

666 kweight kweight to show [None, taken from dataset] 

667 rmax max R to show [None, end of data] 

668 show_mag bool whether to plot |chidr(R)| [True] 

669 show_real bool whether to plot Re[chi(R)] [False] 

670 show_imag bool whether to plot Im[chi(R)] [False] 

671 title string for plot title [None, may use filename if available] 

672 new bool whether to start a new plot [True] 

673 delay_draw bool whether to delay draw until more traces are added [False] 

674 offset vertical offset to use for y-array [0] 

675 win integer plot window to use [1] 

676 

677 """ 

678 if kweight is None: 

679 kweight = dataset.transform.kweight 

680 #endif 

681 if isinstance(kweight, (list, tuple, ndarray)): kweight=kweight[0] 

682 

683 data_chik = dataset.data.chi * dataset.data.k**kweight 

684 model_chik = dataset.model.chi * dataset.model.k**kweight 

685 

686 title = _get_title(dataset, title=title) 

687 

688 opts=dict(labelfontsize=10, legendfontsize=10, linewidth=3, 

689 show_legend=True, delay_draw=True, win=win, title=title, 

690 _larch=_larch) 

691 

692 # k-weighted chi(k) in first plot window 

693 _plot(dataset.data.k, data_chik+offset, xmin=kmin, xmax=kmax, 

694 xlabel=plotlabels.k, ylabel=plotlabels.chikw.format(kweight), 

695 label='data', new=new, **opts) 

696 _plot(dataset.model.k, model_chik+offset, label='fit', **opts) 

697 redraw(win=win, xmin=kmin, xmax=kmax, _larch=_larch) 

698 

699 # show chi(R) in next plot window 

700 opts['win'] = win = win+1 

701 ylabel = plotlabels.chirlab(kweight, show_mag=show_mag, 

702 show_real=show_real, show_imag=show_imag) 

703 

704 opts.update(dict(xlabel=plotlabels.r, ylabel=ylabel, 

705 xmax=rmax, new=True, show_legend=True)) 

706 

707 if show_mag: 

708 _plot(dataset.data.r, dataset.data.chir_mag+offset, 

709 label='|data|', **opts) 

710 opts['new'] = False 

711 _plot(dataset.model.r, dataset.model.chir_mag+offset, 

712 label='|fit|', **opts) 

713 #endif 

714 if show_real: 

715 _plot(dataset.data.r, dataset.data.chir_re+offset, label='Re[data]', **opts) 

716 opts['new'] = False 

717 _plot(dataset.model.r, dataset.model.chir_re+offset, label='Re[fit]', **opts) 

718 #endif 

719 if show_imag: 

720 _plot(dataset.data.r, dataset.data.chir_im+offset, label='Im[data]', **opts) 

721 opts['new'] = False 

722 _plot(dataset.model.r, dataset.model.chir_im+offset, label='Im[fit]', **opts) 

723 #endif 

724 if show_mag or show_real or show_imag: 

725 redraw(win=opts['win'], xmax=opts['xmax'], _larch=_larch) 

726 #endif 

727#enddef 

728 

729def plot_path_k(dataset, ipath=0, kmin=0, kmax=None, offset=0, label=None, 

730 new=False, delay_draw=False, win=1, _larch=None, **kws): 

731 """ 

732 plot_path_k(dataset, ipath, kmin=0, kmax=None, offset=0, 

733 label=None, new=False, win=1, **kws) 

734 

735 Plot k-weighted chi(k) for a single Path of a feffit dataset 

736 

737 Arguments 

738 ---------- 

739 dataset feffit dataset, after running feffit() 

740 ipath index of path, starting count at 0 [0] 

741 kmin min k to show [0] 

742 kmax max k to show [None, end of data] 

743 offset vertical offset to use for plot [0] 

744 label path label ['path %d' % ipath] 

745 new bool whether to start a new plot [True] 

746 delay_draw bool whether to delay draw until more traces are added [False] 

747 win integer plot window to use [1] 

748 kws additional keyword arguments are passed to plot() 

749 """ 

750 kweight = dataset.transform.kweight 

751 path = dataset.pathlist[ipath] 

752 if label is None: label = 'path %i' % (1+ipath) 

753 

754 chi_kw = offset + path.chi * path.k**kweight 

755 

756 _plot(path.k, chi_kw, label=label, xmin=kmin, xmax=kmax, 

757 xlabel=plotlabels.k, ylabel=plotlabels.chikw.format(kweight), 

758 win=win, new=new, delay_draw=delay_draw, _larch=_larch, **kws) 

759 if delay_draw: 

760 redraw(win=win, xmin=kmin, xmax=kmax, _larch=_larch) 

761#enddef 

762 

763def plot_path_r(dataset, ipath, rmax=None, offset=0, label=None, 

764 show_mag=True, show_real=False, show_imag=True, 

765 new=False, delay_draw=False, win=1, _larch=None, 

766 **kws): 

767 """ 

768 plot_path_r(dataset, ipath,rmax=None, offset=0, label=None, 

769 show_mag=True, show_real=False, show_imag=True, 

770 new=False, win=1, **kws) 

771 

772 Plot chi(R) for a single Path of a feffit dataset 

773 

774 Arguments 

775 ---------- 

776 dataset feffit dataset, after running feffit() 

777 ipath index of path, starting count at 0 [0] 

778 rmax max R to show [None, end of data] 

779 offset vertical offset to use for plot [0] 

780 label path label ['path %d' % ipath] 

781 show_mag bool whether to plot |chi(R)| [True] 

782 show_real bool whether to plot Re[chi(R)] [False] 

783 show_imag bool whether to plot Im[chi(R)] [False] 

784 new bool whether to start a new plot [True] 

785 delay_draw bool whether to delay draw until more traces are added [False] 

786 win integer plot window to use [1] 

787 kws additional keyword arguments are passed to plot() 

788 """ 

789 path = dataset.pathlist[ipath] 

790 if label is None: 

791 label = 'path %i' % (1+ipath) 

792 #endif 

793 kweight =dataset.transform.kweight 

794 ylabel = plotlabels.chirlab(kweight, show_mag=show_mag, 

795 show_real=show_real, show_imag=show_imag) 

796 

797 opts = dict(xlabel=plotlabels.r, ylabel=ylabel, xmax=rmax, new=new, 

798 delay_draw=True, _larch=_larch) 

799 

800 opts.update(kws) 

801 if show_mag: 

802 _plot(path.r, offset+path.chir_mag, label=label, **opts) 

803 opts['new'] = False 

804 #endif 

805 if show_real: 

806 _plot(path.r, offset+path.chir_re, label=label, **opts) 

807 opts['new'] = False 

808 #endif 

809 if show_imag: 

810 _plot(path.r, offset+path.chir_im, label=label, **opts) 

811 opts['new'] = False 

812 #endif 

813 redraw(win=win, xmax=rmax, _larch=_larch) 

814#enddef 

815 

816def plot_paths_k(dataset, offset=-1, kmin=0, kmax=None, title=None, 

817 new=True, delay_draw=False, win=1, _larch=None, **kws): 

818 

819 """ 

820 plot_paths_k(dataset, offset=-1, kmin=0, kmax=None, new=True, win=1, **kws): 

821 

822 Plot k-weighted chi(k) for model and all paths of a feffit dataset 

823 

824 Arguments 

825 ---------- 

826 dataset feffit dataset, after running feffit() 

827 kmin min k to show [0] 

828 kmax max k to show [None, end of data] 

829 offset vertical offset to use for paths for plot [-1] 

830 new bool whether to start a new plot [True] 

831 title string for plot title [None, may use filename if available] 

832 win integer plot window to use [1] 

833 delay_draw bool whether to delay draw until more traces are added [False] 

834 kws additional keyword arguments are passed to plot() 

835 """ 

836 # make k-weighted chi(k) 

837 kweight = dataset.transform.kweight 

838 model = dataset.model 

839 

840 model_chi_kw = model.chi * model.k**kweight 

841 

842 title = _get_title(dataset, title=title) 

843 

844 _plot(model.k, model_chi_kw, title=title, label='sum', new=new, 

845 xlabel=plotlabels.r, ylabel=plotlabels.chikw.format(kweight), 

846 xmin=kmin, xmax=kmax, win=win, delay_draw=True,_larch=_larch, 

847 **kws) 

848 

849 for ipath in range(len(dataset.pathlist)): 

850 plot_path_k(dataset, ipath, offset=(ipath+1)*offset, 

851 kmin=kmin, kmax=kmax, new=False, delay_draw=True, 

852 win=win, _larch=_larch) 

853 #endfor 

854 redraw(win=win, xmin=kmin, xmax=kmax, _larch=_larch) 

855#enddef 

856 

857def plot_paths_r(dataset, offset=-0.25, rmax=None, show_mag=True, 

858 show_real=False, show_imag=False, title=None, new=True, 

859 win=1, delay_draw=False, _larch=None, **kws): 

860 """ 

861 plot_paths_r(dataset, offset=-0.5, rmax=None, show_mag=True, show_real=False, 

862 show_imag=False, new=True, win=1, **kws): 

863 

864 Plot chi(R) for model and all paths of a feffit dataset 

865 

866 Arguments 

867 ---------- 

868 dataset feffit dataset, after running feffit() 

869 offset vertical offset to use for paths for plot [-0.5] 

870 rmax max R to show [None, end of data] 

871 show_mag bool whether to plot |chi(R)| [True] 

872 show_real bool whether to plot Re[chi(R)] [False] 

873 show_imag bool whether to plot Im[chi(R)] [False] 

874 title string for plot title [None, may use filename if available] 

875 new bool whether to start a new plot [True] 

876 delay_draw bool whether to delay draw until more traces are added [False] 

877 win integer plot window to use [1] 

878 kws additional keyword arguments are passed to plot() 

879 """ 

880 kweight = dataset.transform.kweight 

881 model = dataset.model 

882 

883 ylabel = plotlabels.chirlab(kweight, show_mag=show_mag, 

884 show_real=show_real, show_imag=show_imag) 

885 title = _get_title(dataset, title=title) 

886 opts = dict(xlabel=plotlabels.r, ylabel=ylabel, xmax=rmax, new=new, 

887 delay_draw=True, title=title, _larch=_larch) 

888 opts.update(kws) 

889 if show_mag: 

890 _plot(model.r, model.chir_mag, label='|sum|', **opts) 

891 opts['new'] = False 

892 #endif 

893 if show_real: 

894 _plot(model.r, model.chir_re, label='Re[sum]', **opts) 

895 opts['new'] = False 

896 #endif 

897 if show_imag: 

898 _plot(model.r, model.chir_im, label='Im[sum]', **opts) 

899 opts['new'] = False 

900 #endif 

901 

902 for ipath in range(len(dataset.pathlist)): 

903 plot_path_r(dataset, ipath, offset=(ipath+1)*offset, 

904 show_mag=show_mag, show_real=show_real, 

905 show_imag=show_imag, **opts) 

906 #endfor 

907 redraw(win=win, xmax=rmax,_larch=_larch) 

908#enddef 

909 

910 

911def extend_plotrange(x, y, xmin=None, xmax=None, extend=0.10): 

912 """return plot limits to extend a plot range for x, y pairs""" 

913 xeps = min(diff(x)) / 5. 

914 if xmin is None: 

915 xmin = min(x) 

916 if xmax is None: 

917 xmax = max(x) 

918 

919 xmin = max(min(x), xmin-5) 

920 xmax = min(max(x), xmax+5) 

921 

922 i0 = index_of(x, xmin + xeps) 

923 i1 = index_of(x, xmax + xeps) + 1 

924 

925 xspan = x[i0:i1] 

926 xrange = max(xspan) - min(xspan) 

927 yspan = y[i0:i1] 

928 yrange = max(yspan) - min(yspan) 

929 

930 return (min(xspan) - extend * xrange, 

931 max(xspan) + extend * xrange, 

932 min(yspan) - extend * yrange, 

933 max(yspan) + extend * yrange) 

934 

935def plot_prepeaks_baseline(dgroup, subtract_baseline=False, show_fitrange=True, 

936 show_peakrange=True, win=1, _larch=None, **kws): 

937 """Plot pre-edge peak baseline fit, as from `pre_edge_baseline` or XAS Viewer 

938 

939 dgroup must have a 'prepeaks' attribute 

940 """ 

941 if not hasattr(dgroup, 'prepeaks'): 

942 raise ValueError('Group needs prepeaks') 

943 #endif 

944 ppeak = dgroup.prepeaks 

945 

946 px0, px1, py0, py1 = extend_plotrange(dgroup.xdat, dgroup.ydat, 

947 xmin=ppeak.emin, xmax=ppeak.emax) 

948 

949 title = "pre_edge baseline\n %s" % dgroup.filename 

950 

951 popts = dict(xmin=px0, xmax=px1, ymin=py0, ymax=py1, title=title, 

952 xlabel='Energy (eV)', ylabel='mu (normalized)', delay_draw=True, 

953 show_legend=True, style='solid', linewidth=3, 

954 label='data', new=True, 

955 marker='None', markersize=4, win=win, _larch=_larch) 

956 popts.update(kws) 

957 

958 ydat = dgroup.ydat 

959 xdat = dgroup.xdat 

960 if subtract_baseline: 

961 xdat = ppeak.energy 

962 ydat = ppeak.baseline 

963 popts['label'] = 'baseline subtracted peaks' 

964 _plot(xdat, ydat, **popts) 

965 else: 

966 _plot(xdat, ydat, **popts) 

967 popts['new'] = False 

968 popts['label'] = 'baseline' 

969 _oplot(ppeak.energy, ppeak.baseline, **popts) 

970 

971 popts = dict(win=win, _larch=_larch, delay_draw=True, 

972 label='_nolegend_') 

973 

974 if show_fitrange: 

975 for x in (ppeak.emin, ppeak.emax): 

976 _plot_axvline(x, color='#DDDDCC', **popts) 

977 _plot_axvline(ppeak.centroid, color='#EECCCC', **popts) 

978 

979 if show_peakrange: 

980 for x in (ppeak.elo, ppeak.ehi): 

981 y = ydat[index_of(xdat, x)] 

982 _plot_marker(x, y, color='#222255', marker='o', size=8, **popts) 

983 

984 redraw(win=win, xmin=px0, xmax=px1, ymin=py0, ymax=py1, 

985 show_legend=True, _larch=_larch) 

986#enddef 

987 

988def plot_prepeaks_fit(dgroup, nfit=0, show_init=False, subtract_baseline=False, 

989 show_residual=False, win=1, _larch=None): 

990 """plot pre-edge peak fit, as from XAS Viewer 

991 

992 dgroup must have a 'peakfit_history' attribute 

993 """ 

994 if not hasattr(dgroup, 'prepeaks'): 

995 raise ValueError('Group needs prepeaks') 

996 #endif 

997 if show_init: 

998 result = pkfit = dgroup.prepeaks 

999 else: 

1000 hist = getattr(dgroup.prepeaks, 'fit_history', None) 

1001 if nfit > len(hist): 

1002 nfit = 0 

1003 pkfit = hist[nfit] 

1004 result = pkfit.result 

1005 #endif 

1006 

1007 if pkfit is None: 

1008 raise ValueError('Group needs prepeaks.fit_history or init_fit') 

1009 #endif 

1010 

1011 opts = pkfit.user_options 

1012 xeps = min(diff(dgroup.xdat)) / 5. 

1013 xdat = 1.0*pkfit.energy 

1014 ydat = 1.0*pkfit.norm 

1015 

1016 xdat_full = 1.0*dgroup.xdat 

1017 ydat_full = 1.0*dgroup.ydat 

1018 

1019 if show_init: 

1020 yfit = pkfit.init_fit 

1021 ycomps = None # pkfit.init_ycomps 

1022 ylabel = 'model' 

1023 else: 

1024 yfit = 1.0*result.best_fit 

1025 ycomps = pkfit.ycomps 

1026 ylabel = 'best fit' 

1027 

1028 baseline = 0.*ydat 

1029 if ycomps is not None: 

1030 for label, ycomp in ycomps.items(): 

1031 if label in opts['bkg_components']: 

1032 baseline += ycomp 

1033 

1034 plotopts = dict(title='%s:\npre-edge peak' % dgroup.filename, 

1035 xlabel='Energy (eV)', ylabel=opts['array_desc'], 

1036 delay_draw=True, show_legend=True, style='solid', 

1037 linewidth=3, marker='None', markersize=4) 

1038 

1039 if subtract_baseline: 

1040 ydat -= baseline 

1041 yfit -= baseline 

1042 ydat_full = 1.0*ydat 

1043 xdat_full = 1.0*xdat 

1044 plotopts['ylabel'] = '%s-baseline' % plotopts['ylabel'] 

1045 

1046 dx0, dx1, dy0, dy1 = extend_plotrange(xdat_full, ydat_full, 

1047 xmin=opts['emin'], xmax=opts['emax']) 

1048 fx0, fx1, fy0, fy1 = extend_plotrange(xdat, yfit, 

1049 xmin=opts['emin'], xmax=opts['emax']) 

1050 

1051 ncolor = 0 

1052 popts = {'win': win, '_larch': _larch} 

1053 plotopts.update(popts) 

1054 dymin = dymax = None 

1055 if show_residual: 

1056 popts['stacked'] = True 

1057 _fitplot(xdat, ydat, yfit, label='data', label2=ylabel, **plotopts) 

1058 dy = yfit - ydat 

1059 dymax, dymin = dy.max(), dy.min() 

1060 dymax += 0.05 * (dymax - dymin) 

1061 dymin -= 0.05 * (dymax - dymin) 

1062 else: 

1063 _plot(xdat_full, ydat_full, new=True, label='data', 

1064 color=LineColors[0], **plotopts) 

1065 _oplot(xdat, yfit, label=ylabel, color=LineColors[1], **plotopts) 

1066 ncolor = 1 

1067 

1068 if ycomps is not None: 

1069 ncomps = len(ycomps) 

1070 if not subtract_baseline: 

1071 ncolor += 1 

1072 _oplot(xdat, baseline, label='baseline', delay_draw=True, 

1073 style='short dashed', marker='None', markersize=5, 

1074 color=LineColors[ncolor], **popts) 

1075 

1076 for icomp, label in enumerate(ycomps): 

1077 ycomp = ycomps[label] 

1078 if label in opts['bkg_components']: 

1079 continue 

1080 ncolor = (ncolor+1) % 10 

1081 _oplot(xdat, ycomp, label=label, delay_draw=(icomp != ncomps-1), 

1082 style='short dashed', marker='None', markersize=5, 

1083 color=LineColors[ncolor], **popts) 

1084 

1085 if opts.get('show_fitrange', False): 

1086 for attr in ('emin', 'emax'): 

1087 _plot_axvline(opts[attr], ymin=0, ymax=1, 

1088 delay_draw=False, color='#DDDDCC', 

1089 label='_nolegend_', **popts) 

1090 

1091 if opts.get('show_centroid', False): 

1092 pcen = getattr(dgroup.prepeaks, 'centroid', None) 

1093 if hasattr(result, 'params'): 

1094 pcen = result.params.get('fit_centroid', None) 

1095 if pcen is not None: 

1096 pcen = pcen.value 

1097 if pcen is not None: 

1098 _plot_axvline(pcen, delay_draw=False, ymin=0, ymax=1, 

1099 color='#EECCCC', label='_nolegend_', **popts) 

1100 

1101 redraw(xmin=dx0, xmax=dx1, ymin=min(dy0, fy0), 

1102 ymax=max(dy1, fy1), dymin=dymin, dymax=dymax, show_legend=True, **popts) 

1103 

1104def _pca_ncomps(result, min_weight=0, ncomps=None): 

1105 if ncomps is None: 

1106 if min_weight > 1.e-12: 

1107 ncomps = where(result.variances < min_weight)[0][0] 

1108 else: 

1109 ncomps = argmin(result.ind) 

1110 return ncomps 

1111 

1112 

1113def plot_pca_components(result, min_weight=0, ncomps=None, min_variance=1.e-5, win=1, _larch=None, **kws): 

1114 """Plot components from PCA result 

1115 

1116 result must be output of `pca_train` 

1117 """ 

1118 title = "PCA components" 

1119 popts = dict(xmin=result.xmin, xmax=result.xmax, title=title, 

1120 xlabel=plotlabels.energy, ylabel=plotlabels.norm, 

1121 delay_draw=True, show_legend=True, style='solid', 

1122 linewidth=3, new=True, marker='None', markersize=4, 

1123 win=win, _larch=_larch) 

1124 

1125 popts.update(kws) 

1126 ncomps = int(result.nsig) 

1127 

1128 _plot(result.x, result.mean, label='Mean', **popts) 

1129 for i, comp in enumerate(result.components): 

1130 if result.variances[i] > min_variance: 

1131 label = 'Comp# %d (%.4f)' % (i+1, result.variances[i]) 

1132 _oplot(result.x, comp, label=label, **popts) 

1133 

1134 redraw(win=win, show_legend=True, _larch=_larch) 

1135 

1136def plot_pca_weights(result, min_weight=0, ncomps=None, win=1, _larch=None, **kws): 

1137 """Plot component weights from PCA result (aka SCREE plot) 

1138 

1139 result must be output of `pca_train` 

1140 """ 

1141 max_comps = len(result.components) 

1142 

1143 title = "PCA Variances (SCREE) and Indicator Values" 

1144 

1145 popts = dict(title=title, xlabel='Component #', zorder=10, 

1146 xmax=max_comps+1.5, xmin=0.25, ymax=1, ylabel='variance', 

1147 style='solid', ylog_scale=True, show_legend=True, 

1148 linewidth=1, new=True, marker='o', win=win, _larch=_larch) 

1149 

1150 popts.update(kws) 

1151 

1152 ncomps = max(1, int(result.nsig)) 

1153 x = 1 + arange(ncomps) 

1154 y = result.variances[:ncomps] 

1155 _plot(x, y, label='significant', **popts) 

1156 

1157 xe = 1 + arange(ncomps-1, max_comps) 

1158 ye = result.variances[ncomps-1:ncomps+max_comps] 

1159 

1160 popts.update(dict(new=False, zorder=5, style='short dashed', 

1161 color='#B34050', ymin=2e-3*result.variances[ncomps-1])) 

1162 _plot(xe, ye, label='not significant', **popts) 

1163 

1164 xi = 1 + arange(len(result.ind)-1) 

1165 

1166 _plot(xi, result.ind[1:], zorder=15, y2label='Indicator Value', 

1167 label='IND', style='solid', win=win, show_legend=True, 

1168 linewidth=1, marker='o', side='right', _larch=_larch) 

1169 

1170 

1171 

1172def plot_pca_fit(dgroup, win=1, with_components=False, _larch=None, **kws): 

1173 """Plot data and fit result from pca_fit, which rom PCA result 

1174 

1175 result must be output of `pca_fit` 

1176 """ 

1177 

1178 title = "PCA fit: %s" % (dgroup.filename) 

1179 result = dgroup.pca_result 

1180 model = result.pca_model 

1181 

1182 popts = dict(xmin=model.xmin, xmax=model.xmax, title=title, 

1183 xlabel=plotlabels.energy, ylabel=plotlabels.norm, 

1184 delay_draw=True, show_legend=True, style='solid', 

1185 linewidth=3, new=True, marker='None', markersize=4, 

1186 stacked=True, win=win, _larch=_larch) 

1187 popts.update(kws) 

1188 _fitplot(result.x, result.ydat, result.yfit, 

1189 label='data', label2='PCA fit', **popts) 

1190 

1191 disp = get_display(win=win, stacked=True, _larch=_larch) 

1192 if with_components and disp is not None: 

1193 disp.panel.oplot(result.x, model.mean, label='mean') 

1194 for n in range(len(result.weights)): 

1195 cval = model.components[n]*result.weights[n] 

1196 disp.panel.oplot(result.x, cval, label='Comp #%d' % (n+1)) 

1197 redraw(win=win, show_legend=True, stacked=True, _larch=_larch) 

1198 

1199def plot_diffkk(dgroup, emin=None, emax=None, new=True, label=None, 

1200 title=None, delay_draw=False, offset=0, win=1, _larch=None): 

1201 """ 

1202 plot_diffkk(dgroup, norm=True, emin=None, emax=None, show_e0=False, label=None, new=True, win=1): 

1203 

1204 Plot mu(E) and background mu0(E) for XAFS data group 

1205 

1206 Arguments 

1207 ---------- 

1208 dgroup group of XAFS data after autobk() results (see Note 1) 

1209 norm bool whether to show normalized data [True] 

1210 emin min energy to show, absolute or relative to E0 [None, start of data] 

1211 emax max energy to show, absolute or relative to E0 [None, end of data] 

1212 show_e0 bool whether to show E0 [False] 

1213 label string for label [``None``: 'mu'] 

1214 title string for plot title [None, may use filename if available] 

1215 new bool whether to start a new plot [True] 

1216 delay_draw bool whether to delay draw until more traces are added [False] 

1217 offset vertical offset to use for y-array [0] 

1218 win integer plot window to use [1] 

1219 

1220 Notes 

1221 ----- 

1222 1. The input data group must have the following attributes: 

1223 energy, mu, bkg, norm, e0, pre_edge, edge_step, filename 

1224 """ 

1225 if hasattr(dgroup, 'f2'): 

1226 f2 = dgroup.f2 

1227 else: 

1228 raise ValueError("Data group has no array for f2") 

1229 #endif 

1230 ylabel = r'$f \rm\,\, (e^{-})$ ' 

1231 emin, emax = _get_erange(dgroup, emin, emax) 

1232 title = _get_title(dgroup, title=title) 

1233 

1234 labels = {'f2': r"$f_2(E)$", 'fpp': r"$f''(E)$", 'fp': r"$f'(E)$", 'f1': r"$f_1(E)$"} 

1235 

1236 opts = dict(win=win, show_legend=True, linewidth=3, 

1237 delay_draw=True, _larch=_larch) 

1238 

1239 _plot(dgroup.energy, f2, xlabel=plotlabels.energy, ylabel=ylabel, 

1240 title=title, label=labels['f2'], zorder=20, new=new, xmin=emin, xmax=emax, 

1241 **opts) 

1242 zorder = 15 

1243 for attr in ('fpp', 'f1', 'fp'): 

1244 yval = getattr(dgroup, attr) 

1245 if yval is not None: 

1246 _plot(dgroup.energy, yval, zorder=zorder, label=labels[attr], **opts) 

1247 zorder = zorder - 3 

1248 

1249 redraw(win=win, xmin=emin, xmax=emax, _larch=_larch) 

1250#enddef 

1251 

1252def plot_feffdat(feffpath, with_phase=True, title=None, 

1253 new=True, delay_draw=False, win=1, _larch=None): 

1254 """ 

1255 plot_feffdat(feffpath, with_phase=True, title=None, new=True, win=1): 

1256 

1257 Plot Feff's magnitude and phase as a function of k for a FeffPath 

1258 

1259 Arguments 

1260 ---------- 

1261 feffpath feff path as read by feffpath() 

1262 with_pase whether to plot phase(k) as well as magnitude [True] 

1263 title string for plot title [None, may use filename if available] 

1264 new bool whether to start a new plot [True] 

1265 delay_draw bool whether to delay draw until more traces are added [False] 

1266 win integer plot window to use [1] 

1267 

1268 Notes 

1269 ----- 

1270 1. The input data group must have the following attributes: 

1271 energy, mu, bkg, norm, e0, pre_edge, edge_step, filename 

1272 """ 

1273 if hasattr(feffpath, '_feffdat'): 

1274 fdat = feffpath._feffdat 

1275 else: 

1276 raise ValueError("must pass in a Feff path as from feffpath()") 

1277 #endif 

1278 

1279 _plot(fdat.k, fdat.mag_feff, xlabel=plotlabels.k, 

1280 ylabel='|F(k)|', title=title, label='magnitude', zorder=20, 

1281 new=new, win=win, show_legend=True, 

1282 delay_draw=delay_draw, linewidth=3, _larch=_larch) 

1283 

1284 if with_phase: 

1285 _plot(fdat.k, fdat.pha_feff, xlabel=plotlabels.k, 

1286 y2label='Phase(k)', title=title, label='phase', side='right', 

1287 zorder=10, new=False, win=win, show_legend=True, 

1288 delay_draw=delay_draw, linewidth=3, _larch=_larch) 

1289 #endif 

1290 

1291 if delay_draw: 

1292 redraw(win=win, xmin=emin, xmax=emax, _larch=_larch) 

1293#enddef