【问题标题】:Passing Python functions to Gnuplot将 Python 函数传递给 Gnuplot
【发布时间】:2015-10-12 07:35:00
【问题描述】:

在 Gnuplot 中绘制 Python 函数并不简单,尽管有 是一些解决方案。例如,可以将其值转换为数组或 手动将其表达式转换为 Gnuplot 的语法。这是一个 使用模块Gnuplot.py作为接口的例子:

#!/usr/bin/env python

import Gnuplot
import numpy as np

## define function ##
func = lambda x, x0, y0, w: y0 * np.exp( -4*np.log(2) * ( (x-x0) / w )**2 )
# also works with a regular function:
# def func(x, x0, y0, w):
    # return y0 * np.exp( -4*np.log(2) * ( (x-x0) / w )**2 )
popt = (10.1, 5, 2)

## linspace ##
x = np.linspace(0, 20, num=1000) # (x min, x max, number of points)
y = func(x, *popt)
func_linspace = Gnuplot.Data(x, y, with_='lines', title='linspace')

## expression “translation” (lambda only) ##
func_translation = Gnuplot.Func(
    '{y0} * exp( -4*log(2) * ( (x-{x0}) / {w} )**2 )'.format(
        x0=popt[0],
        y0=popt[1],
        w=popt[2],
        ),
    title='expression translation')

## plot ##
g = Gnuplot.Gnuplot()
g.plot(func_linspace, func_translation)

第一种方法适用于相当数量的点,但在以下情况下失败 放大太多或改变窗口超出数组的限制,而 第二个适用于任何缩放级别。为了说明这一点,让我们放大 上一个脚本的输出:

因此,找到一种绘制 Python 函数的方法会很有趣 (lambda 或常规函数)作为 Gnuplot 函数。我能想到两个 解决方案:自动翻译表达式(仅适用于“简单” lambda 函数”),或者让 Gnuplot 直接使用 Python 函数。

第一个解决方案:表达式转换(仅限简单的 lambda 函数)

这种方法不仅难以自动化,而且是不可能的 用精细的功能来实现。但是我们仍然可以使用这种方法 对于简单的 lambda 函数。概述实现的行为:

>>> def lambda_to_gnuplot(func, popt):
...     # determine if translation is possible
...     # extract function expression and replace parameters with values
...     return func_expression # str
>>> lambda_to_gnuplot(
...     lambda x, x0, y0, w: y0 * np.exp( -4*np.log(2) * ( (x-x0) / w )**2),
...     (10.1, 5, 2))
'5 * exp( -4*log(2) * ( (x-10.1) / 2 )**2 )'

有没有办法在python中实现这个lambda_to_gnuplot函数?

第二种解决方案:直接将Python函数传递给Gnuplot

“完美”的解决方案是让 Gnuplot 使用 Python 函数。在我的 最大胆的梦想,是这样的:

>>> def func(x, x0, y0, w):
...     if x < x0:
...         return 0
...     else:
...         return y0 * np.exp( -4*np.log(2) * ( (x-x0) / w )**2)
>>> func_direct = Gnuplot.PyFunction(lambda x: func(x, 10.1, 5, 2))
>>> g.plot(func_direct)

这是最容易使用的解决方案,但它的实现会非常 艰难,如果不是不可能的话。 有关此解决方案的任何提示 实现了吗?答案当然可以绕过Gnuplot.py

【问题讨论】:

  • 非常有趣的想法!
  • @Alfe:你觉得这在什么方面特别有趣?
  • 到目前为止,我知道我必须将 Python 函数转换为 Gnuplot 语法才能绘制它,或者在打开 Gnuplot 之前选择样本,从而丢失所有(或大部分) 的 Gnuplot 的交互功能(例如缩放)。现在你的问题让我想到了其他方式的可能性。这就是我觉得有趣的地方。

标签: python python-3.x gnuplot


【解决方案1】:

我不确定我是否完全回答了您的问题,但您可以尝试在 gnuplot 中将您的 python 脚本作为系统调用执行,并传递参数。

例如,想象一下简单的python脚本test.py

import sys

x=float(sys.argv[1])

print x**2

当从 shell 中这样调用时,它将返回参数的平方:

:~$ python test.py 2
4.0
:~$ python test.py 3
9.0
:~$ python test.py 4
16.0

现在,在 gnuplot 中,把它变成一个函数:

gnuplot> f(x) = real(system(sprintf("python test.py %g", x)))
gnuplot> print f(1)
1.0
gnuplot> print f(2)
4.0
gnuplot> print f(3)
9.0
gnuplot> print f(4)
16.0

我添加了real(),以便将系统调用的字符串输出转换为浮点数。这现在允许您将其用作常规 gnuplot 函数。我不需要提到这将需要比plot x**2 更长的时间来执行:

f(x) = real(system(sprintf("python test.py %g", x)))
plot f(x)

【讨论】:

  • 这确实是一个很好的开始,谢谢!我会尝试编写一个 Python 函数来实现这个方法,通过一次调用来最大化它的可用性。
  • @Alfe 谢谢你的建议,我改了。
猜你喜欢
  • 2015-01-23
  • 1970-01-01
  • 1970-01-01
  • 2014-02-22
  • 2012-03-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多