Passing Python functions to Gnuplot
Question: 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`](http://gnuplot-py.sourceforge.net/
"Gnuplot.py \(website unavailable at the moment for some strange reason\)") 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:

![function sampling vs expression
translation](http://i.stack.imgur.com/SZQMM.png)

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`.


Answer: I am not sure if I'm fully answering your question, but you could try
executing your python script as a system call within gnuplot passing the
argument(s).

For instance, imagine the simple python script `test.py`:

    
    
    import sys
    
    x=float(sys.argv[1])
    
    print x**2
    

which will return the square of the argument when called like this from a
shell:

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

Now, within gnuplot, turn this into a function:

    
    
    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
    

I added the `real()` so that the string output from the system call is
converted to float. This now allows you to use it as a regular gnuplot
function. I don't need to mention this will take a lot longer to execute than
just `plot x**2`:

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

[![enter image description
here](http://i.stack.imgur.com/cG4Ds.png)](http://i.stack.imgur.com/cG4Ds.png)

