将 Python 函数传递给 Gnuplot
Passing Python functions to Gnuplot
在 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)
第一种方法在相当数量的点上工作正常,但在以下情况下失败
放大太多或将 window 更改为超出数组的限制,而
第二个适用于任何缩放级别。为了说明这一点,让我们放大
上一个脚本的输出:
出于这个原因,找到一种绘制 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)
这是最容易使用的解决方案,但它的实施会非常困难
艰难,如果不是不可能的话。 有关此解决方案的任何提示
implemented?答案当然可以绕过Gnuplot.py
.
我不确定我是否完全回答了你的问题,但你可以尝试在传递参数的 gnuplot 中将你的 python 脚本作为系统调用执行。
例如,假设简单的 python 脚本 test.py
:
import sys
x=float(sys.argv[1])
print x**2
当从 shell:
这样调用时,将 return 参数的平方
:~$ 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)
在 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)
第一种方法在相当数量的点上工作正常,但在以下情况下失败 放大太多或将 window 更改为超出数组的限制,而 第二个适用于任何缩放级别。为了说明这一点,让我们放大 上一个脚本的输出:
出于这个原因,找到一种绘制 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)
这是最容易使用的解决方案,但它的实施会非常困难
艰难,如果不是不可能的话。 有关此解决方案的任何提示
implemented?答案当然可以绕过Gnuplot.py
.
我不确定我是否完全回答了你的问题,但你可以尝试在传递参数的 gnuplot 中将你的 python 脚本作为系统调用执行。
例如,假设简单的 python 脚本 test.py
:
import sys
x=float(sys.argv[1])
print x**2
当从 shell:
这样调用时,将 return 参数的平方:~$ 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)