# StreamPlot error "ndim" is not an attribute

import numpy as np import matplotlib.pyplot as plt import math as Math

Q = 1 #Columb
E0 = 8.854187817e-12
K = 1/ (4 * Math.pi * E0)

gridx = np.arange(-5,5,0.1)
gridy = np.arange(-5,5,0.1)

x,y = np.meshgrid (gridx, gridy)

eqn(x,y) = K*Q / (x**2 + y**2)^(1/2)

grad = vector ( [ diff(eqn,x), diff(eqn,y) ] )
Ex = diff (eqn, x)
Ey = diff (eqn, y)

U = (K*Q * x) / (x**2 + y**2)^(3/2)
V = (K*Q * y) / (x**2 + y**2)^(3/2)

plt.figure (figsize = (10, 10))
plt.streamplot (x,y, Ex,Ey, color='green')
plt.streamplot (x,y, U,V, color='green')
plt.grid()
plt.show()


Each version produces a different error, I don't understand why. And, I want to know why!

#1 .. missing required positional argument v

#2 .. ndim is not an attribute

edit retag close merge delete

Sort by ยป oldest newest most voted

As asked, your question does not use any Sage specific function and uses Sage as a Python interpreter. It would probably better aimed at a Python list/forum.

But Sage has functions useful for this task. Given :

sage: var("Q,E0")
(Q, E0)
sage: K=1/(4*pi*E0) # Keep constant's definition.
sage: NumVals={Q:1,E0:8.854187817e-12} # Separate symbolic and numeric computations...
sage: f(x,y)=K*Q/sqrt(x^2+y^2) # define f symbolically.


You may compute :

sage: f.gradient()
(x, y) |--> (-1/4*Q*x/(pi*(x^2 + y^2)^(3/2)*E0), -1/4*Q*y/(pi*(x^2 + y^2)^(3/2)*E0))


i. e. a symbolic function of two variables returning a bidimensional vector, better typeset as :

$$\left( x, y \right) \ {\mapsto} \ \left(-\frac{Q x}{4 \, \pi {\left(x^{2} + y^{2}\right)}^{\frac{3}{2}} E_{0}},\,-\frac{Q y}{4 \, \pi {\left(x^{2} + y^{2}\right)}^{\frac{3}{2}} E_{0}}\right)$$

Graphing needs numerical values, but having them in a dictionary allows to keep the working tools (definitions, equations, intermediate results...) symbolic (i. e. understandable) until numerical values are needed.

I'm not sure what Matplotlib's streamplot is supposed to do. I suppose its either :

sage: streamline_plot(f.gradient().subs(NumVals).list(), (-5, 5), (-5, 5))
Launched png viewer for Graphics object consisting of 1 graphics primitive


or, possibly,

sage: plot_vector_field(f.gradient().subs(NumVals), (x, -5, 5), (y, -5, 5))
Launched png viewer for Graphics object consisting of 1 graphics primitive


HTH,

more

I was able to get streamline_plot and plot_vector_field to work. The original code should work, but even you avoided using it to answer the question, which raises the question, "Why doesn't it work?" But thanks for providing the alternatives to others having difficulty with streampliot who need alternatives to complete the task.

( 2023-04-10 02:05:03 +0100 )edit

I think the problem is that you're trying to mix numpy and matplotlib and Sage in ways that are not supported. The documentation for plt.streamplot says:

Parameters
**********

x, y : 1D/2D arrays
Evenly spaced strictly increasing arrays to make a grid.  If 2D,
all rows of *x* must be equal and all columns of *y* must be equal;
i.e., they must be as if generated by "np.meshgrid(x_1d, y_1d)".

u, v : 2D arrays
*x* and *y*-velocities. The number of rows and columns must match
the length of *y* and *x*, respectively.


It looks like you're trying to pass grid in the place of both x and y, but grid is a function, not a pair of arrays of values. You also define x and y using np.meshgrid, but the later assignment eqn(x,y) = K*Q / (x**2 + y**2)^(1/2) redefines x and y to be symbolic variables. I suggest instead:

xx,yy = np.meshgrid (gridx, gridy) # don't redefine x and y


and

G = [grad(x,y) for (x,y) in zip(gridx,gridy)]
Gx = [a[0] for a in G]
Gy = [a[1] for a in G]


and finally

plt.streamplot (Gx, Gy, xx,yy, color='green')


This doesn't work, either, but the error message is different. Maybe you need to do more conversion to get xx and Gx in the same format (convert both to floats? convert Gx to a numpy array?).

more

Thanks you for this attempt. The working examples that I found for streamplot actually used most of the code that I provided. Their method of managing the equation though was different.

https://www.geeksforgeeks.org/matplotlib-pyplot-streamplot-in-python/ (https://www.geeksforgeeks.org/matplot...)

( 2023-04-10 05:39:40 +0100 )edit

The equation is the whole issue: a symbolic expression, like your grad, is not something that matplotlib is designed to handle. I think you need an array of values, not an expression.

( 2023-04-10 06:19:03 +0100 )edit

@John Palmieri, I thought of that, that's why I included 3 different examples of streamplot using the equations. 2 where it was derived through sagemath by 2 different methods, and 1 where I provided the derivative directly as U and V. This didn't make the code work either. More suggestions?

( 2023-04-10 06:58:35 +0100 )edit

type(U) returns <class 'sage.symbolic.expression.Expression'>, and the same with type(Ex). It's the same problem each time: you need an array, not a symbolic expression.

( 2023-04-10 17:46:07 +0100 )edit

@John Plamieri, thanks for the information on the expressions. I'll have to look at example 2 of the URL provided above to see if it's producing the same results concerning U and V. Though, I feel, that regardless of the results, streamplot should use the equations as they are. I'm not sure who to push that feature request to, though.

( 2023-04-11 21:32:43 +0100 )edit
import numpy as np
import matplotlib.pyplot as plt
import math as Math

Q = 1 #Columb
E0 = 8.854187817e-12
K = 1/ (4 * Math.pi * E0)

gridx = np.arange(-5,5,0.1)
gridy = np.arange(-5,5,0.1)

x,y = np.meshgrid (gridx, gridy)

U = (K*Q * x) / (x**2 + y**2)^(3/2)
V = (K*Q * y) / (x**2 + y**2)^(3/2)

# eqn(x,y) = K*Q / (x**2 + y**2)^(1/2)
# grad = vector ( [ diff(eqn,x), diff(eqn,y) ] )
# Ex = diff (eqn, x)
# Ey = diff (eqn, y)

plt.figure (figsize = (10, 10))
#plt.streamplot (x,y, Ex,Ey, color='green')
plt.streamplot (x,y, U,V, color='green')
plt.grid()
plt.show()


So, out of curiosity I attempted to convert the symbolic expression to a numpy array, and didn't find a conversion routine.

The other thing I did, was re-arrange the order of the equations and REM out the lines using the variable eqn. It appears that this one line converted the variables (x,y) to symbolic variables. I consider this to be a major failing of SageMath for not tattling, and for throwing other errors when the variables associated with eqn are passed to streamplot. I also consider it a major failing of streamplot that it can't use symbolic expressions.

So, the fix, is to not use symbolic equations with streamplot, at least and until streamplot updates their code to accommodate symbolic equations.

more