我目前正在使用PySide6开发函数绘图仪GUI应用程序。该应用程序允许用户以字符串的形式输入数学函数,然后对其进行解析和绘制。虽然该应用程序在2D函数上运行良好,但在绘制3D函数时遇到了困难。
在我的实现中,我使用SymPy解析函数字符串并生成用于绘图的数据点。当我试图将数据重塑为Matplotlib中plot_surface函数的适当形状时,就会出现问题。
下面是演示该问题的相关代码片段的简化版本:
import re
import numpy as np
import sympy
from PySide6.QtWidgets import QMessageBox
from mpl_toolkits.mplot3d import Axes3D
class FunctionProcessor():
...
def parse_3d_function(self):
self.function_string = self.function_string.replace("^", "**")
x, y = sympy.symbols('x y')
function = sympy.sympify(self.function_string)
x_data = np.linspace(self.x_range[0], self.x_range[1], 101)
y_data = np.linspace(self.x_range[0], self.x_range[1], 101)
x_data, y_data = np.meshgrid(x_data, y_data)
z_data = np.array([function.subs({x: xi, y: yi}) for xi, yi in zip(x_data, y_data)])
return x_data, y_data, z_data
个字符
我得到错误ValueError: Argument Z must be 2-dimensional.
我试图搜索文档,发现sympy有plot3d功能,但我需要的图形embdeed在GUI中,而不是在一个单独的窗口
1条答案
按热度按时间wnrlj8wa1#
1.为什么代码中有2个
meshgrid
?parse_3d_function
返回3个数组,包括x_data
和y_data
,它们是在此函数中通过以下方式获得的:字符串
然后你在
plot_3d
里面做的是型
那么
x_data, y_data
是一个网格的网格?这意味着一些东西,当然,但可能不是你想要的
2.这里没有zip
如果你想计算
x
和y
所有可能组合z
,那么不要使用zip
!型
可能也没有达到你的预期。这里的
xi
和yi
是x和y值的“行”。如果“function.subs”是矢量化的,那么就没有问题。它可以在一整行x和y上工作,并计算一行结果。但如果是这样,那么,为什么不直接调用function.subs({x:x_data, y:y_data})
呢?如果它是矢量化的,那么它也应该工作。另一方面,如果函数没有被向量化,也就是说,如果
x
和y
被认为只是标量,那么zip
不会下降2步。它不会并行地对两个网格进行2嵌套循环迭代。你得自己去。例如(仍然使用您的“纯Python复合列表”样式。但最好的方法应该是依靠矢量化。我们不知道你的
function.sub
是什么,但如果它来自sympify,它可能不是。所以呢
型
其中
x_data
和y_data
是1d阵列(因此在此之前没有meshgrid)3.无网格:广播
而且,顺便说一句,如果是矢量化的,那么它是
meshgrid
不必要使用的另一个例子。广播就足够了。型
meshgrid
在这里所做的就是浪费好的内存。另外,function.subs
内部可能有一些优化,因为x
和y
本质上是两个一维数组,而不是二维数组。例如,如果你正在计算x²+y²
,那么x_data[None,:]**2+y_data[:,None]**2
是2N**2
运算(N对x,N对y),然后是N²加法。而x,y=np.meshgrid(x_data,y_data); x**2+y**2
是2N²**2
操作(N²用于x,N²用于y)和N²加法。不算meshgrid
本身的成本。所以,广播时没有网格就足够了。
在这里,你没有任何向量化的函数。但是正如您所看到的(本答案的第2节),计算
z
的网格的方法也不使用meshgrid
型
4.`function.subs矢量化
你可以通过某种方式将这个函数向量化,这样它的行为就更像一个经典的numpy函数
型
它不能提供有意义的加速。Is不是真正的向量化(
function.subs
仍然被调用101²次)。但它有一个好处,让你回到一个非常经典的情况:我有x和y的向量,我想通过numpy运算来计算所有可能的x和y的z。这是由一个型
这就是我做的,一旦我向量化你的函数。
(Well,在现实中,如果我相信我经常在这里看到的,它是“经典”完成与
型
但是,正如我所说,这是一个错误。就像你看到的
meshgrid
的95%的使用一样,这是对内存和计算时间的浪费,可以通过广播更好地完成)