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()
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)
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)