如何在python中绘制映射

2024-10-01 13:26:26 发布

您现在位置:Python中文网/ 问答频道 /正文

我不知道如何在python中绘制映射,我所说的映射是指非线性映射,对于线性映射,已经有GeoGebra可以使用它来可视化它们,但是我找不到一个站点,甚至找不到一个python脚本来可视化非线性映射,来理解我所说的非线性映射的含义。这是一张图片

它是从3blue1brown开始的,实际上它是复杂函数f(z)=z**2的一个绘图,但是您可以很容易地将它转换为一个映射,即F(x,y)=(x**2-y**2,2*x*y)

所以我的问题是,我应该使用什么库在python中绘制这些东西


Tags: 函数脚本绘图站点可视化绘制图片线性
2条回答

注意:这绝不是一个好的解决方案,我写这个答案的目的是让你有一个答案,不管答案是好是坏

我的方法是创建一个图像,通过将像素的x坐标插入一个函数,返回一个与像素的y坐标相对应的数字,将每个像素视为图形上的一个点。如果函数的结果等于y坐标,则像素的颜色将发生变化。我添加了一些选项来定制图表的外观。这是函数(它只是一个原型,并不具有潜在的效率,如果您喜欢这种方法,我可以改进代码):

from numbers import Number

def draw_graph(image, math_func, *,
               error=10,
               x_scale=1, y_scale=1,
               x_offset=None, y_offset=None,
               color=(0, 255, 0)):
    if x_offset is None:
        x_offset = image.width // 2
    if y_offset is None:
        y_offset = image.height // 2
    pxls = image.load()
    for x in range(image.width):
        for y in range(image.height):
            output = math_func((x - x_offset) / x_scale)
            if isinstance(output, Number):
                if output - error <= (image.height - y - y_offset) / y_scale <= output + error:
                    pxls[x, y] = color
            elif isinstance(output, tuple):
                for out in output:
                    if out - error <= (image.height - y - y_offset) / y_scale <= out + error:
                        pxls[x, y] = color

image是一个枕头图像对象,math_func是一个函数,它接受一个整数(x)并返回一个数字或一个数字元组(多个值),错误是函数的输出必须接近像素的y坐标才能着色,其余参数是自解释的。如果match_func返回None,函数将忽略它

下面是函数的示例用法(图像应在程序末尾显示):

from PIL import Image
from numbers import Number
from math import sqrt

def third_power(x):
    return 0.01 * x**3

def one_over_x(x):
    return 1 / x if x != 0 else None

def idk(x):
    return sqrt(x*x - 3) if x*x > 3 else None

def draw_graph(image, math_func, *,
               error=10,
               x_scale=1, y_scale=1,
               x_offset=None, y_offset=None,
               color=(0, 255, 0)):
    if x_offset is None:
        x_offset = image.width // 2
    if y_offset is None:
        y_offset = image.height // 2
    pxls = image.load()
    for x in range(image.width):
        for y in range(image.height):
            output = math_func((x - x_offset) / x_scale)
            if isinstance(output, Number):
                if output - error <= (image.height - y - y_offset) / y_scale <= output + error:
                    pxls[x, y] = color
            elif isinstance(output, tuple):
                for out in output:
                    if out - error <= (image.height - y - y_offset) / y_scale <= out + error:
                        pxls[x, y] = color

img1 = Image.new("RGB", (200, 200), "black")

draw_graph(img1, third_power, error=5, x_scale=3)
draw_graph(img1, one_over_x, error=3, x_scale=100, color=(255, 0, 0))
draw_graph(img1, idk, error=1, x_scale=3, y_scale=10, color=(0, 0, 255))
img1.show()

img2 = Image.new("RGB", (2000, 2000), "black")

draw_graph(img2, lambda x: x*x, x_scale=10, y_scale=2)

img2.show()

如果我在这个答案上犯了错误,请发表评论,现在是凌晨3点,我无法抗拒一个好的挑战。我希望你觉得这个答案有用或有创意

你可能想看看Sympy's plotting capabilities。它使用Matplotlib作为后端。由于需要显式指定每一行,因此仍需要一些工作:

 import sympy as sy

# Create symbolic function Fz = (x + i*y)**2:
x, y, t = sy.symbols("x, y, t", real=True)
z = x + sy.I * y
Fz = sy.expand(z**2)

# Create expressions for the grid lines:
x_lines, y_lines = [], []
for g_ in range(-5, 6):
    Fz_y, Fz_x = Fz.subs({x: g_/2, y: t}), Fz.subs({x: t, y: g_/2})
    x_lines.append((sy.re(Fz_x), sy.im(Fz_x)))
    y_lines.append((sy.re(Fz_y), sy.im(Fz_y)))

# Make the plot:
plt0 = sy.plot_parametric(*(x_lines+y_lines), (t, -5, 5), show=False,
                          xlim=(-3, 3), ylim=(-4, 4), axis_center=(-3, -4),
                          xlabel="Re", ylabel="Im")

# Adapt color for each line separately:
for c_, p_ in enumerate(plt0):
    p_.line_color = 'blue' if c_ < len(x_lines) else 'red'

plt0.show()  # do the drawing

# Access matplotlib backend (works only in interactive IPython shell):
ax = plt0._backend.ax[0]  # get matplotlib axis
ax.grid(True)

它给出:

Plot of F(z) ) z**2

或者,您可以使用lambify()将一个Sympy表达式转换为Numpy函数,例如:

Fz_np = sy.lambdify((x, y), Fz)
print(f"Fz(1, 2) = {Fz_np(1, 2)}")

然后可以用传统的方法在Matplotlib中绘制线

相关问题 更多 >