pythonnumpymatplotlibcontour

Sum of functions on one contour plot


There is contour plot where I would like figure sum of three functions. These are same function but difference only in coordinates and separately every function works properly but when I trying get sum of these - plot cuts points which not a common for all this plot.

Maybe problem in mask function?

import numpy as np
import matplotlib.pyplot as plt

xx = np.linspace(-200, 200, 200)
yy = np.linspace(-200, 200, 200)
X, Y = np.meshgrid(xx, yy)        

r1 = np.sqrt(np.square(X) + np.square(Y))
r2 = np.sqrt(np.square(20 - X) + np.square(20 - Y))
r3 = np.sqrt(np.square(-40 - X) + np.square(40 - Y))

# Function with coordinates 1
Z1 = 3 * (r1/100)**4 - 8 * (r1/100)**3 + 6 * (r1/100)**2
Z1 = np.ma.array(Z1, mask=r1>=100)

# Function with coordinates 2
Z11 = 3 * (r2/100)**4 - 8 * (r2/100)**3 + 6 * (r2/100)**2
Z11 = np.ma.array(Z11, mask=r2>=100)

# Function with coordinates 3
Z21 = 3 * (r3/100)**4 - 8 * (r3/100)**3 + 6 * (r3/100)**2
Z21 = np.ma.array(Z21, mask=r3>=100)

#Sum of functions
Z01 = Z1 + Z11 + Z21

cs = plt.contour(X, Y, Z01, 20, cmap=plt.cm.YlGn_r, levels = 10, extend='max')
cs2 = plt.contourf(X, Y, Z01, 20,cmap=plt.cm.YlOrBr, levels = 10, extend='max')

plt.clabel(cs2)
plt.clabel(cs, fontsize=10, colors=plt.cm.Reds(cs.norm(cs.levels)))
plt.colorbar(cs2)
plt.grid(which='major')
plt.title('Contours Plot')
plt.xlabel('X (m)')
plt.ylabel('Y (m)')
plt.xlim([0, 200])
plt.ylim([0, 200])
plt.axis('scaled')

plt.tight_layout()
plt.show()

This example plot with one function (#1) enter image description here

This example with sum of function (I expect that its laying on each other and sum results)

enter image description here


Solution

  • The problem are not the points that the functions do not have in common. The problem are the points where none of the function have a value that is not masked out. You can print the masked arrays and see that for example all the values at the beginning and end are masked out for all three functions.

    As you sum the three functions, you can just set the values to 0 instead of masking them out. This makes sure that there is always a defined value for each point that can be plotted.

    # Function with coordinates 1
    Z1 = 3 * (r1/100)**4 - 8 * (r1/100)**3 + 6 * (r1/100)**2
    Z1[r1 >= 100] = 0
     
    # Function with coordinates 2
    Z11 = 3 * (r2/100)**4 - 8 * (r2/100)**3 + 6 * (r2/100)**2
    Z11[r2 >= 100] = 0
    
    # Function with coordinates 3
    Z21 = 3 * (r3/100)**4 - 8 * (r3/100)**3 + 6 * (r3/100)**2
    Z21[r3 >= 100] = 0