Plotting a Python function in Gnuplot is not straightforward although there
are some solutions. For example, one could either cast its values into an array or
manually translate its expression into Gnuplot’s syntax. Here is an
example that uses the module Gnuplot.py
as an interface:
#!/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)
The first method works fine with a decent number of points but fails when zooming-in too much or changing the window out of the array’s limits, while the second one works at any zoom level. To illustrate this point, let’s zoom-in the output of the previous script:
For this reason, it would be interesting to find a way to plot Python functions (lambda or regular functions) as Gnuplot functions. I can think of two solution: automatically translating the expression (works only for “simple” lambda functions”), or having Gnuplot directly use the Python function.
First solution: expression translation (simple lambda functions only)
This method would not only be tricky to automate, it would also be impossible to implement with elaborate functions. However we could still use this method for simple lambda functions. To sketch the behaviour of an implementation:
>>> 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 )'
Would there be a way to implement this lambda_to_gnuplot
function in python?
Second solution: directly passing the Python function to Gnuplot
The “perfect” solution would be having Gnuplot use the Python function. In my most daring dreams, it is something like:
>>> 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)
This is the easiest solution to use, but its implementation would be very
tough, if not impossible. Any hints on how this solution might be
implemented? The answer may of course bypass Gnuplot.py
.