def svd(self, n=5): """ Plot the SVD-components of the dataset. Parameters ---------- n : int or list of int Determines the plotted SVD-components. If `n` is an int, it plots the first n components. If `n` is a list of ints, then every number is a SVD-component to be plotted. """ is_nm = self.freq_unit is "nm" if is_nm: ph.vis_mode() else: ph.ir_mode() ds = self.dataset x = ds.wavelengths if is_nm else ds.wavenumbers fig, axs = plt.subplots(3, 1, figsize=(4, 5)) u, s, v = np.linalg.svd(ds.data) axs[0].stem(s) axs[0].set_xlim(0, 11) try: len(n) comps = n except TypeError: comps = range(n) for i in comps: axs[1].plot(ds.t, u.T[i], label="%d" % i) axs[2].plot(x, v[i]) ph.lbl_trans(axs[1], use_symlog=True) self.lbl_spec(axs[2])
def svd(self, n=5): """ Plot the SVD-components of the dataset. Parameters ---------- n : int or list of int Determines the plotted SVD-components. If `n` is an int, it plots the first n components. If `n` is a list of ints, then every number is a SVD-component to be plotted. """ is_nm = self.freq_unit is 'nm' if is_nm: ph.vis_mode() else: ph.ir_mode() ds = self.dataset x = ds.wavelengths if is_nm else ds.wavenumbers fig, axs = plt.subplots(3, 1, figsize=(4, 5)) u, s, v = np.linalg.svd(ds.data) axs[0].stem(s) axs[0].set_xlim(0, 11) try: len(n) comps = n except TypeError: comps = range(n) for i in comps: axs[1].plot(ds.t, u.T[i], label='%d' % i) axs[2].plot(x, v[i]) ph.lbl_trans(axs[1], use_symlog=True) self.lbl_spec(axs[2])
def das(tup, x0, from_t=0.4, uniform_fil=None, plot_result=True, fit_kws=None): out = namedtuple('das_result', field_names=[ 'fitter', 'result', 'minimizer']) ti = dv.make_fi(tup.t) if uniform_fil is not None: tupf = filter.uniform_filter(tup, uniform_fil) else: tupf = tup if fit_kws is None: fit_kws = {} import numpy as np #ct = dv.tup(np.hstack((wl, wl)), tup.t[ti(t0):], np.hstack((pa[ti(t0):, :], se[ti(t0):, :]))) ct = dv.tup(tup.wl, tup.t[ti(from_t):], tupf.data[ti(from_t):, :]) f = fitter.Fitter(ct, model_coh=0, model_disp=0) f.lsq_method = 'ridge' kws = dict(full_model=0, lower_bound=0.2, fixed_names=['w']) kws.update(fit_kws) lm = f.start_lmfit(x0, **kws) res = lm.leastsq() import lmfit lmfit.report_fit(res) if plot_result: plt.figure(figsize=(4, 7)) plt.subplot(211) if is_montone(f.wl): monotone = False # Assume wl is repeated N = len(f.wl) else: monotone = True N = len(f.wl) // 2 print(N) l = plt.plot(f.wl[:N], f.c[:N, :], lw=3) if monotone: l2 = plt.plot(f.wl[:N], f.c[N:, :], lw=1) for i, j in zip(l, l2): j.set_color(i.get_color()) plot_helpers.lbl_spec() lbls = ['%.1f' % i for i in f.last_para[1:-1]] + ['const'] plt.legend(lbls) plt.subplot(212) wi = dv.make_fi(tup.wl) for i in range(N)[::6]: l, = plt.plot(tup.t, tupf.data[:, i], '-o', lw=0.7, alpha=0.5, label='%.1f cm-1' % f.wl[i], mec='None', ms=3) plt.plot(f.t, f.model[:, i], lw=3, c=l.get_color()) if monotone: l, = plt.plot(tup.t, tupf.data[:, i+N], '-o', lw=0.7, alpha=0.5, label='%.1f cm-1' % f.wl[i], mec='None', ms=3) plt.plot(f.t, f.model[:, i+N], lw=3, c=l.get_color()) plt.xlim(-1) plt.xscale('symlog', linthreshx=1, linscalex=0.5) plot_helpers.lbl_trans() plt.legend(loc='best') return out(f, res, lm)
def plot_square(self, probe_range, pump_range=None, use_symlog=True, ax=None): if pump_range is None: pump_range = probe_range pr = inbetween(self.ds.probe_wn, min(probe_range), max(probe_range)) reg = self.ds.spec2d[:, pr, :] pu = inbetween(self.ds.pump_wn, min(pump_range), max(pump_range)) reg = reg[:, :, pu] s = reg.sum(1).sum(1) if ax is None: ax = plt.gca() l, = ax.plot(self.ds.t, s) plot_helpers.lbl_trans(ax, use_symlog) return l
def trans_anisotropy(self, wls, symlog=True, ax=None, freq_unit='auto'): """ Plots the anisotropy over time for given frequencies. Parameters ---------- wls : list of floats Which frequencies are plotted. symlog : bool Use symlog scale ax : plt.Axes or None Matplotlib Axes, if `None`, defaults to `plt.gca()`. Returns ------- : list of Line2D List with the line objects. """ if ax is None: ax = ax.gca() ds = self.pol_ds tmp = self.freq_unit if freq_unit == 'auto' else freq_unit is_nm = tmp == 'nm' x = ds.wavelengths if is_nm else ds.wavenumbers if is_nm: ph.vis_mode() else: ph.ir_mode() l = [] for i in wls: idx = dv.fi(x, i) pa, pe = ds.para.data[:, idx], ds.perp.data[:, idx] aniso = (pa - pe) / (2 * pe + pa) l += ax.plot(ds.para.t, aniso, label=ph.time_formatter(ds.t[idx], ph.time_unit)) ph.lbl_trans(use_symlog=symlog) if symlog: ax.set_xscale('symlog') ax.set_xlim(-1, ) return l
def trans_anisotropy(self, wls, symlog=True, ax=None, freq_unit="auto"): """ Plots the anisotropy over time for given frequencies. Parameters ---------- wls : list of floats Which frequencies are plotted. symlog : bool Use symlog scale ax : plt.Axes or None Matplotlib Axes, if `None`, defaults to `plt.gca()`. Returns ------- : list of Line2D List with the line objects. """ if ax is None: ax = ax.gca() ds = self.pol_ds tmp = self.freq_unit if freq_unit == "auto" else freq_unit is_nm = tmp == "nm" x = ds.wavelengths if is_nm else ds.wavenumbers if is_nm: ph.vis_mode() else: ph.ir_mode() l = [] for i in wls: idx = dv.fi(x, i) pa, pe = ds.para.data[:, idx], ds.perp.data[:, idx] aniso = (pa - pe) / (2 * pe + pa) l += ax.plot( ds.para.t, aniso, label=ph.time_formatter(ds.t[idx], ph.time_unit) ) ph.lbl_trans(use_symlog=symlog) if symlog: ax.set_xscale("symlog") ax.set_xlim(-1) return l
def plot_cls(self, ax=None, model_style: Dict = None, symlog=False, **kwargs): if ax is None: ax = plt.gca() ec = ax.errorbar(self.wt, self.slopes, self.slope_errors, **kwargs) if symlog: ax.set_xscale('symlog', linthresh=1) plot_helpers.lbl_trans(ax=ax, use_symlog=symlog) ax.set(xlabel=plot_helpers.time_label, ylabel='Slope') m_line = None if self.exp_fit_result_: xu = np.linspace(min(self.wt), max(self.wt), 300) yu = self.exp_fit_result_.eval(x=xu) style = dict(c='k', zorder=1.8) if model_style: style.update(model_style) m_line = ax.plot(xu, yu, color='k', zorder=1.8) return ec, m_line
def das(tup, x0, from_t=0.4, uniform_fil=None, plot_result=True, fit_kws=None): out = namedtuple('das_result', field_names=['fitter', 'result', 'minimizer']) ti = dv.make_fi(tup.t) if uniform_fil is not None: tupf = filter.uniform_filter(tup, uniform_fil) else: tupf = tup if fit_kws is None: fit_kws = {} #ct = dv.tup(np.hstack((wl, wl)), tup.t[ti(t0):], np.hstack((pa[ti(t0):, :], se[ti(t0):, :]))) ct = dv.tup(tup.wl, tup.t[ti(from_t):], tupf.data[ti(from_t):, :]) f = fitter.Fitter(ct, model_coh=0, model_disp=0) f.lsq_method = 'ridge' kws = dict(full_model=0, lower_bound=0.2, fixed_names=['w']) kws.update(fit_kws) lm = f.start_lmfit(x0, **kws) res = lm.leastsq() import lmfit lmfit.report_fit(res) if plot_result: plt.figure(figsize=(4, 7)) plt.subplot(211) if is_montone(f.wl): monotone = False # Assume wl is repeated N = len(f.wl) else: monotone = True N = len(f.wl) // 2 print(N) l = plt.plot(f.wl[:N], f.c[:N, :], lw=3) if monotone: l2 = plt.plot(f.wl[:N], f.c[N:, :], lw=1) for i, j in zip(l, l2): j.set_color(i.get_color()) plot_helpers.lbl_spec() lbls = ['%.1f' % i for i in f.last_para[1:-1]] + ['const'] plt.legend(lbls) plt.subplot(212) wi = dv.make_fi(tup.wl) for i in range(N)[::6]: l, = plt.plot(tup.t, tupf.data[:, i], '-o', lw=0.7, alpha=0.5, label='%.1f cm-1' % f.wl[i], mec='None', ms=3) plt.plot(f.t, f.model[:, i], lw=3, c=l.get_color()) if monotone: l, = plt.plot(tup.t, tupf.data[:, i + N], '-o', lw=0.7, alpha=0.5, label='%.1f cm-1' % f.wl[i], mec='None', ms=3) plt.plot(f.t, f.model[:, i + N], lw=3, c=l.get_color()) plt.xlim(-1) plt.xscale('symlog', linthreshx=1, linscalex=0.5) plot_helpers.lbl_trans() plt.legend(loc='best') return out(f, res, lm)
def trans(self, wls, symlog=True, norm=False, ax=None, freq_unit='auto', **kwargs): """ Plot the nearest transients for given frequencies. Parameters ---------- wls : list or ndarray Spectral positions, should be given in the same unit as `self.freq_unit`. symlog : bool Determines if the x-scale is symlog. norm : bool or float If `False`, no normalization is used. If `True`, each transient is divided by the maximum absolute value. If `norm` is a float, all transient are normalized by their signal at the time `norm`. ax : plt.Axes or None Takes a matplotlib axes. If none, it uses `plt.gca()` to get the current axes. The lines are plotted in this axis. freq_unit : 'auto', 'cm' or 'nm' How to interpret the given frequencies. If 'auto' it defaults to the plotters freq_unit. All other kwargs are forwarded to the plot function. Returns ------- list of Line2D List containing the plotted lines. """ if ax is None: ax = plt.gca() tmp = self.freq_unit if freq_unit is 'auto' else freq_unit is_nm = tmp == 'nm' if is_nm: ph.vis_mode() else: ph.ir_mode() ds = self.dataset x = ds.wavelengths if is_nm else ds.wavenumbers wl, t, d = ds.wl, ds.t, ds.data l, plotted_vals = [], [] for i in wls: idx = dv.fi(x, i) dat = d[:, idx] if norm is True: dat = np.sign(dat[np.argmax(abs(dat))]) * dat / abs(dat).max() elif norm is False: pass else: dat = dat / dat[dv.fi(t, norm)] plotted_vals.append(dat) l.extend( ax.plot(t, dat, label='%.1f %s' % (x[idx], ph.freq_unit), **kwargs)) if symlog: ax.set_xscale('symlog', linthreshx=1.) ph.lbl_trans(ax=ax, use_symlog=symlog) ax.legend(loc='best', ncol=3) ax.set_xlim(right=t.max()) ax.yaxis.set_tick_params(which='minor', left=True) return l
def trans(self, wls, symlog=True, norm=False, ax=None, freq_unit="auto", **kwargs): """ Plot the nearest transients for given frequencies. Parameters ---------- wls : list or ndarray Spectral positions, should be given in the same unit as `self.freq_unit`. symlog : bool Determines if the x-scale is symlog. norm : bool or float If `False`, no normalization is used. If `True`, each transient is divided by the maximum absolute value. If `norm` is a float, all transient are normalized by their signal at the time `norm`. ax : plt.Axes or None Takes a matplotlib axes. If none, it uses `plt.gca()` to get the current axes. The lines are plotted in this axis. freq_unit : 'auto', 'cm' or 'nm' How to interpret the given frequencies. If 'auto' it defaults to the plotters freq_unit. All other kwargs are forwarded to the plot function. Returns ------- list of Line2D List containing the plotted lines. """ if ax is None: ax = plt.gca() tmp = self.freq_unit if freq_unit is "auto" else freq_unit is_nm = tmp == "nm" if is_nm: ph.vis_mode() else: ph.ir_mode() ds = self.dataset x = ds.wavelengths if is_nm else ds.wavenumbers wl, t, d = ds.wl, ds.t, ds.data l, plotted_vals = [], [] for i in wls: idx = dv.fi(x, i) dat = d[:, idx] if norm is True: dat = np.sign(dat[np.argmax(abs(dat))]) * dat / abs(dat).max() elif norm is False: pass else: dat = dat / dat[dv.fi(t, norm)] plotted_vals.append(dat) l.extend( ax.plot(t, dat, label="%.1f %s" % (x[idx], ph.freq_unit), **kwargs) ) if symlog: ax.set_xscale("symlog", linthreshx=1.0) ph.lbl_trans(ax=ax, use_symlog=symlog) ax.legend(loc="best", ncol=3) ax.set_xlim(right=t.max()) ax.yaxis.set_tick_params(which="minor", left=True) return l
ax[0].set_title('DAS') plot_helpers.lbl_spec(ax[0]) sas = A_inv @ das.T edas = np.cumsum(das, axis=1) ax[1].plot(dsb.wn, sas.T) ax[1].set_title('SAS') plot_helpers.lbl_spec(ax[1]) # %% # As we can see, we sucessfully get the SAS, which in this case are just EDAS. # Let's also look at the concentrations. fig, ax = plt.subplots(2, figsize=(3, 4)) ax[0].plot(dsb.t, fr.fitter.x_vec[:, :2]) ax[0].set_title('DAS') plot_helpers.lbl_trans(ax[0], use_symlog=False) ct = fr.fitter.x_vec[:, :2] @ A ax[1].plot(dsb.t, ct) ax[1].set_title('SAS') plot_helpers.lbl_trans(ax[1], use_symlog=False) # %% # So why does it work? The dataset is given by the outer product of the # concentrations and the spectrum C = fr.fitter.x_vec[:, :2] S = das[:, :2] fit = C @ S.T fit - fr.fitter.model # %%
# All these function offer a number of options. More information can be found in # their docstrings. # # Exponential fitting # ------------------- # Fitting a decay-associated spectra (DAS) is a one-liner in skultrafast. If the # dataset is dispersion corrected, only a starting guess is necessary. Please # look at the docstring to see how the starting guess is structured. # _Note_, the the fitting interface may change in the future. fit_res = new_ds.fit_exp([-0.0, 0.05, 0.2, 2, 20, 10000], model_coh=True, fix_sigma=False, fix_t0=False) fit_res.lmfit_res.params # %% # Lets plot the DAS new_ds.plot.das() # %% # We can always work with the results directly to make plots manually. Here, # the `t_idx`, `wl_idx` and `wn_idx` methods of the dataset are very useful: for wl in [500, 580, 620]: t0 = fit_res.lmfit_res.params['p0'].value idx = new_ds.wl_idx(wl) plt.plot(new_ds.t - t0, fit_res.fitter.data[:, idx], 'o', color='k', ms=4, alpha=0.4) plt.plot(new_ds.t - t0, fit_res.fitter.model[:, idx], lw=2, label='%d nm' % wl) plt.xlim(-1, 10) plot_helpers.lbl_trans(use_symlog=False) plt.legend(loc='best', ncol=1)