Coverage for larch/wxlib/xafsplots.py: 29%

555 statements  

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

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 

21from pathlib import Path 

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 x = r'$x$', 

98 y = r'$y$', 

99 xdat = r'$x$', 

100 ydat = r'$y$', 

101 xplot = r'$x$', 

102 yplot= r'$y$', 

103 ynorm = r'scaled $y$', 

104 xshift = r'shifted $x$', 

105 dydx = r'$dy/dx$', 

106 d2ydx = r'$d^2y/dx^2$', 

107 ) 

108 

109def safetitle(t): 

110 if "'" in t: 

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

112 return t 

113 

114def _get_title(dgroup, title=None): 

115 """get best title for group""" 

116 if title is not None: 

117 return safetitle(title) 

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

119 

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

121 t = getattr(dgroup, attr, None) 

122 if t is not None: 

123 if attr == 'filename': 

124 t = '/'.join(Path(t).absolute().parts[-2:]) 

125 return safetitle(t) 

126 if data_group is not None: 

127 t = getattr(data_group, attr, None) 

128 if t is not None: 

129 return t 

130 return safetitle(repr(dgroup)) 

131 

132 

133def _get_kweight(dgroup, kweight=None): 

134 if kweight is not None: 

135 return kweight 

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

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

138 return ftargs['kweight'] 

139 

140 

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

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

143 values relative to e0. 

144 """ 

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

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

147 if emin is not None: 

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

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

150 emin += e0 

151 if emax is not None: 

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

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

154 emax += e0 

155 return emin, emax 

156#enddef 

157 

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

159 dymin=None, dymax=None, 

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

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

162 if disp is None: 

163 return 

164 panel = disp.panel 

165 panel.conf.show_legend = show_legend 

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

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

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

169 if stacked: 

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

171 

172 panel.unzoom_all() 

173 panel.reset_formats() 

174 if stacked: 

175 disp.panel_bot.unzoom_all() 

176 disp.panel_bot.reset_formats() 

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

178 panel.conf.draw_legend() 

179 else: 

180 panel.canvas.draw() 

181 if stacked: 

182 disp.panel_bot.canvas.draw() 

183 

184 #endif 

185#enddef 

186 

187 

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

189 show_pre=False, show_post=False, show_e0=False, with_deriv=False, 

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

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

192 """ 

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

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

195 new=True, win=1) 

196 

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

198 

199 Arguments 

200 ---------- 

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

202 show_norm bool whether to show normalized data [False] 

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

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

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

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

207 show_e0 bool whether to show E0 [False] 

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

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

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

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

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

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

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

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

216 win integer plot window to use [1] 

217 

218 Notes 

219 ----- 

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

221 energy, mu, norm, e0, pre_edge, edge_step 

222 """ 

223 if hasattr(dgroup, 'mu'): 

224 mu = dgroup.mu 

225 elif hasattr(dgroup, 'mutrans'): 

226 mu = dgroup.mutrans 

227 elif hasattr(dgroup, 'mufluor'): 

228 mu = dgroup.mufluor 

229 else: 

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

231 #endif 

232 ylabel = plotlabels.mu 

233 if label is None: 

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

235 #endif 

236 if show_deriv: 

237 mu = dgroup.dmude 

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

239 dlabel = plotlabels.dmude 

240 elif show_norm: 

241 mu = dgroup.norm 

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

243 dlabel = plotlabels.norm 

244 #endif 

245 elif show_flat: 

246 mu = dgroup.flat 

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

248 dlabel = plotlabels.flat 

249 #endif 

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

251 title = _get_title(dgroup, title=title) 

252 

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

254 title=title, xmin=emin, xmax=emax, 

255 delay_draw=True, _larch=_larch) 

256 

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

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

259 

260 if with_deriv: 

261 dmu = dgroup.dmude 

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

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

264 #endif 

265 if (not show_norm and not show_deriv): 

266 if show_pre: 

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

268 zorder=18, **opts) 

269 #endif 

270 if show_post: 

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

272 zorder=18, **opts) 

273 if show_pre: 

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

275 ypre = dgroup.pre_edge[i] 

276 ypost = dgroup.post_edge[i] 

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

278 color=plotlabels.e0color, width=0.25, 

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

280 #endif 

281 #endif 

282 #endif 

283 if show_e0: 

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

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

286 _larch=_larch) 

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

288 if disp is not None: 

289 disp.panel.conf.draw_legend() 

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

291#enddef 

292 

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

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

295 win=1, _larch=None): 

296 """ 

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

298 

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

300 

301 Arguments 

302 ---------- 

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

304 norm bool whether to show normalized data [True] 

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

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

307 show_e0 bool whether to show E0 [False] 

308 show_ek0 bool whether to show EK0 [False] 

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

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

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

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

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

314 win integer plot window to use [1] 

315 

316 Notes 

317 ----- 

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

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

320 """ 

321 if hasattr(dgroup, 'mu'): 

322 mu = dgroup.mu 

323 elif hasattr(dgroup, 'mutrans'): 

324 mu = dgroup.mutrans 

325 else: 

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

327 #endif 

328 

329 bkg = dgroup.bkg 

330 ylabel = plotlabels.mu 

331 if label is None: 

332 label = 'mu' 

333 #endif 

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

335 if norm: 

336 mu = dgroup.norm 

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

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

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

340 #endif 

341 title = _get_title(dgroup, title=title) 

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

343 delay_draw=True, _larch=_larch) 

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

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

346 **opts) 

347 ymin, ymax = None, None 

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

349 if disp is not None: 

350 xylims = disp.panel.get_viewlimits() 

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

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

353 

354 e0val, e0label = None, 'E0' 

355 if show_e0 and hasattr(dgroup, 'e0'): 

356 e0val = dgroup.e0 

357 elif show_ek0 and hasattr(dgroup, 'ek0'): 

358 e0val, e0label = dgroup.ek0, 'EK0' 

359 

360 if e0val is not None: 

361 ie0 = index_of(dgroup.energy, e0val) 

362 ee0 = dgroup.energy[ie0] 

363 me0 = mu[ie0] + offset 

364 disp.panel.axes.plot([ee0], [me0], marker='o', 

365 markersize=5, label='_nolegend_', 

366 markerfacecolor='#808080', 

367 markeredgecolor='#A03030') 

368 

369 if disp is not None: 

370 disp.panel.conf.draw_legend() 

371 #endif 

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

373#enddef 

374 

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

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

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

378 """ 

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

380 

381 Plot chi(E) for XAFS data group 

382 

383 Arguments 

384 ---------- 

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

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

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

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

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

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

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

392 show_k bool whether to show k values [True] 

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

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

395 win integer plot window to use [1] 

396 

397 Notes 

398 ----- 

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

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

401 """ 

402 if hasattr(dgroup, 'mu'): 

403 mu = dgroup.mu 

404 elif hasattr(dgroup, 'mutrans'): 

405 mu = dgroup.mutrans 

406 else: 

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

408 #endif 

409 e0 = dgroup.e0 

410 chie = (mu - dgroup.bkg) 

411 ylabel = plotlabels.chie 

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

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

414 ylabel = plotlabels.chiew.format(eweight) 

415 

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

417 

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

419 if emin is not None: 

420 emin = emin - e0 

421 if emax is not None: 

422 emax = emax - e0 

423 

424 

425 title = _get_title(dgroup, title=title) 

426 

427 def ek_formatter(x, pos): 

428 ex = float(x) 

429 if ex < 0: 

430 s = '' 

431 else: 

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

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

434 

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

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

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

438 linewidth=3, _larch=_larch) 

439 

440 if show_k: 

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

442 axes = disp.panel.axes 

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

444 

445 if not delay_draw: 

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

447 

448#enddef 

449 

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

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

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

453 """ 

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

455 new=True, win=1) 

456 

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

458 

459 Arguments 

460 ---------- 

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

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

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

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

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

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

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

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

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

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

471 win integer plot window to use [1] 

472 

473 Notes 

474 ----- 

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

476 k, chi, kwin, filename 

477 """ 

478 kweight = _get_kweight(dgroup, kweight) 

479 

480 chi = dgroup.chi * dgroup.k ** kweight 

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

482 _larch=_larch) 

483 if label is None: 

484 label = 'chi' 

485 #endif 

486 if new: 

487 title = _get_title(dgroup, title=title) 

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

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

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

491 

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

493 kwin = dgroup.kwin 

494 if scale_window: 

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

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

497 #endif 

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

499#enddef 

500 

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

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

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

504 """ 

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

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

507 

508 Plot chi(R) for XAFS data group 

509 

510 Arguments 

511 ---------- 

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

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

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

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

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

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

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

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

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

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

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

523 win integer plot window to use [1] 

524 

525 Notes 

526 ----- 

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

528 r, chir_mag, chir_im, chir_re, kweight, filename 

529 """ 

530 kweight = _get_kweight(dgroup, None) 

531 

532 if new: 

533 title = _get_title(dgroup, title=title) 

534 

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

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

537 delay_draw=True, _larch=_larch) 

538 

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

540 show_real=show_real, show_imag=show_imag) 

541 opts['ylabel'] = ylabel 

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

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

544 return 

545 #endif 

546 if label is None: 

547 label = 'chir' 

548 #endif 

549 if show_mag: 

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

551 opts['new'] = False 

552 #endif 

553 if show_real: 

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

555 opts['new'] = False 

556 #endif 

557 if show_imag: 

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

559 #endif 

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

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

562 opts['zorder'] = 15 

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

564 #endif 

565 

566 if show_mag or show_real or show_imag or show_window: 

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

568 #endif 

569#enddef 

570 

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

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

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

574 """ 

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

576 new=True, win=1) 

577 

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

579 

580 Arguments 

581 ---------- 

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

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

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

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

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

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

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

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

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

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

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

593 win integer plot window to use [1] 

594 

595 Notes 

596 ----- 

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

598 k, chi, kwin, filename 

599 """ 

600 kweight = _get_kweight(dgroup, kweight) 

601 nk = len(dgroup.k) 

602 chiq = dgroup.chiq_re[:nk] 

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

604 if label is None: 

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

606 #endif 

607 if new: 

608 title = _get_title(dgroup, title=title) 

609 

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

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

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

613 

614 if show_chik: 

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

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

617 #endif 

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

619 kwin = dgroup.kwin 

620 if scale_window: 

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

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

623 #endif 

624 

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

626#enddef 

627 

628 

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

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

631 """ 

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

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

634 

635 Plot wavelet for XAFS data group 

636 

637 Arguments 

638 ---------- 

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

640 show_mag bool whether to plot wavelet magnitude [True] 

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

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

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

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

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

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

647 win integer image window to use [1] 

648 

649 Notes 

650 ----- 

651 The wavelet will be performed 

652 """ 

653 kweight = _get_kweight(dgroup, kweight) 

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

655 title = _get_title(dgroup, title=title) 

656 

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

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

659 show_axis=True, _larch=_larch) 

660 if show_mag: 

661 _imshow(dgroup.wcauchy_mag, **opts) 

662 elif show_real: 

663 _imshow(dgroup.wcauchy_real, **opts) 

664 elif show_imag: 

665 _imshow(dgroup.wcauchy_imag, **opts) 

666 #endif 

667#enddef 

668 

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

670 show_mag=True, show_real=False, show_imag=False, 

671 show_bkg=False, use_rebkg=False, title=None, new=True, 

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

673 

674 """ 

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

676 show_mag=True, show_real=False, show_imag=False, 

677 new=True, win=1) 

678 

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

680 

681 Arguments 

682 ---------- 

683 dataset feffit dataset, after running feffit() 

684 kmin min k to show [0] 

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

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

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

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

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

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

691 show_bkg bool whether to plot feffit-refined background [False] 

692 use_rebkg bool whether to plot data with feffit-refined background [False] 

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

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

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

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

697 win integer plot window to use [1] 

698 

699 """ 

700 if kweight is None: 

701 kweight = dataset.transform.kweight 

702 #endif 

703 if isinstance(kweight, (list, tuple, ndarray)): 

704 kweight=kweight[0] 

705 

706 title = _get_title(dataset, title=title) 

707 

708 mod = dataset.model 

709 dat = dataset.data 

710 if use_rebkg and hasattr(dataset, 'data_rebkg'): 

711 dat = dataset.data_rebkg 

712 title += ' (refined bkg)' 

713 

714 data_chik = dat.chi * dat.k**kweight 

715 model_chik = mod.chi * mod.k**kweight 

716 

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

718 show_legend=True, delay_draw=True, win=win, title=title, 

719 _larch=_larch) 

720 

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

722 _plot(dat.k, data_chik+offset, xmin=kmin, xmax=kmax, 

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

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

725 _plot(mod.k, model_chik+offset, label='fit', **opts) 

726 

727 if show_bkg and hasattr(dat, 'bkgk'): 

728 _plot(dat.k, dat.bkgk*dat.k**kweight, 

729 label='refined bkg', **opts) 

730 #endif 

731 

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

733 

734 # show chi(R) in next plot window 

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

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

737 show_real=show_real, show_imag=show_imag) 

738 

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

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

741 

742 if show_mag: 

743 _plot(dat.r, dat.chir_mag+offset, label='|data|', **opts) 

744 opts['new'] = False 

745 _plot(mod.r, mod.chir_mag+offset, label='|fit|', **opts) 

746 #endif 

747 if show_real: 

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

749 opts['new'] = False 

750 _plot(mod.r, mod.chir_re+offset, label='Re[fit]', **opts) 

751 #endif 

752 if show_imag: 

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

754 opts['new'] = False 

755 _plot(mod.r, mod.chir_im+offset, label='Im[fit]', **opts) 

756 #endif 

757 if show_mag or show_real or show_imag: 

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

759 #endif 

760#enddef 

761 

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

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

764 """ 

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

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

767 

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

769 

770 Arguments 

771 ---------- 

772 dataset feffit dataset, after running feffit() 

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

774 kmin min k to show [0] 

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

776 offset vertical offset to use for plot [0] 

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

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

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

780 win integer plot window to use [1] 

781 kws additional keyword arguments are passed to plot() 

782 """ 

783 kweight = dataset.transform.kweight 

784 path = dataset.pathlist[ipath] 

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

786 

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

788 

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

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

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

792 if delay_draw: 

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

794#enddef 

795 

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

797 show_mag=True, show_real=False, show_imag=True, 

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

799 **kws): 

800 """ 

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

802 show_mag=True, show_real=False, show_imag=True, 

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

804 

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

806 

807 Arguments 

808 ---------- 

809 dataset feffit dataset, after running feffit() 

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

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

812 offset vertical offset to use for plot [0] 

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

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

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

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

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

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

819 win integer plot window to use [1] 

820 kws additional keyword arguments are passed to plot() 

821 """ 

822 path = dataset.pathlist[ipath] 

823 if label is None: 

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

825 #endif 

826 kweight =dataset.transform.kweight 

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

828 show_real=show_real, show_imag=show_imag) 

829 

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

831 delay_draw=True, _larch=_larch) 

832 

833 opts.update(kws) 

834 if show_mag: 

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

836 opts['new'] = False 

837 #endif 

838 if show_real: 

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

840 opts['new'] = False 

841 #endif 

842 if show_imag: 

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

844 opts['new'] = False 

845 #endif 

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

847#enddef 

848 

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

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

851 

852 """ 

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

854 

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

856 

857 Arguments 

858 ---------- 

859 dataset feffit dataset, after running feffit() 

860 kmin min k to show [0] 

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

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

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

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

865 win integer plot window to use [1] 

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

867 kws additional keyword arguments are passed to plot() 

868 """ 

869 # make k-weighted chi(k) 

870 kweight = dataset.transform.kweight 

871 model = dataset.model 

872 

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

874 

875 title = _get_title(dataset, title=title) 

876 

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

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

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

880 **kws) 

881 

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

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

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

885 win=win, _larch=_larch) 

886 #endfor 

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

888#enddef 

889 

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

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

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

893 """ 

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

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

896 

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

898 

899 Arguments 

900 ---------- 

901 dataset feffit dataset, after running feffit() 

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

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

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

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

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

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

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

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

910 win integer plot window to use [1] 

911 kws additional keyword arguments are passed to plot() 

912 """ 

913 kweight = dataset.transform.kweight 

914 model = dataset.model 

915 

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

917 show_real=show_real, show_imag=show_imag) 

918 title = _get_title(dataset, title=title) 

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

920 delay_draw=True, title=title, _larch=_larch) 

921 opts.update(kws) 

922 if show_mag: 

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

924 opts['new'] = False 

925 #endif 

926 if show_real: 

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

928 opts['new'] = False 

929 #endif 

930 if show_imag: 

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

932 opts['new'] = False 

933 #endif 

934 

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

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

937 show_mag=show_mag, show_real=show_real, 

938 show_imag=show_imag, **opts) 

939 #endfor 

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

941#enddef 

942 

943 

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

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

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

947 if xmin is None: 

948 xmin = min(x) 

949 if xmax is None: 

950 xmax = max(x) 

951 

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

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

954 

955 i0 = index_of(x, xmin + xeps) 

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

957 

958 xspan = x[i0:i1] 

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

960 yspan = y[i0:i1] 

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

962 

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

964 max(xspan) + extend * xrange, 

965 min(yspan) - extend * yrange, 

966 max(yspan) + extend * yrange) 

967 

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

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

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

971 

972 dgroup must have a 'prepeaks' attribute 

973 """ 

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

975 raise ValueError('Group needs prepeaks') 

976 #endif 

977 ppeak = dgroup.prepeaks 

978 

979 yplot = getattr(dgroup, 'yplot', getattr(dgroup, 'ydat', None)) 

980 xplot = getattr(dgroup, 'xplot', getattr(dgroup, 'x', None)) 

981 

982 px0, px1, py0, py1 = extend_plotrange(xplot, yplot, 

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

984 

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

986 

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

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

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

990 label='data', new=True, 

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

992 popts.update(kws) 

993 

994 if subtract_baseline: 

995 xplot = ppeak.energy 

996 yplot = ppeak.baseline 

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

998 _plot(xplot, yplot, **popts) 

999 else: 

1000 _plot(xplot, yplot, **popts) 

1001 popts['new'] = False 

1002 popts['label'] = 'baseline' 

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

1004 

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

1006 label='_nolegend_') 

1007 

1008 if show_fitrange: 

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

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

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

1012 

1013 if show_peakrange: 

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

1015 y = yplot[index_of(xplot, x)] 

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

1017 

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

1019 show_legend=True, _larch=_larch) 

1020#enddef 

1021 

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

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

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

1025 

1026 dgroup must have a 'peakfit_history' attribute 

1027 """ 

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

1029 raise ValueError('Group needs prepeaks') 

1030 #endif 

1031 if show_init: 

1032 result = pkfit = dgroup.prepeaks 

1033 else: 

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

1035 if nfit > len(hist): 

1036 nfit = 0 

1037 pkfit = hist[nfit] 

1038 result = pkfit.result 

1039 #endif 

1040 

1041 if pkfit is None: 

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

1043 #endif 

1044 

1045 opts = pkfit.user_options 

1046 xeps = min(diff(dgroup.xplot)) / 5. 

1047 xplot = 1.0*pkfit.energy 

1048 yplot = 1.0*pkfit.norm 

1049 

1050 xplot_full = 1.0*dgroup.xplot 

1051 yplot_full = 1.0*dgroup.yplot 

1052 

1053 if show_init: 

1054 yfit = pkfit.init_fit 

1055 ycomps = None # pkfit.init_ycomps 

1056 ylabel = 'model' 

1057 else: 

1058 yfit = 1.0*result.best_fit 

1059 ycomps = pkfit.ycomps 

1060 ylabel = 'best fit' 

1061 

1062 baseline = 0.*yplot 

1063 if ycomps is not None: 

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

1065 if label in opts['bkg_components']: 

1066 baseline += ycomp 

1067 

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

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

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

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

1072 

1073 if subtract_baseline: 

1074 yplot -= baseline 

1075 yfit -= baseline 

1076 yplot_full = 1.0*yplot 

1077 xplot_full = 1.0*xplot 

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

1079 

1080 dx0, dx1, dy0, dy1 = extend_plotrange(xplot_full, yplot_full, 

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

1082 fx0, fx1, fy0, fy1 = extend_plotrange(xplot, yfit, 

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

1084 

1085 ncolor = 0 

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

1087 plotopts.update(popts) 

1088 dymin = dymax = None 

1089 if show_residual: 

1090 popts['stacked'] = True 

1091 _fitplot(xplot, yplot, yfit, label='data', label2=ylabel, **plotopts) 

1092 dy = yfit - yplot 

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

1094 dymax += 0.05 * (dymax - dymin) 

1095 dymin -= 0.05 * (dymax - dymin) 

1096 else: 

1097 _plot(xplot_full, yplot_full, new=True, label='data', 

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

1099 _oplot(xplot, yfit, label=ylabel, color=LineColors[1], **plotopts) 

1100 ncolor = 1 

1101 

1102 if ycomps is not None: 

1103 ncomps = len(ycomps) 

1104 if not subtract_baseline: 

1105 ncolor += 1 

1106 _oplot(xplot, baseline, label='baseline', delay_draw=True, 

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

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

1109 

1110 for icomp, label in enumerate(ycomps): 

1111 ycomp = ycomps[label] 

1112 if label in opts['bkg_components']: 

1113 continue 

1114 ncolor = (ncolor+1) % 10 

1115 _oplot(xplot, ycomp, label=label, delay_draw=(icomp != ncomps-1), 

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

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

1118 

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

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

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

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

1123 label='_nolegend_', **popts) 

1124 

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

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

1127 if hasattr(result, 'params'): 

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

1129 if pcen is not None: 

1130 pcen = pcen.value 

1131 if pcen is not None: 

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

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

1134 

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

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

1137 

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

1139 if ncomps is None: 

1140 if min_weight > 1.e-12: 

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

1142 else: 

1143 ncomps = argmin(result.ind) 

1144 return ncomps 

1145 

1146 

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

1148 """Plot components from PCA result 

1149 

1150 result must be output of `pca_train` 

1151 """ 

1152 title = "PCA components" 

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

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

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

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

1157 win=win, _larch=_larch) 

1158 

1159 popts.update(kws) 

1160 ncomps = int(result.nsig) 

1161 

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

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

1164 if result.variances[i] > min_variance: 

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

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

1167 

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

1169 

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

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

1172 

1173 result must be output of `pca_train` 

1174 """ 

1175 max_comps = len(result.components) 

1176 

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

1178 

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

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

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

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

1183 

1184 popts.update(kws) 

1185 

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

1187 x = 1 + arange(ncomps) 

1188 y = result.variances[:ncomps] 

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

1190 

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

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

1193 

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

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

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

1197 

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

1199 

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

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

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

1203 

1204 

1205 

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

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

1208 

1209 result must be output of `pca_fit` 

1210 """ 

1211 

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

1213 result = dgroup.pca_result 

1214 model = result.pca_model 

1215 

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

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

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

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

1220 stacked=True, win=win, _larch=_larch) 

1221 popts.update(kws) 

1222 yplot = getattr(result, 'yplot', getattr(result, 'ydat', None)) 

1223 if yplot is None: 

1224 raise ValueError('cannot find y data for PCA plot') 

1225 

1226 _fitplot(result.x, yplot, result.yfit, 

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

1228 

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

1230 if with_components and disp is not None: 

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

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

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

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

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

1236 

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

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

1239 """ 

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

1241 

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

1243 

1244 Arguments 

1245 ---------- 

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

1247 norm bool whether to show normalized data [True] 

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

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

1250 show_e0 bool whether to show E0 [False] 

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

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

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

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

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

1256 win integer plot window to use [1] 

1257 

1258 Notes 

1259 ----- 

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

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

1262 """ 

1263 if hasattr(dgroup, 'f2'): 

1264 f2 = dgroup.f2 

1265 else: 

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

1267 #endif 

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

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

1270 title = _get_title(dgroup, title=title) 

1271 

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

1273 

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

1275 delay_draw=True, _larch=_larch) 

1276 

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

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

1279 **opts) 

1280 zorder = 15 

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

1282 yval = getattr(dgroup, attr) 

1283 if yval is not None: 

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

1285 zorder = zorder - 3 

1286 

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

1288#enddef 

1289 

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

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

1292 """ 

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

1294 

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

1296 

1297 Arguments 

1298 ---------- 

1299 feffpath feff path as read by feffpath() 

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

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

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

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

1304 win integer plot window to use [1] 

1305 

1306 Notes 

1307 ----- 

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

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

1310 """ 

1311 if hasattr(feffpath, '_feffdat'): 

1312 fdat = feffpath._feffdat 

1313 else: 

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

1315 #endif 

1316 

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

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

1319 new=new, win=win, show_legend=True, 

1320 delay_draw=delay_draw, linewidth=3, _larch=_larch) 

1321 

1322 if with_phase: 

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

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

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

1326 delay_draw=delay_draw, linewidth=3, _larch=_larch) 

1327 #endif 

1328 

1329 if delay_draw: 

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

1331#enddef