0

I currently have a curve defined by (x_orig, y_orig), and I want to plot the shaded region between two new curves defined by (x_orig - c, y_orig) and (x_orig + c, y_orig). When using matplotlib's fill_betweenx(), it does most of what I want, except when the two curves have opposite signs of their slope, they cross each other and there is nothing filled between them. I actually want the full space between the two filled. Imagine you grab the line (x_orig - c, y_orig) and drag it to the right to (x_orig + c, y_orig), I want to shade all of that area. I want to find the points that define the upper and lower shaded region so that I can additionally mask scatter points that happen to be in there.

I originally wrote an overcomplicated function that mostly does what I want, but it doesn't correctly handle the areas where the lines switch slope. Is there a more "pythonic" way of doing something that I want that isn't needlessly complicated?

def shaded_region(x_left, x_right, y_left, y_right):
    y_upper = []
    y_lower = []
    y_lower.append(y_left[0])
    y_upper.append(y_left[0])
    #
    s = np.sign((y_left[1] - y_left[0]))
    #
    x_new = []
    x_new.append(x_left[0])
    #
    for i in range(0, len(x_left)-1):
        m = (y_left[i+1] - y_left[i])
        s_new = np.sign(m)
        #
        if s_new == s:
            if m < 0:
                y_upper.append(y_left[i])
                y_lower.append(y_left[i+1])
            if m > 0:
                y_upper.append(y_left[i+1])
                y_lower.append(y_left[i])
            x_new.append((x_left[i+1]+x_right[i])/2)
        else:
            p1 = np.array([x_left[i+1], y_left[i+1]])
            p2 = np.array([x_left[i], y_left[i]])
            p3 = np.array([x_right[i], y_right[i]])
            p4 = np.array([x_right[i-1], y_right[i-1]])
            #
            # print(i)
            # print(p1,p2,p3,p4)
            intersection = seg_intersect(p1, p2, p3, p4)
            x_new.append(intersection[0])
            #
            if (s_new > 0) and (s < 0):
                y_upper.append(intersection[1])
                y_lower.append(np.min((y_right[i], y_right[i-1])))
                dx = (intersection[0]-x_left[i])
                x_new.append(intersection[0]+dx)
                y_upper.append(y_left[i+1])
                y_lower.append(y_left[i])
            if (s_new < 0) and (s > 0):
                y_upper.append(np.max((y_right[i+1], y_right[i])))
                y_lower.append(intersection[1])
                dx = (intersection[0]-x_left[i])
                x_new.append(intersection[0]+dx)
                y_upper.append(y_right[i])
                y_lower.append(y_right[i+1])
        #
        s = s_new
    y_upper.append(y_left[-1])
    y_lower.append(y_left[-1])
    x_new.append(x_right[-1])
    #
    return x_new, y_lower, y_upper

I'm attaching a figure that shows the results from fill_betweenx() to show the additional area I want to shade.

enter image description here

4
  • Do you definitely want an x-offset and not a y-offset? Commented Mar 3, 2024 at 1:20
  • Unfortunately, I do. I'm accounting for an predicted error in the x-property, and I want to shade the area that shows the +/- error. Commented Mar 3, 2024 at 1:44
  • It's not clear what should be below the curve. Should it not be a straight line connecting the cusps of the two shaded regions? Commented Mar 3, 2024 at 2:17
  • Yes, I want it to be a straight line with that triangle area shaded as well. So if you were to drag the curve from left to right, I want the whole area shaded in the plot. If I could find all the points of the cusps that define the shaded area I want, which is what I was trying to do, then I can just use the regular fill_between to do it, I think Commented Mar 3, 2024 at 2:22

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.