Mirko
Mirko

Reputation: 773

Find Inflection and Stationary points in a numpy 1d-array

Lets assume I have the following numpy array:

import numpy as np
import matplotlib.pyplot as plt
x = np.array([11.53333333, 11.86666667, 11.1, 10.66666667, 11.2, 11.3,
              11.06666667, 12.06666667, 11.8, 13.03333333, 12.4,
              12.33333333, 12.53333333, 13.33333333, 12.43333333, 13., 13.2,
              13.76666667, 14.96666667, 19.16666667, 25.1, 32.,
              83.33333333, 103.76666667, 110.7, 118.63333333, 129.26666667,
              139.06666667, 150.3, 161.53333333, 171.16666667, 184.56666667,
              196.6, 210.26666667, 221.63333333, 231.3, 244.16666667,
              253.5, 254.66666667, 255., 255., 255., 255.,
              255., 255., 255., 255., 255., 255.,
              255., 255., 255., 255., 255., 255.,
              255., 255., 255., 255., 255.])

plt.plot(x)
plt.show()

Here's the plotted output:

plotted x

How can I easily get the turning points in this graph? For example the first turning point is round about at x=20, another one at x=37.

Is it possible to get all turning points in an descending order, so I can afterwards grab the 3 most destinctive turning points?


Update: I am interested in getting the Inflection Points as well as the Stationary points. Is there a simple solution in numpy / scipy?

Upvotes: 4

Views: 21819

Answers (2)

Fidel Castro
Fidel Castro

Reputation: 29

I was looking for this answer too. This is one way how to find inflection point in python:

How to find the inflection point in a noisy curve?

The inflection point is [x0, y0]

#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
import matplotlib.pyplot as plt
import numpy as np
from scipy.ndimage import gaussian_filter


def generate_fake_data():
    """Generate data that looks like an example given."""
    xs = np.arange(0, 25, 0.05)
    ys = - 20 * 1./(1 + np.exp(-(xs - 5.)/0.3))
    m = xs > 7.
    ys[m] = -20.*np.exp(-(xs - 7.)[m] / 5.)

    # add noise
    ys += np.random.normal(0, 0.2, xs.size)
    return xs, ys


def main():
    xs, ys = generate_fake_data()

    # smooth out noise
    smoothed = gaussian_filter(ys, 3.)

    # find the point where the signal goes above the background noise
    # level (assumed to be zero here).
    base = 0.
    std = (ys[xs < 3] - base).std()
    m = smoothed < (base - 3. * std)
    x0 = xs[m][0]
    y0 = ys[m][0]

    plt.plot(xs, ys, '.')
    plt.plot(xs, smoothed, '-')
    plt.plot(x0, y0, 'o')
    plt.show()


if __name__ == '__main__':
    main()

Example output of how to find inflection point in python

Upvotes: 2

gabe
gabe

Reputation: 2511

There are many possible answers -- depending what you actually want. One idea would be to smooth the data by taking moving averages or splines or something and then take the second derivative and look for when it changes sign. This would find approximate "inflection points" or "turning points" -- literally, it would find when the concavity changes.

See:

Upvotes: 2

Related Questions