I have a code that plots data from a text file. I have been able to get the integrals under each data curve (although I do not know the functions for any of them, so I just used integral = s = simps(y, x)
). Two of the curves overlap horizontally, and I would like to find the area between where they overlap. I am having some trouble with this since they overlap horizontally rather than vertically. The area I would like to find is between the red and blue lines on this graph. The data are in numpy arrays, for example bx
and by
for the blue lines x and y, and rx
and ry
for the red lines x and y. I have no function to represent them but they are in those arrays. It is hard to know how to proceed because they overlap horizontally rather than vertically.
I'm pretty stuck on this, any help would be greatly appreciated!
Update: The code provided by JohanC has worked in one case but not another. The non-working plot initially looks like this (I want the area only of that middle overlapping area), but when that did not work either, I had tried limiting the x range to hopefully help the code narrow in on the area where I would like the overlapping integral to be calculated (that is where that plot with the smaller range came from). The code I am currently using is the one JohanC provided and looks like this:
def get_overlap_integral(bx, by, rx, ry):
fig, ax = plt.subplots()
ax.plot(bx, by, color='b')
ax.plot(rx, ry, color='r')
# create a common x range
gx = np.linspace(min(bx.min(), rx.min()), max(bx.max(), rx.max()), 1000)
gby = np.interp(gx, bx, by) # set bx,by onto the common x range
gry = np.interp(gx, rx, ry) # set rx,ry onto the common x range
gy = np.minimum(gby, gry) # let gx,gy be the intersection of the two curves
ax.fill_between(gx, gy, color='g', alpha=0.3)
area = np.trapz(gy, gx) # calculate the green area
ax.text(0.05, 0.95, f'Overlap: {area:.3f}', color='g', ha='left', va='top', transform=ax.transAxes)
plt.show()
return area
The text bx, by, rx, and ry are values such as these:
BX: [999.5 999. 998.5 ... 201. 200.5 200. ]
BY: [-3.786867e-05 -4.366451e-05 -4.745308e-05 ... 1.068685e-05 1.555391e-05
-8.949840e-06]
RX: [999.5 999. 998.5 ... 201. 200.5 200. ]
RY: [-5.865443e-05 -7.808241e-05 -5.887286e-05 ... -1.556630e-06 -3.473830e-06
-6.367470e-06]
I am not sure why this function will not work for one case but will work perfectly for another. Any help would be greatly appreciated!
np.interp(new_x, old_x, old_y)
can calculate a curve for a new x range. When set on a common x range, np.minimum
finds the common area of two positive-valued curves. np.trapz
calculates the area.
Here is some example code, starting with the creation of test data:
from matplotlib import pyplot as plt
import numpy as np
# create some test data
Nb = 300
bx = np.linspace(320, 750, Nb)
by = np.random.randn(Nb).cumsum()
by -= by[0] # start at zero
by -= np.linspace(0, 1, Nb) * by[-1] # let end in zero
by = (by ** 2) ** .3 # positive curve starting and ending with zero
Nr = 200
rx = np.linspace(610, 1080, Nr)
ry = np.random.randn(Nr).cumsum()
ry -= ry[0] # start at zero
ry -= np.linspace(0, 1, Nr) * ry[-1] # let end in zero
ry = (ry ** 2) ** .3 # positive curve starting and ending with zero
fig, ax = plt.subplots()
ax.plot(bx, by, color='b')
ax.plot(rx, ry, color='r')
# create a common x range
gx = np.linspace(min(bx.min(), rx.min()), max(bx.max(), rx.max()), 1000)
gby = np.interp(gx, bx, by) # set bx,by onto the common x range
gry = np.interp(gx, rx, ry) # set rx,ry onto the common x range
gy = np.minimum(gby, gry) # let gx,gy be the intersection of the two curves
ax.fill_between(gx, gy, color='g', alpha=0.3)
area = np.trapz(gy, gx) # calculate the green area
ax.text(0.05, 0.95, f'Overlap: {area:.3f}', color='g', ha='left', va='top', transform=ax.transAxes)
plt.show()