Michael G
Michael G

Reputation: 41

How can I find the intersection of two lines more efficiently? (nested for loops in Python)

I need to find the intersection point of two data sets, as illustrated here:

Data plot

I have used the nested loops below to achieve this, but it takes impractically long to run for a dataframe with more (~1000) rows. How can I do this more efficiently?

For clarity, here is a screenshot of the CSV used in the example (len=20):

CSV

import pandas as pd

data = pd.read_csv("Less_Data.csv")

#Intersection of line A (points 1 & 2) and line B (points 3 & 4)
def findIntersection(x1,y1,x2,y2,x3,y3,x4,y4):
    px= (( (x1*y2-y1*x2)*(x3-x4)-(x1-x2)*(x3*y4-y3*x4) )
      / ( (x1-x2)*(y3-y4)-(y1-y2)*(x3-x4) ))
    py= (( (x1*y2-y1*x2)*(y3-y4)-(y1-y2)*(x3*y4-y3*x4) )
      / ( (x1-x2)*(y3-y4)-(y1-y2)*(x3-x4) ))
    return [px, py]

#Find intersection of two series
intersections = {}
error_x = {}
error_y = {}
count = 0
print('All intersections found:')

for i in range(len(data)):
    i_storage_modulus = data.iloc[i]['Storage_Modulus_Pa']
    i_storage_stress = data.iloc[i]['Storage_Oscillation_Stress_Pa']
    for j in range(len(data)):
        j_storage_modulus = data.iloc[j]['Storage_Modulus_Pa']
        j_storage_stress = data.iloc[j]['Storage_Oscillation_Stress_Pa']
        if i == j + 1:
            for k in range(len(data)):
                k_loss_stress = data.iloc[k]['Loss_Oscillation_Stress_Pa']
                k_loss_modulus = data.iloc[k]['Loss_Modulus_Pa']
                for l in range(len(data)):
                    l_loss_stress = data.iloc[l]['Loss_Oscillation_Stress_Pa']
                    l_loss_modulus = data.iloc[l]['Loss_Modulus_Pa']
                    if k == l + 1:
                        if (max(k_loss_modulus, l_loss_modulus)
    <= min(i_storage_modulus, j_storage_modulus)):
                            continue
                        else:
                            sample_intersect = findIntersection(i_storage_stress,
                                                 i_storage_modulus,
                                                 j_storage_stress,
                                                 j_storage_modulus,
                                                 k_loss_stress,
                                                 k_loss_modulus,
                                                 l_loss_stress,
                                                 l_loss_modulus)
                            if (min(i_storage_stress, j_storage_stress)
              <= sample_intersect[0]
              <= max(i_storage_stress, j_storage_stress)):
                                if (min(k_loss_stress, l_loss_stress)
               <= sample_intersect[0]
               <= max(k_loss_stress, l_loss_stress)):
                                      print(sample_intersect)
                                      intersections[count] = sample_intersect
                                      error_x[count] = ([i_storage_stress,
                                                 j_storage_stress,
                                                 k_loss_stress,
                                                 l_loss_stress])
                                      error_y[count] = ([i_storage_modulus,
                                                 j_storage_modulus,
                                                 k_loss_modulus,
                                                 l_loss_modulus])
                                      count += 1

#Determine error bars
min_x_poss = []
max_x_poss = []
for i in error_x[0]:
    if i < intersections[0][0]:
        min_x_poss.append(i)
    if i > intersections[0][0]:
        max_x_poss.append(i)
x_error = (min(max_x_poss) - max(min_x_poss)) / 2

min_y_poss = []
max_y_poss = []
for i in error_y[0]:
    if i < intersections[0][1]:
        min_y_poss.append(i)
    if i > intersections[0][1]:
        max_y_poss.append(i)
y_error = (min(max_y_poss) - max(min_y_poss)) / 2

#Print results
print('\n', 'Yield Stress: ' + str(int(intersections[0][0])) + ' ± ' +
      str(int(x_error)) + ' Pa (' +
      str(int(x_error*100/intersections[0][0]))+'%)')
print('\n', 'Yield Modulus: ' + str(int(intersections[0][1])) + ' ± ' +
      str(int(y_error)) + ' Pa (' +
      str(int(y_error*100/intersections[0][1]))+'%)')

Upvotes: 0

Views: 771

Answers (1)

jsmart
jsmart

Reputation: 3001

Can you create a new function y = (Storage Modulus - Loss Modulus) vs Oscillation Stress? The point of intersection is where y changes sign from positive to negative. The secant method should find this point in a few iterations.
https://en.wikipedia.org/wiki/Secant_method

Upvotes: 1

Related Questions