Sine fits using fit_pandas_GUI()¶

You can try this notebook live by lauching it in Binder.This can take a while to launch, be patient. Binder.

First we import pandas, numpy and pandas_GUI and then create some data to fit.

In [1]:
import pandas as pd
from pandas_GUI import *
import numpy as np
X = [k*np.pi/10 for k in range(-30,30)]
Y = 98*np.sin(X)+np.random.default_rng().normal(0,3,60)
df = pd.DataFrame({'X':X, 'Y':Y})

Default plot of the data set¶

This is the plot made using the default settings of plot_pandas_GUI(). See step-by-step example.

In [2]:
# CODE BLOCK generated using plot_pandas_GUI().
# See https://jupyterphysscilab.github.io/jupyter_Pandas_GUI.
from plotly import graph_objects as go
Figure_1 = go.FigureWidget(layout_template="simple_white")

# Trace declaration(s) and trace formatting
scat = go.Scatter(x = df['X'], y = df['Y'],
        mode = 'lines', name = 'Noisy Sine',)
Figure_1.add_trace(scat)

# Axes labels
Figure_1.update_xaxes(title= 'X')
Figure_1.update_yaxes(title= 'Y')

# Plot formatting
Figure_1.update_layout(title = 'Noisy Sine Wave Default Plot', template = 'simple_white', autosize=True)
Figure_1.show(config = {'toImageButtonOptions': {'format': 'svg'}})
−8−6−4−202468−100−50050100
Noisy Sine Wave Default PlotXY
plotly-logomark

Figure 1: A plot of the noisy sine wave data. This should display a live plotly plot. If you are running a live notebook and do not see the plot make sure you have trusted the notebook (button near the kernel name and status).

Fit the data with a sine function¶

The fit was done by running the command fit_pandas_GUI() in an empty code cell.

1. On the first tab¶

the data set, which columns contained the X- and Y-data and a name for the trace were chosen.

Fit tab 1

2. On the second tab¶

the the default 'none' value was kept for uncertainties.

Fit_tab_2

3. On the third tab¶

the SineModel was chosen and all the boxes were left in their default state.

Fit_tab_3

4. The fourth tab was skipped¶

because we fit the whole range of data.

5. On the fifth tab¶

labels for the X and Y axis were input and the Display Mirror Axes box was checked.

Fit_tab_5

6. On the last (sixth) tab¶

the final checks were done and then the 'Do Fit' button was clicked, closing the GUI and running the code in the cell below to perform the fit and display the results.

Fit_tab_6

In [4]:
# CODE BLOCK generated using fit_pandas_GUI().
# See https://jupyterphysscilab.github.io/jupyter_Pandas_GUI.
# Integers wrapped in `int()` to avoid having them cast 
# as other types by interactive preparsers. 
# Imports (no effect if already imported)
import numpy as np
import lmfit as lmfit
import round_using_error as rue
import copy as copy
from plotly import graph_objects as go
from IPython.display import HTML, Math

# Define data and trace name
Xvals = df["X"]
Yvals = df["Y"]
tracename = "Noisy Sine"

# Define error (uncertainty)
Yerr = df["Y"]*0.0 + 1.0

# Define the fit model, initial guesses, and constraints
fitmod = lmfit.models.SineModel()
fitmod.set_param_hint("amplitude", vary = True, value = 99.19027781700053, min = 0.0)
fitmod.set_param_hint("frequency", vary = True, value = 0.9267698328089888, min = 0.0)
fitmod.set_param_hint("shift", vary = True, value = 0.0, min = -6.283195307179586, max = 6.283195307179586)

# Do fit
Fit_2 = fitmod.fit(Yvals, x=Xvals, weights = 1/Yerr, scale_covar = True, nan_policy = "omit")

# Calculate residuals (data - fit) because lmfit
#  does not calculate for all points under all conditions
resid = []
# explicit int(0) below avoids collisions with some preparsers.
for i in range(int(0),len(Fit_2.data)):
    resid.append(Fit_2.data[i]-Fit_2.best_fit[i])

# Plot Results
# explicit int(..) below avoids collisions with some preparsers.
Fit_2_Figure = go.FigureWidget(layout_template="simple_white")
Fit_2_Figure.update_layout(title = "Fit_2_Figure",autosize=True)
Fit_2_Figure.set_subplots(rows=int(2), cols=int(1), row_heights=[0.2,0.8], shared_xaxes=True)
scat = go.Scatter(y=resid,x=Xvals, mode="markers",name = "residuals")
Fit_2_Figure.update_yaxes(title = "Residuals", row=int(1), col=int(1), zeroline=True, zerolinecolor = "lightgrey")
Fit_2_Figure.add_trace(scat,col=int(1),row=int(1))
scat = go.Scatter(x=Xvals, y=Yvals, mode="markers", name=tracename)
Fit_2_Figure.add_trace(scat, col=int(1), row=int(2))
Fit_2_Figure.update_yaxes(title = "Y", row=int(2), col=int(1))
Fit_2_Figure.update_xaxes(title = "X", row=int(2), col=int(1))
scat = go.Scatter(y=Fit_2.best_fit,x=Xvals, mode="lines", name="fit", line_color = "black", line_dash="solid")
Fit_2_Figure.add_trace(scat,col=int(1),row=int(2))
Fit_2_Figure.show(config = {'toImageButtonOptions': {'format': 'svg'}})

# Display best fit equation
ampstr = ''
freqstr = ''
shiftstr = ''
for k in Fit_2.params.keys():
    if Fit_2.params[k].vary:
        if Fit_2.params[k].stderr:
            paramstr = r'({\color{red}{'+rue.latex_rndwitherr(Fit_2.params[k].value,
                                       Fit_2.params[k].stderr,
                                       errdig=int(1),
                                       lowmag=-int(3))+'}})'
        else:
            paramstr = r'{\color{red}{'+str(Fit_2.params[k].value)+'}}'
    else:
        paramstr = r'{\color{blue}{'+str(Fit_2.params[k].value)+'}}'
    if k == 'amplitude':
        ampstr = paramstr
    if k == 'frequency':
        freqstr = paramstr
    if k == 'shift' and Fit_2.params[k].value != 0.0:
        shiftstr = ' + ' + paramstr
fitstr = r'$fit = '+ampstr + 'sin[' + freqstr + 'x' + shiftstr + ']$'
captionstr = r'<p>Use the command <code>Fit_2</code> as the last line of a code cell for more details.</p>'
display(Math(fitstr))
display(HTML(captionstr))
−50510−10−50510−100−50050100
residualsNoisy SinefitFit_2_FigureXResidualsY
plotly-logomark
fit=(98.5±0.5)sin[(1.0002±0.0010)x+(−0.001±0.005)]fit=(98.5±0.5)sin[(1.0002±0.0010)x+(−0.001±0.005)]

Use the command Fit_2 as the last line of a code cell for more details.

Figure 2: The results of fitting the noisy sine data to using default settings. Alternative formatting of line styles, markers, etc... can be accessed by editing the code produced by the GUI. Overall plot styling can be adjusted on tab 5.

Learn More¶

In addition to trying it below if this is a live notebook, you can look at the other examples listed in the Pandas GUI website.

Try It¶

If you are running this notebook live in binder you can try it here by running the first cell to import the tools and create the data. Then run the cell below to create the GUI. Note: You may want to expand the collapsed instructions to learn more about each tab.

In [ ]:
fit_pandas_GUI()