-1

I am trying to use the content of a python function to make a contour plot. For example I try:

import numpy as np
import matplotlib.mlab as mlab
import matplotlib.pyplot as plt

# Building my equation from a series of matrix operation

def func_M(X, Y): 

    z_mat = np.array([[X**2, Y], 
                       [Y, X]]) 
    z_other = np.array([[X],
                        [Y]])
    z_matInv = (np.linalg.inv(z_mat))
    z_final=np.dot(z_matInv,z_other)

    return z_final[0][0]

# print out the return of the function evaluated at X = .1.5, and Y = 2.

print func_M(1.5,2.)

# Building and x and y grid to plot:

x = np.arange(-5, 5, 0.01)
y = np.arange(-5, 5, 0.01)
xx, yy = np.meshgrid(x, y, sparse=True)

# Making the z component and contour plotting function:

#z_plot_M = func_M(xx,yy)
#h = plt.contourf(x,y,z_plot_M)
#plt.show()

So, the print function prints out 2.8, which is the first element of the final matrix evaluated at x = 1.0 and y =2.0.

However, if I try to evaluate this to plot as a countour (the commented bit) it doesn't work.

Here's the simple code I was was using as the basis:

x = np.arange(-5, 5, 0.01)
y = np.arange(-5, 5, 0.01)
xx, yy = np.meshgrid(x, y, sparse=True)

def func_eq(X, Y):
    z = np.sin(X**2) + np.sin(Y**2)
    return z

z_plot = func_eq(xx,yy)

h = plt.contourf(x,y,z_plot)
plt.show()

Is there a reason why this works but when I have matrices instead of a simple equation it doesn't? and is there an easy fix it for the first case?

Mac
  • 991
  • 3
  • 11
  • 22

1 Answers1

0
In [263]: x = np.arange(-5, 5, 0.01)
     ...: y = np.arange(-5, 5, 0.01)
     ...: xx, yy = np.meshgrid(x, y, sparse=True)
     ...: 
In [264]: x.shape
Out[264]: (1000,)
In [265]: xx.shape
Out[265]: (1, 1000)
In [266]: yy.shape
Out[266]: (1000, 1)

By specify spare=True, xx and yy have different shapes. They broadcast together, as in xx+yy. but trying to make a new array, as you do creates object dtype arrays:

In [267]: z_other=np.array([[xx],[yy]])
<ipython-input-267-80e1b3aae946>:1: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray
  z_other=np.array([[xx],[yy]])
In [268]: z_other.shape
Out[268]: (2, 1)

In [269]: z_mat = np.array([[xx**2, yy],
     ...:                        [yy, xx]])
<ipython-input-269-a02f5f8ab715>:1: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray
  z_mat = np.array([[xx**2, yy],
In [270]: z_mat.shape
Out[270]: (2, 2)

And trying to do a numeric inv on such array, produces an error:

In [271]: np.linalg.inv(z_mat)
Traceback (most recent call last):
  File "<ipython-input-271-f9e7af1a2be5>", line 1, in <module>
    np.linalg.inv(z_mat)
  File "<__array_function__ internals>", line 5, in inv
  File "/usr/local/lib/python3.8/dist-packages/numpy/linalg/linalg.py", line 546, in inv
    ainv = _umath_linalg.inv(a, signature=signature, extobj=extobj)
TypeError: No loop matching the specified signature and casting was found for ufunc inv

====

Remove the sparse=True, produces 2 2d arrays:

In [272]: x = np.arange(-5, 5, 0.01)
     ...: y = np.arange(-5, 5, 0.01)
     ...: xx, yy = np.meshgrid(x, y)
In [273]: xx.shape, yy.shape
Out[273]: ((1000, 1000), (1000, 1000))

which combine to make a 4d array.

In [274]: z_mat = np.array([[xx**2, yy],
     ...:                        [yy, xx]])
In [275]: z_mat.shape
Out[275]: (2, 2, 1000, 1000)

That matches the specs (...,M,M), which should produce (2,2) inverses - except for the fact that these arrays are singular.

In [276]: C = np.linalg.inv(z_mat)
Traceback (most recent call last):
  File "<ipython-input-276-7ae416f9f924>", line 1, in <module>
    C = np.linalg.inv(z_mat)
  File "<__array_function__ internals>", line 5, in inv
  File "/usr/local/lib/python3.8/dist-packages/numpy/linalg/linalg.py", line 546, in inv
    ainv = _umath_linalg.inv(a, signature=signature, extobj=extobj)
  File "/usr/local/lib/python3.8/dist-packages/numpy/linalg/linalg.py", line 88, in _raise_linalgerror_singular
    raise LinAlgError("Singular matrix")
LinAlgError: Singular matrix

I leave it to you to construct non-singular arrays.

hpaulj
  • 221,503
  • 14
  • 230
  • 353
  • Thanks for commenting, but that's not what I am doing though. the function is independent of the arrays for xx and yy. I only try to evaluate the return of the function after all the matrix operations are done. – Mac Dec 11 '20 at 04:18
  • I'm trying to show the kinds of errors that `func_M(xx,yy)` would produce. If that's not what you are doing, then why do you generate `xx, yy` and have this commented line. You also mention a bunch of errors, but don't show them. If you want real help, post a clear question! – hpaulj Dec 11 '20 at 04:21
  • I see. I am not sure how to build an array otherwise then. I was just assuming it would pick a value for x and for y and do it, then the next one and so on.... I mean, this works fine for a simple equation inside the function – Mac Dec 11 '20 at 04:26