Show interception values, matplotlib

I'm ploting some curves Imax vs Ciclo de servicio for several frequencies.

To do that I'm making two nested sweeps for the independent variables, Fs and Vo

Although equations are a bit more complex I'm basically doing this:

for Fs in np.linspace(70e3,200e3,4):
    Vo_sweep = np.linspace(0,1,1000)
     delta_I = [I_max(Vo) for Vo in Vo_sweep]
     plt.plot(Vo_sweep,delta_I)

enter image description here

And I'm particularly interested in the point where 'ciclo de servicio' is 0.71.

How Can I show the value 0.71 in the X axes and Y value of the interception of the blue line with each curve

Upvotes: 1

Views: 1540

Answers (1)

armatita
armatita

Reputation: 13465

If you want to plot your interception markers using arbitrary data (whatever your functions and vertical lines might be) I would advise that you calculate the intersection points (where they exist). A few months ago I gave an answer that might be useful to you. You can check it here.

Adapting a similar solution to your problem:

import numpy as np
import matplotlib.pyplot as plt

def line_intersection(line1, line2):
    xdiff = (line1[0][0] - line1[1][0], line2[0][0] - line2[1][0])
    ydiff = (line1[0][1] - line1[1][1], line2[0][1] - line2[1][1]) #Typo was here

    def det(a, b):
        return a[0] * b[1] - a[1] * b[0]

    div = det(xdiff, ydiff)
    if div == 0:
        return None

    d = (det(*line1), det(*line2))
    x = det(d, xdiff) / div
    y = det(d, ydiff) / div
    return x, y

def near(a, b, rtol=1e-5, atol=1e-8):
    return abs(a - b) < (atol + rtol * abs(b))
def crosses(line1, line2):
    """
    Return True if line segment line1 intersects line segment line2 and 
    line1 and line2 are not parallel.
    """
    (x1,y1), (x2,y2) = line1
    (u1,v1), (u2,v2) = line2
    (a,b), (c,d) = (x2-x1, u1-u2), (y2-y1, v1-v2)
    e, f = u1-x1, v1-y1
    denom = float(a*d - b*c)
    if near(denom, 0):
        # parallel
        return False
    else:
        t = (e*d - b*f)/denom
        s = (a*f - e*c)/denom
        # When 0<=t<=1 and 0<=s<=1 the point of intersection occurs within the
        # line segments
        return 0<=t<=1 and 0<=s<=1


for Fs in np.linspace(70e3,200e3,4):
    Vo_sweep = np.linspace(0,1,1000)
    delta_I = [i*Fs*np.log((i+1.1)/10) for i in range(len(Vo_sweep))] #[I_max(Vo) for Vo in Vo_sweep]
    plt.plot(Vo_sweep,delta_I)

plt.vlines(0.71,min(delta_I),max(delta_I))

for Fs in np.linspace(70e3,200e3,4):
    x = np.linspace(0,1,1000)
    y = [i*Fs*np.log((i+1.1)/10) for i in range(len(Vo_sweep))]
    for i in range(1,len(delta_I)):
        p1 = np.array([x[i-1],y[i-1]],dtype='float')
        p2 = np.array([x[i],y[i]],dtype='float')
        k1 = np.array([0.71,min(delta_I)],dtype='float')
        k2 = np.array([0.71,max(delta_I)],dtype='float')
        if crosses((p2,p1),(k1,k2)):
            seg = line_intersection((p2,p1),(k1,k2))
            plt.scatter(seg[0],seg[1],c='red',s=90)
            print(seg)

plt.ylim(min(delta_I),max(delta_I))
plt.xlim(0,1)

plt.show()

, which results in this:

Plots markers intercepts matplotlib

This particular recipe is also printing the interception coordinate if that might be of interest to you:

(0.70999999999999985, 211670610.06954533)
(0.70999999999999985, 342704797.25546497)
(0.70999999999999985, 473738984.44138455)
(0.70999999999999985, 604773171.62730408)

Since you didn't provided the data I had to make a fast synthetic one but It should be as easy as replacing by your I_max() function in the definition of delta_I.

Upvotes: 2

Related Questions