• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

APN-Pucky / smpl / 3619610364

pending completion
3619610364

push

github

GitHub
Poetry (#110)

510 of 510 new or added lines in 28 files covered. (100.0%)

1275 of 1544 relevant lines covered (82.58%)

0.83 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

91.42
/smpl/plot/plot.py
1
import itertools
1✔
2

3
import matplotlib
1✔
4
import matplotlib.pylab as pylab
1✔
5
import matplotlib.pyplot as plt
1✔
6
import numpy as np
1✔
7
import sympy
1✔
8
import uncertainties
1✔
9
import uncertainties.unumpy as unp
1✔
10

11
# local imports
12
from smpl import doc
1✔
13
from smpl import fit as ffit
1✔
14
from smpl import interpolate, io, stat, util, wrap
1✔
15

16

17
def set_plot_style():
1✔
18
    # fig_size = (8, 6)
19
    # fig_legendsize = 14
20
    # fig_labelsize = 12 # ‘xx-small’, ‘x-small’, ‘small’, ‘medium’, ‘large’, ‘x-large’, ‘xx-large’.
21
    params = {
×
22
        "legend.fontsize": "x-large",
23
        "figure.figsize": (8, 6),
24
        "axes.labelsize": "x-large",
25
        "axes.titlesize": "x-large",
26
        "xtick.labelsize": "x-large",
27
        "ytick.labelsize": "x-large",
28
    }
29
    pylab.rcParams.update(params)
×
30
    matplotlib.rcParams.update(params)
×
31
    # matplotlib.rcParams.update({'font.size': fig_labelsize})
32
    # colors = dict(mcolors.BASE_COLORS, **mcolors.CSS4_COLORS)
33

34

35
unv = unp.nominal_values
1✔
36
usd = unp.std_devs
1✔
37

38
default = {
1✔
39
    #    'params'        :[None      ,"Initial fit parameters",
40
    "title": [None, "Plot title"],
41
    "xlabel": [
42
        "",
43
        "X axis label",
44
    ],
45
    "ylabel": [
46
        "",
47
        "Y axis label",
48
    ],
49
    "label": [
50
        None,
51
        "Legend name of plotted ``data``",
52
    ],
53
    "fmt": [
54
        ".",
55
        "Format for plotting fit function",
56
    ],
57
    "units": [
58
        None,
59
        "Units of the fit parameters as strings. Displayed in the Legend",
60
    ],
61
    "save": [
62
        None,
63
        " File to save the plot",
64
    ],
65
    "lpos": [
66
        0,
67
        "Legend position",
68
    ],
69
    "tight": [
70
        True,
71
        "tight_layout",
72
    ],
73
    #          'frange'        :[None      ,"Limit the fit to given range. First integer is the lowest and second the highest index.",],
74
    "prange": [
75
        None,
76
        "Limit the plot of the fit to given range",
77
    ],
78
    "sigmas": [
79
        0,
80
        "Color the array of given ``sigma`` times uncertainty. Only works if the fit function is coded with ``unp``",
81
    ],
82
    "data_sigmas": [
83
        1,
84
        "Color the array of given ``sigma`` times uncertainty. Only works if the data has uncertainties",
85
    ],
86
    "init": [False, "Initialize a new plot"],
87
    "ss": [
88
        True,
89
        "save, add legends and grid to the plot",
90
    ],
91
    "also_data": [True, " also plot the data"],
92
    "also_fit": [
93
        True,
94
        "also plot the fit",
95
    ],
96
    "auto_fit": [
97
        False,
98
        "automatically fit",
99
    ],
100
    "logy": [
101
        False,
102
        "logarithmic x axis",
103
    ],
104
    "logx": [
105
        False,
106
        "logarithmic y axis",
107
    ],
108
    "function_color": [
109
        None,
110
        "Color of the function plot",
111
    ],
112
    "data_color": [
113
        None,
114
        "Color of the data plot",
115
    ],
116
    "fit_color": [
117
        None,
118
        "Color of the fit plot",
119
    ],
120
    "fit_fmt": [
121
        "-",
122
        "Format of the fit plot",
123
    ],
124
    "residue": [
125
        False,
126
        "Display difference between fit and data in a second plot",
127
    ],
128
    "residue_err": [
129
        True,
130
        "Differences between fit and data will have errorbars",
131
    ],
132
    "show": [
133
        False,
134
        "Call plt.show()",
135
    ],
136
    "size": [
137
        None,
138
        "Size of the plot as a tuple (x,y). Only has an effect if ``init`` is True",
139
    ],
140
    "number_format": [
141
        io.gf(4),
142
        "Format to display numbers.",
143
    ],
144
    # ,          'selector'      :[ None     ,"Function that takes ``x`` and ``y`` as parameters and returns an array mask in order to limit the data points for fitting. Alternatively a mask for selecting elements from datax and datay.",],
145
    # ,          'fixed_params'  :[ True     ,"Enable fixing parameters by choosing the same-named variables from ``kwargs``.",],
146
    # ,          'sortbyx'       :[ True     , "Enable sorting the x and y data so that x is sorted.",],
147
    "interpolate": [False, "Enable interpolation of the data."],
148
    "interpolate_fmt": [
149
        "-",
150
        "Either format string or linestyle tuple.",
151
    ],
152
    "interpolate_label": [
153
        None,
154
        "Label for the interpolation.",
155
    ],
156
    "extrapolate": [
157
        True,
158
        "Enable extrapolation of whole data if fit range is limited by ``frange`` or ``fselector``.",
159
    ],
160
    "extrapolate_min": [
161
        None,
162
        "Lower extrapolation bound",
163
    ],
164
    "extrapolate_max": [
165
        None,
166
        "Higher extrapolation bound",
167
    ],
168
    "extrapolate_fmt": [
169
        "--",
170
        "Format of the extrapolation line",
171
    ],
172
    "extrapolate_hatch": [
173
        r"||",
174
        "Extrapolation shape/hatch for filled area in case of ``sigmas``>0. See https://matplotlib.org/stable/gallery/shapes_and_collections/hatch_style_reference.html",
175
    ],
176
    "bbox_to_anchor": [
177
        None,
178
        "Position in a tuple (x,y),Shift position of the legend out of the main pane. ",
179
    ],
180
    "ncol": [
181
        None,
182
        "Columns in the legend if used with ``bbox_to_anchor``.",
183
    ],
184
    "steps": [
185
        1000,
186
        "resolution of the plotted function",
187
    ],
188
    "fitinline": [
189
        False,
190
        "No newlines for each fit parameter",
191
    ],
192
    "grid": [
193
        True,
194
        "Enable grid for the plot",
195
    ],
196
    "hist": [
197
        False,
198
        "Enable histogram plot",
199
    ],
200
    "stairs": [
201
        False,
202
        "Enable stair plot",
203
    ],
204
    "capsize": [5, "size of cap on error bar plot"],
205
    "axes": [None, "set current axis"],
206
    "linestyle": [None, "linestyle, only active if `fmt`=None"],
207
    "xspace": [
208
        np.linspace,
209
        "xspace gets called with xspace(xmin,xmax,steps) in :func:`function` to get the points of the function that will be drawn.",
210
    ],
211
    "alpha": [0.2, "alpha value for the fill_between plot"],
212
}
213

214

215
@doc.append_doc(ffit.fit_kwargs)
1✔
216
@doc.append_str("\t")
1✔
217
@doc.append_str(doc.table(default, init=False))
1✔
218
@doc.append_str(
1✔
219
    doc.table({"plot_kwargs        ": ["default", "description"]}, bottom=False)
220
)
221
def plot_kwargs(kwargs):
1✔
222
    """Set default plot_kwargs if not set."""
223
    kwargs = ffit.fit_kwargs(kwargs)
1✔
224
    for k, v in default.items():
1✔
225
        if not k in kwargs:
1✔
226
            kwargs[k] = v[0]
1✔
227
    return kwargs
1✔
228

229

230
# TODO optimize to minimize number of calls to function
231
# @append_doc(default_kwargs)
232

233

234
def fit(func, *adata, **kwargs):
1✔
235
    """
236
    Fit and plot function to datax and datay.
237

238
    Parameters
239
    ----------
240
    datax : array_like
241
        X data either as ``unp.uarray`` or ``np.array`` or ``list``
242
    datay : array_like
243
        Y data either as ``unp.uarray`` or ``np.array`` or ``list``
244
    function : func
245
        Fit function with parameters: ``x``, ``params``
246
    **kwargs : optional
247
        see :func:`plot_kwargs`.
248
    Fit parameters can be fixed via ``kwargs`` eg. ``a=5``.
249

250
    Returns
251
    -------
252
    array_like
253
        Optimized fit parameters of ``function`` to ``datax`` and ``datay``.
254
        If ``datay`` is complex, both the real and imaginary part are returned.
255

256
    Examples
257
    --------
258

259
    .. plot::
260
        :include-source:
261

262
        >>> from smpl import functions as f
263
        >>> from smpl import plot
264
        >>> param = plot.fit([0,1,2],[0,1,2],f.line)
265
        >>> plot.unv(param).round()[0]
266
        1.0
267

268
    """
269
    function = func
1✔
270
    if "function" in kwargs:
1✔
271
        function = kwargs["function"]
1✔
272
        del kwargs["function"]
1✔
273
        adata = [func, *adata]
1✔
274
    # Fix parameter order if necessary
275
    elif isinstance(function, (list, tuple, np.ndarray)):
1✔
276
        adata = [adata[-1], function, *adata[:-1]]
1✔
277
        function = adata[0]
1✔
278
        adata = adata[1:]
1✔
279
    if util.true("bins", kwargs):
1✔
280
        # yvalue will be overwritten
281
        ndata = [*adata, *adata]
1✔
282
        for i, o in enumerate(adata):
1✔
283
            ndata[2 * i] = o
1✔
284
            ndata[2 * i + 1] = o * 0
1✔
285
        adata = ndata
1✔
286

287
    assert len(adata) % 2 == 0, "data must be pairs of x and y data"
1✔
288
    if len(adata) == 2:
1✔
289
        datax, datay = adata
1✔
290
    else:
291
        rs = []
1✔
292
        for i in range(0, len(adata), 2):
1✔
293
            datax, datay = adata[i], adata[i + 1]
1✔
294
            if util.true("bins", kwargs):
1✔
295
                rs.append(fit(function, datax, **kwargs))
1✔
296
            else:
297
                rs.append(fit(function, datax, datay, **kwargs))
×
298
        return rs
1✔
299

300
    kwargs = plot_kwargs(kwargs)
1✔
301

302
    if np.any(np.iscomplex(datay)):
1✔
303
        label = util.get("label", kwargs, "")
×
304
        kwargs["label"] = label + "(real)"
×
305
        r = fit(datax, datay.real, function=function, **kwargs)
×
306
        kwargs["label"] = label + "(imag)"
×
307
        i = fit(datax, datay.imag, function=function, **kwargs)
×
308
        return r, i
×
309
    if kwargs["auto_fit"]:
1✔
310
        print("function:", function)
1✔
311
        best_f, best_ff, lambda_f = ffit.auto(datax, datay, function, **kwargs)
1✔
312
        if best_f is not None:
1✔
313
            del kwargs["auto_fit"]
1✔
314
            fit(datax, datay, best_f, **kwargs)
1✔
315
        return best_f, best_ff, lambda_f
1✔
316
    if kwargs["also_fit"] == False and kwargs["label"] is None and kwargs["lpos"] == 0:
1✔
317
        kwargs["lpos"] = -1
1✔
318
    return _fit_impl(datax, datay, function, **kwargs)
1✔
319

320

321
def _fit_impl(datax, datay, function, **kwargs):
1✔
322
    x = None
1✔
323
    y = None
1✔
324
    rfit = None
1✔
325
    ifit = None
1✔
326
    fig = None
1✔
327
    fig = init_plot(kwargs)
1✔
328
    ll = None
1✔
329
    if kwargs["also_data"]:
1✔
330
        ll = plt_data(datax, datay, **kwargs).get_color()
1✔
331
    if kwargs["interpolate"]:
1✔
332
        ifit, _, x, y = plt_interpolate(datax, datay, icolor=ll, **kwargs)
1✔
333
    if kwargs["also_fit"]:
1✔
334
        assert function is not None, "function must be given"
1✔
335
        rfit, kwargs["fit_color"], _, _ = plt_fit(datax, datay, function, **kwargs)
1✔
336
    if kwargs["ss"]:
1✔
337
        kwargs["oldshow"] = kwargs["show"]
1✔
338
        kwargs["show"] = kwargs["show"] and not kwargs["residue"]
1✔
339
        save_plot(**kwargs)
1✔
340
        kwargs["show"] = kwargs["oldshow"]
1✔
341
    if kwargs["residue"] and fig is not None:
1✔
342
        plt_residue(datax, datay, function, rfit, fig, **kwargs)
1✔
343
    if not kwargs["also_fit"] and kwargs["interpolate"]:
1✔
344
        return (ifit, x, y)
1✔
345
        # return ifit
346
    return rfit
1✔
347

348

349
# @append_doc(default_kwargs)
350

351

352
def data(*data, function=None, **kwargs):
1✔
353
    """
354
    Plot datay against datax via :func:`fit`
355

356
    Parameters
357
    ----------
358
    datax : array_like
359
        X data either as ``unp.uarray`` or ``np.array`` or ``list``
360
    datay : array_like
361
        Y data either as ``unp.uarray`` or ``np.array`` or ``list``
362
    function : func,optional
363
        Fit function with parameters: ``x``, ``params``
364
    **kwargs : optional
365
        see :func:`plot_kwargs`.
366
    Returns
367
    -------
368
    array_like
369
        Optimized fit parameters of ``function`` to ``datax`` and ``datay``
370
    """
371
    if "also_fit" not in kwargs:
1✔
372
        kwargs["also_fit"] = False
1✔
373
    kwargs = plot_kwargs(kwargs)
1✔
374
    return fit(function=function, *data, **kwargs)
1✔
375

376

377
# @append_doc(default_kwargs)
378

379

380
def auto(*adata, funcs=None, **kwargs):
1✔
381
    """
382
    Automatically loop over functions and fit the best one.
383

384
    Parameters
385
    ----------
386
    funcs : function array
387
        functions to consider as fit. Default all ``smpl.functions``.
388
    **kwargs : optional
389
        see :func:`plot_kwargs`.
390

391
    Returns
392
    -------
393
    The best fit function and it's parameters. Also a lambda function where the parameters are already applied.
394

395

396

397
    """
398
    if "auto_fit" not in kwargs:
1✔
399
        kwargs["auto_fit"] = True
1✔
400
    kwargs = plot_kwargs(kwargs)
1✔
401
    return fit(function=funcs, *adata, **kwargs)
1✔
402

403

404
def _function(func, xfit, **kwargs):
1✔
405
    kargs = {}
1✔
406
    if util.has("fmt", kwargs):
1✔
407
        kargs["fmt"] = kwargs["fmt"]
1✔
408
    if util.has("label", kwargs) and kwargs["label"] != "":
1✔
409
        kargs["label"] = kwargs["label"]
1✔
410
    if util.has("function_color", kwargs) and kwargs["function_color"] != "":
1✔
411
        kargs["color"] = kwargs["function_color"]
1✔
412
    if util.has("sigmas", kwargs) and kwargs["sigmas"] != "":
1✔
413
        kargs["sigmas"] = kwargs["sigmas"]
1✔
414
    if util.has("alpha", kwargs) and kwargs["alpha"] != "":
1✔
415
        kargs["alpha"] = kwargs["alpha"]
1✔
416
    __function(func, xfit, **kargs)
1✔
417

418

419
def plt_plt(x, y, fmt, color, label, linestyle):
1✔
420
    if linestyle is None and fmt is not None:
1✔
421
        return plt.plot(x, y, fmt, label=label, color=color)
1✔
422
    elif linestyle is not None and fmt is None:
1✔
423
        return plt.plot(x, y, label=label, color=color, linestyle=linestyle)
×
424
    elif linestyle is None and fmt is None:
1✔
425
        return plt.plot(x, y, label=label, color=color)
1✔
426

427

428
def __function(
1✔
429
    gfunc,
430
    xlinspace,
431
    fmt="-",
432
    label=None,
433
    color=None,
434
    hatch=None,
435
    sigmas=0.0,
436
    linestyle=None,
437
    alpha=0.4,
438
):
439
    func = gfunc
1✔
440
    x = xlinspace
1✔
441
    l = label
1✔
442

443
    if isinstance(func(x)[0], uncertainties.UFloat):
1✔
444
        if sigmas > 0:
1✔
445
            (ll,) = plt_plt(
1✔
446
                x, unv(func(x)), fmt, label=None, color=color, linestyle=linestyle
447
            )
448
            y = func(x)
1✔
449
            plt.fill_between(
1✔
450
                x,
451
                unv(y) - sigmas * usd(y),
452
                unv(y) + sigmas * usd(y),
453
                alpha=alpha,
454
                label=l,
455
                color=ll.get_color(),
456
                hatch=hatch,
457
            )
458
        else:
459
            (ll,) = plt_plt(
1✔
460
                x, unv(func(x)), fmt, label=l, color=color, linestyle=linestyle
461
            )
462
    else:
463
        (ll,) = plt_plt(x, func(x), fmt, label=l, color=color, linestyle=linestyle)
1✔
464
    return ll
1✔
465

466

467
def function(func, *args, **kwargs):
1✔
468
    """
469
    Plot function ``func`` between ``xmin`` and ``xmax``
470

471
    Parameters
472
    ----------
473
    func : function
474
        Function to be plotted between ``xmin`` and ``xmax``, only taking `array_like` ``x`` as parameter
475
    *args : optional
476
        arguments for ``func``
477
    **kwargs : optional
478
        see :func:`plot_kwargs`.
479
    """
480
    if not util.has("xmin", kwargs) or not util.has("xmax", kwargs):
1✔
481
        kwargs["xmin"], kwargs["xmax"] = stat.get_interesting_domain(func)
×
482
        # raise Exception("xmin or xmax missing.")
483

484
    # if not util.has('lpos', kwargs) and not util.has('label', kwargs):
485
    #    kwargs['lpos'] = -1
486
    if not util.has("fmt", kwargs):
1✔
487
        kwargs["fmt"] = "-"
1✔
488

489
    if "label" not in kwargs:
1✔
490
        kwargs = plot_kwargs(kwargs)
1✔
491
        kwargs["label"] = get_fnc_legend(func, args, **kwargs)
1✔
492
    else:
493
        kwargs = plot_kwargs(kwargs)
1✔
494

495
    xlin = kwargs["xspace"](kwargs["xmin"], kwargs["xmax"], kwargs["steps"])
1✔
496
    init_plot(kwargs)
1✔
497

498
    # kwargs['lpos'] = 0
499
    # _plot(xfit, func(xfit, *args), **kwargs)
500
    _function(wrap.get_lambda_argd(func, kwargs["xvar"], *args), xlin, **kwargs)
1✔
501
    if kwargs["ss"]:
1✔
502
        save_plot(**kwargs)
1✔
503

504

505
# xaxis="",yaxis="",fit_color=None,save = None,residue_err=True,show=False):
506
def plt_residue(datax, datay, gfunction, rfit, fig, **kwargs):
1✔
507
    function = wrap.get_lambda(gfunction, kwargs["xvar"])
1✔
508
    fig.add_axes((0.1, 0.1, 0.8, 0.2))
1✔
509
    kwargs["yaxis"] = "$\\Delta$" + kwargs["yaxis"]
1✔
510
    kwargs["data_color"] = kwargs["fit_color"]
1✔
511

512
    if kwargs["residue_err"]:
1✔
513
        plt_data(datax, datay - function(datax, *rfit), **kwargs)
1✔
514
    else:
515
        plt_data(unv(datax), unv(datay - function(datax, *rfit)), **kwargs)
1✔
516
    kwargs["lpos"] = -1
1✔
517
    save_plot(**kwargs)
1✔
518

519

520
def data_split(datax, datay, **kwargs):
1✔
521
    return ffit.data_split(datax, datay, **kwargs)
1✔
522

523

524
def _fit(datax, datay, function, **kwargs):
1✔
525
    """
526
    Returns a fit like :func:`fit` but does no plotting.
527
    """
528
    return ffit.fit(datax, datay, function, **kwargs)
1✔
529

530

531
def plt_data(datax, datay, **kwargs):
1✔
532
    """
533
    Plot datay vs datax
534
    """
535
    x, y, xerr, yerr = data_split(datax, datay, **kwargs)
1✔
536
    if xerr is not None:
1✔
537
        xerr = xerr * kwargs["data_sigmas"]
1✔
538
    if yerr is not None:
1✔
539
        yerr = yerr * kwargs["data_sigmas"]
1✔
540

541
    ll = None
1✔
542
    if xerr is None and yerr is None:
1✔
543
        if kwargs["fmt"] is None:
1✔
544
            if kwargs["linestyle"] is None:
×
545
                (ll,) = plt.plot(
×
546
                    x, y, label=kwargs["label"], color=kwargs["data_color"]
547
                )
548
            else:
549
                (ll,) = plt.plot(
×
550
                    x,
551
                    y,
552
                    label=kwargs["label"],
553
                    color=kwargs["data_color"],
554
                    linestyle=kwargs["linestyle"],
555
                )
556
        elif kwargs["fmt"] == "step":
1✔
557
            (ll,) = plt.step(
×
558
                x, y, where="mid", label=kwargs["label"], color=kwargs["data_color"]
559
            )
560
        elif kwargs["fmt"] == "hist":
1✔
561
            (ll,) = plt.step(
1✔
562
                x, y, where="mid", label=kwargs["label"], color=kwargs["data_color"]
563
            )
564
            plt.fill_between(x, y, step="mid", color=ll.get_color())
1✔
565
        else:
566
            (ll,) = plt.plot(
1✔
567
                x, y, kwargs["fmt"], label=kwargs["label"], color=kwargs["data_color"]
568
            )
569
    else:
570
        if kwargs["fmt"] is None:
1✔
571
            if kwargs["linestyle"] is None:
1✔
572
                ll, _, _, = plt.errorbar(
1✔
573
                    x,
574
                    y,
575
                    yerr=yerr,
576
                    xerr=xerr,
577
                    fmt=" ",
578
                    capsize=kwargs["capsize"],
579
                    label=kwargs["label"],
580
                    color=kwargs["data_color"],
581
                )
582
            else:
583
                ll, _, _, = plt.errorbar(
×
584
                    x,
585
                    y,
586
                    yerr=yerr,
587
                    xerr=xerr,
588
                    fmt=" ",
589
                    capsize=kwargs["capsize"],
590
                    label=kwargs["label"],
591
                    color=kwargs["data_color"],
592
                    linestyle=kwargs["linestyle"],
593
                )
594
        elif kwargs["fmt"] == "step":
1✔
595
            (ll,) = plt.step(x, y, where="mid", color=kwargs["data_color"])
1✔
596
            if xerr is not None:
1✔
597
                for ix, xv in enumerate(x):
1✔
598
                    dx = xerr[ix]
1✔
599
                    tx = [xv - dx, xv + dx]
1✔
600
                    plt.fill_between(
1✔
601
                        tx,
602
                        y[ix] - yerr[ix],
603
                        y[ix] + yerr[ix],
604
                        label=kwargs["label"] if ix == 1 else None,
605
                        alpha=kwargs["alpha"],
606
                        step="pre",
607
                        color=ll.get_color(),
608
                    )
609
            else:
610
                plt.fill_between(
1✔
611
                    x,
612
                    y - yerr,
613
                    y + yerr,
614
                    label=kwargs["label"],
615
                    alpha=kwargs["alpha"],
616
                    step="mid",
617
                    color=ll.get_color(),
618
                )
619
        elif kwargs["fmt"] == "hist":
1✔
620
            ll, _, _, = plt.errorbar(
1✔
621
                x,
622
                y,
623
                yerr=yerr,
624
                xerr=xerr,
625
                fmt=" ",
626
                capsize=kwargs["capsize"],
627
                color="black",
628
            )
629
            plt.fill_between(
1✔
630
                x, y, step="mid", label=kwargs["label"], color=ll.get_color()
631
            )
632
        else:
633
            ll, _, _, = plt.errorbar(
1✔
634
                x,
635
                y,
636
                yerr=yerr,
637
                xerr=xerr,
638
                fmt=kwargs["fmt"],
639
                capsize=kwargs["capsize"],
640
                label=kwargs["label"],
641
                color=kwargs["data_color"],
642
            )
643
    return ll
1✔
644

645

646
def get_fnc_legend(function, rfit, **kwargs):
1✔
647
    l = wrap.get_latex(function)
1✔
648

649
    vnames = wrap.get_varnames(function, kwargs["xvar"])
1✔
650
    for i in range(1, len(vnames)):
1✔
651
        l = l + ("\n" if not kwargs["fitinline"] or i == 1 else " ")
1✔
652
        l = l + "$" + sympy.latex(sympy.symbols(str(vnames[i]))) + "$="
1✔
653
        if kwargs["units"] is not None and usd(rfit[i - 1]) > 0:
1✔
654
            l = l + "("
1✔
655
        if "number_format" in kwargs:
1✔
656
            l = l + kwargs["number_format"].format(rfit[i - 1])
1✔
657
        else:
658
            l = l + "%s" % (rfit[i - 1])
×
659

660
        if kwargs["units"] is not None and usd(rfit[i - 1]) > 0:
1✔
661
            l = l + ")"
1✔
662
        if kwargs["units"] is not None:
1✔
663
            l = l + " " + kwargs["units"][i - 1]
1✔
664
    return l
1✔
665

666

667
def plt_fit_or_interpolate(
1✔
668
    datax, datay, fitted, l=None, c=None, f=None, ls=None, **kwargs
669
):
670
    if kwargs["prange"] is None:
1✔
671
        x, _, _, _ = ffit.fit_split(datax, datay, **kwargs)
1✔
672
        xfit = kwargs["xspace"](np.min(unv(x)), np.max(unv(x)), kwargs["steps"])
1✔
673
    else:
674
        xfit = kwargs["xspace"](
×
675
            kwargs["prange"][0], kwargs["prange"][1], kwargs["steps"]
676
        )
677
    ll = __function(
1✔
678
        fitted,
679
        xfit,
680
        kwargs["fit_fmt"] if f is not None and ls is None else f,
681
        label=l,
682
        color=kwargs["fit_color"] if c is None else c,
683
        sigmas=kwargs["sigmas"],
684
        linestyle=ls,
685
        alpha=kwargs["alpha"],
686
    )
687

688
    if (
1✔
689
        (kwargs["frange"] is not None or kwargs["fselector"] is not None)
690
        and util.true("extrapolate", kwargs)
691
        or util.has("extrapolate_max", kwargs)
692
        or util.has("extrapolate_min", kwargs)
693
    ):
694
        xxfit = kwargs["xspace"](
1✔
695
            util.get("extrapolate_min", kwargs, np.min(unv(datax))),
696
            util.get("extrapolate_max", kwargs, np.max(unv(datax))),
697
            kwargs["steps"],
698
        )
699
        __function(
1✔
700
            fitted,
701
            kwargs["xspace"](np.min(xxfit), np.min(xfit), kwargs["steps"]),
702
            util.get("extrapolate_fmt", kwargs, "--"),
703
            color=ll.get_color(),
704
            hatch=util.get("extrapolate_hatch", kwargs, r"||"),
705
            sigmas=kwargs["sigmas"],
706
            alpha=kwargs["alpha"],
707
        )
708
        __function(
1✔
709
            fitted,
710
            kwargs["xspace"](np.max(xfit), np.max(xxfit), kwargs["steps"]),
711
            util.get("extrapolate_fmt", kwargs, "--"),
712
            color=ll.get_color(),
713
            hatch=util.get("extrapolate_hatch", kwargs, r"||"),
714
            sigmas=kwargs["sigmas"],
715
            alpha=kwargs["alpha"],
716
        )
717
    return ll.get_color(), xfit, fitted(xfit)
1✔
718

719

720
def plt_interpolate(datax, datay, icolor=None, **kwargs):
1✔
721
    """
722
    Interpolate and Plot that Interpolation.
723
    """
724
    inter = interpolate.interpolate(datax, datay, **kwargs)
1✔
725
    kargs = {}
1✔
726
    if isinstance(kwargs["interpolate_fmt"], tuple):
1✔
727
        kargs["ls"] = kwargs["interpolate_fmt"]
×
728
    else:
729
        kargs["f"] = kwargs["interpolate_fmt"]
1✔
730
    if kwargs["interpolate_label"] is not None:
1✔
731
        kargs["l"] = kwargs["interpolate_label"]
1✔
732
    # l = None so that no label
733
    return (
1✔
734
        inter,
735
        *plt_fit_or_interpolate(datax, datay, inter, c=icolor, **kargs, **kwargs),
736
    )
737

738

739
def plt_fit(datax, datay, gfunction, **kwargs):
1✔
740
    """
741
    Fit and Plot that Fit.
742
    """
743
    func = wrap.get_lambda(gfunction, kwargs["xvar"])
1✔
744
    rfit = _fit(datax, datay, gfunction, **kwargs)
1✔
745

746
    def fitted(x):
1✔
747
        return func(x, *rfit)
1✔
748

749
    l = get_fnc_legend(gfunction, rfit, **kwargs)
1✔
750
    return (rfit, *plt_fit_or_interpolate(datax, datay, fitted, l, **kwargs))
1✔
751

752

753
def init_plot(kwargs):
1✔
754
    fig = None
1✔
755
    if util.has("axes", kwargs) and kwargs["axes"] is not None:
1✔
756
        plt.sca(kwargs["axes"])
1✔
757
        fig = kwargs["axes"].get_figure()
1✔
758
    if kwargs["init"] or util.true("residue", kwargs):
1✔
759
        if kwargs["size"] is None:
1✔
760
            fig = plt.figure()
1✔
761
        else:
762
            fig = plt.figure(figsize=kwargs["size"])
×
763
        if kwargs["residue"]:
1✔
764
            fig.add_axes((0.1, 0.3, 0.8, 0.6))
1✔
765
    if util.has("xlabel", kwargs) and kwargs["xlabel"] != "":
1✔
766
        plt.xlabel(kwargs["xlabel"])
1✔
767
    if util.has("ylabel", kwargs) and kwargs["ylabel"] != "":
1✔
768
        plt.ylabel(kwargs["ylabel"])
1✔
769
    if util.has("xaxis", kwargs) and kwargs["xaxis"] != "":
1✔
770
        plt.xlabel(kwargs["xaxis"])
1✔
771
    if util.has("yaxis", kwargs) and kwargs["yaxis"] != "":
1✔
772
        plt.ylabel(kwargs["yaxis"])
1✔
773
    if util.has("next_color", kwargs) and not kwargs["next_color"]:
1✔
774
        it1, it2 = itertools.tee(iter(plt.gca()._get_lines.prop_cycler))
1✔
775
        plt.gca()._get_lines.prop_cycler = it2
1✔
776
        tmp_color = next(it1)["color"]
1✔
777
        if kwargs["data_color"] is None:
1✔
778
            kwargs["data_color"] = tmp_color
1✔
779
        if kwargs["fit_color"] is None:
1✔
780
            kwargs["fit_color"] = tmp_color
1✔
781
        if kwargs["function_color"] is None:
1✔
782
            kwargs["function_color"] = tmp_color
1✔
783
    return fig
1✔
784

785

786
def save_plot(**kwargs):
1✔
787
    """
788
    save plot
789
    """
790
    if "title" in kwargs and kwargs["title"] is not None:
1✔
791
        plt.title(kwargs["title"])
×
792
    if "logy" in kwargs and kwargs["logy"]:
1✔
793
        plt.gca().set_yscale("log")
1✔
794
    if "logx" in kwargs and kwargs["logx"]:
1✔
795
        plt.gca().set_xscale("log")
1✔
796
    if "tight" in kwargs and kwargs["tight"]:
1✔
797
        plt.tight_layout()
1✔
798
    if "lpos" in kwargs and kwargs["lpos"] >= 0:
1✔
799
        if util.has("bbox_to_anchor", kwargs):
1✔
800
            if util.has("ncol", kwargs):
1✔
801
                plt.legend(
1✔
802
                    loc=kwargs["lpos"],
803
                    bbox_to_anchor=kwargs["bbox_to_anchor"],
804
                    ncol=kwargs["ncol"],
805
                    borderaxespad=0,
806
                )
807
            else:
808
                plt.legend(loc=kwargs["lpos"], bbox_to_anchor=kwargs["bbox_to_anchor"])
1✔
809
        else:
810
            plt.legend(loc=kwargs["lpos"])
1✔
811
    # plt.gca().set_xlim([kwargs['xmin'],kwargs['xmax']])
812
    # plt.gca().set_ylim([kwargs['ymin'],kwargs['ymax']])
813
    if "save" in kwargs and not kwargs["save"] is None:
1✔
814
        io.mkdirs(kwargs["save"])
×
815
        plt.savefig(kwargs["save"] + ".pdf")
×
816
    plt.grid(b=kwargs["grid"])
1✔
817
    if "show" in kwargs and kwargs["show"]:
1✔
818
        show(**kwargs)
1✔
819

820

821
def show(**kwargs):
1✔
822
    kwargs = plot_kwargs(kwargs)
1✔
823

824
    plt.grid(b=kwargs["grid"])
1✔
825
    plt.show()
1✔
826

827

828
if __name__ == "__main__":
1✔
829
    import doctest
×
830

831
    doctest.testmod()
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc