From: <and...@us...> - 2008-08-13 22:27:21
|
Revision: 8642 http://plplot.svn.sourceforge.net/plplot/?rev=8642&view=rev Author: andrewross Date: 2008-08-13 22:27:30 +0000 (Wed, 13 Aug 2008) Log Message: ----------- Add python support for plimagefr. Update example 20 to use this (consistent with C version). Modified Paths: -------------- trunk/bindings/python/plplot.py.Numeric trunk/bindings/python/plplot.py.numpy trunk/bindings/python/plplotcmodule.i trunk/bindings/swig-support/plplotcapi.i trunk/examples/python/xw20.py Modified: trunk/bindings/python/plplot.py.Numeric =================================================================== --- trunk/bindings/python/plplot.py.Numeric 2008-08-13 16:02:19 UTC (rev 8641) +++ trunk/bindings/python/plplot.py.Numeric 2008-08-13 22:27:30 UTC (rev 8642) @@ -1,4 +1,5 @@ # Copyright 2002 Gary Bishop and Alan W. Irwin +# Copyright 2008 Andrew Ross # This file is part of PLplot. # PLplot is free software; you can redistribute it and/or modify @@ -251,6 +252,99 @@ _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 = Numeric.asarray(img) + + if len(img.shape) != 2: + raise ValueError, "Expected 2D img array" + + if len(args) >= 8 : + for i in range(8) : + if (type(args[i]) != types.FloatType and type(args[i]) != types.IntType) : + 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 ( \ + type(args[0]) == types.StringType 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 type(pltr) == types.StringType: + 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 = Numeric.asarray(args[0]) + if len(xg.shape) < 1 or len(xg.shape) > 2: + raise ValueError, "xg must be 1D or 2D array" + yg = Numeric.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 type(args[0]) == types.IntType: + 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 = Numeric.resize(img, (img.shape[0]+1, u.shape[1])) + xg = Numeric.resize(xg, (xg.shape[0]+1, xg.shape[1])) + yg = Numeric.resize(yg, (yg.shape[0]+1, yg.shape[1])) + elif wrap == 2: + img = Numeric.transpose(Numeric.resize( \ + Numeric.transpose(img), (img.shape[1]+1, img.shape[0]))) + xg = Numeric.transpose(Numeric.resize( \ + Numeric.transpose(xg), (xg.shape[1]+1, xg.shape[0]))) + yg = Numeric.transpose(Numeric.resize( \ + Numeric.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 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: Modified: trunk/bindings/python/plplot.py.numpy =================================================================== --- trunk/bindings/python/plplot.py.numpy 2008-08-13 16:02:19 UTC (rev 8641) +++ trunk/bindings/python/plplot.py.numpy 2008-08-13 22:27:30 UTC (rev 8642) @@ -1,4 +1,5 @@ # Copyright 2002 Gary Bishop and Alan W. Irwin +# Copyright 2008 Andrew Ross # This file is part of PLplot. # PLplot is free software; you can redistribute it and/or modify @@ -251,6 +252,101 @@ _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 (type(args[i]) != types.FloatType and \ + type(args[i]) != numpy.float64 and \ + type(args[i]) != types.IntType) : + 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 ( \ + type(args[0]) == types.StringType 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 type(pltr) == types.StringType: + 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 type(args[0]) == types.IntType: + 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 identity transformation + pltr = pltr0 + 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: @@ -265,10 +361,10 @@ raise ValueError, "Expected 2D z array" if len(args) > 4 and \ - (type(args[0]) == types.FloatType or type(args[0]) == types.IntType) and \ - (type(args[1]) == types.FloatType or type(args[1]) == types.IntType) and \ - (type(args[2]) == types.FloatType or type(args[2]) == types.IntType) and \ - (type(args[3]) == types.FloatType or type(args[3]) == types.IntType): + (type(args[0]) == types.FloatType or type(args[0]) == numpy.float64 or type(args[0]) == types.IntType) and \ + (type(args[1]) == types.FloatType or type(args[1]) == numpy.float64 or type(args[1]) == types.IntType) and \ + (type(args[2]) == types.FloatType or type(args[2]) == numpy.float64 or type(args[2]) == types.IntType) and \ + (type(args[3]) == types.FloatType or type(args[3]) == numpy.float64 or type(args[3]) == types.IntType): # These 4 args are xmin, xmax, ymin, ymax xmin, xmax, ymin, ymax = args[0:4] args = args[4:] Modified: trunk/bindings/python/plplotcmodule.i =================================================================== --- trunk/bindings/python/plplotcmodule.i 2008-08-13 16:02:19 UTC (rev 8641) +++ trunk/bindings/python/plplotcmodule.i 2008-08-13 22:27:30 UTC (rev 8642) @@ -489,7 +489,7 @@ static PLcGrid tmpGrid1; static PLcGrid2 tmpGrid2; - PLcGrid* marshal_PLcGrid1(PyObject* input) { + PLcGrid* marshal_PLcGrid1(PyObject* input, int isimg) { /* fprintf(stderr, "marshal PLcGrid1\n"); */ if(!PySequence_Check(input) || PySequence_Size(input) != 2) { PyErr_SetString(PyExc_ValueError, "Expected a sequence of two arrays."); @@ -505,10 +505,18 @@ } tmpGrid1.nx = pltr_xg->dimensions[0]; tmpGrid1.ny = pltr_yg->dimensions[0]; - if(Xlen != tmpGrid1.nx || Ylen != tmpGrid1.ny) { - PyErr_SetString(PyExc_ValueError, "pltr arguments must have X and Y dimensions of first arg."); - return NULL; + if (isimg == 0) { + if(Xlen != tmpGrid1.nx || Ylen != tmpGrid1.ny) { + PyErr_SetString(PyExc_ValueError, "pltr arguments must have X and Y dimensions of first arg."); + return NULL; + } } + else { + if(Xlen != tmpGrid1.nx-1 || Ylen != tmpGrid1.ny-1) { + PyErr_SetString(PyExc_ValueError, "pltr arguments must have X and Y dimensions of first arg + 1."); + return NULL; + } + } tmpGrid1.xg = (PLFLT*)pltr_xg->data; tmpGrid1.yg = (PLFLT*)pltr_yg->data; return &tmpGrid1; @@ -520,7 +528,7 @@ Py_DECREF(pltr_yg); } - PLcGrid2* marshal_PLcGrid2(PyObject* input) { + PLcGrid2* marshal_PLcGrid2(PyObject* input, int isimg) { int i, size; /* fprintf(stderr, "marshal PLcGrid2\n"); */ if(!PySequence_Check(input) || PySequence_Size(input) != 2) { @@ -542,10 +550,18 @@ } tmpGrid2.nx = pltr_xg->dimensions[0]; tmpGrid2.ny = pltr_xg->dimensions[1]; - if(Xlen != tmpGrid2.nx || Ylen != tmpGrid2.ny) { - PyErr_SetString(PyExc_ValueError, "pltr arguments must have X and Y dimensions of first arg."); - return NULL; + if (isimg == 0) { + if(Xlen != tmpGrid2.nx || Ylen != tmpGrid2.ny) { + PyErr_SetString(PyExc_ValueError, "pltr arguments must have X and Y dimensions of first arg."); + return NULL; + } } + else { + if(Xlen != tmpGrid2.nx-1 || Ylen != tmpGrid2.ny-1) { + PyErr_SetString(PyExc_ValueError, "pltr arguments must have X and Y dimensions of first arg + 1."); + return NULL; + } + } size = sizeof(PLFLT)*tmpGrid2.ny; tmpGrid2.xg = (PLFLT**)malloc(sizeof(PLFLT*)*tmpGrid2.nx); for(i=0; i<tmpGrid2.nx; i++) @@ -566,7 +582,7 @@ %} %typemap(in) PLcGrid* cgrid { - $1 = marshal_PLcGrid1($input); + $1 = marshal_PLcGrid1($input,0); if(!$1) return NULL; } @@ -582,7 +598,7 @@ structure that pltr2 expects */ %typemap(in) PLcGrid2* cgrid { - $1 = marshal_PLcGrid2($input); + $1 = marshal_PLcGrid2($input,0); if(!$1) return NULL; } @@ -775,18 +791,18 @@ python_pltr = 0; } - PLPointer marshal_PLPointer(PyObject* input) { + PLPointer marshal_PLPointer(PyObject* input,int isimg) { PLPointer result = NULL; switch(pltr_type) { case CB_0: break; case CB_1: if(input != Py_None) - result = marshal_PLcGrid1(input); + result = marshal_PLcGrid1(input,isimg); break; case CB_2: if(input != Py_None) - result = marshal_PLcGrid2(input); + result = marshal_PLcGrid2(input,isimg); break; case CB_Python: Py_XINCREF(input); @@ -844,7 +860,7 @@ if($input == Py_None) $1 = NULL; else { - $1 = marshal_PLPointer($input); + $1 = marshal_PLPointer($input,0); } } %typemap(freearg) PLPointer PYOBJECT_DATA { @@ -856,6 +872,23 @@ $1 = NULL; } +/* convert an arbitrary Python object into the void* pointer they want */ +%typemap(in) PLPointer PYOBJECT_DATA_img { + if($input == Py_None) + $1 = NULL; + else { + $1 = marshal_PLPointer($input,1); + } +} +%typemap(freearg) PLPointer PYOBJECT_DATA_img { + cleanup_PLPointer(); +} + +/* you can omit the data too */ +%typemap(default) PLPointer PYOBJECT_DATA_img { + $1 = NULL; +} + /* marshall the f2eval function pointer argument */ %typemap(in) f2eval_func f2eval { /* it must be a callable */ Modified: trunk/bindings/swig-support/plplotcapi.i =================================================================== --- trunk/bindings/swig-support/plplotcapi.i 2008-08-13 16:02:19 UTC (rev 8641) +++ trunk/bindings/swig-support/plplotcapi.i 2008-08-13 22:27:30 UTC (rev 8642) @@ -171,7 +171,7 @@ #ifdef SWIG_PYTHON #define SWIG_OBJECT_DATA PYOBJECT_DATA -#define SWIG_OBJECT_DATA_img PYOBJECT_DATA +#define SWIG_OBJECT_DATA_img PYOBJECT_DATA_img #define pltr_img pltr #else #define SWIG_OBJECT_DATA OBJECT_DATA Modified: trunk/examples/python/xw20.py =================================================================== --- trunk/examples/python/xw20.py 2008-08-13 16:02:19 UTC (rev 8641) +++ trunk/examples/python/xw20.py 2008-08-13 22:27:30 UTC (rev 8642) @@ -4,9 +4,6 @@ from plplot_py_demos import * -import os.path -import sys - XDIM = 260 YDIM = 220 @@ -152,7 +149,16 @@ else: # Driver has no xormod capability, just do nothing return [0, xi, xe, yi, ye] + +def mypltr(x, y, stretch): + x0 = (stretch[0] + stretch[1])*0.5 + y0 = (stretch[2] + stretch[3])*0.5 + dy = (stretch[3] - stretch[2])*0.5 + result0 = x0 + multiply.outer((x0-x),(1.0 - stretch[4]*cos((y-y0)/dy*pi*0.5))) + result1 = multiply.outer(ones(len(x)),y) + return array((result0, result1)) + # main # # @@ -190,9 +196,9 @@ r = sqrt( multiply.outer(x*x,ones(YDIM)) + multiply.outer(ones(XDIM),y*y)) + 1e-3 z = sin(r) / r - pllab("No, an amplitude clipped \"sombrero\"", "", "Saturn?"); - plptex(2., 2., 3., 4., 0., "Transparent image"); - plimage(z, 0., 2.*pi, 0, 3.*pi, 0.05, 1.,0., 2.*pi, 0, 3.*pi); + pllab("No, an amplitude clipped \"sombrero\"", "", "Saturn?") + plptex(2., 2., 3., 4., 0., "Transparent image") + plimage(z, 0., 2.*pi, 0, 3.*pi, 0.05, 1.,0., 2.*pi, 0, 3.*pi) # Save the plot if (f_name != ""): @@ -249,8 +255,34 @@ plenv(xi, xe, ye, yi, 1, -1) plimage(img, 1., width, 1., height, 0., 0., xi, xe, ye, yi) pladv(0) - plend() - sys.exit(0) + # Base the dynamic range on the image contents. + img_min = min(img.flat) + img_max = max(img.flat) + + # Draw a saturated version of the original image. Only use the middle 50% + # of the image's full dynamic range. + plcol0(2) + plenv(0, width, 0, height, 1, -1) + pllab("", "", "Reduced dynamic range image example") + plimagefr(img, 0., width, 0., height, 0., 0., img_min + img_max * 0.25, \ + img_max - img_max * 0.25) + + # Draw a distorted version of the original image, showing its full dynamic range. + plenv(0, width, 0, height, 1, -1) + pllab("", "", "Distorted image example") + + stretch = zeros(5) + stretch[1] = width + stretch[3] = height + stretch[4] = 0.5 + + xg = mypltr(arange(width+1),arange(height+1),stretch)[0] + yg = mypltr(arange(width+1),arange(height+1),stretch)[1] + plimagefr(img, 0., width, 0., height, 0., 0., img_min, img_max, \ + pltr2, xg, yg) + pladv(0) + + main() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |