# Copyright 2002 Gary Bishop # Copyright 2002-2016 Alan W. Irwin # Copyright 2008 Andrew Ross # This file is part of PLplot. # PLplot is free software; you can redistribute it and/or modify # it under the terms of the GNU Library General Public License as published by # the Free Software Foundation; version 2 of the License. # PLplot is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Library General Public License for more details. # You should have received a copy of the GNU Library General Public License # along with the file PLplot; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # Wrap raw python interface to C API, plplotc, with this user-friendly version # which implements some useful variations of the argument lists. from plplotc import * import types import numpy # Redefine plcont to have the user-friendly interface # Allowable syntaxes: # plcont( z, [kx, lx, ky, ly], clev, [pltr, [pltr_data] or [xg, yg, [wrap]]]) # N.B. Brackets represent options here and not python lists! # All unbracketed arguments within brackets must all be present or all be # missing. Furthermore, z must be a 2D array, kx, lx, ky, ly must all be # integers, clev must be a 1D array, pltr can be a function reference or # string, pltr_data is an optional arbitrary data object, xg and yg are # optional 1D or 2D arrays and wrap (which only works if xg and yg # are specified) is 0, 1, or 2. # If pltr is a string it must be either "pltr0", "pltr1", or "pltr2" to # refer to those built-in transformation functions. Alternatively, the # function names pltr0, pltr1, or pltr2 may be specified to refer to # the built-in transformation functions or an arbitrary name for a # user-defined transformation function may be specified. Such functions # must have x, y, and optional pltr_data arguments and return arbitrarily # transformed x' and y' in a tuple. The built-in pltr's such as pltr1 and # pltr2 use pltr_data = tuple(xg, yg), and for this oft-used case (and any # other user-defined pltr which uses a tuple of two arrays for pltr_data), # we also provide optional xg and yg arguments separately as an alternative # to the tuple method of providing these data. Note, that pltr_data cannot # be in the argument list if xg and yg are there, and vice versa. Also note # that the built-in pltr0 and some user-defined transformation functions # ignore the auxiliary pltr_data (or the alternative xg and yg) in which # case neither pltr_data nor xg and yg need to be specified. _plcont = plcont def plcont(z, *args): z = numpy.asarray(z) if len(z.shape) != 2: raise ValueError("Expected 2D z array") if len(args) > 4 and isinstance(args[0], int): for i in range(1,4): if not isinstance(args[i], int): raise ValueError("Expected 4 ints for kx,lx,ky,ly") else: # these 4 args are the kx, lx, ky, ly ints ifdefault_range = 0 kx,lx,ky,ly = args[0:4] args = args[4:] else: ifdefault_range = 1 if len(args) > 0: clev = numpy.asarray(args[0]) if len(clev.shape) !=1: raise ValueError("Expected 1D clev array") args = args[1:] else: raise ValueError("Missing clev argument") if len(args) > 0 and (isinstance(args[0], str) or \ type(args[0]) == types.FunctionType or \ type(args[0]) == types.BuiltinFunctionType): pltr = args[0] # Handle the string names for the callbacks though specifying the # built-in function name directly (without the surrounding quotes) # or specifying any user-defined transformation function # (following above rules) works fine too. if isinstance(pltr, str): if pltr == "pltr0": pltr = pltr0 elif pltr == "pltr1": pltr = pltr1 elif pltr == "pltr2": pltr = pltr2 else: raise ValueError("pltr string is unrecognized") args = args[1:] # Handle pltr_data or separate xg, yg, [wrap] if len(args) == 0: # Default pltr_data pltr_data = None elif len(args) == 1: #Must be pltr_data pltr_data = args[0] args = args[1:] elif len(args) >= 2: xg = numpy.asarray(args[0]) if len(xg.shape) < 1 or len(xg.shape) > 2: raise ValueError("xg must be 1D or 2D array") yg = numpy.asarray(args[1]) if len(yg.shape) != len(xg.shape): raise ValueError("yg must have same number of dimensions as xg") args = args[2:] # wrap only relevant if xg and yg specified. if len(args) > 0: if isinstance(args[0], int): wrap = args[0] args = args[1:] if len(xg.shape) == 2 and len(yg.shape) == 2 and \ z.shape == xg.shape and z.shape == yg.shape: # handle wrap if wrap == 1: z = numpy.resize(z, (z.shape[0]+1, z.shape[1])) xg = numpy.resize(xg, (xg.shape[0]+1, xg.shape[1])) yg = numpy.resize(yg, (yg.shape[0]+1, yg.shape[1])) elif wrap == 2: z = numpy.transpose(numpy.resize( \ numpy.transpose(z), (z.shape[1]+1, z.shape[0]))) xg = numpy.transpose(numpy.resize( \ numpy.transpose(xg), (xg.shape[1]+1, xg.shape[0]))) yg = numpy.transpose(numpy.resize( \ numpy.transpose(yg), (yg.shape[1]+1, yg.shape[0]))) elif wrap != 0: raise ValueError("Invalid wrap specifier, must be 0, 1 or 2.") elif wrap != 0: raise ValueError("Non-zero wrap specified and xg and yg are not 2D arrays") else: raise ValueError("Specified wrap is not an integer") pltr_data = (xg, yg) else: # default is identity transformation pltr = pltr0 pltr_data = None if len(args) > 0: raise ValueError("Too many arguments for plcont") if ifdefault_range: # Default is to take full range (still using fortran convention # for indices which is embedded in the PLplot library API) kx = 1 lx = z.shape[0] ky = 1 ly = z.shape[1] _plcont(z, kx, lx, ky, ly, clev, pltr, pltr_data) plcont.__doc__ = _plcont.__doc__ # Redefine plvect to have the user-friendly interface # Allowable syntaxes: # plvect( u, v, scaling, [pltr, [pltr_data] or [xg, yg, [wrap]]]) _plvect = plvect def plvect(u, v, *args): u = numpy.asarray(u) v = numpy.asarray(v) if len(u.shape) != 2: raise ValueError("Expected 2D u array") if len(v.shape) != 2: raise ValueError("Expected 2D v array") if (u.shape[0] != v.shape[0]) or (u.shape[1] != v.shape[1]) : raise ValueError("Expected u and v arrays to be the same dimensions") if len(args) > 0 and (type(args[0]) in [float, numpy.float64]): scaling = args[0] args = args[1:] else: raise ValueError("Missing scaling argument") if len(args) > 0 and (isinstance(args[0], str) or \ type(args[0]) == types.FunctionType or \ type(args[0]) == types.BuiltinFunctionType): pltr = args[0] # Handle the string names for the callbacks though specifying the # built-in function name directly (without the surrounding quotes) # or specifying any user-defined transformation function # (following above rules) works fine too. if isinstance(pltr, str): if pltr == "pltr0": pltr = pltr0 elif pltr == "pltr1": pltr = pltr1 elif pltr == "pltr2": pltr = pltr2 else: raise ValueError("pltr string is unrecognized") args = args[1:] # Handle pltr_data or separate xg, yg, [wrap] if len(args) == 0: # Default pltr_data pltr_data = None elif len(args) == 1: #Must be pltr_data pltr_data = args[0] args = args[1:] elif len(args) >= 2: xg = numpy.asarray(args[0]) if len(xg.shape) < 1 or len(xg.shape) > 2: raise ValueError("xg must be 1D or 2D array") yg = numpy.asarray(args[1]) if len(yg.shape) != len(xg.shape): raise ValueError("yg must have same number of dimensions as xg") args = args[2:] # wrap only relevant if xg and yg specified. if len(args) > 0: if isinstance(args[0], int): wrap = args[0] args = args[1:] if len(xg.shape) == 2 and len(yg.shape) == 2 and \ u.shape == xg.shape and u.shape == yg.shape: # handle wrap if wrap == 1: u = numpy.resize(u, (u.shape[0]+1, u.shape[1])) v = numpy.resize(v, (v.shape[0]+1, v.shape[1])) xg = numpy.resize(xg, (xg.shape[0]+1, xg.shape[1])) yg = numpy.resize(yg, (yg.shape[0]+1, yg.shape[1])) elif wrap == 2: u = numpy.transpose(numpy.resize( \ numpy.transpose(u), (u.shape[1]+1, u.shape[0]))) v = numpy.transpose(numpy.resize( \ numpy.transpose(v), (v.shape[1]+1, v.shape[0]))) xg = numpy.transpose(numpy.resize( \ numpy.transpose(xg), (xg.shape[1]+1, xg.shape[0]))) yg = numpy.transpose(numpy.resize( \ numpy.transpose(yg), (yg.shape[1]+1, yg.shape[0]))) elif wrap != 0: raise ValueError("Invalid wrap specifier, must be 0, 1 or 2.") elif wrap != 0: raise ValueError("Non-zero wrap specified and xg and yg are not 2D arrays") else: raise ValueError("Specified wrap is not an integer") pltr_data = (xg, yg) else: # default is identity transformation pltr = pltr0 pltr_data = None if len(args) > 0: raise ValueError("Too many arguments for plvect") _plvect(u, v, scaling, pltr, pltr_data) plvect.__doc__ = _plvect.__doc__ # Redefine plimagefr to have the user-friendly interface # Allowable syntaxes: # plimagefr( img, xmin, xmax, ymin, ymax, zmin, zmax, valuemin, valuemax, [pltr, [pltr_data] or [xg, yg, [wrap]]]) _plimagefr = plimagefr def plimagefr(img, *args): img = numpy.asarray(img) if len(img.shape) != 2: raise ValueError("Expected 2D img array") if len(args) >= 8 : for i in range(8) : if (not isinstance(args[i], float)) and \ type(args[i]) != numpy.float64 and \ not isinstance(args[i], int): raise ValueError("Expected 8 numbers for xmin, xmax, ymin, ymax, zmin, zmax, valuemin, valuemax") else: # These 8 args are xmin, xmax, ymin, ymax, zmin, zmax, valuemin, valuemax xmin, xmax, ymin, ymax, zmin, zmax, valuemin, valuemax = args[0:8] args = args[8:] else: raise ValueError("Expected 8 numbers for xmin, xmax, ymin, ymax, zmin, zmax, valuemin, valuemax") if len(args) > 0 and (isinstance(args[0], str) or \ type(args[0]) == types.FunctionType or \ type(args[0]) == types.BuiltinFunctionType): pltr = args[0] # Handle the string names for the callbacks though specifying the # built-in function name directly (without the surrounding quotes) # or specifying any user-defined transformation function # (following above rules) works fine too. if isinstance(pltr, str): if pltr == "pltr0": pltr = pltr0 elif pltr == "pltr1": pltr = pltr1 elif pltr == "pltr2": pltr = pltr2 else: raise ValueError("pltr string is unrecognized") args = args[1:] # Handle pltr_data or separate xg, yg, [wrap] if len(args) == 0: # Default pltr_data pltr_data = None elif len(args) == 1: #Must be pltr_data pltr_data = args[0] args = args[1:] elif len(args) >= 2: xg = numpy.asarray(args[0]) if len(xg.shape) < 1 or len(xg.shape) > 2: raise ValueError("xg must be 1D or 2D array") yg = numpy.asarray(args[1]) if len(yg.shape) != len(xg.shape): raise ValueError("yg must have same number of dimensions as xg") args = args[2:] # wrap only relevant if xg and yg specified. if len(args) > 0: if isinstance(args[0], int): wrap = args[0] args = args[1:] if len(xg.shape) == 2 and len(yg.shape) == 2 and \ img.shape[0] == xg.shape[0]-1 and img.shape[1] == xg.shape[1]-1: # handle wrap if wrap == 1: img = numpy.resize(img, (img.shape[0]+1, u.shape[1])) xg = numpy.resize(xg, (xg.shape[0]+1, xg.shape[1])) yg = numpy.resize(yg, (yg.shape[0]+1, yg.shape[1])) elif wrap == 2: img = numpy.transpose(numpy.resize( \ numpy.transpose(img), (img.shape[1]+1, img.shape[0]))) xg = numpy.transpose(numpy.resize( \ numpy.transpose(xg), (xg.shape[1]+1, xg.shape[0]))) yg = numpy.transpose(numpy.resize( \ numpy.transpose(yg), (yg.shape[1]+1, yg.shape[0]))) elif wrap != 0: raise ValueError("Invalid wrap specifier, must be 0, 1 or 2.") elif wrap != 0: raise ValueError("Non-zero wrap specified and xg and yg are not 2D arrays") else: raise ValueError("Specified wrap is not an integer") pltr_data = (xg, yg) else: # default is NULL callback arguments. pltr = None pltr_data = None if len(args) > 0: raise ValueError("Too many arguments for plimagefr") _plimagefr(img, xmin, xmax, ymin, ymax, zmin, zmax, valuemin, valuemax, pltr, pltr_data) plimagefr.__doc__ = _plimagefr.__doc__ # Redefine plshades to have the user-friendly interface # Allowable syntaxes: # plshades(z, [xmin, xmax, ymin, ymax,] clev, \ # fill_width, [cont_color, cont_width,], rect, \ # [pltr, [pltr_data] or [xg, yg, [wrap]]]) _plshades = plshades def plshades(z, *args): z = numpy.asarray(z) if len(z.shape) != 2: raise ValueError("Expected 2D z array") if len(args) > 4 and \ (type(args[0]) in [int, float, numpy.float64]) and \ (type(args[1]) in [int, float, numpy.float64]) and \ (type(args[2]) in [int, float, numpy.float64]) and \ (type(args[3]) in [int, float, numpy.float64]): # These 4 args are xmin, xmax, ymin, ymax xmin, xmax, ymin, ymax = args[0:4] args = args[4:] else: # These values are ignored if pltr and pltr_data are defined in any case. # So pick some convenient defaults that work for the pltr0, None case xmin = -1. xmax = 1. ymin = -1. ymax = 1. # clev must be present. if len(args) > 0: clev = numpy.asarray(args[0]) if len(clev.shape) !=1: raise ValueError("Expected 1D clev array") args = args[1:] else: raise ValueError("Missing clev argument") # fill_width must be present if len(args) > 0 and (isinstance(args[0], float) or type(args[0]) == numpy.float64): fill_width = args[0] args = args[1:] else: raise ValueError("fill_width argument must be present and of types.FloatType or numpy.float64 type") # cont_color and cont_width are optional. if len(args) > 2 and \ isinstance(args[0], int) and \ (type(args[1]) in [float, numpy.float64]): # These 2 args are cont_color, cont_width = args[0:2] args = args[2:] else: # Turn off contouring. cont_color, cont_width = (0,0.) # rect must be present. if len(args) > 0 and isinstance(args[0], int): rect = args[0] args = args[1:] else: raise ValueError("Missing rect argument") if len(args) > 0 and (type(args[0]) in [type(None), str, types.FunctionType, types.BuiltinFunctionType]): pltr = args[0] # Handle the string names for the callbacks though specifying the # built-in function name directly (without the surrounding quotes) # or specifying any user-defined transformation function # (following above rules) works fine too. if isinstance(pltr, str): if pltr == "pltr0": pltr = pltr0 elif pltr == "pltr1": pltr = pltr1 elif pltr == "pltr2": pltr = pltr2 else: raise ValueError("pltr string is unrecognized") args = args[1:] # Handle pltr_data or separate xg, yg, [wrap] if len(args) == 0: # Default pltr_data pltr_data = None elif len(args) == 1: #Must be pltr_data pltr_data = args[0] args = args[1:] elif len(args) >= 2: xg = numpy.asarray(args[0]) if len(xg.shape) < 1 or len(xg.shape) > 2: raise ValueError("xg must be 1D or 2D array") yg = numpy.asarray(args[1]) if len(yg.shape) != len(xg.shape): raise ValueError("yg must have same number of dimensions as xg") args = args[2:] # wrap only relevant if xg and yg specified. if len(args) > 0: if isinstance(args[0], int): wrap = args[0] args = args[1:] if len(xg.shape) == 2 and len(yg.shape) == 2 and \ z.shape == xg.shape and z.shape == yg.shape: # handle wrap if wrap == 1: z = numpy.resize(z, (z.shape[0]+1, z.shape[1])) xg = numpy.resize(xg, (xg.shape[0]+1, xg.shape[1])) yg = numpy.resize(yg, (yg.shape[0]+1, yg.shape[1])) elif wrap == 2: z = numpy.transpose(numpy.resize( \ numpy.transpose(z), (z.shape[1]+1, z.shape[0]))) xg = numpy.transpose(numpy.resize( \ numpy.transpose(xg), (xg.shape[1]+1, xg.shape[0]))) yg = numpy.transpose(numpy.resize( \ numpy.transpose(yg), (yg.shape[1]+1, yg.shape[0]))) elif wrap != 0: raise ValueError("Invalid wrap specifier, must be 0, 1 or 2.") elif wrap != 0: raise ValueError("Non-zero wrap specified and xg and yg are not 2D arrays") else: raise ValueError("Specified wrap is not an integer") pltr_data = (xg, yg) else: # default is identity transformation pltr = pltr0 pltr_data = None if len(args) > 0: raise ValueError("Too many arguments for plshades") _plshades(z, xmin, xmax, ymin, ymax, clev, \ fill_width, cont_color, cont_width, rect, pltr, pltr_data) plshades.__doc__ = _plshades.__doc__ # Redefine plshade to have the user-friendly interface # Allowable syntaxes: # _plshade(z, [xmin, xmax, ymin, ymax,] \ # shade_min, shade_max, sh_cmap, sh_color, sh_width, \ # [min_color, min_width, max_color, max_width,] rect, \ # [pltr, [pltr_data] or [xg, yg, [wrap]]]) _plshade = plshade def plshade(z, *args): z = numpy.asarray(z) if len(z.shape) != 2: raise ValueError("Expected 2D z array") # Extra check on shade_min = float on end is absolutely necessary # to unambiguously figure out where we are in the argument list. if len(args) > 9 and \ (type(args[0]) in [int, float, numpy.float64]) and \ (type(args[1]) in [int, float, numpy.float64]) and \ (type(args[2]) in [int, float, numpy.float64]) and \ (type(args[3]) in [int, float, numpy.float64]) and \ (type(args[4]) in [float, numpy.float64]): # These 4 args are xmin, xmax, ymin, ymax xmin, xmax, ymin, ymax = args[0:4] args = args[4:] else: # These values are ignored if pltr and pltr_data are defined in any case. # So pick some convenient defaults that work for the pltr0, None case xmin = -1. xmax = 1. ymin = -1. ymax = 1. # shade_min, shade_max, sh_cmap, sh_color, sh_width, must be present. # sh_color can be either integer or float. if len(args) > 5 and \ (type(args[0]) in [float, numpy.float64]) and \ (type(args[1]) in [float, numpy.float64]) and \ isinstance(args[2], int) and \ (type(args[0]) in [int, float, numpy.float64]) and \ (type(args[0]) in [float, numpy.float64]): shade_min, shade_max, sh_cmap, sh_color, sh_width = args[0:5] args = args[5:] else: raise ValueError("shade_min, shade_max, sh_cmap, sh_color, sh_width, must be present with sh_cmap of types.IntType type and the rest of types.FloatType or numpy.float64 type") # min_color, min_width, max_color, max_width are optional. if len(args) > 4 and \ isinstance(args[0], int) and \ (type(args[1]) in [float, numpy.float64]) and \ isinstance(args[2], int) and \ (type(args[3]) in [float, numpy.float64]): # These 4 args are min_color, min_width, max_color, max_width = args[0:4] args = args[4:] else: # Turn off boundary colouring min_color, min_width, max_color, max_width = (0,0.,0,0.) # rect must be present. if len(args) > 0 and isinstance(args[0], int): rect = args[0] args = args[1:] else: raise ValueError("Missing rect argument") if len(args) > 0 and (type(args[0]) in [type(None), str, types.FunctionType, types.BuiltinFunctionType]): pltr = args[0] # Handle the string names for the callbacks though specifying the # built-in function name directly (without the surrounding quotes) # or specifying any user-defined transformation function # (following above rules) works fine too. if isinstance(pltr, str): if pltr == "pltr0": pltr = pltr0 elif pltr == "pltr1": pltr = pltr1 elif pltr == "pltr2": pltr = pltr2 else: raise ValueError("pltr string is unrecognized") args = args[1:] # Handle pltr_data or separate xg, yg, [wrap] if len(args) == 0: # Default pltr_data pltr_data = None elif len(args) == 1: #Must be pltr_data pltr_data = args[0] args = args[1:] elif len(args) >= 2: xg = numpy.asarray(args[0]) if len(xg.shape) < 1 or len(xg.shape) > 2: raise ValueError("xg must be 1D or 2D array") yg = numpy.asarray(args[1]) if len(yg.shape) != len(xg.shape): raise ValueError("yg must have same number of dimensions as xg") args = args[2:] # wrap only relevant if xg and yg specified. if len(args) > 0: if isinstance(args[0], int): wrap = args[0] args = args[1:] if len(xg.shape) == 2 and len(yg.shape) == 2 and \ z.shape == xg.shape and z.shape == yg.shape: # handle wrap if wrap == 1: z = numpy.resize(z, (z.shape[0]+1, z.shape[1])) xg = numpy.resize(xg, (xg.shape[0]+1, xg.shape[1])) yg = numpy.resize(yg, (yg.shape[0]+1, yg.shape[1])) elif wrap == 2: z = numpy.transpose(numpy.resize( \ numpy.transpose(z), (z.shape[1]+1, z.shape[0]))) xg = numpy.transpose(numpy.resize( \ numpy.transpose(xg), (xg.shape[1]+1, xg.shape[0]))) yg = numpy.transpose(numpy.resize( \ numpy.transpose(yg), (yg.shape[1]+1, yg.shape[0]))) elif wrap != 0: raise ValueError("Invalid wrap specifier, must be 0, 1 or 2.") elif wrap != 0: raise ValueError("Non-zero wrap specified and xg and yg are not 2D arrays") else: raise ValueError("Specified wrap is not an integer") pltr_data = (xg, yg) else: # default is identity transformation pltr = pltr0 pltr_data = None if len(args) > 0: raise ValueError("Too many arguments for plshade") _plshade(z, xmin, xmax, ymin, ymax, \ shade_min, shade_max, sh_cmap, sh_color, sh_width, \ min_color, min_width, max_color, max_width, rect, pltr, pltr_data) plshade.__doc__ = _plshade.__doc__ # Redefine plscmap1l to have the user-friendly interface # Allowable syntaxes: # plscmap1l(itype, pos, coord1, coord2, coord3[, alt_hue_path]) _plscmap1l = plscmap1l def plscmap1l(itype, pos, coord1, coord2, coord3, *args): pos = numpy.asarray(pos) if len(pos.shape) != 1: raise ValueError("Expected 1D pos array") if len(args) == 0: # Default alt_hue_path alt_hue_path = numpy.zeros(pos.shape[0]-1,dtype="int") elif len(args) == 1: alt_hue_path = numpy.asarray(args[0]) else: raise ValueError("Too many arguments to plscmap1l") _plscmap1l(itype, pos, coord1, coord2, coord3, alt_hue_path) plscmap1l.__doc__ = _plscmap1l.__doc__