home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-11-06 | 54.6 KB | 2,483 lines | [TEXT/RLAB] |
- #
- # New plot.r for use with PLPLOT library.
- # The help files for these functions are in
- # misc/plhelp
- #
-
- # plplot.r
-
- # This file is a part of RLaB ("Our"-LaB)
- # Copyright (C) 1994 Ian R. Searle
-
- # This program is free software; you can redistribute it and/or modify
- # it under the terms of the GNU General Public License as published by
- # the Free Software Foundation; either version 2 of the License, or
- # (at your option) any later version.
-
- # This program 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 General Public License for more details.
-
- # You should have received a copy of the GNU General Public License
- # along with this program; if not, write to the Free Software
- # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- # See the file ../COPYING
-
- #
- # If your system does not deal with Infs and NaNs well, then
- # uncomment the following lines.
- #
-
- # static (isinf, isnan)
- #
- # isinf = function ( A ) { return (0); };
- # isnan = function ( A ) { return (0); };
-
- static (WIN) # The static plot window structure
- static (P) # The active/current plot window
-
- #
- # Static (private) functions. For use from within
- # this file only.
- #
-
- static (create_plot_object)
- static (check_plot_object)
- static (xy_scales)
- static (x_scales)
- static (y_scales)
- static (z_scales)
- static (XYZ_scales)
- static (list_scales)
- static (list_sort)
- static (hist_scales)
- static (plot_matrix)
- static (plot_list)
- static (check_3d_list)
- static (find_char)
- static (get_style)
- static (make_legend)
- static (plhold_first)
-
- #
- # Defaults
- #
-
- static (grid_x_default, grid_y_default)
- static (grid_3x_default, grid_3y_default, grid_3z_default)
-
- grid_x_default = "bcnst";
- grid_y_default = "bcnstv";
- grid_3x_default = "bnstu";
- grid_3y_default = "bnstu";
- grid_3z_default = "bcdmnstuv";
-
- static (subplot_f)
- subplot_f = 0;
-
- #
- # Create the default plot-object.
- # Initialize to all the default values
- #
-
- if (!exist (WIN))
- {
- # Create the plot-object list
- WIN = <<>>;
- }
-
- create_plot_object = function ( N, nx, ny )
- {
- if (!exist (N)) { N = 0; }
-
- pobj = <<>>;
- pobj.subplot = 0; # The current subplot no.
- pobj.nplot = nx*ny; # Total no. of plots on window
-
- pobj.fontld = 0; # Loaded extended fonts?
-
- for (i in 1:(nx*ny))
- {
- pobj.style.[i] = "line"; # The type/style of plot to draw
- pobj.pstyle[i] = 1; # The point-style
- pobj.nbin[i] = 1j; # The number of bins for a histogram
- pobj.width[i] = 1; # The pen width for current plot
- pobj.font[i] = 1; # The current font
- pobj.xlabel[i] = "";
- pobj.ylabel[i] = "";
- pobj.zlabel[i] = "";
- pobj.title[i] = "";
- pobj.orientation[i] = "portrait";
- pobj.desc.[i] = "default"; # The legend description
- pobj.gridx[i] = grid_x_default; # Plot axes style, 2D-X
- pobj.gridy[i] = grid_y_default; # Plot axes style, 2D-Y
- pobj.grid3x[i] = grid_3x_default; # Plot axes style, 3D-X
- pobj.grid3y[i] = grid_3y_default; # Plot axes style, 3D-Y
- pobj.grid3z[i] = grid_3z_default; # Plot axes style, 3D-Z
- pobj.aspect[i] = 0; # Plot aspect style
- pobj.alt[i] = 60;
- pobj.az[i] = 45;
-
- pobj.xmin[i] = 1j;
- pobj.xmax[i] = 1j;
- pobj.ymin[i] = 1j;
- pobj.ymax[i] = 1j;
- pobj.zmin[i] = 1j;
- pobj.zmax[i] = 1j;
-
- pobj.page.xp = 0;
- pobj.page.yp = 0;
- pobj.xleng = 400;
- pobj.yleng = 300;
- pobj.xoff = 200;
- pobj.yoff = 200;
-
- for (j in 1:14) { pobj.color[i;j] = j; }
- for (j in 1:8) { pobj.lstyle[i;j] = j; }
- }
-
- #
- # Save the newly generated plot-object
- # in a list of plot-objects.
-
- WIN.[N] = pobj;
- };
-
- ##############################################################################
- #
- # Check to make sure a plot-object exists. If one
- # does not exist, create it.
- #
-
- check_plot_object = function ()
- {
- if (length (WIN) == 0)
- {
- pstart();
- return 0;
- }
- return 1;
- };
-
- ##############################################################################
- #
- # Set the current plot window
- # Default value = 0
- #
-
- pwin = function ( N )
- {
- check_plot_object ();
- if (!exist (N)) { N = 0; }
-
- # Check to make sure N is valid
-
- for (i in members (WIN))
- {
- if (N == strtod (i))
- {
- _plsstrm (N);
- return P = N;
- }
- }
- printf ("pwin: invalid argument, N = %i\n", N);
- printf (" valid values are:\n");
- WIN?
- };
-
- ##############################################################################
- #
- # Show the current plot-window, and the possibilities
- #
-
- showpwin = function ( all )
- {
- if (length (WIN) == 0)
- {
- printf ("No plot objects\n");
- return 0;
- }
-
- printf ("Current plot-window is:\t\t%i\n", P);
- printf ("Available plot windows are:\t");
- for (i in members (WIN))
- {
- printf ("%s ", i);
- }
- printf ("\n");
-
- if (exist (all))
- {
- for (i in members (WIN.[P]))
- {
- WIN.[P].[i]
- }
- }
- };
-
- ##############################################################################
- #
- # Set/start/select the plot device
- #
-
- pstart = function ( nx, ny, dev )
- {
- if (!exist (nx)) { nx = 1; }
- if (!exist (ny)) { ny = 1; }
- if (!exist (dev)) { dev = "?"; }
-
- # Create the plot-object
- # First, figure out the index
- if (!exist (P))
- {
- P = 0;
- else
- P = P + 1;
- }
-
- create_plot_object (P, nx, ny);
- _plsstrm (P);
-
- #_plscolbg (255,255,255); # white
- # Default window size for X
- _plspage (0, 0, 400, 300, 200, 200);
-
- # Start up the plot-window
- _plstart (dev, nx, ny);
-
- _plwid (8);
-
- # Turn between plot pause off
- _plspause (0);
- _pltext ();
-
- return P;
- };
-
- ##############################################################################
- #
- # Close a plot device. We must destroy the current plot-object
- # And switch the output stream back to the default.
- #
-
- pclose = function ()
- {
- if (size (WIN) > 1)
- {
- #
- # Clear WIN.[P] and reset P to 1st plot-window
- #
-
- clear (WIN.[P]);
- _plend1 ();
- _plsstrm (strtod (members (WIN)[1]));
- P = strtod (members (WIN)[1]);
- else
- if (exist (WIN.[P]))
- {
- clear (WIN.[P]);
- clear (P);
- }
- _plend1 ();
- }
- };
-
- ##############################################################################
- #
- # Close ALL the plot-windows
- #
-
- pend = function ()
- {
- _plend ();
- if (exist (WIN)) { clear (WIN); }
- if (exist (P)) { clear (P); }
- WIN = <<>>;
- };
-
- ##############################################################################
- #
- # Change plot aspect ratio
- #
-
- plaspect = function ( aspect )
- {
- check_plot_object ();
- i = mod (WIN.[P].subplot, WIN.[P].nplot) + 1;
- if (!exist (aspect))
- {
- WIN.[P].aspect[i] = 0;
- else
- WIN.[P].aspect[i] = aspect;
- }
- };
-
- ##############################################################################
- #
- # Change plot line style
- #
-
- plstyle = function ( style )
- {
- check_plot_object ();
- i = mod (WIN.[P].subplot, WIN.[P].nplot) + 1;
-
- if (exist (style))
- {
- if (class (style) == "string")
- {
- WIN.[P].style.[i] = style;
- }
- return 1;
- }
- WIN.[P].style.[i] = "line";
- };
-
- ##############################################################################
- #
- # Get the right value of line-style
- #
-
- get_style = function ( STY, K )
- {
- local (sty);
- sty = mod(K, STY.n);
- if(sty == 0)
- {
- sty = STY.n;
- }
- return STY[sty];
- };
-
- ##############################################################################
- #
- # Change fonts
- #
-
- plfont = function ( font )
- {
- check_plot_object ();
- i = mod (WIN.[P].subplot, WIN.[P].nplot) + 1;
-
- if (!exist (font)) { font = 1; }
-
- if (WIN.[P].fontld == 0)
- {
- _plfontld (1);
- WIN.[P].fontld = 1;
- }
-
- WIN.[P].font[i] = font;
- return P;
- };
-
- ##############################################################################
- #
- # Change pen width
- #
-
- plwid = function ( width )
- {
- check_plot_object ();
- i = mod (WIN.[P].subplot, WIN.[P].nplot) + 1;
-
- if (!exist (width)) { width = 1; }
- WIN.[P].width[i] = width;
- return P;
- };
-
- ##############################################################################
- #
- # Place some text on the plot
- #
-
- plptex = function ( text, x , y , dx , dy , just )
- {
- if (!check_plot_object ())
- {
- printf ("Must use plot() before plptex()\n");
- return 0;
- }
-
- if (!exist (x)) { x = 0; }
- if (!exist (y)) { y = 0; }
- if (!exist (dx)) { dx = abs(x)+1; }
- if (!exist (dy)) { dy = 0; }
- if (!exist (just)) { just = 0; }
-
- _plptex (x, y, dx, dy, just, text);
- };
-
- ##############################################################################
- #
- # Set up the viewing altitude for 3-D plots
- #
-
- plalt = function ( ALT )
- {
- check_plot_object ();
- i = mod (WIN.[P].subplot, WIN.[P].nplot) + 1;
-
- if (exist (ALT))
- {
- WIN.[P].alt[i] = ALT;
- else
- WIN.[P].alt[i] = 60;
- }
- return P;
- };
-
- ##############################################################################
- #
- # Set the viewing azimuth for 3-D plots
- #
-
- plaz = function ( AZ )
- {
- check_plot_object ();
- i = mod (WIN.[P].subplot, WIN.[P].nplot) + 1;
-
- if (exist (AZ))
- {
- WIN.[P].az[i] = AZ;
- else
- WIN.[P].az[i] = 45;
- }
- return P;
- };
-
- ##############################################################################
- #
- # Find a character in a string
- #
-
- find_char = function ( str , char )
- {
- tmp = strsplt (str);
- for (i in 1:tmp.n)
- {
- if (tmp[i] == char)
- {
- return i;
- }
- }
- return 0;
- };
-
- ##############################################################################
- #
- # Sort list element names/labels by numeric order, then string order.
- #
-
- list_sort = function ( L )
- {
- tl = <<>>;
- j = k = 1;
-
- for (i in members (L))
- {
- if (!isnan (strtod (i)))
- {
- num[j] = i;
- j++;
- else
- char[k] = i;
- k++;
- }
- }
-
- # Sort the numeric labels
-
- if (exist (num))
- {
- num = sort (strtod (num)).val;
- tl.num = num;
- }
-
- if (exist (char))
- {
- tl.char = char;
- }
-
- return tl;
- };
-
- ##############################################################################
- #
- # Set the subplot, this overides the action in plot().
- #
-
- subplot = function ( sub )
- {
- check_plot_object ();
-
- if (!exist (sub))
- {
- sub = 0;
- #WIN.[P].subplot = WIN.[P].subplot + 1;
- subplot_f = 0;
- _pladv (0);
- else
- if (sub > WIN.[P].nplot)
- {
- error ("Current window does not have this many subplots");
- }
- WIN.[P].subplot = sub - 1;
- subplot_f = 1;
- _pladv (sub);
- }
- };
-
- ##############################################################################
- #
- # Plot the columns of a matrix (X-Y plot).
- #
- ##############################################################################
-
- plot = function ( data, key )
- {
- check_plot_object ();
-
- p = mod (WIN.[P].subplot, WIN.[P].nplot) + 1; # The current index
- if (!exist (key)) { key = 1; }
-
- #
- # Draw the graph
- # Step through the matrix plotting
- # each column versus the 1st
- #
-
- if (class (data) == "num")
- {
- #
- # Set up the plot basics
- #
-
- if (abs (key) > data.nc)
- {
- error_1 ("plot: KEY argument > M.nc");
- }
-
- _plgra ();
- _plcol (1);
- _pllsty (1);
- _plfont (WIN.[P].font[p]);
- _plwid (WIN.[P].width[p]);
-
- if (!subplot_f)
- {
- _pladv (0); # Advance 1 subplot
- else
- subplot_f = 0; # The user has set the subplot
- }
-
- if (WIN.[P].aspect[p] != 0)
- {
- _plvasp (WIN.[P].aspect[p]);
- else
- _plvsta ();
- }
-
- #
- # Compute scale limits
- #
-
- k = find ((1:data.nc) != abs (key));
- if (key > 0)
- {
- if (data.nc != 1)
- {
- x_scales ( real(data)[;key], p, xmin, xmax );
- y_scales ( real(data)[;k], p, ymin, ymax );
- else
- x_scales ( (1:data.nr)', p, xmin, xmax );
- y_scales ( real(data), p, ymin, ymax );
- }
- else if (key < 0) {
- x_scales ( real(data)[;k], p, xmin, xmax );
- y_scales ( real(data)[;abs(key)], p, ymin, ymax );
- else
- x_scales ( (1:data.nr)', p, xmin, xmax );
- y_scales ( real(data), p, ymin, ymax );
- } }
-
- _plwind (xmin, xmax, ymin, ymax);
- _plbox (WIN.[P].gridx[p], 0, 0, WIN.[P].gridy[p], 0, 0);
- if (plot_matrix ( data, key, p, 0, xmin, xmax, ymin, ymax, ymax-ymin ) < 0)
- {
- return -1;
- }
-
- else if (class (data) == "list") {
-
- _plgra ();
- _plcol (1);
- _pllsty (1);
- _plfont (WIN.[P].font[p]);
- _plwid (WIN.[P].width[p]);
-
- list_scales ( data, key, p, xmin, xmax, ymin, ymax );
-
- if (!subplot_f)
- {
- _pladv (0); # Advance 1 subplot
- else
- subplot_f = 0; # The user has set the subplot
- }
-
- if (WIN.[P].aspect[p] != 0)
- {
- _plvasp (WIN.[P].aspect[p]);
- else
- _plvsta ();
- }
-
- _plwind (xmin, xmax, ymin, ymax);
- _plbox (WIN.[P].gridx[p], 0, 0, WIN.[P].gridy[p], 0, 0);
- if (plot_list ( data, key, p, xmin, xmax, ymin, ymax ) < 0)
- {
- return -1;
- }
-
- else
- error ("plot: un-acceptable argument");
- } }
-
- _pllsty (1);
- _plcol (1);
- _pllab (WIN.[P].xlabel[p], WIN.[P].ylabel[p], WIN.[P].title[p]);
- _plflush ();
- _pltext ();
-
- #
- # Increment the plot no. so that next time
- # we use the correct settings.
- #
-
- WIN.[P].subplot = WIN.[P].subplot + 1;
- return P;
- };
-
- #
- # plhold:
- # Plot some data, and "hold" on for more.
- # Plot the data, setting up the plot as usual the first time.
- # On subsequent plots do not do any setup, just plot some
- # more. plhold_off must be called to finish up.
- #
-
- plhold_first = 1; # True (1) if plhold() has NOT been used.
- # Or if plhold_off() has been used.
- # False (0) if plhold is in use
-
- static (hxmin, hxmax, hymin, hymax)
-
- plhold = function ( data, key )
- {
- check_plot_object ();
-
- p = mod (WIN.[P].subplot, WIN.[P].nplot) + 1; # The current index
- if (!exist (key)) { key = 1; }
- if (abs (key) > data.nc)
- {
- error_1 ("plot: KEY argument > M.nc");
- }
-
- if (plhold_first)
- {
- if (class (data) == "num")
- {
- #
- # Do the setup ONCE
- #
- hxmin = hxmax = hymin = hymax = 0;
- _plgra ();
- _plcol (1);
- _pllsty (1);
- _plfont (WIN.[P].font[p]);
- _plwid (WIN.[P].width[p]);
-
- if (!subplot_f)
- {
- _pladv (0); # Advance 1 subplot
- else
- subplot_f = 0; # The user has set the subplot
- }
-
- if (WIN.[P].aspect[p] != 0)
- {
- _plvasp (WIN.[P].aspect[p]);
- else
- _plvsta ();
- }
-
- xy_scales ( real(data), p, hxmin, hxmax, hymin, hymax );
-
- k = find ((1:data.nc) != abs (key));
- if (key > 0)
- {
- x_scales ( real(data)[;key], p, xmin, xmax );
- if (data.nc != 1)
- {
- y_scales ( real(data)[;k], p, ymin, ymax );
- else
- y_scales ( (1:data.nr)', p, ymin, ymax );
- }
- else if (key < 0) {
- x_scales ( real(data)[;k], p, xmin, xmax );
- y_scales ( real(data)[;abs(key)], p, ymin, ymax );
- else
- x_scales ( (1:data.nr)', p, xmin, xmax );
- y_scales ( real(data), p, ymin, ymax );
- } }
-
- _plwind (hxmin, hxmax, hymin, hymax);
- _plbox (WIN.[P].gridx[p], 0, 0, WIN.[P].gridy[p], 0, 0);
- _pllab (WIN.[P].xlabel[p], WIN.[P].ylabel[p], WIN.[P].title[p]);
- else
- error ("plot: un-acceptable argument");
- }
- plhold_first = 0;
- }
-
- if (plot_matrix ( data, key, p, 0, hxmin, hxmax, hymin, hymax, hymax-hymin ) < 0)
- {
- return -1;
- }
-
- _plcol (1);
- _plflush ();
- _pltext ();
-
- return P;
- };
-
- ##############################################################################
- #
- # Clean up the plotting environment and get ready
- # for normal interactive usage.
- #
-
- plhold_off = function ( )
- {
- p = mod (WIN.[P].subplot, WIN.[P].nplot) + 1; # The current index
- plhold_first = 1;
- _plcol (1);
- _plflush ();
- _pltext ();
- WIN.[P].subplot = WIN.[P].subplot + 1;
- return P;
- };
-
- ##############################################################################
- #
- # Plot a 3-Dimensional graph. The data is composed in a list, with
- # elements `x', `y', and `z'. x and y are single-dimension arrays
- # (row or column matrices), and z is a two-dimensional array. The
- # array z, is a function of x and y: z = f(x,y). Thus, the values in
- # the array x can be thought of a "row-labels", and the values of y
- # can be thought of as "column-lables" for the 2-dimensioal array z.
- #
- # At present plot3 can plot 3 distinct lists. Each list may have
- # different X, Y, and Z scales.
- #
- ##############################################################################
-
- plot3 = function ( L31, L32, L33 )
- {
- check_plot_object ();
-
- #
- # 1st check list contents
- #
-
- if (exist (L31)) { check_3d_list (L31); }
- if (exist (L32)) { check_3d_list (L32); }
- if (exist (L33)) { check_3d_list (L33); }
-
- p = mod (WIN.[P].subplot, WIN.[P].nplot) + 1; # The current index
-
- #
- # Figure out the scale limits.
- # Needs improvement!
- #
-
- xmin = xmax = ymin = ymax = zmin = zmax = 0;
- if (exist (L31))
- {
- XYZ_scales (L31.x, L31.y, L31.z, p, Xmin, Xmax, Ymin, Ymax, Zmin, Zmax);
- xmin = Xmin; xmax = Xmax;
- ymin = Ymin; ymax = Ymax;
- zmin = Zmin; zmax = Zmax;
- }
- if (exist (L32))
- {
- XYZ_scales (L32.x, L32.y, L32.z, p, Xmin, Xmax, Ymin, Ymax, Zmin, Zmax);
- if (Xmin < xmin) { xmin = Xmin; } if (Xmax > xmax) { xmax = Xmax; }
- if (Ymin < ymin) { ymin = Ymin; } if (Ymax > ymax) { ymax = Ymax; }
- if (Zmin < zmin) { zmin = Zmin; } if (Zmax > zmax) { zmax = Zmax; }
- }
- if (exist (L33))
- {
- XYZ_scales (L33.x, L33.y, L33.z, p, Xmin, Xmax, Ymin, Ymax, Zmin, Zmax);
- if (Xmin < xmin) { xmin = Xmin; } if (Xmax > xmax) { xmax = Xmax; }
- if (Ymin < ymin) { ymin = Ymin; } if (Ymax > ymax) { ymax = Ymax; }
- if (Zmin < zmin) { zmin = Zmin; } if (Zmax > zmax) { zmax = Zmax; }
- }
-
- _plgra ();
- _plcol (1);
- _pllsty (1);
- _plfont (WIN.[P].font[p]);
- _plwid (WIN.[P].width[p]);
-
- basex = 2; basey = 2; height = 4;
- xmin2d = -2.0; xmax2d = 2.0;
- ymin2d = -3.0; ymax2d = 5.0;
-
- _plenv (xmin2d, xmax2d, ymin2d, ymax2d, 0, -2);
- _plw3d (basex, basey, height, xmin, xmax, ymin, ymax, ...
- zmin, zmax, WIN.[P].alt[p], WIN.[P].az[p]);
- _plbox3 (WIN.[P].grid3x[p], WIN.[P].xlabel[p], 0, 0, ...
- WIN.[P].grid3y[p], WIN.[P].ylabel[p], 0, 0, ...
- WIN.[P].grid3z[p], WIN.[P].zlabel[p], 0, 0);
- _plmtex ("t", 1.0, 0.5, 0.5, WIN.[P].title[p]);
-
- if (exist (L31))
- {
- if (find_char (WIN.[P].grid3x[p], "l"))
- { x = log10 (real (L31.x)); else x = real (L31.x); }
- if (find_char (WIN.[P].grid3y[p], "l"))
- { y = log10 (real (L31.y)); else y = real (L31.y); }
- if (find_char (WIN.[P].grid3z[p], "l"))
- { z = log10 (real (L31.z)); else z = real (L31.z); }
-
- _plcol (2);
- _plot3d (x, y, z, L31.x.n, L31.y.n, 3, 0);
- }
- if (exist (L32))
- {
- if (find_char (WIN.[P].grid3x[p], "l"))
- { x = log10 (real (L32.x)); else x = real (L32.x); }
- if (find_char (WIN.[P].grid3y[p], "l"))
- { y = log10 (real (L32.y)); else y = real (L32.y); }
- if (find_char (WIN.[P].grid3z[p], "l"))
- { z = log10 (real (L32.z)); else z = real (L32.z); }
-
- _plcol (3);
- _pllsty (2);
- _plot3d (x, y, z, L32.x.n, L32.y.n, 3, 0);
- }
- if (exist (L33))
- {
- if (find_char (WIN.[P].grid3x[p], "l"))
- { x = log10 (real (L33.x)); else x = real (L33.x); }
- if (find_char (WIN.[P].grid3y[p], "l"))
- { y = log10 (real (L33.y)); else y = real (L33.y); }
- if (find_char (WIN.[P].grid3z[p], "l"))
- { z = log10 (real (L33.z)); else z = real (L33.z); }
-
- _plcol (4);
- _pllsty (3);
- _plot3d (x, y, z, L33.x.n, L33.y.n, 3, 0);
- }
-
- _plflush ();
- _pltext ();
-
- #
- # Increment the plot no. so that next time
- # we use the correct settings.
- #
-
- WIN.[P].subplot = WIN.[P].subplot + 1;
-
- return P;
- };
-
- ##############################################################################
- #
- # Plot a 3-Dimensional graph. The data is composed in a list, with
- # elements `x', `y', and `z'. x and y are single-dimension arrays
- # (row or column matrices), and z is a two-dimensional array. The
- # array z, is a function of x and y: z = f(x,y). Thus, the values in
- # the array x can be thought of a "row-labels", and the values of y
- # can be thought of as "column-lables" for the 2-dimensioal array z.
- #
- # At present plmesh can plot 3 distinct lists. Each list may have
- # different X, Y, and Z scales.
- #
- ##############################################################################
-
- plmesh = function ( L31, L32, L33 )
- {
- check_plot_object ();
-
- #
- # 1st check list contents
- #
-
- if (exist (L31)) { check_3d_list (L31); }
- if (exist (L32)) { check_3d_list (L32); }
- if (exist (L33)) { check_3d_list (L33); }
-
- p = mod (WIN.[P].subplot, WIN.[P].nplot) + 1; # The current index
-
- #
- # Figure out the scale limits.
- # Needs improvement!
- #
-
- xmin = xmax = ymin = ymax = zmin = zmax = 0;
- if (exist (L31))
- {
- XYZ_scales (L31.x, L31.y, L31.z, p, Xmin, Xmax, Ymin, Ymax, Zmin, Zmax);
- xmin = Xmin; xmax = Xmax;
- ymin = Ymin; ymax = Ymax;
- zmin = Zmin; zmax = Zmax;
- }
- if (exist (L32))
- {
- XYZ_scales (L32.x, L32.y, L32.z, p, Xmin, Xmax, Ymin, Ymax, Zmin, Zmax);
- if (Xmin < xmin) { xmin = Xmin; } if (Xmax > xmax) { xmax = Xmax; }
- if (Ymin < ymin) { ymin = Ymin; } if (Ymax > ymax) { ymax = Ymax; }
- if (Zmin < zmin) { zmin = Zmin; } if (Zmax > zmax) { zmax = Zmax; }
- }
- if (exist (L33))
- {
- XYZ_scales (L33.x, L33.y, L33.z, p, Xmin, Xmax, Ymin, Ymax, Zmin, Zmax);
- if (Xmin < xmin) { xmin = Xmin; } if (Xmax > xmax) { xmax = Xmax; }
- if (Ymin < ymin) { ymin = Ymin; } if (Ymax > ymax) { ymax = Ymax; }
- if (Zmin < zmin) { zmin = Zmin; } if (Zmax > zmax) { zmax = Zmax; }
- }
-
- _plgra ();
- _plcol (1);
- _pllsty (1);
- _plfont (WIN.[P].font[p]);
- _plwid (WIN.[P].width[p]);
-
- basex = 2; basey = 2; height = 4;
- xmin2d = -2.0; xmax2d = 2.0;
- ymin2d = -3.0; ymax2d = 5.0;
-
- _plenv (xmin2d, xmax2d, ymin2d, ymax2d, 0, -2);
- _plw3d (basex, basey, height, xmin, xmax, ymin, ymax, ...
- zmin, zmax, WIN.[P].alt[p], WIN.[P].az[p]);
- _plbox3 (WIN.[P].grid3x[p], WIN.[P].xlabel[p], 0, 0, ...
- WIN.[P].grid3y[p], WIN.[P].ylabel[p], 0, 0, ...
- WIN.[P].grid3z[p], WIN.[P].zlabel[p], 0, 0);
- _plmtex ("t", 1.0, 0.5, 0.5, WIN.[P].title[p]);
-
- if (exist (L31))
- {
- if (find_char (WIN.[P].grid3x[p], "l"))
- { x = log10 (real (L31.x)); else x = real (L31.x); }
- if (find_char (WIN.[P].grid3y[p], "l"))
- { y = log10 (real (L31.y)); else y = real (L31.y); }
- if (find_char (WIN.[P].grid3z[p], "l"))
- { z = log10 (real (L31.z)); else z = real (L31.z); }
-
- _plcol (2);
- _plmesh (x, y, z, L31.x.n, L31.y.n, 3);
- }
- if (exist (L32))
- {
- if (find_char (WIN.[P].grid3x[p], "l"))
- { x = log10 (real (L32.x)); else x = real (L32.x); }
- if (find_char (WIN.[P].grid3y[p], "l"))
- { y = log10 (real (L32.y)); else y = real (L32.y); }
- if (find_char (WIN.[P].grid3z[p], "l"))
- { z = log10 (real (L32.z)); else z = real (L32.z); }
-
- _plcol (3);
- _pllsty (2);
- _plmesh (x, y, z, L32.x.n, L32.y.n, 3);
- }
- if (exist (L33))
- {
- if (find_char (WIN.[P].grid3x[p], "l"))
- { x = log10 (real (L33.x)); else x = real (L33.x); }
- if (find_char (WIN.[P].grid3y[p], "l"))
- { y = log10 (real (L33.y)); else y = real (L33.y); }
- if (find_char (WIN.[P].grid3z[p], "l"))
- { z = log10 (real (L33.z)); else z = real (L33.z); }
-
- _plcol (4);
- _pllsty (3);
- _plmesh (x, y, z, L33.x.n, L33.y.n, 3);
- }
-
- _plflush ();
- _pltext ();
-
- #
- # Increment the plot no. so that next time
- # we use the correct settings.
- #
-
- WIN.[P].subplot = WIN.[P].subplot + 1;
-
- return P;
- };
-
- ##############################################################################
- #
- # Plot contours. The data is composed in a list, with
- # elements `x', `y', and `z'. x and y are single-dimension arrays
- # (row or column matrices), and z is a two-dimensional array. The
- # array z, is a function of x and y: z = f(x,y). Thus, the values in
- # the array x can be thought of a "row-labels", and the values of y
- # can be thought of as "column-lables" for the 2-dimensioal array z.
- #
- ##############################################################################
-
- plcont = function ( CL )
- {
- check_plot_object ();
-
- #
- # 1st check list contents
- #
-
- if (exist (CL)) { check_3d_list (CL); }
-
- p = mod (WIN.[P].subplot, WIN.[P].nplot) + 1; # The current index
-
- #
- # Figure out the scale limits.
- # Needs improvement!
- #
-
- xmin = xmax = ymin = ymax = zmin = zmax = 0;
- if (exist (CL))
- {
- XYZ_scales (CL.x, CL.y, CL.z, p, Xmin, Xmax, Ymin, Ymax, Zmin, Zmax);
- if (Xmin < xmin) { xmin = Xmin; } if (Xmax > xmax) { xmax = Xmax; }
- if (Ymin < ymin) { ymin = Ymin; } if (Ymax > ymax) { ymax = Ymax; }
- if (Zmin < zmin) { zmin = Zmin; } if (Zmax > zmax) { zmax = Zmax; }
- }
-
- _plgra ();
- _plcol (1);
- _pllsty (1);
- _plfont (WIN.[P].font[p]);
- _plwid (WIN.[P].width[p]);
-
- #
- # Set up the 1st viewport for drawing the plot.
- #
-
- if (!subplot_f)
- {
- _pladv (0); # Advance 1 subplot
- else
- subplot_f = 0; # The user has set the subplot
- }
-
- _plvpas (0.15, 0.75, 0.15, 0.85, WIN.[P].aspect[p]);
- # _plvpor (0.15, 0.75, 0.15, 0.85);
- _plwind (xmin, xmax, ymin, ymax);
- _plbox (WIN.[P].gridx[p], 0, 0, WIN.[P].gridy[p], 0, 0);
-
- # Convert the data to log data if necessary.
- if (find_char (WIN.[P].gridx[p], "l"))
- { x = log10 (real (CL.x)); else x = real (CL.x); }
- if (find_char (WIN.[P].gridy[p], "l"))
- { y = log10 (real (CL.y)); else y = real (CL.y); }
- z = real (CL.z);
-
- if (exist (CL.clevel))
- {
- clevel = CL.clevel;
- else
- clevel = linspace(zmin, zmax, 10);
- }
-
- #
- # Draw the contours
- #
-
- l = 1;
- for (i in 1:clevel.n)
- {
- k = mod (i-1, 14) + 1;
- j = mod (i-1, 8) + 1;
- _pllsty(j);
- _plcol (1+k);
- if (_plcont (x, y, z, 1, CL.x.n, 1, CL.y.n, clevel[i]))
- {
- llevel[l] = clevel[i];
- l = l + 1;
- }
- }
-
- #
- # Reset color and draw the labels.
- #
-
- _plcol (1);
- _pllab (WIN.[P].xlabel[p], WIN.[P].ylabel[p], WIN.[P].title[p]);
-
- #
- # Draw the contour legend. Use a new viewport to the right
- # of the contour plot.
- #
-
- #_plvpas (0.75, 1.0, 0.15, 0.85, WIN.[P].aspect[p]);
- _plvpor (0.75, 1.0, 0.15, 0.85);
- _plwind (0, 1, 0, 1);
-
- v = 1 - 1/(2*llevel.n);
-
- for (i in 1:llevel.n)
- {
- xl = [0.1, 0.2, 0.3]';
- yl = [v, v, v]';
- v = v - 1/llevel.n;
-
- k = mod (i-1, 14) + 1;
- j = mod (i-1, 8) + 1;
-
- _plcol (1+k);
- _pllsty (j);
-
- _plline (3, xl, yl);
- sprintf (stmp, "%.2g", llevel[i]);
- plptex (stmp, xl[3]+.1, yl[3], , , 0);
- }
-
- # Flush and go back to text mode.
- _plflush ();
- _pltext ();
-
- #
- # Increment the plot no. so that next time
- # we use the correct settings.
- #
-
- WIN.[P].subplot = WIN.[P].subplot + 1;
-
- return P;
- };
-
- ##############################################################################
- #
- # Plot 3-D lines, etc...
- #
-
- pl3d = function ( X, Y, Z, BR )
- {
- local (X, Y, Z, BR)
- check_plot_object ();
-
- p = mod (WIN.[P].subplot, WIN.[P].nplot) + 1; # The current index
-
- #
- # Some basic checks
- #
-
- if ((N = X.n) != Y.n) { error ("pl3d: X and Y must have same length"); }
- if (N != Z.n) { error ("pl3d: X and Z must have same length"); }
-
- if (!exist (BR)) { BR = N; }
- if (mod (N, BR) != 0) { error ("pl3d: X.n must be divisible by BR"); }
- iBR = int (N / BR);
- if (iBR == 1) { k = N; else k = BR; }
-
- #
- # Figure out the scale limits.
- # Needs improvement!
- #
-
- xmin = xmax = ymin = ymax = zmin = zmax = 0;
- XYZ_scales (X, Y, Z, p, xmin, xmax, ymin, ymax, zmin, zmax);
-
- _plgra ();
- _plcol (1);
- _pllsty (1);
- _plfont (WIN.[P].font[p]);
- _plwid (WIN.[P].width[p]);
-
- if (!subplot_f)
- {
- _pladv (0); # Advance 1 subplot
- else
- subplot_f = 0; # The user has set the subplot
- }
-
- if (find_char (WIN.[P].grid3x[p], "l"))
- { X = log10 (real (X)); else X = real (X); }
- if (find_char (WIN.[P].grid3y[p], "l"))
- { Y = log10 (real (Y)); else Y = real (Y); }
- if (find_char (WIN.[P].grid3z[p], "l"))
- { Z = log10 (real (Z)); else Z = real (Z); }
-
- basex = 2; basey = 2; height = 4;
- xmin2d = -2.0; xmax2d = 2.0;
- ymin2d = -3.0; ymax2d = 5.0;
-
- _plvpas (0.15, 0.85, 0.15, 0.85, WIN.[P].aspect[p]);
- _plwind (xmin2d, xmax2d, ymin2d, ymax2d);
- _plw3d (basex, basey, height, xmin, xmax, ymin, ymax, ...
- zmin, zmax, WIN.[P].alt[p], WIN.[P].az[p]);
- _plbox3 (WIN.[P].grid3x[p], WIN.[P].xlabel[p], 0, 0, ...
- WIN.[P].grid3y[p], WIN.[P].ylabel[p], 0, 0, ...
- WIN.[P].grid3z[p], WIN.[P].zlabel[p], 0, 0);
- _plmtex ("t", 1.0, 0.5, 0.5, WIN.[P].title[p]);
-
- _plcol (2);
- for (i in 1:iBR)
- {
- j = [(i-1)*k+1:i*k];
- _plline3 (k, X[j], Y[j], Z[j]);
- }
- _plflush ();
- _pltext ();
-
- #
- # Increment the plot no. so that next time
- # we use the correct settings.
- #
-
- WIN.[P].subplot = WIN.[P].subplot + 1;
-
- return P;
- };
-
- ##############################################################################
- #
- # error bar plot
- #
-
- plerry = function (x, y, y_low, y_high)
- {
- check_plot_object ();
-
- p = mod (WIN.[P].subplot, WIN.[P].nplot) + 1; # The current index
- WIN.[P].desc.[p] = 1j; // use own legend
-
- if (x.nr != y.nr || x.nr != y_low.nr || x.nr != y_high.nr)
- {
- error(" Size inconsistent in plerry.");
- }
- _plgra ();
- _plcol (1);
- _pllsty (1);
- _plfont (WIN.[P].font[p]);
- _plwid (WIN.[P].width[p]);
- xy_scales ( real([x,y,y_low,y_high]), p, xmin, xmax, ymin, ymax );
-
- if (!subplot_f)
- {
- _pladv (0); # Advance 1 subplot
- else
- subplot_f = 0; # The user has set the subplot
- }
-
- if (WIN.[P].aspect[p] != 0)
- {
- _plvasp (WIN.[P].aspect[p]);
- else
- _plvsta ();
- }
-
- _plwind (xmin, xmax, ymin, ymax);
- _plbox (WIN.[P].gridx[p], 0, 0, WIN.[P].gridy[p], 0, 0);
-
- if (plot_matrix ( [x,y], p, 0, xmin, xmax, ymin, ymax, ymax-ymin ) < 0)
- {
- return -1;
- }
-
- _plcol (3);
- _plerry(x.nr, x, y_low, y_high);
- _plcol (1);
- _pllab (WIN.[P].xlabel[p], WIN.[P].ylabel[p], WIN.[P].title[p]);
- _plflush ();
- _pltext ();
-
- #
- # Increment the plot no. so that next time
- # we use the correct settings.
- #
-
- WIN.[P].subplot = WIN.[P].subplot + 1;
- return P;
- };
-
- ##############################################################################
- #
- # Plot a Histogram(s), from the columns of a matrix.
- #
- ##############################################################################
-
- plhist = function ( M , nbin )
- {
- check_plot_object ();
-
- if (!exist (nbin)) { nbin = 10; }
-
- p = mod (WIN.[P].subplot, WIN.[P].nplot) + 1; # The current index
- np = M.nr;
-
- # Compute max/min values of data
-
- ymin = min (min (real (M)));
- ymax = max (max (real (M)));
-
- #
- # Check computed scale limits against user's
- #
-
- if (WIN.[P].ymin[p] != 1j) { ymin = WIN.[P].ymin[p]; }
- if (WIN.[P].ymax[p] != 1j) { ymax = WIN.[P].ymax[p]; }
-
- _plgra ();
- _plcol (1);
- _plfont (WIN.[P].font[p]);
- _plwid (WIN.[P].width[p]);
-
- for (i in 1:M.nc)
- {
- hscale[i] = hist_scales (M[;i], nbin);
- }
-
- if (!subplot_f) {
- _pladv (0); # Advance 1 subplot
- else
- subplot_f = 0; # The user has set the subplot
- }
-
- if (WIN.[P].aspect[p] != 0)
- {
- _plvasp (WIN.[P].aspect[p]);
- else
- _plvsta ();
- }
-
- _plwind (ymin, ymax, 0, max (hscale));
- _plbox (WIN.[P].gridx[p], 0, 0, WIN.[P].gridy[p], 0, 0);
-
- v = max (hscale);
- xmax = ymax;
- for (i in 1:M.nc)
- {
- k = mod (i, 14) + 1;
- _plcol (WIN.[P].color[p;k]);
- _plhist (np, real(M[;i]), ymin, ymax, nbin, 1);
-
- if (!any (any (WIN.[P].desc.[p] == 1j)))
- {
- # Use the default if necessary
- if (WIN.[P].desc.[p][1] == "default")
- {
- desc = "c"+num2str(i);
- else if (WIN.[P].desc.[p].n >= i) {
- desc = WIN.[P].desc.[p][i];
- else
- # Not sure what to do, user has messed up.
- desc = "";
- } }
-
- v = v - max(hscale)/11;
- xl = (ymax-ymin)*[10.5/12, 11/12, 11.5/12]' + ymin;
- yl = [v, v, v]';
-
- _plline (3, xl, yl);
- plptex(desc, xl[1]-(ymax-ymin)/25, yl[3], , , 1);
- }
- }
-
- _plcol (1);
- _pllab (WIN.[P].xlabel[p], WIN.[P].ylabel[p], WIN.[P].title[p]);
- _plflush ();
- _pltext ();
-
- #
- # Increment the plot no. so that next time
- # we use the correct settings.
- #
-
- WIN.[P].subplot = WIN.[P].subplot + 1;
-
- return 1;
- };
-
- ##############################################################################
- #
- # Various support functions for the WIN list
- #
- ##############################################################################
-
- #
- # Replot
- #
-
- replot = function ( )
- {
- check_plot_object ();
- _replot ();
- };
-
- ##############################################################################
- #
- # Set the X-axis label
- #
-
- xlabel = function ( xstr )
- {
- check_plot_object ();
- if (!exist (xstr)) { xstr = ""; }
- i = mod (WIN.[P].subplot, WIN.[P].nplot) + 1;
- WIN.[P].xlabel[i] = xstr;
- };
-
- ##############################################################################
- #
- # Set the Y-axis label
- #
-
- ylabel = function ( xstr )
- {
- check_plot_object ();
- if (!exist (xstr)) { xstr = ""; }
- i = mod (WIN.[P].subplot, WIN.[P].nplot) + 1;
- WIN.[P].ylabel[i] = xstr;
- };
-
- ##############################################################################
- #
- # Set the Z-axis label
- #
-
- zlabel = function ( xstr )
- {
- check_plot_object ();
- if (!exist (xstr)) { xstr = ""; }
- i = mod (WIN.[P].subplot, WIN.[P].nplot) + 1;
- WIN.[P].zlabel[i] = xstr;
- };
-
- ##############################################################################
- #
- # Set the plot-title
- #
-
- ptitle = function ( xstr )
- {
- check_plot_object ();
- if (!exist (xstr)) { xstr = ""; }
- p = mod (WIN.[P].subplot, WIN.[P].nplot) + 1; # The current index
- WIN.[P].title[p] = xstr;
- };
-
- ##############################################################################
- #
- # Set the scale limits.
- #
-
- plimits = function ( xmin, xmax, ymin, ymax, zmin, zmax )
- {
- check_plot_object ();
- i = mod (WIN.[P].subplot, WIN.[P].nplot) + 1;
-
- if (exist (xmin))
- {
- WIN.[P].xmin[i] = xmin;
- else
- WIN.[P].xmin[i] = 1j;
- }
- if (exist (xmax))
- {
- WIN.[P].xmax[i] = xmax;
- else
- WIN.[P].xmax[i] = 1j;
- }
-
- if (exist (ymin))
- {
- WIN.[P].ymin[i] = ymin;
- else
- WIN.[P].ymin[i] = 1j;
- }
- if (exist (ymax))
- {
- WIN.[P].ymax[i] = ymax;
- else
- WIN.[P].ymax[i] = 1j;
- }
-
- if (exist (zmin))
- {
- WIN.[P].zmin[i] = zmin;
- else
- WIN.[P].zmin[i] = 1j;
- }
- if (exist (zmax))
- {
- WIN.[P].zmax[i] = zmax;
- else
- WIN.[P].zmax[i] = 1j;
- }
- };
-
- ##############################################################################
- #
- # Set 2-D grid styles. A not-so-friendly interface.
- #
-
- plgrid = function ( sty_x, sty_y )
- {
- check_plot_object ();
- i = mod (WIN.[P].subplot, WIN.[P].nplot) + 1;
-
- if (exist (sty_x))
- {
- if (class (sty_x) == "string")
- {
- WIN.[P].gridx[i] = sty_x;
- else
- error ("plgrid: requires string argument GRID_STY_X");
- }
- else
- WIN.[P].gridx[i] = grid_x_default;
- }
- if (exist (sty_y))
- {
- if (class (sty_y) == "string")
- {
- WIN.[P].gridy[i] = sty_y;
- else
- error ("plgrid: requires string argument GRID_STY_Y");
- }
- else
- WIN.[P].gridy[i] = grid_y_default;
- }
- };
-
- ##############################################################################
- #
- # Set 3-D grid (axis) styles
- #
-
- plgrid3 = function ( sty_x, sty_y, sty_z )
- {
- check_plot_object ();
- i = mod (WIN.[P].subplot, WIN.[P].nplot) + 1;
- if (exist (sty_x))
- {
- if (class (sty_x) == "string")
- {
- WIN.[P].grid3x[i] = sty_x;
- else
- error ("plgrid3: requires string argument GRID_STY_X");
- }
- else
- WIN.[P].grid3x[i] = grid_3x_default;
- }
- if (exist (sty_y))
- {
- if (class (sty_y) == "string")
- {
- WIN.[P].grid3y[i] = sty_y;
- else
- error ("plgrid3: requires string argument GRID_STY_Y");
- }
- else
- WIN.[P].grid3y[i] = grid_3y_default;
- }
- if (exist (sty_z))
- {
- if (class (sty_z) == "string")
- {
- WIN.[P].grid3z[i] = sty_z;
- else
- error ("plgrid3: requires string argument GRID_STY_Z");
- }
- else
- WIN.[P].grid3z[i] = grid_3z_default;
- }
- };
-
- ##############################################################################
- #
- # A friendlier interface to changing 2-D grid/axis
- # styles.
- #
-
- plaxis = function ( X_STR, Y_STR )
- {
- check_plot_object ();
- i = mod (WIN.[P].subplot, WIN.[P].nplot) + 1;
-
- if (exist (X_STR))
- {
- if (X_STR == "log") { WIN.[P].gridx[i] = "bcngstl"; }
- else
- WIN.[P].gridx[i] = grid_x_default;
- }
-
- if (exist (Y_STR))
- {
- if (Y_STR == "log") { WIN.[P].gridy[i] = "bcngstlv"; }
- else
- WIN.[P].gridy[i] = grid_y_default;
- }
- return P;
- };
-
- ##############################################################################
- #
- # Various internal support functions. Eventually these will be static.
- #
- ##############################################################################
-
- #
- # Find the X or Y scale limits .
- # M can be a multi-column matrix, all columns
- # will be used.
- #
-
- x_scales = function ( M, p, xmin, xmax )
- {
- #
- # 1st check for un-plottable data
- #
-
- if (any (any (isinf (M))))
- { error ("plot: cannot plot Infs"); }
- if (any (any (isnan (M))))
- { error ("plot: cannot plot NaNs"); }
-
- xmin = min (min (M));
- xmax = max (max (M));
-
- #
- # Check computed scale limits against user's
- #
-
- if (WIN.[P].xmin[p] != 1j) { xmin = WIN.[P].xmin[p]; }
- if (WIN.[P].xmax[p] != 1j) { xmax = WIN.[P].xmax[p]; }
-
- #
- # Check for potential errors
- #
-
- if (xmin == xmax)
- {
- # As good a guess as any
- xmin = xmin - 1;
- xmax = xmax + 1;
- }
-
- #
- # Finally, adjust if log-scales
- #
-
- if (find_char (WIN.[P].gridx[p], "l"))
- {
- if (xmin <= 0 || xmax <= 0) { error ("cannot plot log(x<=0)"); }
- xmin = log10 (xmin);
- xmax = log10 (xmax);
- }
-
- return 1;
- };
-
- y_scales = function ( M, p, xmin, xmax )
- {
-
- #
- # 1st check for un-plottable data
- #
-
- if (any (any (isinf (M))))
- { error ("plot: cannot plot Infs"); }
- if (any (any (isnan (M))))
- { error ("plot: cannot plot NaNs"); }
-
- xmin = min (min (M));
- xmax = max (max (M));
-
- #
- # Check computed scale limits against user's
- #
-
- if (WIN.[P].ymin[p] != 1j) { xmin = WIN.[P].ymin[p]; }
- if (WIN.[P].ymax[p] != 1j) { xmax = WIN.[P].ymax[p]; }
-
- #
- # Check for potential errors
- #
-
- if (xmin == xmax)
- {
- # As good a guess as any
- xmin = xmin - 1;
- xmax = xmax + 1;
- }
-
- #
- # Finally, adjust if log-scales
- #
-
- if (find_char (WIN.[P].gridy[p], "l"))
- {
- if (xmin <= 0 || xmax <= 0) { error ("cannot plot log(y<=0)"); }
- xmin = log10 (xmin);
- xmax = log10 (xmax);
- }
-
- return 1;
- };
-
- z_scales = function ( M, p, xmin, xmax )
- {
-
- #
- # 1st check for un-plottable data
- #
-
- if (any (any (isinf (M))))
- { error ("plot: cannot plot Infs"); }
- if (any (any (isnan (M))))
- { error ("plot: cannot plot NaNs"); }
-
- xmin = min (min (M));
- xmax = max (max (M));
-
- #
- # Check computed scale limits against user's
- #
-
- if (WIN.[P].zmin[p] != 1j) { xmin = WIN.[P].zmin[p]; }
- if (WIN.[P].zmax[p] != 1j) { xmax = WIN.[P].zmax[p]; }
-
- #
- # Check for potential errors
- #
-
- if (xmin == xmax)
- {
- # As good a guess as any
- xmin = xmin - 1;
- xmax = xmax + 1;
- }
-
- #
- # Finally, adjust if log-scales
- #
-
- if (find_char (WIN.[P].gridz[p], "l"))
- {
- if (xmin <= 0 || xmax <= 0) { error ("plot: cannot plot log(z<=0)"); }
- xmin = log10 (xmin);
- xmax = log10 (xmax);
- }
-
- return 1;
- };
-
- ##############################################################################
- #
- # Find the X and Y scales for a single matrix. (OLD)
- #
-
- xy_scales = function ( M, p, xmin, xmax, ymin, ymax )
- {
- #
- # 1st check for un-plottable data
- #
-
- if (any (any (isinf (M))))
- { error ("plot: cannot plot infs"); }
- if (any (any (isnan (M))))
- { error ("plot: cannot plot NaNs"); }
-
- if (M.nc == 1)
- {
- xmin = 1;
- xmax = M.nr;
- ymin = min (M);
- ymax = max (M);
- else
- xmin = min (M[;1]);
- xmax = max (M[;1]);
- ymin = min (min (M[;2:M.nc]));
- ymax = max (max (M[;2:M.nc]));
- }
-
- #
- # Check computed scale limits against user's
- #
-
- if (WIN.[P].xmin[p] != 1j) { xmin = WIN.[P].xmin[p]; }
- if (WIN.[P].xmax[p] != 1j) { xmax = WIN.[P].xmax[p]; }
- if (WIN.[P].ymin[p] != 1j) { ymin = WIN.[P].ymin[p]; }
- if (WIN.[P].ymax[p] != 1j) { ymax = WIN.[P].ymax[p]; }
-
- #
- # Check for potential errors
- #
-
- if (xmin == xmax)
- {
- xmin = xmin - 1;
- xmax = xmax + 1;
- }
-
- if (ymin == ymax)
- {
- ymin = ymin - 1;
- ymax = ymax + 1;
- }
-
- #
- # Finally, adjust if log-scales
- #
-
- if (find_char (WIN.[P].gridx[p], "l"))
- {
- if (xmin <= 0 || xmax <= 0) { error ("plot: cannot plot log <= 0"); }
- xmin = log10 (xmin);
- xmax = log10 (xmax);
- }
- if (find_char (WIN.[P].gridy[p], "l"))
- {
- if (ymin <= 0 || ymax <= 0) { error ("plot: cannot plot log <= 0"); }
- ymin = log10 (ymin);
- ymax = log10 (ymax);
- }
-
- return 1;
- };
-
- ##############################################################################
- #
- # Find the X, Y and Z scales for a single matrix.
- #
-
- XYZ_scales = function ( X, Y, Z, p, xmin, xmax, ymin, ymax, zmin, zmax )
- {
- # X - scale
- if (any (any (isinf (X))))
- { error ("cannot plot infs"); }
- if (any (any (isnan (X))))
- { error ("cannot plot NaNs"); }
-
- xmin = min (real (X));
- xmax = max (real (X));
-
- # Y - scale
- if (any (any (isinf (Y))))
- { error ("cannot plot infs"); }
- if (any (any (isnan (Y))))
- { error ("cannot plot NaNs"); }
-
- ymin = min (real (Y));
- ymax = max (real (Y));
-
- # Z - scale
- if (any (any (isinf (Y))))
- { error ("cannot plot infs"); }
- if (any (any (isnan (Y))))
- { error ("cannot plot NaNs"); }
-
- zmin = min (min (real (Z)));
- zmax = max (max (real (Z)));
-
- #
- # Check computed scale limits against user's
- #
-
- if (WIN.[P].xmin[p] != 1j) { xmin = WIN.[P].xmin[p]; }
- if (WIN.[P].xmax[p] != 1j) { xmax = WIN.[P].xmax[p]; }
- if (WIN.[P].ymin[p] != 1j) { ymin = WIN.[P].ymin[p]; }
- if (WIN.[P].ymax[p] != 1j) { ymax = WIN.[P].ymax[p]; }
- if (WIN.[P].zmin[p] != 1j) { zmin = WIN.[P].zmin[p]; }
- if (WIN.[P].zmax[p] != 1j) { zmax = WIN.[P].zmax[p]; }
-
- #
- # Check for potential errors
- #
-
- if (xmin == xmax)
- {
- # As good a guess as any
- xmin = xmin - 1;
- xmax = xmax + 1;
- }
-
- if (ymin == ymax)
- {
- # As good a guess as any
- ymin = ymin - 1;
- ymax = ymax + 1;
- }
-
- if (zmin == zmax)
- {
- # As good a guess as any
- zmin = zmin - 1;
- zmax = zmax + 1;
- }
-
- #
- # Finally, adjust if log-scales
- #
-
- if (find_char (WIN.[P].grid3x[p], "l"))
- {
- if (xmin <= 0 || xmax <= 0) { error ("plot: cannot plot log(x<=0)"); }
- xmin = log10 (xmin);
- xmax = log10 (xmax);
- }
-
- if (find_char (WIN.[P].grid3y[p], "l"))
- {
- if (ymin <= 0 || ymax <= 0) { error ("plot: cannot plot log(y<=0)"); }
- ymin = log10 (ymin);
- ymax = log10 (ymax);
- }
-
- if (find_char (WIN.[P].grid3z[p], "l"))
- {
- if (zmin <= 0 || zmax <= 0) { error ("plot: cannot plot log(z<=0)"); }
- zmin = log10 (zmin);
- zmax = log10 (zmax);
- }
-
- return 1;
- };
-
- ##############################################################################
- #
- # Find the X and Y scales for a list of matrices
- #
-
- list_scales = function ( data, key, p, Xmin, Xmax, Ymin, Ymax )
- {
- once = 1;
-
- for (i in members (data))
- {
- M = real (data.[i]);
- if (class (M) != "num") { continue; }
-
- if (abs (key) > M.nc)
- {
- error_1 ("plot: KEY argument > M.nc");
- }
-
- #
- # 1st check for un-plottable data
- #
-
- if (any (any (isinf (M))))
- { error ("plot: cannot plot infs"); }
- if (any (any (isnan (M))))
- { error ("plot: cannot plot NaNs"); }
-
- k = find ((1:M.nc) != abs (key));
- if (key > 0)
- {
- if (M.nc != 1)
- {
- x_scales ( real(M)[;key], p, xmin, xmax );
- y_scales ( real(M)[;k], p, ymin, ymax );
- else
- x_scales ( (1:M.nr)', p, xmin, xmax );
- y_scales ( real(M), p, ymin, ymax );
- }
- else if (key < 0) {
- x_scales ( real(M)[;k], p, xmin, xmax );
- y_scales ( real(M)[;abs(key)], p, ymin, ymax );
- else
- x_scales ( (1:M.nr)', p, xmin, xmax );
- y_scales ( real(M), p, ymin, ymax );
- } }
-
- if (once)
- {
- Xmin = xmin; Xmax = xmax; Ymin = ymin; Ymax = ymax;
- once = 0;
- }
- if (xmin < Xmin) { Xmin = xmin; }
- if (xmax > Xmax) { Xmax = xmax; }
- if (ymin < Ymin) { Ymin = ymin; }
- if (ymax > Ymax) { Ymax = ymax; }
- }
-
- return 1;
- };
-
- ##############################################################################
- #
- # Find the maximum number of elements in a bin for a single
- # column matrix.
- #
-
- hist_scales = function ( data, nbin )
- {
- dmin = min (real (data));
- dmax = max (real (data));
- dbin = linspace (dmin, dmax, nbin+1);
- binval = zeros (nbin, 1);
-
- for (i in 1:nbin)
- {
- binval[i] = length (find (data >= dbin[i] && data < dbin[i+1]));
- }
-
- return max (binval);
- };
-
- ##############################################################################
- #
- # Plot the columns of a matrix (core function)
- #
- # Notes: This is the core function for plotting a matrix. If the
- # matrix is a single column, then the matrix elements are plotted
- # versus the row numbers. If it is a multi-column matrix, then
- # columns 2:N are plotted versus column 1.
- #
- # p, K, k and l are indices for plot features.
- # p: the current plot index (the plot #)
- # K: usually 0. This index is used to start of the line style and
- # color index (k = color index, l = line-style index). This is mostly
- # used by plot_list, which may call plot_matrix repeatedly.
- # k: the line color index. This value determines the line color used
- # for each column of data. If K = 0, then k goes like 2:14, then
- # flops back to 1:14.
- # l: the line style inex. This value determines the line style used
- # for each column of data - not the line-type (points, or lines). If
- # K = 0, then l goes like 2:8, then flops back to 1:8.
- #
- ##############################################################################
-
- plot_matrix = function ( M, key, p, K, xmin, xmax, ymin, ymax, v )
- {
- np = M.nr;
-
- if (M.nc == 1)
- {
- x = 1:M.nr;
- y = real (M);
- k = mod (1+K, 14) + 1;
- l = mod (1+K, 8);
-
- if (find_char (WIN.[P].gridx[p], "l"))
- { x = log10 (x); }
- if (find_char (WIN.[P].gridy[p], "l"))
- { y = log10 (y); }
-
- _plcol (WIN.[P].color[p;k]);
- _pllsty (WIN.[P].lstyle[p;l]);
-
- if (get_style (WIN.[P].style.[p], k-1) == "line")
- {
- _plline (M.nr, x, y);
- else if (get_style (WIN.[P].style.[p], k-1) == "point") {
- _plpoin (M.nr, x, y, WIN.[P].pstyle[p]+k);
- else if (get_style (WIN.[P].style.[p], k-1) == "line-point") {
- _plline (M.nr, x, y);
- _plpoin (M.nr, x, y, WIN.[P].pstyle[p]+k);
- else {
- _plline (M.nr, x, y);
- }}}}
-
- #
- # Now do the legend
- #
-
- if (!any (any (WIN.[P].desc.[p] == 1j)))
- {
- # Use the default if necessary
- if (WIN.[P].desc.[p][1] == "default")
- {
- desc = "c1";
- else if (WIN.[P].desc.[p].n >= k-1) {
- desc = WIN.[P].desc.[p][k-1];
- else
- # Not sure what to do, user has messed up.
- desc = "";
- } }
-
- v = v - (ymax-ymin)/11;
- xl = (xmax-xmin)*[10.5/12, 11/12, 11.5/12]' + xmin;
- yl = [v, v, v]' + ymin;
-
- if (get_style (WIN.[P].style.[p], k-1) == "line")
- {
- _plline (3, xl, yl);
- else if (get_style (WIN.[P].style.[p], k-1) == "point") {
- _plpoin (3, xl, yl, WIN.[P].pstyle[p]+k);
- else if (get_style (WIN.[P].style.[p], k-1) == "line-point") {
- _plline (3, xl, yl);
- _plpoin (3, xl, yl, WIN.[P].pstyle[p]+k);
- } } }
-
- plptex(desc, xl[1]-(xmax-xmin)/25, yl[3], , , 1);
-
- }
-
- else
-
- #
- # Check for large column dimension
- #
-
- if (M.nc > 3*M.nr)
- {
- printf (" Plot %i columns and %i rows, are you sure (y/n) ? "...
- , M.nc, M.nr);
- ans = getline ("stdin");
- if (ans.[1] != "y") { return -1; }
- }
-
- ki = find ((1:M.nc) != abs (key));
- for (i in ki)
- {
- if (key > 0)
- {
- x = real (M[;key]);
- y = real (M[;i]);
- else if (key < 0) {
- x = real (M[;i]);
- y = real (M[;abs(key)]);
- else
- x = (1:M.nr)';
- y = real (M[;i]);
- } }
-
- # Check for log scales, adjust if necessary
- if (find_char (WIN.[P].gridx[p], "l"))
- { x = log10 (x); }
- if (find_char (WIN.[P].gridy[p], "l"))
- { y = log10 (y); }
-
- k = mod (i-1 + K, 14) + 1;
- l = mod (8 + i-2 + K, 8) + 1;
-
- _plcol (WIN.[P].color[p;k]);
- _pllsty (WIN.[P].lstyle[p;l]);
-
- if (get_style (WIN.[P].style.[p], k-1) == "line")
- {
- _plline (np, x, y);
- else if (get_style (WIN.[P].style.[p], k-1) == "point") {
- _plpoin (np, x, y, WIN.[P].pstyle[p]+k);
- else if (get_style (WIN.[P].style.[p], k-1) == "line-point") {
- _plline (np, x, y);
- _plpoin (np, x, y, WIN.[P].pstyle[p]+k);
- else {
- _plline (np, x, y);
- }}}}
-
- #
- # Now do the legend
- #
-
- if (!any (any (WIN.[P].desc.[p] == 1j)))
- {
- # Use the default if necessary
- if (WIN.[P].desc.[p][1] == "default")
- {
- desc = "c" + num2str (i);
- else if (WIN.[P].desc.[p].n >= k-1) {
- desc = WIN.[P].desc.[p][k-1];
- else
- # Not sure what to do, user has messed up.
- desc = "";
- }}
-
- v = v - (ymax-ymin)/11;
- xl = (xmax-xmin)*[10.5/12, 11/12, 11.5/12]' + xmin;
- yl = [v, v, v]' + ymin;
-
- if (get_style (WIN.[P].style.[p], k-1) == "line")
- {
- _plline (3, xl, yl);
- else if (get_style (WIN.[P].style.[p], k-1) == "point") {
- _plpoin (3, xl, yl, WIN.[P].pstyle[p]+k);
- else if (get_style (WIN.[P].style.[p], k-1) == "line-point") {
- _plline (3, xl, yl);
- _plpoin (3, xl, yl, WIN.[P].pstyle[p]+k);
- }}}
-
- plptex(desc, xl[1]-(xmax-xmin)/25, yl[3], , , 1);
-
- }
- }
- }
-
- return k-1;
- };
-
- ##############################################################################
- #
- # Plot all of the matrices in a list on the same plot
- #
-
- plot_list = function ( L, key, p, xmin, xmax, ymin, ymax )
- {
- k = 0;
- v = ymax - ymin;
-
- #
- # Sort out the list members
- #
-
- sl = list_sort (L);
-
- # Plot the list members with numeric labels 1st.
- if (exist (sl.num))
- {
- for (i in sl.num)
- {
- M = L.[i];
- if (class (M) != "num") { continue; }
- if ((k = plot_matrix (M, key, p, k, xmin, xmax, ymin, ymax, v)) < 0)
- {
- return k;
- }
- }
- }
-
- # Now plot the list members with string labels.
- if (exist (sl.char))
- {
- for (i in sl.char)
- {
- M = L.[i];
- if (class (M) != "num") { continue; }
- if ((k = plot_matrix (M, key, p, k, xmin, xmax, ymin, ymax, v)) < 0)
- {
- return k;
- }
- }
- }
- return 1;
- };
-
- ##############################################################################
- #
- # Check the elements of LIST.
- # LIST must contain elements `x', `y',
- # and `z'
- #
-
- check_3d_list = function ( LIST )
- {
- #
- # Check existence and types
- #
-
- if (class (LIST) != "list") {
- error ("plot3: argument must be a list");
- }
- if (!exist (LIST.x)) {
- error ("plot3: arg must contain `x' member");
- else if (class (LIST.x) != "num") {
- error ("plot3: x must be numeric");
- } }
- if (!exist (LIST.y)) {
- error ("plot3: arg must contain `y' member");
- else if (class (LIST.y) != "num") {
- error ("plot3: y must be numeric");
- } }
- if (!exist (LIST.z)) {
- error ("plot3: arg must contain `z' member");
- else if (class (LIST.z) != "num") {
- error ("plot3: z must be numeric");
- } }
-
- #
- # Check sizes
- #
-
- if (LIST.x.n != LIST.z.nr)
- {
- error ("plot3: x.n != z.nr");
- }
-
- if (LIST.y.n != LIST.z.nc)
- {
- error ("plot3: y.n != z.nc");
- }
-
- };
-
- ##############################################################################
- #
- # A special type of histogram plot.
- #
-
- plhistx = function ( M , nbin )
- {
- check_plot_object ();
-
- if (!exist (nbin)) { nbin = 10; }
-
- p = mod (WIN.[P].subplot, WIN.[P].nplot) + 1; # The current index
- np = M.nr;
-
- # Compute max/min values of data
-
- ymin = min (min(real (M)));
- ymax = max (max(real (M)));
-
- #
- # Check computed scale limits against user's
- #
-
- if (WIN.[P].ymin[p] != 1j) { ymin = WIN.[P].ymin[p]; }
- if (WIN.[P].ymax[p] != 1j) { ymax = WIN.[P].ymax[p]; }
-
- _plgra ();
- _plcol (15);
- _plfont (WIN.[P].font[p]);
- _plwid (WIN.[P].width[p]);
-
- dbin = (linspace (ymin, ymax, nbin+1))';
- for (j in 1:M.nc)
- {
- // counting
- for (i in 1:nbin)
- {
- binval[i;j] = length (find (M[;j] >= dbin[i] && M[;j] < dbin[i+1]));
- }
- }
-
- if (!subplot_f) {
- _pladv (0); # Advance 1 subplot
- else
- subplot_f = 0; # The user has set the subplot
- }
-
- if (WIN.[P].aspect[p] != 0)
- {
- _plvasp (WIN.[P].aspect[p]);
- else
- _plvsta ();
- }
-
- xmin = 0;
- xmax = max(max(binval));
- _plwind (ymin, ymax, xmin, xmax);
- _plbox (WIN.[P].gridx[p], 0, 0, WIN.[P].gridy[p], 0, 0);
-
- #
- # Now reorganize dbin and binval so we plot points in
- # the middle of the bins.
- #
-
- delbin = abs(dbin[2] - dbin[1]);
- dbin = (linspace (ymin+delbin/2, ymax-delbin/2, nbin))';
- dbin = [ymin ; dbin ; ymax];
- binval = [zeros(1,binval.nc); binval; zeros(1,binval.nc)];
-
- v = xmax;
- for (i in 1:M.nc)
- {
- k = mod (i, 14) + 1;
- l = mod (i, 8) + 1;
- _plcol (WIN.[P].color[p;k]);
- _pllsty (WIN.[P].lstyle[p;l]);
-
- if (get_style (WIN.[P].style.[p], k-1) == "line")
- {
- _plline (nbin+2, dbin, binval[;i]);
- else if (get_style (WIN.[P].style.[p], k-1) == "point") {
- _plpoin (nbin+2, dbin, binval[;i], WIN.[P].pstyle[p]+k);
- else if (get_style (WIN.[P].style.[p], k-1) == "line-point") {
- _plline (nbin+2, dbin, binval[;i]);
- _plpoin (nbin+2, dbin, binval[;i], WIN.[P].pstyle[p]+k);
- } } }
-
- // write legend around upper-right corner.
- // it is better to have user to choose location for legend.
-
- if (!any (any (WIN.[P].desc.[p] == 1j)))
- {
- # Use the default if necessary
- if (WIN.[P].desc.[p][1] == "default")
- {
- desc = "c"+num2str(i);
- else if (WIN.[P].desc.[p].n >= i) {
- desc = WIN.[P].desc.[p][i];
- else
- # Not sure what to do, user has messed up.
- desc = "";
- } }
-
- v = v - (xmax)/11;
- xt = (ymax-ymin)*[10.5/12, 11/12, 11.5/12]' + ymin;
- yt = [v, v, v]';
-
- if (get_style (WIN.[P].style.[p], k-1) == "line")
- {
- _plline (3, xt, yt);
- else if (get_style (WIN.[P].style.[p], k-1) == "point") {
- _plpoin (3, xt, yt, WIN.[P].pstyle[p]+k);
- else if (get_style (WIN.[P].style.[p], k-1) == "line-point") {
- _plline (3, xt, yt);
- _plpoin (3, xt, yt, WIN.[P].pstyle[p]+k);
- } } }
-
- plptex(desc, xt[1]-(ymax-ymin)/25, yt[3], , , 1);
- }
- }
-
- _plcol (15);
- _pllab (WIN.[P].xlabel[p], WIN.[P].ylabel[p], WIN.[P].title[p]);
- _plflush ();
- _pltext ();
-
- #
- # Increment the plot no. so that next time
- # we use the correct settings.
- #
-
- WIN.[P].subplot = WIN.[P].subplot + 1;
-
- return 1;
- };
-
-
- ##############################################################################
- #
- # Create a legend in the current plot window
- #
- # if pobj.desc.[p] = inf() no legend
- # if pobj.desc.[p] = "default" default ("c1", "c2", ...)
- # if pobj.desc.[p] = "string" use "string" as description
- #
-
- #
- # Set the current plot legend string
- #
-
- plegend = function ( LEGEND )
- {
- check_plot_object ();
-
- p = mod (WIN.[P].subplot, WIN.[P].nplot) + 1; # The current index
-
- if (!exist (LEGEND))
- {
- WIN.[P].desc.[p] = 1j;
- return P;
- }
-
- if (class (LEGEND) == "string")
- {
- WIN.[P].desc.[p] = LEGEND;
- }
-
- return P;
- };
-