Show Sidebar Hide Sidebar

Peak Fitting in Python

Learn how to fit to peaks in Python

New to Plotly?

Plotly's Python library is free and open source! Get started by downloading the client and reading the primer.
You can set up Plotly to work in online or offline mode, or in jupyter notebooks.
We also have a quick-reference cheatsheet (new!) to help you get started!

Imports

The tutorial below imports NumPy, Pandas, SciPy and PeakUtils.

In [1]:
import plotly.plotly as py
import plotly.graph_objs as go
from plotly.tools import FigureFactory as FF

import numpy as np
import pandas as pd
import scipy
import peakutils

from scipy import signal

Import Data

Let us import some stock data for our fitting:

In [2]:
stock_data = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/stockdata.csv')
df = stock_data[0:15]

table = FF.create_table(df)
py.iplot(table, filename='stockdata-peak-fitting')
Out[2]:

Original Plot

Let us plot the SBUX column of the data and highlight a section we will fit to:

In [3]:
left_endpt=1857
right_endpt=1940

original_trace = go.Scatter(
    x = [j for j in range(len(stock_data['SBUX']))],
    y = stock_data['SBUX'][0:left_endpt].tolist() + [None for k in range(right_endpt - left_endpt)] +
        stock_data['SBUX'][right_endpt + 1:len(stock_data['SBUX'])].tolist(),
    mode = 'lines',
    name = 'Full Data',
    marker = dict(color = 'rgb(160,200,250)')
)

highlighted_trace = go.Scatter(
    x = [j for j in range(left_endpt, right_endpt)],
    y = stock_data['SBUX'][left_endpt:right_endpt],
    mode = 'lines',
    name = 'Highlighted Section',
    marker = dict(color = 'rgb(0,56,210)')
)

data = [original_trace, highlighted_trace,]
py.iplot(data, filename='stock-data-SBUX')
Out[3]:

Peak Detection

Before we are able to apply Peak Fitting we need to detect the peaks in this waveform to properly specify a peak to fit to.

In [5]:
x = [j for j in range(len(stock_data))][left_endpt:right_endpt]
y = stock_data['SBUX'][left_endpt:right_endpt]
y = y.tolist()

cb = np.array(y)
indices = peakutils.indexes(cb, thres=0.75, min_dist=0.1)

trace = go.Scatter(
    x=x,
    y=y,
    mode='lines',
    marker=dict(
        color='rgb(0,56,210)'
    ),
    name='Highlighted Plot'
)

trace2 = go.Scatter(
    x=indices + left_endpt,
    y=[y[j] for j in indices],
    mode='markers',
    marker=dict(
        size=8,
        color='rgb(255,0,0)',
        symbol='cross'
    ),
    name='Detected Peaks'
)

data = [trace, trace2]
py.iplot(data, filename='stock-data-with-peaks')
Out[5]:

Peak Fitting

Since we have detected all the local maximum points on the data, we can now isolate a few peaks and superimpose a fitted gaussian over one.

In [6]:
def gaussian(x, mu, sig):
    return np.exp(-np.power(x - mu, 2.) / (2 * np.power(sig, 2.)))

first_index = indices[6]
left_gauss_bound = 1894
right_gauss_bound = 1910

x_values_1 = np.asarray(x[left_gauss_bound-left_endpt:right_gauss_bound-left_endpt])
y_values_1 = np.asarray(y[left_gauss_bound-left_endpt:right_gauss_bound-left_endpt])

gaussian_params_1 = peakutils.gaussian_fit(x_values_1, y_values_1, center_only=False)
gaussian_y_1 = [gaussian(x_dummy, gaussian_params_1[1], 1.5) for x_dummy in x_values_1]

trace = go.Scatter(
    x=x,
    y=y,
    mode='lines',
    marker=dict(
        color='rgb(0,56,210)'
    ),
    name='Highlighted Plot'
)

trace2 = go.Scatter(
    x=indices + left_endpt,
    y=[y[j] for j in indices],
    mode='markers',
    marker=dict(
        size=8,
        color='rgb(255,0,0)',
        symbol='cross'
    ),
    name='Detected Peaks'
)

trace3 = go.Scatter(
    #x=x_values_1,
    x=[item_x + 1.5 for item_x in x_values_1],
    y=[item_y + 38.2 for item_y in gaussian_y_1],
    mode='lines',
    marker=dict(
        size=2,
        color='rgb(200,0,250)',
    ),
    name='Gaussian Fit'
)

data = [trace, trace2, trace3]
py.iplot(data, filename='stock-data-with-peaks-and-fit')
Out[6]:
Still need help?
Contact Us

For guaranteed 24 hour response turnarounds, upgrade to a Developer Support Plan.