0

I could not remotely figure out how to define a plot over a triangular region in matplotlib. That is the first problem I have.

As a workaround, I thought to define the function using a conditional expression, to avoid problems where the function is not defined.

def f(x,y):
    for a in x:
        for b in y:
            if a>b:
                g = log(a-b)
            else:
                g = 0
     return  

 x = np.linspace(0.1, 1000, 30)
 y = np.linspace(0.1, 3, 30)

 X, Y = np.meshgrid(x, y)
 Z = f(X, Y)

but I get the error message

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

which at least made me understand (sort of) what meshgrid does.

To summarise:

1) what is the neatest way to plot a function over a triangle?

2) what is the advantages of plotting over a meshgrid, instead of defining a single array as ([X1,Y1], [X1,Y2], ..., [X1,YN], [X2, Y1], [X2, Y2], ..)?

Thanks a lot

user37292
  • 248
  • 2
  • 12
  • It really depends on what kind of data you start with and what you want to show. The easiest by far is probably to a scatter plot `ax.scatter(x,y,c=z)`. If interested in a contour plot instead, read https://stackoverflow.com/questions/42045921/why-does-pyplot-contour-require-z-to-be-a-2d-array – ImportanceOfBeingErnest Dec 15 '19 at 01:31
  • @ImportanceOfBeingErnest, thanks for the comment and the reference. I am interested in a surface plot, and from what I understood, the triangulation option is not directly applicable. – user37292 Dec 15 '19 at 20:03
  • 1
    There is [`plot_trisurf`](https://matplotlib.org/tutorials/toolkits/mplot3d.html#tri-surface-plots) – ImportanceOfBeingErnest Dec 15 '19 at 20:11

1 Answers1

2

The problem that you encounter is using a normal Python function for NumPy arrays. This does not work always as expected, especially when you use conditionals like <. You can simplify f as:

import math
def f(x,y):
    if x > y:
        return math.log(x-y)
    else:
        return 0.0  # or math.nan

and than make a numpy ufunc from it using np.frompyfunc:

f_np = np.frompyfunc(f,2,1)

Now you can do:

Z = f_np(X,Y)

Notes: If you intend to use plt.contourf(X,Y,Z), everything will clearer if you use y = np.linspace(0.1, 1000, 30) instead of y = np.linspace(0.1, 3, 30) so that the triangle is exactly half of the plot. If you use math.nan in f instead of 0.0, the triangle will be left blank in the contourplot.

Jan Kuiken
  • 1,930
  • 17
  • 17
  • thanks for your excellent suggestion, which works well for plt.contourf. I actually need a surface 3D plot, and when I issue #plt.contourf(X,Y,Z,100) surf = ax.plot_surface(X, Y, Z, cmap=cm.coolwarm, linewidth=0, antialiased=False) – user37292 Dec 15 '19 at 20:28
  • I get an error message, it looks the nan trick is not accepted any more, any suggestion would be most helpful, thanks a lot – user37292 Dec 15 '19 at 20:29