0

I'm searching to plot multiple graphs (here is 2) from colormap or contourf functions with different axis X, Y and data Z in the same figure. However I only want to display the maximum of each data with a single color bar for all of the graphs.

In this example, I create a single figure in which I add each graph but the second graph overwrite the first one, regardless of whether its data are lower or higher.

import matplotlib.pyplot as plt
import numpy as np

a = [1,0.25]

fig = plt.figure(1)
ax = fig.gca()

for i in range(2):
    x = np.linspace(-3, 3, 51)
    y = np.linspace(-2*a[i], 2*a[i], 41)

    X, Y = np.meshgrid(x, y)
    if i == 0:
        Z = (1 - X/2 + X**5 + Y**3) * np.exp(-X**2 - Y**2)
    else:
        Z = 0.5*np.ones((41,51))

    graph = ax.contourf(X,Y,Z)  
    bar = fig.colorbar(graph)

plt.show()

Figure 1 displayed by the code

Here is what I want to display :

Figure 2 desired

Thank you a lot, Tristan

Tristan
  • 3
  • 2
  • Is it intentional that your y-values in the first iteration only go from -0.5 to 0.5 while your y-values in the second iteration go from -2 to 2? – eandklahn Dec 07 '21 at 19:31
  • Yes, It's to show that I can have graphs with different meshs and data. I can't simply calculate and compare to obtain a maximum Z and plot by X and Y because X and Y are not the same for each graph. – Tristan Dec 07 '21 at 19:51
  • Ok, so it seems to me that you want a belt over all x-values but with y between -0.5 and 0.5 where the graph either has the height 0.5 or the height of the Z-function, whichever has the largest Z-value. Is this correct? – eandklahn Dec 07 '21 at 20:24
  • Yes for this example but I would an answer that could fit any value of Z and X-Y scales. I add an image in my post about what I want, maded in paint. – Tristan Dec 07 '21 at 20:50

1 Answers1

0

According to the discussion we had in the comments to your post, I think you can edit your code to achieve what you want as below.

First, as a general comment, I suggest that you move your variables to the top of the script.

Second, and this is the main part, you can make do with plotting only one graph if you use comparisons to test which value to fill in your Z-array. You can chain several comparisons using np.logical_and and then use np.where to fill a Z-array with either the function values or the constant value, based on whether you are inside your desired box of x- and y-values and whether the function value or the desired constant value is largest.

fig = plt.figure()
ax = fig.gca()

xmin, xmax, nx = -3, 3, 51
ymin, ymax, ny = -2, 2, 41

# box values
xbmin, xbmax = -3, 3
ybmin, ybmax = -0.5, 0.5
zlevel = 0.5

x = np.linspace(xmin, xmax, nx)
y = np.linspace(ymin, ymax, ny)
X, Y = np.meshgrid(x,y)
Z = (1 - X/2 + X**5 + Y**3) * np.exp(-X**2 - Y**2)

test1 = Z<zlevel
test2 = np.logical_and(X>=xbmin, X<=xbmax)
test3 = np.logical_and(Y>=ybmin, Y<=ybmax)

mask = np.logical_and(np.logical_and(test1, test2), test3)
Z = np.where(mask, zlevel*np.ones(Z.shape), Z)

graph = ax.contourf(X,Y,Z)
bar = fig.colorbar(graph)

plt.show()
eandklahn
  • 537
  • 4
  • 8
  • Thank you E.Klahn for your answer of my question. This answer works on this example but I can't implement this method in my project because I have too much graphs to overlay and compare. I was hopping that matplotlib would have the ability to nest all the data into each other to get the maximum out of them. I also try an other method to draw 3d plot and take a view from above but 3d graph are displayed badly on matplotlib unlike other tools as in Matlab where everything is done cleanly. – Tristan Dec 07 '21 at 22:34
  • But do you think that this method should work with n graphs and n groups of data(x,y,X,Y,Z) that we all compare with each other ? – Tristan Dec 07 '21 at 22:58
  • Something like this could be modified to work for n graphs, yes. But it depends on what you want. If you have multiple functions, would you like that it is always the maximum value that is kept when comparing two functions? Do you want the ability to add many of these square areas with a constant height? These things could certainly be done, but there are some choices to be made then. – eandklahn Dec 07 '21 at 23:58
  • Imagine several independant waves of which I wish to have a top view on the same figure (so with the same axis and color bar). Then yes I want to keep always the maximum values when comparing two functions. This square area with a constant height was just an example. In my project I want to display that top view (in 2D) of the maximum of several (n) complicated functions. I can show you what I have done on Matlab to understand what I'm trying to do. – Tristan Dec 08 '21 at 01:55
  • What you can do in that case is to make an array (we'll call that A) of shape (nx, ny, N), where N is the number of graphs you want to compare. Then fill the array with your functions, so that the first function (we can call that Z0) goes to [:,:,0], Z1 goes to [:,:,1] in the array, and so on. Finally, compare all arrays by calculating Z = np.amax(A, axis=2). – eandklahn Dec 08 '21 at 10:01
  • But this is not correct to compare 2 Z functions with different coordinates (X, Y). I have a n surfaces with its own X, Y and Z and I want to draw a top view of these surfaces. I really don't know how we could do it by comparisons. – Tristan Dec 08 '21 at 21:33
  • If you use `test1` in my answer here, you can replace `z_level` with your other Z-values, and xbmin, xbmax, ybmin and ybmax are then the values within which you want to replace the new Z-values if they are larger than the first ones. Then you do that for all of your N functions. – eandklahn Dec 08 '21 at 21:53
  • But I can't compare the element Z1[i] from coordinates (x1[i],y1[i]) with an element Z2[i] from coordinates (x2[i],y2[i]) where x1 is not equal to x2, and the same for y1 and y2. – Tristan Dec 08 '21 at 22:17
  • That is true. You would have to define a common grid to calculate the functions on. But then you can use `test2` and `test3` to only fill the parts of the array with Z2 where you actually want Z2 appearing. – eandklahn Dec 09 '21 at 12:33