def test_set_dict_defaults_inplace(): d1 = {} set_dict_defaults_inplace(d1, {}, {}) assert d1 == {} d2 = {} set_dict_defaults_inplace(d2, {1: 2}, {1: 4, 2: 8}) assert d2 == {1: 4, 2: 8} d3 = {} set_dict_defaults_inplace(d3, {1: 2}) assert d3 == {1: 2} d4 = {1: 1, 2: 4} set_dict_defaults_inplace( d4, {2: 8, 3: 27}, {3: 81, 4: 256}) assert d4 == {1: 1, 2: 4, 3: 81, 4: 256}
def plot_C_vs_t_in_bin( rd, tout, Cout, bi=0, ax=None, labels=None, xscale="log", yscale="log", substances=None, ttlfmt=None, legend_kwargs=None, ls=None, c=None, xlabel=None, ylabel=None, ): """ Plots bin local concentration as function of time for selected substances. Parameters ---------- rd: ReactionDiffusion tout: 1D array of floats Cout: concentration trajectories from solver bi: bin index ax: Axes instance labels: sequence of strings xscale: matplotlib scale choice (e.g. 'log', 'symlog') yscale: matplotlib scale choice (e.g. 'log', 'symlog') substances: sequence of indies or names of substances ttlfmt: string formatted with bin boundaries (set to empty to suppress) legend_kwargs: dict kwargs passed to matplotlib legend function, (default: {'loc': None, 'prop': {'size': 12}}), set to False to suppress legend. ls: sequence of strings linestyles c: sequence of strings colors Returns ======= Axes instance """ if ttlfmt is None: if rd.N == 1: ttlfmt = "C(t)" else: ttlfmt = r"C(t) in bin: {0:.2g} m $\langle$" + r" x $\langle$ {1:.2g} m" legend_kwargs = legend_kwargs or {} set_dict_defaults_inplace(legend_kwargs, dict(loc="upper left", prop={"size": 12})) ls = ls or DEFAULT["ls"] c = c or DEFAULT["c"] ax, substances, labels = _init_ax_substances_labels(rd, ax, substances, labels, xscale, yscale) for i, lbl in zip(substances, labels): ax.plot(tout, Cout[:, bi, i], label=lbl, ls=ls[i % len(ls)], c=c[i % len(c)]) try: ax.set_xlabel(xlabel or "t / " + str(tout.dimensionality.latex), {"fontsize": 16}) ax.set_ylabel(ylabel or "C / " + str(Cout.dimensionality.latex), {"fontsize": 16}) except AttributeError: pass if ttlfmt: ax.set_title(ttlfmt.format(rd.x[bi], rd.x[bi + 1])) if legend_kwargs is not False: ax.legend(**legend_kwargs) return ax
def plot_solver_linear_error( integration, Cref=0, ax=None, x=None, ti=slice(None), bi=0, si=0, plot_kwargs=None, fill_between_kwargs=None, scale_err=1.0, fill=True, **kwargs ): """ Parameters ---------- integration: chemreac.integrate.Integration result from integration. Cref: array or float analytic solution to compare with ax: Axes instance or dict if ax is a dict it is used as key word arguments passed to matplotlib.pyplot.axes (default: None) x: array (optional) x-values, when None it is deduced to be either t or x (when ti or bi are slices repecitvely) (default: None) ti: slice time indices bi: slice bin indices si: integer specie index plot_kwargs: dict keyword arguments passed to matplotlib.pyplot.plot (default: None) fill_between_kwargs: dict keyword arguments passed to matplotlib.pyplot.fill_between (default: None) scale_err: float value with which errors are scaled. (default: 1.0) fill: bool whether or not to fill error span \*\*kwargs common keyword arguments of plot_kwargs and fill_between_kwargs, e.g. 'color', (default: None). See Also -------- plot_solver_linear_excess_error """ ax = _init_axes(ax) Cerr = integration.Cout - to_unitless(Cref, get_derived_unit(integration.rd.unit_registry, "concentration")) if x is None: if isinstance(ti, slice): x = integration.tout[ti] elif isinstance(bi, slice): x = integration.rd.xcenters[bi] else: raise NotImplementedError("Failed to deduce x-axis.") plot_kwargs = plot_kwargs or {} set_dict_defaults_inplace(plot_kwargs, kwargs) plt.plot(np.asarray(x), np.asarray(scale_err * Cerr[ti, bi, si]), **plot_kwargs) if fill: le_l, le_u = solver_linear_error_from_integration(integration, ti=ti, bi=bi, si=si) Cerr_u = le_u - Cref[ti, bi, si] Cerr_l = le_l - Cref[ti, bi, si] fill_between_kwargs = fill_between_kwargs or {} set_dict_defaults_inplace(fill_between_kwargs, {"alpha": 0.2}, kwargs) plt.fill_between( np.asarray(x), np.asarray(scale_err * Cerr_l), np.asarray(scale_err * Cerr_u), **fill_between_kwargs ) return ax
def _plot_analysis( cb, labels, rd, tout, yout, indices, axes=None, titles=None, lintreshy=1e-10, logx=True, legend_kwargs=None, ls=None, c=None, ): """ Parameters ---------- cb: callback callback with signature (rd, tout, yout, indices) returning 3-dimensional array with shape (tout.size, len(axes), len(labels)) labels: sequence of strings labels of individual plots rd: ReactionDiffusion instance tout: 1-dimensional array of floats yout: solver output indices: 4th argument for callback axes: sequence of matplotlib Axes instances (default: len(indices) number of subplot axes) titles: titles per axis lintreshy: float symlog option 'linthreshy' (default: 1e-10) logx: set x scale to 'log' legend_kwargs: dict dict of kwargs to pass to matplotlib legend function (default: {'loc': None, 'prop': {'size': 12}}), set to False to suppress legend. ls: sequence of strings linestyles c: sequence of strings colors """ legend_kwargs = legend_kwargs or {} set_dict_defaults_inplace(legend_kwargs, dict(loc=None, prop={"size": 12})) if axes is None: axes = [plt.subplot(len(indices), 1, i + 1) for i in range(len(indices))] else: assert len(axes) == len(indices) ls = ls or DEFAULT["ls"] c = c or DEFAULT["c"] row_out = cb(rd, tout, yout, indices) for i, ax in enumerate(axes): ax.set_yscale("symlog", linthreshy=lintreshy) if logx: ax.set_xscale("log") istl = 0 # style counter for j, lbl in enumerate(labels): if np.all(np.abs(row_out[:, i, j]) < lintreshy): continue ax.plot(tout, row_out[:, i, j], label=lbl, c=c[istl % len(c)], ls=ls[istl % len(ls)]) istl += 1 if legend_kwargs is not False: ax.legend(**legend_kwargs) if titles: ax.set_title(titles[i]) ax.set_xlabel("t / s") return axes