Home > Software design >  Find the point at which a curve touches the X axis
Find the point at which a curve touches the X axis

Time:11-30

I have the following plot made with some data points,Plot. What is the best Pythonic way to find the point through which the curve intersects the X-axis? Thanks for any help.

-2.0   -2.22537043
-1.9   -2.22609532
-1.8   -2.22075396
-1.7   -2.22729678
-1.6   -2.22353721
-1.5   -2.22341588
-1.4   -2.2180032
-1.3   -2.22850037
-1.2   -2.22553919
-1.1   -2.22866368
-1.0   -2.22400234
-0.9   -2.22865694
-0.8   -2.22058969
-0.7   -2.22399086
-0.6   -2.20372207
-0.5   -2.22639477
-0.4   -2.10633351
-0.3   -2.03573848
-0.2   -1.52582935
-0.1   -0.344812049
0.0     1.61330696
0.1     2.21013059
0.2     2.22698993
0.3     2.22698993
0.4     2.22698993
0.5     2.22698993
0.6   2.22698993
0.7   2.21522144
0.8   2.22699297
0.9   2.22361681
1.0   2.22055266
1.1   2.22299154
1.2   2.21155482
1.3   2.22212628
1.4   2.22437687
1.5   2.22365865
1.6   2.21749658
1.7   2.22603657
1.8   2.22736
1.9   2.22471317
2.0   2.22724296

Update: Here is the data point. How I'm finding it now? I take my mouse to the plot window and find the point manually, why it is not working? It is slow.

CodePudding user response:

There is really not enough information given in this question to solve the problem outright. That said, if I understand correctly, you perhaps are looking to see where any two functions (line or curve) are intersecting.

There are a few approaches. The most simple I'd say would be to use robust curve intersection approach such as this implementation by plot showing sigmoid and sine wave functions and their intersection points

Edit (#2 to solve for x at y=0)

I do not have the reputation to comment on the original post, but will mention this sounds instead like a root finding problem.

For completeness, here's a rework of the same approach using the data supplied by OP. The intersecting line in this case is a line spanning the min/max of x1 where . Essentially, this is now a graphical look at finding the roots.

from intersect import intersection
import matplotlib.pyplot as plt
import numpy as np

data = np.array(
    [
        [-2.0, -2.22537043],
        [-1.9, -2.22609532],
        [-1.8, -2.22075396],
        [-1.7, -2.22729678],
        [-1.6, -2.22353721],
        [-1.5, -2.22341588],
        [-1.4, -2.2180032],
        [-1.3, -2.22850037],
        [-1.2, -2.22553919],
        [-1.1, -2.22866368],
        [-1.0, -2.22400234],
        [-0.9, -2.22865694],
        [-0.8, -2.22058969],
        [-0.7, -2.22399086],
        [-0.6, -2.20372207],
        [-0.5, -2.22639477],
        [-0.4, -2.10633351],
        [-0.3, -2.03573848],
        [-0.2, -1.52582935],
        [-0.1, -0.344812049],
        [0.0, 1.61330696],
        [0.1, 2.21013059],
        [0.2, 2.22698993],
        [0.3, 2.22698993],
        [0.4, 2.22698993],
        [0.5, 2.22698993],
        [0.6, 2.22698993],
        [0.7, 2.21522144],
        [0.8, 2.22699297],
        [0.9, 2.22361681],
        [1.0, 2.22055266],
        [1.1, 2.22299154],
        [1.2, 2.21155482],
        [1.3, 2.22212628],
        [1.4, 2.22437687],
        [1.5, 2.22365865],
        [1.6, 2.21749658],
        [1.7, 2.22603657],
        [1.8, 2.22736],
        [1.9, 2.22471317],
        [2.0, 2.227242961]
    ]
)
x1, y1 = data[:, 0], data[:, 1]

x2 = [np.min(x1), np.max(x1)]
y2 = [0, 0]

x, y = intersection(x1, y1, x2, y2)

plt.plot(x1, y1, c="r")
plt.plot(x2, y2, c="g")
plt.plot(x, y, "*k")
plt.show()

plot showing OP's data and intersection of a line at y=0

CodePudding user response:

I don't know if there is anything standard in matplotlib, but the below algorithm in a loop

  1. Find xi where y[xi] > 0. Call that location i.
  2. If y[xi - 1] == 0, don't continue - its an x intercept add it to the array, else
  3. Compute the slope -> y2 - y1 / x2 -x1.
  4. Plugin an (x0, y0) pair to solve for the intercept.
  5. Solve for the x, instead of the y.

can compute those values.

import numpy as np
values = np.loadtxt(r"test.txt", delimiter=" ")
x_intercepts = []
for i, v in enumerate(values):
    if i > 0:
        # if y > 0
        if v[1] > 0:
            previous_v = values[i - 1]
            # if the previous y == 0
            if previous_v[1] == 0:
                x_intercepts.append(previous_v[0])
            elif previous_v[1] < 0:
                # slope = y2 - y1 / x2 - x1
                # formula of linear equation -> y = mx   b
                # intercept -> b = y - m(x)
                slope = (v[1] - previous_v[1]) / (v[0] - previous_v[0])
                # if the slope is changing and not a constant
                if slope != 0:
                    intercept = v[1] - (slope * v[0])
                    # equation -> y = (slope * x)   intercept
                    # equation -> y - intercept = (slope * x)
                    # equation -> (y - intercept) / slope = x
                    x_intercept = (0 - intercept) / slope
                    x_intercepts.append(x_intercept)
        else:
            # if the if doesn't make it, we still need to check if the previous value was 0
            if values[i - 1][1] == 0:
                x_intercepts.append(values[i - 1][0])
print(x_intercepts)

Give this a whirl and let me know how it works for you.


Explanation

  • The for loop gives us the index (i) of the current value v.
  • We want to be able to use the current value as the pair (x2, y2) and the previous value as (x1, y1), so I check to make sure we aren't on the first iteration with if i > 0:
  • If y2 < 0 (the only else statement), check if y1 is == to 0 -> if so add it as an x intercept.
  • If y2 > 0, check if y1 is == to 0 -> if so add it as an x intercept.
  • If its not, check if it is less than 0.
  • Compute the slope and check if the slope is not 0 -> we want to avoid a division by 0 error.
  • Compute the y intercept.
  • Solve for the x intercept and add it to the list of x intercepts.
  • Related