Coverage for /Users/Newville/Codes/xraylarch/larch/plot/plotly_xafsplots.py: 0%
641 statements
« prev ^ index » next coverage.py v7.3.2, created at 2023-11-09 10:08 -0600
« 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
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"""
21import os
22import numpy as np
23import time
24import logging
25from copy import deepcopy
26from matplotlib.ticker import FuncFormatter
28from larch import Group
29from larch.math import (index_of, index_nearest, interp)
30from larch.xafs import cauchy_wavelet, etok, ktoe
32def nullfunc(*args, **kws):
33 pass
35get_display = _plot = _oplot = _newplot = _fitplot = _plot_text = nullfunc
36_plot_marker = _plot_arrow = _plot_axvline = _plot_axhline = nullfunc
39HAS_PLOTLY = True
40try:
41 import plotly
42except ImportError:
43 HAS_PLOTLY = False
45if HAS_PLOTLY:
46 import plotly.graph_objs as pgo
47 from plotly.subplots import make_subplots
49def get_display(win=1, *args, **kws):
50 pass
52LineColors = ('#1f77b4', '#d62728', '#2ca02c', '#ff7f0e', '#9467bd',
53 '#8c564b', '#e377c2', '#7f7f7f', '#bcbd22', '#17becf')
55LineStyles = ('solid', 'dashed', 'dotted')
56NCOLORS = len(LineColors)
57NSTYLES = len(LineStyles)
59FIGSTYLE = dict(width=650, height=500,
60 showlegend=True, hovermode='closest',
61 legend=dict(borderwidth=0.5, bgcolor='#F2F2F2'),
62 # orientation='v') #, x=0.1, y=1.15)# , yanchor='top'),
63 plot_bgcolor='#FDFDFF',
64 xaxis=dict(showgrid=True, gridcolor='#D8D8D8',
65 color='#004', zerolinecolor='#DDD'),
66 yaxis=dict(showgrid=True, gridcolor='#D8D8D8',
67 color='#004', zerolinecolor='#DDD')
68 )
70def set_label_weight(label, w):
71 return label.replace('__W__', '{0:g}'.format(w))
73# common XAFS plot labels
74def chirlab(kweight, show_mag=True, show_real=False, show_imag=False):
75 """generate chi(R) label for a kweight
77 Arguments
78 ----------
79 kweight k-weight to use (required)
80 show_mag bool whether to plot |chi(R)| [True]
81 show_real bool whether to plot Re[chi(R)] [False]
82 show_imag bool whether to plot Im[chi(R)] [False]
83 """
84 ylab = []
85 if show_mag: ylab.append(plotlabels.chirmag)
86 if show_real: ylab.append(plotlabels.chirre)
87 if show_imag: ylab.append(plotlabels.chirim)
88 if len(ylab) > 1: ylab = [plotlabels.chir]
89 return set_label_weight(ylab[0], kweight+1)
90#enddef
92plotlabels = Group(k = r'$k \rm\,(\AA^{-1})$',
93 r = r'$R \rm\,(\AA)$',
94 energy = r'$E\rm\,(eV)$',
95 ewithk = r'$E\rm\,(eV)$' + '\n' + r'$[k \rm\,(\AA^{-1})]$',
96 mu = r'$\mu(E)$',
97 norm = r'normalized $\mu(E)$',
98 flat = r'flattened $\mu(E)$',
99 deconv = r'deconvolved $\mu(E)$',
100 dmude = r'$d\mu_{\rm norm}(E)/dE$',
101 d2mude = r'$d^2\mu_{\rm norm}(E)/dE^2$',
102 chie = r'$\chi(E)$',
103 chie0 = r'$\chi(E)$',
104 chie1 = r'$E\chi(E) \rm\, (eV)$',
105 chiew = r'$E^{__W__}\chi(E) \rm\,(eV^{__W__})$',
106 chikw = r'$k^{{__W__}}\chi(k) \rm\,(\AA^{{-__W__}})$',
107 chi0 = r'$\chi(k)$',
108 chi1 = r'$k\chi(k) \rm\,(\AA^{-1})$',
109 chi2 = r'$k^2\chi(k) \rm\,(\AA^{-2})$',
110 chi3 = r'$k^3\chi(k) \rm\,(\AA^{-3})$',
111 chir = r'$\chi(R) \rm\,(\AA^{{-__W__}})$',
112 chirmag = r'$|\chi(R)| \rm\,(\AA^{{-__W__}})$',
113 chirre = r'${{\rm Re}}[\chi(R)] \rm\,(\AA^{{-__W__}})$',
114 chirim = r'${{\rm Im}}[\chi(R)] \rm\,(\AA^{{-__W__}})$',
115 chirpha = r'${{\rm Phase}}[\chi(R)] \rm\,(\AA^{{-__W__}})$',
116 e0color = '#B2B282',
117 chirlab = chirlab)
119# plotly's mathjax needs an extra package to support \AA:
120for attr in dir(plotlabels):
121 val = getattr(plotlabels, attr)
122 if isinstance(val, str) and r'\AA' in val:
123 setattr(plotlabels, attr, r'$\require{mediawiki-texvc} ' + val[1:])
126def safetitle(t):
127 if "'" in t:
128 t = t.replace("'", "\\'")
129 return t
131def _get_title(dgroup, title=None):
132 """get best title for group"""
133 if title is not None:
134 return safetitle(title)
135 data_group = getattr(dgroup, 'data', None)
137 for attr in ('title', 'plot_title', 'filename', 'name', '__name__'):
138 t = getattr(dgroup, attr, None)
139 if t is not None:
140 if attr == 'filename':
141 folder, file = os.path.split(t)
142 if folder == '':
143 t = file
144 else:
145 top, folder = os.path.split(folder)
146 t = '/'.join((folder, file))
147 return safetitle(t)
148 if data_group is not None:
149 t = getattr(data_group, attr, None)
150 if t is not None:
151 return t
152 return safetitle(repr(dgroup))
155def _get_kweight(dgroup, kweight=None):
156 if kweight is not None:
157 return kweight
158 callargs = getattr(dgroup, 'callargs', None)
159 ftargs = getattr(callargs, 'xftf', {'kweight':0})
160 return ftargs['kweight']
164def _get_erange(dgroup, emin=None, emax=None):
165 """get absolute emin/emax for data range, allowing using
166 values relative to e0.
167 """
168 dat_emin, dat_emax = min(dgroup.energy)-100, max(dgroup.energy)+100
169 e0 = getattr(dgroup, 'e0', 0.0)
170 if emin is not None:
171 if not (emin > dat_emin and emin < dat_emax):
172 if emin+e0 > dat_emin and emin+e0 < dat_emax:
173 emin += e0
174 else:
175 emin = dat_emin
176 if emax is not None:
177 if not (emax > dat_emin and emax < dat_emax):
178 if emax+e0 > dat_emin and emax+e0 < dat_emax:
179 emax += e0
180 else:
181 emax = dat_emax
182 return emin, emax
183#enddef
185def redraw(win=1, xmin=None, xmax=None, ymin=None, ymax=None,
186 dymin=None, dymax=None,
187 show_legend=True, stacked=False, _larch=None):
188 disp = get_display(win=win, stacked=stacked, _larch=_larch)
189 if disp is None:
190 return
191 panel = disp.panel
192 panel.conf.show_legend = show_legend
193 if (xmin is not None or xmax is not None or
194 ymin is not None or ymax is not None):
195 panel.set_xylims((xmin, xmax, ymin, ymax))
196 if stacked:
197 disp.panel_bot.set_xylims((xmin, xmax, dymin, dymax))
199 panel.unzoom_all()
200 panel.reset_formats()
201 if stacked:
202 disp.panel_bot.unzoom_all()
203 disp.panel_bot.reset_formats()
204 if show_legend: # note: draw_legend *will* redraw the canvas
205 panel.conf.draw_legend()
206 else:
207 panel.canvas.draw()
208 if stacked:
209 disp.panel_bot.canvas.draw()
211 #endif
212#enddef
215class PlotlyFigure:
216 """wrapping of Plotly Figure
217 """
219 def __init__(self, two_yaxis=False, style=None):
220 self.two_yaxis = two_yaxis
221 self.style = deepcopy(FIGSTYLE)
222 if style is not None:
223 self.style.update(style)
224 if self.two_yaxis:
225 self.fig = make_subplots(specs=[[{"secondary_y": True}]])
226 else:
227 self.fig = pgo.FigureWidget()
229 self.traces = []
231 def clear(self):
232 self.traces = []
234 def add_plot(self, x, y, label=None, color=None, linewidth=3,
235 style='solid', marker=None, side='left'):
236 itrace = len(self.traces)
238 if label is None:
239 label = "trace %d" % (1+itrace)
240 if color is None:
241 color = LineColors[itrace % NCOLORS]
242 if style is None:
243 style = LineStyles[ int(itrace*1.0 / NCOLORS) % NSTYLES]
245 trace_opts = {}
246 if self.two_yaxis:
247 trace_opts['secondary_y'] = (side.lower().startswith('l'))
249 lineopts = dict(color=color, width=linewidth)
250 trace = pgo.Scatter(x=x, y=y, name=label, line=lineopts)
252 self.traces.append(trace)
254 self.fig.add_trace(trace, **trace_opts)
257 def add_vline(self, *args, **kws):
258 self.fig.add_vline(*args, **kws)
260 def set_xrange(self, xmin, xmax):
261 self.fig.update_xaxes(range=[xmin, xmax])
263 def set_yrange(self, ymin, ymax):
264 self.fig.update_yaxes(range=[ymin, ymax])
266 def set_style(self, **kws):
267 self.style.update(**kws)
268 self.fig.update_layout(**self.style)
270 def show(self):
271 self.fig.show()
273def plot(xdata, ydata, dy=None, new=False, label=None, xlabel=None,
274 ylabel=None, y2label=None, title=None, side='left', ylog_scale=None,
275 xlog_scale=None, grid=None, xmin=None, xmax=None, ymin=None,
276 ymax=None, color=None, style='solid', alpha=None, fill=False,
277 drawstyle=None, linewidth=2, marker=None, markersize=None,
278 show_legend=None, bgcolor=None, framecolor=None, gridcolor=None,
279 textcolor=None, labelfontsize=None, titlefontsize=None,
280 legendfontsize=None, fullbox=None, axes_style=None, zorder=None,
281 delay_draw=False, **kws):
283 """emulate wxmplot plot() function, probably incompletely"""
285 fig = PlotlyFigure(two_yaxis=(side=='right'))
286 if new:
287 fig.clear()
289 fig.add_plot(xdata, ydata, label=label, color=color, linewidth=linewidth,
290 style=style, marker=marker, side=side)
292 fig.set_style(title=title, xaxis_title=xlabel, yaxis_title=ylabel)
293 if xmin is not None or xmax is not None:
294 fig.set_xrange(xmin, xmax)
295 if ymin is not None or ymax is not None:
296 fig.set_yrange(ymin, ymax)
298 fig.show()
299 return fig
302def multi_plot(plotsets):
303 """plot multiple traces with an array of dictionaries emulating
304 multiplot calls to plot:
306 instead of
308 >>> plot(x1, y1, label='thing1', color='blue')
309 >>> plot(x2, y2, label='thing2', color='red')
311 you can do
313 >>> multi_plot([dict(xdata=x1, ydata=y1, label='thing1', color='blue'),
314 dict(xdata=x2, ydata=y2, label='thing2', color='red')])
316 """
317 two_axis = False
318 for pset in plotsets[:]:
319 side = pset.get('side', None)
320 if side == 'right':
321 two_axis = True
324 fig = PlotlyFigure(two_yaxis=two_axis)
325 fig.clear()
327 sopts = dict(title=None, xlabel=None, ylabel=None,
328 xmin=None, xmax=None, ymin=None, ymax=None)
330 for pset in plotsets[:]:
331 xdata = pset['xdata']
332 ydata = pset['ydata']
333 popts = dict(label=None, color=None, side='left', style=None,
334 linewidth=3, marker=None)
335 for w in ('label', 'color', 'style', 'linewidth', 'marker', 'side'):
336 if w in pset:
337 popts[w] = pset[w]
338 for w in ('xmin', 'xmax', 'ymin', 'ymax', 'title', 'xlabel', 'ylabel'):
339 if w in pset:
340 sopts[w] = pset[w]
342 fig.add_plot(xdata, ydata, **popts)
344 xmin = sopts.pop('xmin')
345 xmax = sopts.pop('xmax')
346 ymin = sopts.pop('ymin')
347 ymax = sopts.pop('ymax')
349 sopts['xaxis_title'] = sopts.pop('xlabel')
350 sopts['yaxis_title'] = sopts.pop('ylabel')
351 fig.set_style(**sopts)
353 if xmin is not None or xmax is not None:
354 fig.set_xrange(xmin, xmax)
355 if ymin is not None or ymax is not None:
356 fig.set_yrange(ymin, ymax)
357 fig.show()
358 return fig
362def plot_mu(dgroup, show_norm=False, show_flat=False, show_deriv=False,
363 show_pre=False, show_post=False, show_e0=False, with_deriv=False,
364 emin=None, emax=None, label='mu', new=True, delay_draw=False,
365 offset=0, title=None, win=1, _larch=None):
366 """
367 plot_mu(dgroup, norm=False, deriv=False, show_pre=False, show_post=False,
368 show_e0=False, show_deriv=False, emin=None, emax=None, label=None,
369 new=True, win=1)
371 Plot mu(E) for an XAFS data group in various forms
373 Arplguments
374 ----------
375 dgroup group of XAFS data after pre_edge() results (see Note 1)
376 show_norm bool whether to show normalized data [False]
377 show_flat bool whether to show flattened, normalized data [False]
378 show_deriv bool whether to show derivative of normalized data [False]
379 show_pre bool whether to show pre-edge curve [False]
380 show_post bool whether to show post-edge curve [False]
381 show_e0 bool whether to show E0 [False]
382 with_deriv bool whether to show deriv (dmu/de) together with mu [False]
383 emin min energy to show, absolute or relative to E0 [None, start of data]
384 emax max energy to show, absolute or relative to E0 [None, end of data]
385 label string for label [None: 'mu', `dmu/dE', or 'mu norm']
386 title string for plot title [None, may use filename if available]
387 new bool whether to start a new plot [True]
388 delay_draw bool whether to delay draw until more traces are added [False]
389 offset vertical offset to use for y-array [0]
390 win integer plot window to use [1]
392 Notes
393 -----
394 1. The input data group must have the following attributes:
395 energy, mu, norm, e0, pre_edge, edge_step
396 """
397 if not HAS_PLOTLY:
398 logging.getLogger().error('Need plotply installed')
399 return
401 if hasattr(dgroup, 'mu'):
402 mu = dgroup.mu
403 elif hasattr(dgroup, 'mutrans'):
404 mu = dgroup.mutrans
405 elif hasattr(dgroup, 'mufluor'):
406 mu = dgroup.mufluor
407 else:
408 raise ValueError("XAFS data group has no array for mu")
409 #endif
410 ylabel = plotlabels.mu
411 if label is None:
412 label = getattr(dgroup, 'filename', 'mu')
413 #endif
414 if show_deriv:
415 mu = dgroup.dmude
416 ylabel = f"{ylabel} (deriv)"
417 dlabel = plotlabels.dmude
418 elif show_norm:
419 mu = dgroup.norm
420 ylabel = f"{ylabel} (norm)"
421 dlabel = plotlabels.norm
422 #endif
423 elif show_flat:
424 mu = dgroup.flat
425 ylabel = f"{ylabel} (flat)"
426 dlabel = plotlabels.flat
427 #endif
428 emin, emax = _get_erange(dgroup, emin, emax)
429 title = _get_title(dgroup, title=title)
432 fig = PlotlyFigure(two_yaxis=with_deriv)
433 fig.add_plot(dgroup.energy, mu+offset, label=label)
435 if with_deriv:
436 fig.add_plot(dgroup.energy, dgroup.dmude+offset, label=f"{ylabel} (deriv)", side='right')
438 else:
439 if not show_norm and show_pre:
440 fig.add_plot(dgroup.energy, dgroup.pre_edge+offset, label='pre_edge')
441 if not show_norm and show_post:
442 fig.add_plot(dgroup.energy, dgroup.post_edge+offset, label='post_edge')
444 if show_e0:
445 fig.add_vline(x=dgroup.e0, line_width=2, line_dash="dash", line_color="#AAC")
447 fig.set_xrange(emin, emax)
448 fig.set_style(title=title, xaxis_title=plotlabels.energy, yaxis_title=ylabel)
449 fig.show()
450 return fig
453def plot_bkg(dgroup, norm=True, emin=None, emax=None, show_e0=False,
454 label=None, title=None, new=True, delay_draw=False, offset=0,
455 win=1, _larch=None):
456 """
457 plot_bkg(dgroup, norm=True, emin=None, emax=None, show_e0=False, label=None, new=True, win=1):
459 Plot mu(E) and background mu0(E) for XAFS data group
461 Arguments
462 ----------
463 dgroup group of XAFS data after autobk() results (see Note 1)
464 norm bool whether to show normalized data [True]
465 emin min energy to show, absolute or relative to E0 [None, start of data]
466 emax max energy to show, absolute or relative to E0 [None, end of data]
467 show_e0 bool whether to show E0 [False]
468 label string for label [``None``: 'mu']
469 title string for plot titlte [None, may use filename if available]
470 new bool whether to start a new plot [True]
471 delay_draw bool whether to delay draw until more traces are added [False]
472 offset vertical offset to use for y-array [0]
473 win integer plot window to use [1]
475 Notes
476 -----
477 1. The input data group must have the following attributes:
478 energy, mu, bkg, norm, e0, pre_edge, edge_step, filename
479 """
480 if hasattr(dgroup, 'mu'):
481 mu = dgroup.mu
482 elif hasattr(dgroup, 'mutrans'):
483 mu = dgroup.mutrans
484 else:
485 raise ValueError("XAFS data group has no array for mu")
486 #endif
488 bkg = dgroup.bkg
489 ylabel = plotlabels.mu
490 if label is None:
491 label = 'mu'
492 #endif
493 emin, emax = _get_erange(dgroup, emin, emax)
494 if norm:
495 mu = dgroup.norm
496 bkg = (dgroup.bkg - dgroup.pre_edge) / dgroup.edge_step
497 ylabel = f"{ylabel} (norm)"
498 label = f"{ylabel} (norm)"
499 #endif
500 title = _get_title(dgroup, title=title)
502 fig = PlotlyFigure(two_yaxis=False)
503 fig.add_plot(dgroup.energy, mu+offset, label=label)
504 fig.add_plot(dgroup.energy, bkg+offset, label='bkg')
506 if show_e0:
507 fig.add_vline(x=dgroup.e0, line_width=2, line_dash="dash", line_color="#AAC")
508 fig.set_xrange(emin, emax)
509 fig.set_style(title=title, xaxis_title=plotlabels.energy, yaxis_title=ylabel)
510 fig.show()
511 return fig
514def plot_chie(dgroup, emin=-5, emax=None, label=None, title=None,
515 eweight=0, new=True, delay_draw=False,
516 offset=0, win=1, show_k=False, _larch=None):
517 """
518 plot_chie(dgroup, emin=None, emax=None, label=None, new=True, win=1):
520 Plot chi(E) for XAFS data group
522 Arguments
523 ----------
524 dgroup group of XAFS data after autobk() results (see Note 1)
525 emin min energy to show, absolute or relative to E0 [-25]
526 emax max energy to show, absolute or relative to E0 [None, end of data]
527 label string for label [``None``: 'mu']
528 title string for plot title [None, may use filename if available]
529 new bool whether to start a new plot [True]
530 eweight energy weightingn for energisdef es>e0 [0]
531 delay_draw bool whether to delay draw until more traces are added [False]
532 offset vertical offset to use for y-array [0]
533 win integer plot window to use [1]
535 Notes
536 -----
537 1. The input data group must have the following attributes:
538 energy, mu, bkg, norm, e0, pre_edge, edge_step, filename
539 """
540 if hasattr(dgroup, 'mu'):
541 mu = dgroup.mu
542 elif hasattr(dgroup, 'mutrans'):
543 mu = dgroup.mutrans
544 else:
545 raise ValueError("XAFS data group has no array for mu")
546 #endif
547 e0 = dgroup.e0
548 chie = (mu - dgroup.bkg)
549 ylabel = plotlabels.chie
550 if abs(eweight) > 1.e-2:
551 chie *= (dgroup.energy-e0)**(eweight)
552 ylabel = set_label_weight(plotlabels.chiew, eweight)
553 xlabel = plotlabels.energy
555 emin, emax = _get_erange(dgroup, emin, emax)
556 if emin is not None:
557 emin = emin - e0
558 if emax is not None:
559 emax = emax - e0
562 title = _get_title(dgroup, title=title)
564 def ek_formatter(x, pos):
565 ex = float(x)
566 if ex < 0:
567 s = ''
568 else:
569 s = f"\n[{etok(ex):.2f}]"
570 return r"%1.4g%s" % (x, s)
572 fig = PlotlyFigure(two_yaxis=False)
573 fig.add_plot(dgroup.energy-e0, chie+offset, label=label)
575 fig.set_xrange(emin, emax)
576 fig.set_style(title=title, xaxis_title=xlabel, yaxis_title=ylabel)
577 fig.show()
578 return fig
581def plot_chik(dgroup, kweight=None, kmax=None, show_window=True,
582 scale_window=True, label=None, title=None, new=True,
583 delay_draw=False, offset=0, win=1, _larch=None):
584 """
585 plot_chik(dgroup, kweight=None, kmax=None, show_window=True, label=None,
586 new=True, win=1)
588 Plot k-weighted chi(k) for XAFS data group
590 Arguments
591 ----------
592 dgroup group of XAFS data after autobk() results (see Note 1)
593 kweight k-weighting for plot [read from last xftf(), or 0]
594 kmax max k to show [None, end of data]
595 show_window bool whether to also plot k-window [True]
596 scale_window bool whether to scale k-window to max |chi(k)| [True]
597 label string for label [``None`` to use 'chi']
598 title string for plot title [None, may use filename if available]
599 new bool whether to start a new plot [True]
600 delay_draw bool whether to delay draw until more traces are added [False]
601 offset vertical offset to use for y-array [0]
602 win integer plot window to use [1]
604 Notes
605 -----
606 1. The input data group must have the following attributes:
607 k, chi, kwin, filename
608 """
609 kweight = _get_kweight(dgroup, kweight)
611 chi = dgroup.chi * dgroup.k ** kweight
612 opts = dict(win=win, show_legend=True, delay_draw=True, linewidth=3,
613 _larch=_larch)
614 if label is None:
615 label = 'chi'
616 #endif
617 if new:
618 title = _get_title(dgroup, title=title)
620 fig = PlotlyFigure(two_yaxis=False)
621 fig.add_plot(dgroup.k, chi+offset, label=label)
623 if show_window and hasattr(dgroup, 'kwin'):
624 kwin = dgroup.kwin
625 if scale_window:
626 kwin = kwin*max(abs(chi))
627 fig.add_plot(dgroup.k, kwin+offset, label='window')
629 if kmax is not None:
630 fig.set_xrange(0, kmax)
631 ylabel = set_label_weight(plotlabels.chikw, kweight)
632 fig.set_style(title=title, xaxis_title=plotlabels.k,
633 yaxis_title=ylabel)
635 fig.show()
636 return fig
638#enddef
640def plot_chir(dgroup, show_mag=True, show_real=False, show_imag=False,
641 show_window=False, rmax=None, label=None, title=None,
642 new=True, delay_draw=False, offset=0, win=1, _larch=None):
643 """
644 plot_chir(dgroup, show_mag=True, show_real=False, show_imag=False,
645 rmax=None, label=None, new=True, win=1)
647 Plot chi(R) for XAFS data group
649 Arguments
650 ----------
651 dgroup group of XAFS data after xftf() results (see Note 1)
652 show_mag bool whether to plot |chi(R)| [True]
653 show_real bool whether to plot Re[chi(R)] [False]
654 show_imag bool whether to plot Im[chi(R)] [False]
655 show_window bool whether to R-windw for back FT (will be scaled) [False]
656 label string for label [``None`` to use 'chir']
657 title string for plot title [None, may use filename if available]
658 rmax max R to show [None, end of data]
659 new bool whether to start a new plot [True]
660 delay_draw bool whether to delay draw until more traces are added [False]
661 offset vertical offset to use for y-array [0]
662 win integer plot window to use [1]
664 Notes
665 -----
666 1. The input data group must have the following attributes:
667 r, chir_mag, chir_im, chir_re, kweight, filename
668 """
669 kweight = _get_kweight(dgroup, None)
671 if new:
672 title = _get_title(dgroup, title=title)
674 opts = dict(win=win, show_legend=True, linewidth=3, title=title,
675 zorder=20, xmax=rmax, xlabel=plotlabels.r, new=new,
676 delay_draw=True, _larch=_larch)
678 ylabel = plotlabels.chirlab(kweight, show_mag=show_mag,
679 show_real=show_real, show_imag=show_imag)
680 opts['ylabel'] = ylabel
681 if not hasattr(dgroup, 'r'):
682 print("group does not have chi(R) data")
683 return
684 #endif
685 if label is None:
686 label = 'chir'
687 #endif
688 fig = PlotlyFigure(two_yaxis=False)
689 if show_mag:
690 fig.add_plot(dgroup.r, dgroup.chir_mag+offset, label=f'{label} (mag)')
691 #endif
692 if show_real:
693 fig.add_plot(dgroup.r, dgroup.chir_re+offset, label=f'{label} (real)')
694 opts['new'] = False
695 #endif
696 if show_imag:
697 fig.add_plot(dgroup.r, dgroup.chir_im+offset, label=f'{label} (imag)')
698 #endif
699 if show_window and hasattr(dgroup, 'rwin'):
700 rwin = dgroup.rwin * max(dgroup.chir_mag)
701 fig.add_plot(dgroup.r, rwin+offset, label='window')
702 #endif
703 if rmax is not None:
704 fig.set_xrange(0, rmax)
706 fig.set_style(title=title, xaxis_title=plotlabels.r, yaxis_title=ylabel)
707 fig.show()
708 return fig
710#enddef
712def plot_chiq(dgroup, kweight=None, kmax=None, show_chik=False, label=None,
713 title=None, new=True, delay_draw=False, offset=0, win=1,
714 show_window=False, scale_window=True, _larch=None):
715 """
716 plot_chiq(dgroup, kweight=None, kmax=None, show_chik=False, label=None,
717 new=True, win=1)
719 Plot Fourier filtered chi(k), optionally with k-weighted chi(k) for XAFS data group
721 Arguments
722 ----------
723 dgroup group of XAFS data after autobk() results (see Note 1)
724 kweight k-weighting for plot [read from last xftf(), or 0]
725 kmax max k to show [None, end of data]
726 show_chik bool whether to also plot k-weighted chi(k) [False]
727 show_window bool whether to also plot FT k-window [False]
728 scale_window bool whether to scale FT k-window to max |chi(q)| [True]
729 label string for label [``None`` to use 'chi']
730 title string for plot title [None, may use filename if available]
731 new bool whether to start a new plot [True]
732 delay_draw bool whether to delay draw until more traces are added [False]
733 offset vertical offset to use for y-array [0]
734 win integer plot window to use [1]
736 Notes
737 -----
738 1. The input data group must have the following attributes:
739 k, chi, kwin, filename
740 """
741 kweight = _get_kweight(dgroup, kweight)
742 nk = len(dgroup.k)
743 chiq = dgroup.chiq_re[:nk]
744 opts = dict(win=win, show_legend=True, delay_draw=True, linewidth=3, _larch=_larch)
745 if label is None:
746 label = 'chi(q) (filtered)'
747 #endif
748 if new:
749 title = _get_title(dgroup, title=title)
751 _plot(dgroup.k, chiq+offset, xlabel=plotlabels.k,
752 ylabel=set_label_weight(plotlabels.chikw, kweight),
753 title=title, label=label, zorder=20, new=new, xmax=kmax, **opts)
755 if show_chik:
756 chik = dgroup.chi * dgroup.k ** kweight
757 _plot(dgroup.k, chik+offset, zorder=16, label='chi(k)', **opts)
758 #endif
759 if show_window and hasattr(dgroup, 'kwin'):
760 kwin = dgroup.kwin
761 if scale_window:
762 kwin = kwin*max(abs(chiq))
763 _plot(dgroup.k, kwin+offset, zorder=12, label='window', **opts)
764 #endif
766 redraw(win=win, xmax=kmax, _larch=_larch)
767#enddef
770def plot_wavelet(dgroup, show_mag=True, show_real=False, show_imag=False,
771 rmax=None, kmax=None, kweight=None, title=None, win=1, _larch=None):
772 """
773 plot_wavelet(dgroup, show_mag=True, show_real=False, show_imag=False,
774 rmax=None, kmax=None, kweight=None, title=None, win=1)
776 Plot wavelet for XAFS data group
778 Arguments
779 ----------
780 dgroup group of XAFS data after xftf() results (see Note 1)
781 show_mag bool whether to plot wavelet magnitude [True]
782 show_real bool whether to plot real part of wavelet [False]
783 show_imag bool whether to plot imaginary part of wavelet [False]
784 title string for plot title [None, may use filename if available]
785 rmax max R to show [None, end of data]
786 kmax max k to show [None, end of data]
787 kweight k-weight to use to construct wavelet [None, take from group]
788 win integer image window to use [1]
790 Notes
791 -----
792 The wavelet will be performed
793 """
794 kweight = _get_kweight(dgroup, kweight)
795 cauchy_wavelet(dgroup, kweight=kweight, rmax_out=rmax)
796 title = _get_title(dgroup, title=title)
798 opts = dict(win=win, title=title, x=dgroup.k, y=dgroup.wcauchy_r, xmax=kmax,
799 ymax=rmax, xlabel=plotlabels.k, ylabel=plotlabels.r,
800 show_axis=True, _larch=_larch)
801 if show_mag:
802 _imshow(dgroup.wcauchy_mag, **opts)
803 elif show_real:
804 _imshow(dgroup.wcauchy_real, **opts)
805 elif show_imag:
806 _imshow(dgroup.wcauchy_imag, **opts)
807 #endif
808#enddef
810def plot_chifit(dataset, kmin=0, kmax=None, kweight=None, rmax=None,
811 show_mag=True, show_real=False, show_imag=False,
812 title=None, new=True, delay_draw=False, offset=0, win=1,
813 _larch=None):
814 """
815 plot_chifit(dataset, kmin=0, kmax=None, rmax=None,
816 show_mag=True, show_real=False, show_imag=False,
817 new=True, win=1)
819 Plot k-weighted chi(k) and chi(R) for fit to feffit dataset
821 Arguments
822 ----------
823 dataset feffit dataset, after running feffit()
824 kmin min k to show [0]
825 kmax max k to show [None, end of data]
826 kweight kweight to show [None, taken from dataset]
827 rmax max R to show [None, end of data]
828 show_mag bool whether to plot |chidr(R)| [True]
829 show_real bool whether to plot Re[chi(R)] [False]
830 show_imag bool whether to plot Im[chi(R)] [False]
831 title string for plot title [None, may use filename if available]
832 new bool whether to start a new plot [True]
833 delay_draw bool whether to delay draw until more traces are added [False]
834 offset vertical offset to use for y-array [0]
835 win integer plot window to use [1]
837 """
838 if kweight is None:
839 kweight = dataset.transform.kweight
840 #endif
841 if isinstance(kweight, (list, tuple, np.ndarray)): kweight=kweight[0]
843 data_chik = dataset.data.chi * dataset.data.k**kweight
844 model_chik = dataset.model.chi * dataset.model.k**kweight
846 title = _get_title(dataset, title=title)
848# opts=dict(labelfontsize=10, legendfontsize=10, linewidth=3,
849# show_legend=True, delay_draw=True, win=win, title=title,
850# _larch=_larch)
851 fig = PlotlyFigure(two_yaxis=False)
853 # k-weighted chi(k) in first plot window
854 _plot(dataset.data.k, data_chik+offset, xmin=kmin, xmax=kmax,
855 xlabel=plotlabels.k,
856 ylabel=set_label_weight(plotlabels.chikw, kweight),
857 label='data', new=new, **opts)
858 _plot(dataset.model.k, model_chik+offset, label='fit', **opts)
859 redraw(win=win, xmin=kmin, xmax=kmax, _larch=_larch)
861 # show chi(R) in next plot window
862 opts['win'] = win = win+1
863 ylabel = plotlabels.chirlab(kweight, show_mag=show_mag,
864 show_real=show_real, show_imag=show_imag)
866 opts.update(dict(xlabel=plotlabels.r, ylabel=ylabel,
867 xmax=rmax, new=True, show_legend=True))
869 if show_mag:
870 _plot(dataset.data.r, dataset.data.chir_mag+offset,
871 label='|data|', **opts)
872 opts['new'] = False
873 _plot(dataset.model.r, dataset.model.chir_mag+offset,
874 label='|fit|', **opts)
875 #endif
876 if show_real:
877 _plot(dataset.data.r, dataset.data.chir_re+offset, label='Re[data]', **opts)
878 opts['new'] = False
879 _plot(dataset.model.r, dataset.model.chir_re+offset, label='Re[fit]', **opts)
880 #endif
881 if show_imag:
882 _plot(dataset.data.r, dataset.data.chir_im+offset, label='Im[data]', **opts)
883 opts['new'] = False
884 _plot(dataset.model.r, dataset.model.chir_im+offset, label='Im[fit]', **opts)
885 #endif
886 if show_mag or show_real or show_imag:
887 redraw(win=opts['win'], xmax=opts['xmax'], _larch=_larch)
888 #endif
889#enddef
891def plot_path_k(dataset, ipath=0, kmin=0, kmax=None, offset=0, label=None,
892 new=False, delay_draw=False, win=1, _larch=None, **kws):
893 """
894 plot_path_k(dataset, ipath, kmin=0, kmax=None, offset=0,
895 label=None, new=False, win=1, **kws)
897 Plot k-weighted chi(k) for a single Path of a feffit dataset
899 Arguments
900 ----------
901 dataset feffit dataset, after running feffit()
902 ipath index of path, starting count at 0 [0]
903 kmin min k to show [0]
904 kmax max k to show [None, end of data]
905 offset vertical offset to use for plot [0]
906 label path label ['path %d' % ipath]
907 new bool whether to start a new plot [True]
908 delay_draw bool whether to delay draw until more traces are added [False]
909 win integer plot window to use [1]
910 kws additional keyword arguments are passed to plot()
911 """
912 kweight = dataset.transform.kweight
913 path = dataset.pathlist[ipath]
914 if label is None: label = 'path %i' % (1+ipath)
916 chi_kw = offset + path.chi * path.k**kweight
918 _plot(path.k, chi_kw, label=label, xmin=kmin, xmax=kmax,
919 xlabel=plotlabels.k,
920 ylabel=set_label_weight(plotlabels.chikw, kweight),
921 win=win, new=new, delay_draw=delay_draw, _larch=_larch, **kws)
922 if delay_draw:
923 redraw(win=win, xmin=kmin, xmax=kmax, _larch=_larch)
924#enddef
926def plot_path_r(dataset, ipath, rmax=None, offset=0, label=None,
927 show_mag=True, show_real=False, show_imag=True,
928 new=False, delay_draw=False, win=1, _larch=None,
929 **kws):
930 """
931 plot_path_r(dataset, ipath,rmax=None, offset=0, label=None,
932 show_mag=True, show_real=False, show_imag=True,
933 new=False, win=1, **kws)
935 Plot chi(R) for a single Path of a feffit dataset
937 Arguments
938 ----------
939 dataset feffit dataset, after running feffit()
940 ipath index of path, starting count at 0 [0]
941 rmax max R to show [None, end of data]
942 offset vertical offset to use for plot [0]
943 label path label ['path %d' % ipath]
944 show_mag bool whether to plot |chi(R)| [True]
945 show_real bool whether to plot Re[chi(R)] [False]
946 show_imag bool whether to plot Im[chi(R)] [False]
947 new bool whether to start a new plot [True]
948 delay_draw bool whether to delay draw until more traces are added [False]
949 win integer plot window to use [1]
950 kws additional keyword arguments are passed to plot()
951 """
952 path = dataset.pathlist[ipath]
953 if label is None:
954 label = 'path %i' % (1+ipath)
955 #endif
956 kweight =dataset.transform.kweight
957 ylabel = plotlabels.chirlab(kweight, show_mag=show_mag,
958 show_real=show_real, show_imag=show_imag)
960 opts = dict(xlabel=plotlabels.r, ylabel=ylabel, xmax=rmax, new=new,
961 delay_draw=True, _larch=_larch)
963 opts.update(kws)
964 if show_mag:
965 _plot(path.r, offset+path.chir_mag, label=label, **opts)
966 opts['new'] = False
967 #endif
968 if show_real:
969 _plot(path.r, offset+path.chir_re, label=label, **opts)
970 opts['new'] = False
971 #endif
972 if show_imag:
973 _plot(path.r, offset+path.chir_im, label=label, **opts)
974 opts['new'] = False
975 #endif
976 redraw(win=win, xmax=rmax, _larch=_larch)
977#enddef
979def plot_paths_k(dataset, offset=-1, kmin=0, kmax=None, title=None,
980 new=True, delay_draw=False, win=1, _larch=None, **kws):
982 """
983 plot_paths_k(dataset, offset=-1, kmin=0, kmax=None, new=True, win=1, **kws):
985 Plot k-weighted chi(k) for model and all paths of a feffit dataset
987 Arguments
988 ----------
989 dataset feffit dataset, after running feffit()
990 kmin min k to show [0]
991 kmax max k to show [None, end of data]
992 offset vertical offset to use for paths for plot [-1]
993 new bool whether to start a new plot [True]
994 title string for plot title [None, may use filename if available]
995 win integer plot window to use [1]
996 delay_draw bool whether to delay draw until more traces are added [False]
997 kws additional keyword arguments are passed to plot()
998 """
999 # make k-weighted chi(k)
1000 kweight = dataset.transform.kweight
1001 model = dataset.model
1003 model_chi_kw = model.chi * model.k**kweight
1005 title = _get_title(dataset, title=title)
1007 _plot(model.k, model_chi_kw, title=title, label='sum', new=new,
1008 xlabel=plotlabels.r, ylabel=plotlabels.chikw.format(kweight),
1009 xmin=kmin, xmax=kmax, win=win, delay_draw=True,_larch=_larch,
1010 **kws)
1012 for ipath in range(len(dataset.pathlist)):
1013 plot_path_k(dataset, ipath, offset=(ipath+1)*offset,
1014 kmin=kmin, kmax=kmax, new=False, delay_draw=True,
1015 win=win, _larch=_larch)
1016 #endfor
1017 redraw(win=win, xmin=kmin, xmax=kmax, _larch=_larch)
1018#enddef
1020def plot_paths_r(dataset, offset=-0.25, rmax=None, show_mag=True,
1021 show_real=False, show_imag=False, title=None, new=True,
1022 win=1, delay_draw=False, _larch=None, **kws):
1023 """
1024 plot_paths_r(dataset, offset=-0.5, rmax=None, show_mag=True, show_real=False,
1025 show_imag=False, new=True, win=1, **kws):
1027 Plot chi(R) for model and all paths of a feffit dataset
1029 Arguments
1030 ----------
1031 dataset feffit dataset, after running feffit()
1032 offset vertical offset to use for paths for plot [-0.5]
1033 rmax max R to show [None, end of data]
1034 show_mag bool whether to plot |chi(R)| [True]
1035 show_real bool whether to plot Re[chi(R)] [False]
1036 show_imag bool whether to plot Im[chi(R)] [False]
1037 title string for plot title [None, may use filename if available]
1038 new bool whether to start a new plot [True]
1039 delay_draw bool whether to delay draw until more traces are added [False]
1040 win integer plot window to use [1]
1041 kws additional keyword arguments are passed to plot()
1042 """
1043 kweight = dataset.transform.kweight
1044 model = dataset.model
1046 ylabel = plotlabels.chirlab(kweight, show_mag=show_mag,
1047 show_real=show_real, show_imag=show_imag)
1048 title = _get_title(dataset, title=title)
1049 opts = dict(xlabel=plotlabels.r, ylabel=ylabel, xmax=rmax, new=new,
1050 delay_draw=True, title=title, _larch=_larch)
1051 opts.update(kws)
1052 if show_mag:
1053 _plot(model.r, model.chir_mag, label='|sum|', **opts)
1054 opts['new'] = False
1055 #endif
1056 if show_real:
1057 _plot(model.r, model.chir_re, label='Re[sum]', **opts)
1058 opts['new'] = False
1059 #endif
1060 if show_imag:
1061 _plot(model.r, model.chir_im, label='Im[sum]', **opts)
1062 opts['new'] = False
1063 #endif
1065 for ipath in range(len(dataset.pathlist)):
1066 plot_path_r(dataset, ipath, offset=(ipath+1)*offset,
1067 show_mag=show_mag, show_real=show_real,
1068 show_imag=show_imag, **opts)
1069 #endfor
1070 redraw(win=win, xmax=rmax,_larch=_larch)
1071#enddef
1074def extend_plotrange(x, y, xmin=None, xmax=None, extend=0.10):
1075 """return plot limits to extend a plot range for x, y pairs"""
1076 xeps = min(diff(x)) / 5.
1077 if xmin is None:
1078 xmin = min(x)
1079 if xmax is None:
1080 xmax = max(x)
1082 xmin = max(min(x), xmin-5)
1083 xmax = min(max(x), xmax+5)
1085 i0 = index_of(x, xmin + xeps)
1086 i1 = index_of(x, xmax + xeps) + 1
1088 xspan = x[i0:i1]
1089 xrange = max(xspan) - min(xspan)
1090 yspan = y[i0:i1]
1091 yrange = max(yspan) - min(yspan)
1093 return (min(xspan) - extend * xrange,
1094 max(xspan) + extend * xrange,
1095 min(yspan) - extend * yrange,
1096 max(yspan) + extend * yrange)
1098def plot_prepeaks_baseline(dgroup, subtract_baseline=False, show_fitrange=True,
1099 show_peakrange=True, win=1, _larch=None, **kws):
1100 """Plot pre-edge peak baseline fit, as from `pre_edge_baseline` or XAS Viewer
1102 dgroup must have a 'prepeaks' attribute
1103 """
1104 if not hasattr(dgroup, 'prepeaks'):
1105 raise ValueError('Group needs prepeaks')
1106 #endif
1107 ppeak = dgroup.prepeaks
1109 px0, px1, py0, py1 = extend_plotrange(dgroup.xdat, dgroup.ydat,
1110 xmin=ppeak.emin, xmax=ppeak.emax)
1112 title = "pre_edge baseline\n %s" % dgroup.filename
1114 popts = dict(xmin=px0, xmax=px1, ymin=py0, ymax=py1, title=title,
1115 xlabel='Energy (eV)', ylabel='mu (normalized)', delay_draw=True,
1116 show_legend=True, style='solid', linewidth=3,
1117 label='data', new=True,
1118 marker='None', markersize=4, win=win, _larch=_larch)
1119 popts.update(kws)
1121 ydat = dgroup.ydat
1122 xdat = dgroup.xdat
1123 if subtract_baseline:
1124 xdat = ppeak.energy
1125 ydat = ppeak.baseline
1126 popts['label'] = 'baseline subtracted peaks'
1127 _plot(xdat, ydat, **popts)
1128 else:
1129 _plot(xdat, ydat, **popts)
1130 popts['new'] = False
1131 popts['label'] = 'baseline'
1132 _oplot(ppeak.energy, ppeak.baseline, **popts)
1134 popts = dict(win=win, _larch=_larch, delay_draw=True,
1135 label='_nolegend_')
1137 if show_fitrange:
1138 for x in (ppeak.emin, ppeak.emax):
1139 _plot_axvline(x, color='#DDDDCC', **popts)
1140 _plot_axvline(ppeak.centroid, color='#EECCCC', **popts)
1142 if show_peakrange:
1143 for x in (ppeak.elo, ppeak.ehi):
1144 y = ydat[index_of(xdat, x)]
1145 _plot_marker(x, y, color='#222255', marker='o', size=8, **popts)
1147 redraw(win=win, xmin=px0, xmax=px1, ymin=py0, ymax=py1,
1148 show_legend=True, _larch=_larch)
1149#enddef
1151def plot_prepeaks_fit(dgroup, nfit=0, show_init=False, subtract_baseline=False,
1152 show_residual=False, win=1, _larch=None):
1153 """plot pre-edge peak fit, as from XAS Viewer
1155 dgroup must have a 'peakfit_history' attribute
1156 """
1157 if not hasattr(dgroup, 'prepeaks'):
1158 raise ValueError('Group needs prepeaks')
1159 #endif
1160 if show_init:
1161 result = pkfit = dgroup.prepeaks
1162 else:
1163 hist = getattr(dgroup.prepeaks, 'fit_history', None)
1164 if nfit > len(hist):
1165 nfit = 0
1166 pkfit = hist[nfit]
1167 result = pkfit.result
1168 #endif
1170 if pkfit is None:
1171 raise ValueError('Group needs prepeaks.fit_history or init_fit')
1172 #endif
1174 opts = pkfit.user_options
1175 xeps = min(diff(dgroup.xdat)) / 5.
1176 xdat = 1.0*pkfit.energy
1177 ydat = 1.0*pkfit.norm
1179 xdat_full = 1.0*dgroup.xdat
1180 ydat_full = 1.0*dgroup.ydat
1182 if show_init:
1183 yfit = pkfit.init_fit
1184 ycomps = None # pkfit.init_ycomps
1185 ylabel = 'model'
1186 else:
1187 yfit = 1.0*result.best_fit
1188 ycomps = pkfit.ycomps
1189 ylabel = 'best fit'
1191 baseline = 0.*ydat
1192 if ycomps is not None:
1193 for label, ycomp in ycomps.items():
1194 if label in opts['bkg_components']:
1195 baseline += ycomp
1197 plotopts = dict(title='%s:\npre-edge peak' % dgroup.filename,
1198 xlabel='Energy (eV)', ylabel=opts['array_desc'],
1199 delay_draw=True, show_legend=True, style='solid',
1200 linewidth=3, marker='None', markersize=4)
1202 if subtract_baseline:
1203 ydat -= baseline
1204 yfit -= baseline
1205 ydat_full = 1.0*ydat
1206 xdat_full = 1.0*xdat
1207 plotopts['ylabel'] = '%s-baseline' % plotopts['ylabel']
1209 dx0, dx1, dy0, dy1 = extend_plotrange(xdat_full, ydat_full,
1210 xmin=opts['emin'], xmax=opts['emax'])
1211 fx0, fx1, fy0, fy1 = extend_plotrange(xdat, yfit,
1212 xmin=opts['emin'], xmax=opts['emax'])
1214 ncolor = 0
1215 popts = {'win': win, '_larch': _larch}
1216 plotopts.update(popts)
1217 dymin = dymax = None
1218 if show_residual:
1219 popts['stacked'] = True
1220 _fitplot(xdat, ydat, yfit, label='data', label2=ylabel, **plotopts)
1221 dy = yfit - ydat
1222 dymax, dymin = dy.max(), dy.min()
1223 dymax += 0.05 * (dymax - dymin)
1224 dymin -= 0.05 * (dymax - dymin)
1225 else:
1226 _plot(xdat_full, ydat_full, new=True, label='data',
1227 color=LineColors[0], **plotopts)
1228 _oplot(xdat, yfit, label=ylabel, color=LineColors[1], **plotopts)
1229 ncolor = 1
1231 if ycomps is not None:
1232 ncomps = len(ycomps)
1233 if not subtract_baseline:
1234 ncolor += 1
1235 _oplot(xdat, baseline, label='baseline', delay_draw=True,
1236 style='short dashed', marker='None', markersize=5,
1237 color=LineColors[ncolor], **popts)
1239 for icomp, label in enumerate(ycomps):
1240 ycomp = ycomps[label]
1241 if label in opts['bkg_components']:
1242 continue
1243 ncolor = (ncolor+1) % 10
1244 _oplot(xdat, ycomp, label=label, delay_draw=(icomp != ncomps-1),
1245 style='short dashed', marker='None', markersize=5,
1246 color=LineColors[ncolor], **popts)
1248 if opts.get('show_fitrange', False):
1249 for attr in ('emin', 'emax'):
1250 _plot_axvline(opts[attr], ymin=0, ymax=1,
1251 delay_draw=False, color='#DDDDCC',
1252 label='_nolegend_', **popts)
1254 if opts.get('show_centroid', False):
1255 pcen = getattr(dgroup.prepeaks, 'centroid', None)
1256 if hasattr(result, 'params'):
1257 pcen = result.params.get('fit_centroid', None)
1258 if pcen is not None:
1259 pcen = pcen.value
1260 if pcen is not None:
1261 _plot_axvline(pcen, delay_draw=False, ymin=0, ymax=1,
1262 color='#EECCCC', label='_nolegend_', **popts)
1264 redraw(xmin=dx0, xmax=dx1, ymin=min(dy0, fy0),
1265 ymax=max(dy1, fy1), dymin=dymin, dymax=dymax, show_legend=True, **popts)
1267def _pca_ncomps(result, min_weight=0, ncomps=None):
1268 if ncomps is None:
1269 if min_weight > 1.e-12:
1270 ncomps = where(result.variances < min_weight)[0][0]
1271 else:
1272 ncomps = argmin(result.ind)
1273 return ncomps
1276def plot_pca_components(result, min_weight=0, ncomps=None, min_variance=1.e-5, win=1, _larch=None, **kws):
1277 """Plot components from PCA result
1279 result must be output of `pca_train`
1280 """
1281 title = "PCA components"
1282 popts = dict(xmin=result.xmin, xmax=result.xmax, title=title,
1283 xlabel=plotlabels.energy, ylabel=plotlabels.norm,
1284 delay_draw=True, show_legend=True, style='solid',
1285 linewidth=3, new=True, marker='None', markersize=4,
1286 win=win, _larch=_larch)
1288 popts.update(kws)
1289 ncomps = int(result.nsig)
1291 _plot(result.x, result.mean, label='Mean', **popts)
1292 for i, comp in enumerate(result.components):
1293 if result.variances[i] > min_variance:
1294 label = 'Comp# %d (%.4f)' % (i+1, result.variances[i])
1295 _oplot(result.x, comp, label=label, **popts)
1297 redraw(win=win, show_legend=True, _larch=_larch)
1299def plot_pca_weights(result, min_weight=0, ncomps=None, win=1, _larch=None, **kws):
1300 """Plot component weights from PCA result (aka SCREE plot)
1302 result must be output of `pca_train`
1303 """
1304 max_comps = len(result.components)
1306 title = "PCA Variances (SCREE) and Indicator Values"
1308 popts = dict(title=title, xlabel='Component #', zorder=10,
1309 xmax=max_comps+1.5, xmin=0.25, ymax=1, ylabel='variance',
1310 style='solid', ylog_scale=True, show_legend=True,
1311 linewidth=1, new=True, marker='o', win=win, _larch=_larch)
1313 popts.update(kws)
1315 ncomps = max(1, int(result.nsig))
1316 x = 1 + arange(ncomps)
1317 y = result.variances[:ncomps]
1318 _plot(x, y, label='significant', **popts)
1320 xe = 1 + arange(ncomps-1, max_comps)
1321 ye = result.variances[ncomps-1:ncomps+max_comps]
1323 popts.update(dict(new=False, zorder=5, style='short dashed',
1324 color='#B34050', ymin=2e-3*result.variances[ncomps-1]))
1325 _plot(xe, ye, label='not significant', **popts)
1327 xi = 1 + arange(len(result.ind)-1)
1329 _plot(xi, result.ind[1:], zorder=15, y2label='Indicator Value',
1330 label='IND', style='solid', win=win, show_legend=True,
1331 linewidth=1, marker='o', side='right', _larch=_larch)
1335def plot_pca_fit(dgroup, win=1, with_components=False, _larch=None, **kws):
1336 """Plot data and fit result from pca_fit, which rom PCA result
1338 result must be output of `pca_fit`
1339 """
1341 title = "PCA fit: %s" % (dgroup.filename)
1342 result = dgroup.pca_result
1343 model = result.pca_model
1345 popts = dict(xmin=model.xmin, xmax=model.xmax, title=title,
1346 xlabel=plotlabels.energy, ylabel=plotlabels.norm,
1347 delay_draw=True, show_legend=True, style='solid',
1348 linewidth=3, new=True, marker='None', markersize=4,
1349 stacked=True, win=win, _larch=_larch)
1350 popts.update(kws)
1351 _fitplot(result.x, result.ydat, result.yfit,
1352 label='data', label2='PCA fit', **popts)
1354 disp = get_display(win=win, stacked=True, _larch=_larch)
1355 if with_components and disp is not None:
1356 disp.panel.oplot(result.x, model.mean, label='mean')
1357 for n in range(len(result.weights)):
1358 cval = model.components[n]*result.weights[n]
1359 disp.panel.oplot(result.x, cval, label='Comp #%d' % (n+1))
1360 redraw(win=win, show_legend=True, stacked=True, _larch=_larch)
1362def plot_diffkk(dgroup, emin=None, emax=None, new=True, label=None,
1363 title=None, delay_draw=False, offset=0, win=1, _larch=None):
1364 """
1365 plot_diffkk(dgroup, norm=True, emin=None, emax=None, show_e0=False, label=None, new=True, win=1):
1367 Plot mu(E) and background mu0(E) for XAFS data group
1369 Arguments
1370 ----------
1371 dgroup group of XAFS data after autobk() results (see Note 1)
1372 norm bool whether to show normalized data [True]
1373 emin min energy to show, absolute or relative to E0 [None, start of data]
1374 emax max energy to show, absolute or relative to E0 [None, end of data]
1375 show_e0 bool whether to show E0 [False]
1376 label string for label [``None``: 'mu']
1377 title string for plot title [None, may use filename if available]
1378 new bool whether to start a new plot [True]
1379 delay_draw bool whether to delay draw until more traces are added [False]
1380 offset vertical offset to use for y-array [0]
1381 win integer plot window to use [1]
1383 Notes
1384 -----
1385 1. The input data group must have the following attributes:
1386 energy, mu, bkg, norm, e0, pre_edge, edge_step, filename
1387 """
1388 if hasattr(dgroup, 'f2'):
1389 f2 = dgroup.f2
1390 else:
1391 raise ValueError("Data group has no array for f2")
1392 #endif
1393 ylabel = r'$f \rm\,\, (e^{-})$ '
1394 emin, emax = _get_erange(dgroup, emin, emax)
1395 title = _get_title(dgroup, title=title)
1397 labels = {'f2': r"$f_2(E)$", 'fpp': r"$f''(E)$", 'fp': r"$f'(E)$", 'f1': r"$f_1(E)$"}
1399 opts = dict(win=win, show_legend=True, linewidth=3,
1400 delay_draw=True, _larch=_larch)
1402 _plot(dgroup.energy, f2, xlabel=plotlabels.energy, ylabel=ylabel,
1403 title=title, label=labels['f2'], zorder=20, new=new, xmin=emin, xmax=emax,
1404 **opts)
1405 zorder = 15
1406 for attr in ('fpp', 'f1', 'fp'):
1407 yval = getattr(dgroup, attr)
1408 if yval is not None:
1409 _plot(dgroup.energy, yval, zorder=zorder, label=labels[attr], **opts)
1410 zorder = zorder - 3
1412 redraw(win=win, xmin=emin, xmax=emax, _larch=_larch)
1413#enddef
1415def plot_feffdat(feffpath, with_phase=True, title=None,
1416 new=True, delay_draw=False, win=1, _larch=None):
1417 """
1418 plot_feffdat(feffpath, with_phase=True, title=None, new=True, win=1):
1420 Plot Feff's magnitude and phase as a function of k for a FeffPath
1422 Arguments
1423 ----------
1424 feffpath feff path as read by feffpath()
1425 with_pase whether to plot phase(k) as well as magnitude [True]
1426 title string for plot title [None, may use filename if available]
1427 new bool whether to start a new plot [True]
1428 delay_draw bool whether to delay draw until more traces are added [False]
1429 win integer plot window to use [1]
1431 Notes
1432 -----
1433 1. The input data group must have the following attributes:
1434 energy, mu, bkg, norm, e0, pre_edge, edge_step, filename
1435 """
1436 if hasattr(feffpath, '_feffdat'):
1437 fdat = feffpath._feffdat
1438 else:
1439 raise ValueError("must pass in a Feff path as from feffpath()")
1440 #endif
1442 _plot(fdat.k, fdat.mag_feff, xlabel=plotlabels.k,
1443 ylabel='|F(k)|', title=title, label='magnitude', zorder=20,
1444 new=new, win=win, show_legend=True,
1445 delay_draw=delay_draw, linewidth=3, _larch=_larch)
1447 if with_phase:
1448 _plot(fdat.k, fdat.pha_feff, xlabel=plotlabels.k,
1449 y2label='Phase(k)', title=title, label='phase', side='right',
1450 zorder=10, new=False, win=win, show_legend=True,
1451 delay_draw=delay_draw, linewidth=3, _larch=_larch)
1452 #endif
1454 if delay_draw:
1455 redraw(win=win, xmin=emin, xmax=emax, _larch=_larch)
1456#enddef