def a2str(vector):
    """converts an array to a string that can be used with gnuplot

    By setting a Gnuplot.Data object's attribute <content> the the
    result of this output, updates the Gnuplot internal data; a
    succsequent replot() or plot() command will show the new data..
    """
    # convert to a large float array 
    vector = asarray(vector, Float64)

    # use Gnuplot's way of conversion
    # (taken from Gnuplot.PlotItems.Data function)
    dim = len(shape(vector))
    if (dim == 1): vector = vector[:,NewAxis]
    f = StringIO()
    write_array(f, vector)

    return f.getvalue()
Ejemplo n.º 2
0
def GridData(data, xvals=None, yvals=None, inline=_unset, filename=None, **keyw):
    """Return a _FileItem representing a function of two variables.

    'GridData' represents a function that has been tabulated on a
    rectangular grid.  The data are written to a file; no copy is kept
    in memory.

    Arguments:

        'data' -- the data to plot: a 2-d array with dimensions
            (numx,numy).

        'xvals' -- a 1-d array with dimension 'numx'

        'yvals' -- a 1-d array with dimension 'numy'

        'binary=<bool>' -- send data to gnuplot in binary format?

        'inline=<bool>' -- send data to gnuplot "inline"?

        'filename=<string>' -- save data to a permanent file.

    Note the unusual argument order!  The data are specified *before*
    the x and y values.  (This inconsistency was probably a mistake;
    after all, the default xvals and yvals are not very useful.)

    'data' must be a data array holding the values of a function
    f(x,y) tabulated on a grid of points, such that 'data[i,j] ==
    f(xvals[i], yvals[j])'.  If 'xvals' and/or 'yvals' are omitted,
    integers (starting with 0) are used for that coordinate.  The data
    are written to a temporary file; no copy of the data is kept in
    memory.

    If 'binary=0' then the data are written to a datafile as 'x y
    f(x,y)' triplets (y changes most rapidly) that can be used by
    gnuplot's 'splot' command.  Blank lines are included each time the
    value of x changes so that gnuplot knows to plot a surface through
    the data.

    If 'binary=1' then the data are written to a file in a binary
    format that 'splot' can understand.  Binary format is faster and
    usually saves disk space but is not human-readable.  If your
    version of gnuplot doesn't support binary format (it is a
    recently-added feature), this behavior can be disabled by setting
    the configuration variable
    'gp.GnuplotOpts.recognizes_binary_splot=0' in the appropriate
    gp*.py file.

    Thus if you have three arrays in the above format and a Gnuplot
    instance called g, you can plot your data by typing
    'g.splot(Gnuplot.GridData(data,xvals,yvals))'.

    """

    # Try to interpret data as an array:
    data = utils.float_array(data)
    try:
        (numx, numy) = data.shape
    except ValueError:
        raise Errors.DataError("data array must be two-dimensional")

    if xvals is None:
        xvals = numpy.arange(numx)
    else:
        xvals = utils.float_array(xvals)
        if xvals.shape != (numx,):
            raise Errors.DataError(
                "The size of xvals must be the same as the size of " "the first dimension of the data array"
            )

    if yvals is None:
        yvals = numpy.arange(numy)
    else:
        yvals = utils.float_array(yvals)
        if yvals.shape != (numy,):
            raise Errors.DataError(
                "The size of yvals must be the same as the size of " "the second dimension of the data array"
            )

    # Binary defaults to true if recognizes_binary_plot is set;
    # otherwise it is forced to false.
    binary = keyw.get("binary", 1) and gp.GnuplotOpts.recognizes_binary_splot
    keyw["binary"] = binary

    if inline is _unset:
        inline = (not binary) and (not filename) and gp.GnuplotOpts.prefer_inline_data
    elif inline and filename:
        raise Errors.OptionError("cannot pass data both inline and via a file")

    # xvals, yvals, and data are now all filled with arrays of data.
    if binary:
        if inline:
            raise Errors.OptionError("binary inline data not supported")

        # write file in binary format

        # It seems that the gnuplot documentation for binary mode
        # disagrees with its actual behavior (as of v. 3.7).  The
        # documentation has the roles of x and y exchanged.  We ignore
        # the documentation and go with the code.

        mout = numpy.zeros((numy + 1, numx + 1), numpy.float32)
        mout[0, 0] = numx
        mout[0, 1:] = xvals.astype(numpy.float32)
        mout[1:, 0] = yvals.astype(numpy.float32)
        try:
            # try copying without the additional copy implied by astype():
            mout[1:, 1:] = numpy.transpose(data)
        except:
            # if that didn't work then downcasting from double
            # must be necessary:
            mout[1:, 1:] = numpy.transpose(data.astype(numpy.float32))

        content = mout.tostring()
        if (not filename) and gp.GnuplotOpts.prefer_fifo_data:
            return _FIFOFileItem(content, **keyw)
        else:
            return _NewFileItem(content, filename=filename, **keyw)
    else:
        # output data to file as "x y f(x)" triplets.  This
        # requires numy copies of each x value and numx copies of
        # each y value.  First reformat the data:
        set = numpy.transpose(
            numpy.array((numpy.transpose(numpy.resize(xvals, (numy, numx))), numpy.resize(yvals, (numx, numy)), data)),
            (1, 2, 0),
        )

        # Now output the data with the usual routine.  This will
        # produce data properly formatted in blocks separated by blank
        # lines so that gnuplot can connect the points into a grid.
        f = StringIO()
        utils.write_array(f, set)
        content = f.getvalue()

        if inline:
            return _InlineFileItem(content, **keyw)
        elif filename:
            return _NewFileItem(content, filename=filename, **keyw)
        elif gp.GnuplotOpts.prefer_fifo_data:
            return _FIFOFileItem(content, **keyw)
        else:
            return _NewFileItem(content, **keyw)
Ejemplo n.º 3
0
def Data(*data, **keyw):
    """Create and return a _FileItem representing the data from *data.

    Create a '_FileItem' object (which is a type of 'PlotItem') out of
    one or more Float Python numpy arrays (or objects that can be
    converted to a float numpy array).  If the routine is passed a
    single with multiple dimensions, then the last index ranges over
    the values comprising a single data point (e.g., [<x>, <y>,
    <sigma>]) and the rest of the indices select the data point.  If
    passed a single array with 1 dimension, then each point is
    considered to have only one value (i.e., by default the values
    will be plotted against their indices).  If the routine is passed
    more than one array, they must have identical shapes, and then
    each data point is composed of one point from each array.  E.g.,
    'Data(x,x**2)' is a 'PlotItem' that represents x squared as a
    function of x.  For the output format, see the comments for
    'write_array()'.

    How the data are written to gnuplot depends on the 'inline'
    argument and preference settings for the platform in use.

    Keyword arguments:

        'cols=<tuple>' -- write only the specified columns from each
            data point to the file.  Since cols is used by python, the
            columns should be numbered in the python style (starting
            from 0), not the gnuplot style (starting from 1).

        'inline=<bool>' -- transmit the data to gnuplot 'inline'
            rather than through a temporary file.  The default is the
            value of gp.GnuplotOpts.prefer_inline_data.

        'filename=<string>' -- save data to a permanent file.

    The keyword arguments recognized by '_FileItem' can also be used
    here.

    """

    if len(data) == 1:
        # data was passed as a single structure
        data = utils.float_array(data[0])

        # As a special case, if passed a single 1-D array, then it is
        # treated as one value per point (by default, plotted against
        # its index):
        if len(data.shape) == 1:
            data = data[:, numpy.newaxis]
    else:
        # data was passed column by column (for example,
        # Data(x,y)); pack it into one big array (this will test
        # that sizes are all the same):
        data = utils.float_array(data)
        dims = len(data.shape)
        # transpose so that the last index selects x vs. y:
        data = numpy.transpose(data, (dims - 1,) + tuple(range(dims - 1)))
    if "cols" in keyw:
        cols = keyw["cols"]
        del keyw["cols"]
        if isinstance(cols, int):
            cols = (cols,)
        data = numpy.take(data, cols, -1)

    if "filename" in keyw:
        filename = keyw["filename"] or None
        del keyw["filename"]
    else:
        filename = None

    if "inline" in keyw:
        inline = keyw["inline"]
        del keyw["inline"]
        if inline and filename:
            raise Errors.OptionError("cannot pass data both inline and via a file")
    else:
        inline = (not filename) and gp.GnuplotOpts.prefer_inline_data

    # Output the content into a string:
    f = StringIO()
    utils.write_array(f, data)
    content = f.getvalue()
    if inline:
        return _InlineFileItem(content, **keyw)
    elif filename:
        return _NewFileItem(content, filename=filename, **keyw)
    elif gp.GnuplotOpts.prefer_fifo_data:
        return _FIFOFileItem(content, **keyw)
    else:
        return _NewFileItem(content, **keyw)