octave-maintainers
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Scatter and Scatter3 functions


From: David Bateman
Subject: Scatter and Scatter3 functions
Date: Tue, 20 Nov 2007 00:36:48 +0100
User-agent: Thunderbird 1.5.0.7 (X11/20060921)

The attached patch adds the scatter and scatter3 functions. These use
patch objects with markers to define the points. This allows the
colormap to determine the colors of the point whereas if a line object
was used its not clear that this could be done. This of course means
that each point has a separate plot command to gnuplot and so with a
large number of points this is a bit slow to display initially.

D.
*** ./scripts/plot/__patch__.m.orig14   2007-11-19 21:33:16.779636774 +0100
--- ./scripts/plot/__patch__.m  2007-11-20 00:26:59.030589083 +0100
***************
*** 159,164 ****
--- 159,165 ----
        clim = get(ax, "clim");
        if (c(1) < clim(1))
            set (ax, "clim", [c(1), clim(2)])
+         clim(1) = c(1);
        endif
        if (c(1) > clim(2))
            set (ax, "clim", [clim(1), c(1)])
*** ./scripts/plot/__go_draw_axes__.m.orig14    2007-11-19 23:30:51.274540979 
+0100
--- ./scripts/plot/__go_draw_axes__.m   2007-11-20 00:28:34.510742380 +0100
***************
*** 436,442 ****
  
         case "patch"
           cmap = parent_figure_obj.colormap;
!          clim = axis_obj.clim;
         [nr, nc] = size (obj.xdata);
  
         if (! isempty (obj.cdata))
--- 436,442 ----
  
         case "patch"
           cmap = parent_figure_obj.colormap;
!        clim = axis_obj.clim;
         [nr, nc] = size (obj.xdata);
  
         if (! isempty (obj.cdata))
***************
*** 494,507 ****
                 titlespec{data_idx} = strcat ("title \"", tmp, "\"");
               endif
               usingclause{data_idx} = "";
!                if (isfield (obj, "facecolor") && isfield (obj, "cdata"))
!                if (strncmp (obj.facecolor, "flat", 4)
!                    || strncmp (obj.facecolor, "interp", 6))
                   if (ndims (obj.cdata) == 2
!                      && ((nr > 3 && size (obj.cdata, 2) == nc)
!                          || (size (obj.cdata, 1) > 1
!                              && size (obj.cdata, 2) == nc)))
                     ccol = cdat (:, i);
                   elseif (ndims (obj.cdata) == 3)
                     ccol = permute (cdat (:, i, :), [1, 3, 2]);
                   else
--- 494,513 ----
                 titlespec{data_idx} = strcat ("title \"", tmp, "\"");
               endif
               usingclause{data_idx} = "";
!                if (isfield (obj, "facecolor"))
!                if ((strncmp (obj.facecolor, "flat", 4)
!                    || strncmp (obj.facecolor, "interp", 6)) &&
!                    isfield (obj, "cdata"))
                   if (ndims (obj.cdata) == 2
!                      && (size (obj.cdata, 2) == nc
!                          && (size (obj.cdata, 1) == 1
!                              || size (obj.cdata, 1) == 3)))
                     ccol = cdat (:, i);
+                  elseif (ndims (obj.cdata) == 2
+                      && (size (obj.cdata, 1) == nc
+                          && (size (obj.cdata, 2) == 1
+                              || size (obj.cdata, 2) == 3)))
+                    ccol = cdat (i, :);
                   elseif (ndims (obj.cdata) == 3)
                     ccol = permute (cdat (:, i, :), [1, 3, 2]);
                   else
***************
*** 511,518 ****
                     if (numel(ccol) == 3)
                       color = ccol;
                     else
!                      r = 1 + round ((size (cmap, 1) - 1)
!                                     * (ccol - clim(1))/(clim(2) - clim(1)));
                       r = max (1, min (r, size (cmap, 1)));
                       color = cmap(r, :);
                     endif
--- 517,529 ----
                     if (numel(ccol) == 3)
                       color = ccol;
                     else
!                      if (cautoscale)
!                        r = 1 + round ((size (cmap, 1) - 1)
!                                       * (ccol - cmin)/(cmax - cmin));
!                      else
!                        r = 1 + round ((size (cmap, 1) - 1)
!                                       * (ccol - clim(1))/(clim(2) - clim(1)));
!                      endif
                       r = max (1, min (r, size (cmap, 1)));
                       color = cmap(r, :);
                     endif
***************
*** 522,529 ****
                     r = max (1, min (r, size (cmap, 1)));
                     color = cmap(r,:);
                   endif
!                else
                   color = obj.facecolor;
                 endif
                 else
                 color = [0, 1, 0];
--- 533,542 ----
                     r = max (1, min (r, size (cmap, 1)));
                     color = cmap(r,:);
                   endif
!                elseif (isnumeric (obj.facecolor))
                   color = obj.facecolor;
+                else
+                  color = [0, 1, 0];
                 endif
                 else
                 color = [0, 1, 0];
***************
*** 574,598 ****
             have_cdata(data_idx) = false;
               titlespec{data_idx} = "title \"\"";
             usingclause{data_idx} = "";
!              if (isfield (obj, "edgecolor") && isfield (obj, "cdata"))
!              if (strncmp (obj.edgecolor, "flat", 4)
!                  || strncmp (obj.edgecolor, "interp", 6))
                 if (ndims (obj.cdata) == 2
!                    && ((nr > 3 && size (obj.cdata, 2) == nc)
!                        || (size (obj.cdata, 1) > 1
!                            && size (obj.cdata, 2) == nc)))
                   ccol = cdat (:, i);
                 elseif (ndims (obj.cdata) == 3)
                   ccol = permute (cdat (:, i, :), [1, 3, 2]);
                 else
                   ccol = cdat;
                 endif
                 if (strncmp (obj.edgecolor, "flat", 4))
!                  if (numel (ccol) == 3)
                     color = ccol;
                   else
!                    r = 1 + round ((size (cmap, 1) - 1)
!                                   * (ccol - clim(1))/(clim(2) - clim(1)));
                     r = max (1, min (r, size (cmap, 1)));
                     color = cmap(r, :);
                   endif
--- 587,627 ----
             have_cdata(data_idx) = false;
               titlespec{data_idx} = "title \"\"";
             usingclause{data_idx} = "";
! 
!            if (isfield (obj, "markersize"))
!              mdat = obj.markersize;
!            endif
! 
!              if (isfield (obj, "edgecolor"))
!              if ((strncmp (obj.edgecolor, "flat", 4)
!                   || strncmp (obj.edgecolor, "interp", 6)) &&
!                  isfield (obj, "cdata"))
                 if (ndims (obj.cdata) == 2
!                    && (size (obj.cdata, 2) == nc
!                        && (size (obj.cdata, 1) == 1
!                            || size (obj.cdata, 1) == 3)))
                   ccol = cdat (:, i);
+                elseif (ndims (obj.cdata) == 2
+                        && (size (obj.cdata, 1) == nc
+                            && (size (obj.cdata, 2) == 1
+                                || size (obj.cdata, 2) == 3)))
+                  ccol = cdat (i, :);
                 elseif (ndims (obj.cdata) == 3)
                   ccol = permute (cdat (:, i, :), [1, 3, 2]);
                 else
                   ccol = cdat;
                 endif
                 if (strncmp (obj.edgecolor, "flat", 4))
!                  if (numel(ccol) == 3)
                     color = ccol;
                   else
!                    if (cautoscale)
!                      r = 1 + round ((size (cmap, 1) - 1)
!                                     * (ccol - cmin)/(cmax - cmin));
!                    else
!                      r = 1 + round ((size (cmap, 1) - 1)
!                                     * (ccol - clim(1))/(clim(2) - clim(1)));
!                    endif
                     r = max (1, min (r, size (cmap, 1)));
                     color = cmap(r, :);
                   endif
***************
*** 602,617 ****
                   r = max (1, min (r, size (cmap, 1)));
                   color = cmap(r,:);
                 endif
               endif
-              elseif (isfield (obj, "edgecolor") && isnumeric (obj.edgecolor))
-              color = obj.edgecolor;
               else
!                color = [0, 0, 0];
               endif
             if (have_newer_gnuplot)
               withclause{data_idx} ...
!                  = sprintf ("with lines lc rgb \"#%02x%02x%02x\"",
!                             round (255*color));
             else
               if (isequal (color, [0,0,0]))
                 typ = -1;
--- 631,735 ----
                   r = max (1, min (r, size (cmap, 1)));
                   color = cmap(r,:);
                 endif
+              elseif (isnumeric (obj.edgecolor))
+                color = obj.edgecolor;
+              else
+                color = [0, 0, 0];
               endif
               else
!              color = [0, 0, 0];
               endif
+ 
+            if (isfield (obj, "linestyle"))
+              switch (obj.linestyle)
+                case "-"
+                  lt = "1";
+                case "--"
+                  lt = "2";
+                case ":"
+                  lt = "3";
+                case "-."
+                  lt = "6";
+                case "none"
+                  lt = "";
+                otherwise
+                  lt = "";
+              endswitch
+            else
+              lt = "";
+            endif
+ 
+            if (isfield (obj, "marker"))
+              if (isfield (obj, "marker"))
+                switch (obj.marker)
+                  case "+"
+                    pt = "pt 1";
+                  case "o"
+                    pt = "pt 6";
+                  case "*"
+                    pt = "pt 3";
+                  case "."
+                    pt = "pt 0";
+                  case "x"
+                    pt = "pt 2";
+                  case {"square", "s"}
+                    pt = "pt 5";
+                  case {"diamond", "d"}
+                    pt = "pt 13";
+                  case "^"
+                    pt = "pt 9";
+                  case "v"
+                    pt = "pt 11";
+                  case ">"
+                    pt = "pt 8";
+                  case "<"
+                    pt = "pt 10";
+                  case {"pentagram", "p"}
+                    pt = "pt 4";
+                  case {"hexagram", "h"}
+                    pt = "pt 12";
+                  case "none"
+                    pt = "";
+                  otherwise
+                    pt = "";
+                endswitch
+              endif
+            else
+              pt = "";
+            endif
+ 
+            style = "lines";
+            if (isempty (lt))
+              if (! isempty (pt))
+                style = "points";
+              endif
+            elseif (! isempty (pt))
+              style = "linespoints";
+            endif
+ 
+            if (isfield (obj, "markersize"))
+              if (length (mdat) == nc)
+                m = mdat(i);
+              else
+                m = mdat;
+              endif
+              if (! strcmpi (style, "lines"))
+                if (have_newer_gnuplot)
+                  ps = sprintf("pointsize %f", m);
+                else
+                  ps = sprintf("ps %f", m);
+                endif
+              else
+                ps = "";
+              endif
+            else
+              ps = "";
+            endif
+ 
             if (have_newer_gnuplot)
               withclause{data_idx} ...
!                  = sprintf ("with %s %s %s lc rgb \"#%02x%02x%02x\"",
!                             style, pt, ps, round (255*color));
             else
               if (isequal (color, [0,0,0]))
                 typ = -1;
***************
*** 632,638 ****
               else
                 typ = -1;
               endif
!              withclause{data_idx} = sprintf ("with lines lt %d", typ);
             endif
  
             if (! isempty (zcol))
--- 750,757 ----
               else
                 typ = -1;
               endif
!              withclause{data_idx} = sprintf ("with %s %s %s lt %d", 
!                                              style, pt, ps, typ);
             endif
  
             if (! isempty (zcol))
*** ./scripts/plot/scatter.m.orig14     2007-11-19 22:49:26.532669870 +0100
--- ./scripts/plot/scatter.m    2007-11-20 00:09:12.543725413 +0100
***************
*** 0 ****
--- 1,83 ----
+ ## Copyright (C) 2007 David Bateman
+ ##
+ ## This file is part of Octave.
+ ##
+ ## Octave 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 3 of the License, or (at
+ ## your option) any later version.
+ ##
+ ## Octave 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 Octave; see the file COPYING.  If not, see
+ ## <http://www.gnu.org/licenses/>.
+ 
+ ## -*- texinfo -*-
+ ## @deftypefn {Function File} {} scatter (@var{x}, @var{y}, @var{s}, @var{c})
+ ## @deftypefnx {Function File} {} scatter (@dots{}, 'filled')
+ ## @deftypefnx {Function File} {} scatter (@dots{}, @var{style})
+ ## @deftypefnx {Function File} {} scatter (@dots{}, @var{prop}, @var{val})
+ ## @deftypefnx {Function File} {} scatter (@var{h}, @dots{})
+ ## @deftypefnx {Function File} address@hidden =} scatter (@dots{})
+ ##
+ ## Plot a scatter plot of the data. A marker is ploted at each point 
+ ## defined by the points in the vectors @var{x} and @var{y}. The size of
+ ## the markers used is determined by the @var{s}, which can be a scalar, 
+ ## a vector of the same length of @var{x} and @var{y}. If @var{s} is not 
+ ## given or is an empty matrix, then the default value of 8 points is used.
+ ##
+ ## The color of the markers is determined by @var{c}, which can be a string
+ ## defining a fixed color, a 3 element vector giving the red, green and blue 
+ ## components of the color, a vector of the same length as @var{x} that gives
+ ## a scaled index into the current colormap, or a @var{n}-by-3 matrix defining
+ ## the colors of each of the markers individually.
+ ##
+ ## The marker to use can be changed with the @var{style} argument, that is a 
+ ## string defining a marker in the same manner as the @code{plot} command. 
+ ## If the argument 'filled' is given then the markers as filled. All 
+ ## additional arguments are passed to the underlying patch command.
+ ##
+ ## The optional return value @var{h} provides a handle to the patch object
+ ##
+ ## @example
+ ## @group
+ ## x = randn (100, 1);
+ ## y = randn (100, 1);
+ ## scatter (x, y, [], sqrt(x.^2 + y.^2));
+ ## @end group
+ ## @end example
+ ##
+ ## @seealso{plot, patch, scatter3}
+ ## @end deftypefn
+ 
+ function retval = scatter (varargin)
+ 
+   if (nargin < 2)
+     print_usage ();
+   elseif (isscalar (varargin{1}) && ishandle (varargin{1}))
+     h = varargin {1};
+     if (! strcmp (get (h, "type"), "axes"))
+       error ("scatter: expecting first argument to be an axes object");
+     endif
+     oldh = gca ();
+     unwind_protect
+       axes (h);
+       newplot ();
+       tmp = __scatter__ (h, 2, "scatter", varargin{2:end});
+     unwind_protect_cleanup
+       axes (oldh);
+     end_unwind_protect
+   else
+     newplot ();
+     tmp = __scatter__ (gca (), 2, "scatter", varargin{:});
+   endif
+ 
+   if (nargout > 0)
+     retval = tmp;
+   endif
+ 
+ endfunction
*** ./scripts/plot/scatter3.m.orig14    2007-11-19 22:49:28.686560535 +0100
--- ./scripts/plot/scatter3.m   2007-11-20 00:13:08.503747760 +0100
***************
*** 0 ****
--- 1,86 ----
+ ## Copyright (C) 2007 David Bateman
+ ##
+ ## This file is part of Octave.
+ ##
+ ## Octave 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 3 of the License, or (at
+ ## your option) any later version.
+ ##
+ ## Octave 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 Octave; see the file COPYING.  If not, see
+ ## <http://www.gnu.org/licenses/>.
+ 
+ ## -*- texinfo -*-
+ ## @deftypefn {Function File} {} scatter3 (@var{x}, @var{y}, @var{s}, @var{c})
+ ## @deftypefnx {Function File} {} scatter3 (@dots{}, 'filled')
+ ## @deftypefnx {Function File} {} scatter3 (@dots{}, @var{style})
+ ## @deftypefnx {Function File} {} scatter3 (@dots{}, @var{prop}, @var{val})
+ ## @deftypefnx {Function File} {} scatter3 (@var{h}, @dots{})
+ ## @deftypefnx {Function File} address@hidden =} scatter3 (@dots{})
+ ##
+ ## Plot a scatter plot of the data in 3D. A marker is ploted at each point 
+ ## defined by the points in the vectors @var{x} and @var{y}. The size of
+ ## the markers used is determined by the @var{s}, which can be a scalar, 
+ ## a vector of the same length of @var{x} and @var{y}. If @var{s} is not 
+ ## given or is an empty matrix, then the default value of 8 points is used.
+ ##
+ ## The color of the markers is determined by @var{c}, which can be a string
+ ## defining a fixed color, a 3 element vector giving the red, green and blue 
+ ## components of the color, a vector of the same length as @var{x} that gives
+ ## a scaled index into the current colormap, or a @var{n}-by-3 matrix defining
+ ## the colors of each of the markers individually.
+ ##
+ ## The marker to use can be changed with the @var{style} argument, that is a 
+ ## string defining a marker in the same manner as the @code{plot} command. 
+ ## If the argument 'filled' is given then the markers as filled. All 
+ ## additional arguments are passed to the underlying patch command.
+ ##
+ ## The optional return value @var{h} provides a handle to the patch object
+ ##
+ ## @example
+ ## @group
+ ## [x, y, z] = peaks (20);
+ ## scatter3 (x(:), y(:), z(:), [], z(:));
+ ## @end group
+ ## @end example
+ ##
+ ## @seealso{plot, patch, scatter}
+ ## @end deftypefn
+ 
+ function retval = scatter3 (varargin)
+ 
+   if (nargin < 2)
+     print_usage ();
+   elseif (isscalar (varargin{1}) && ishandle (varargin{1}))
+     h = varargin {1};
+     if (! strcmp (get (h, "type"), "axes"))
+       error ("scatter3: expecting first argument to be an axes object");
+     endif
+     oldh = gca ();
+     unwind_protect
+       axes (h);
+       newplot ();
+       tmp = __scatter__ (h, 3, "scatter3", varargin{2:end});
+     unwind_protect_cleanup
+       axes (oldh);
+     end_unwind_protect
+   else
+     newplot ();
+     tmp = __scatter__ (gca (), 3, "scatter3", varargin{:});
+   endif
+ 
+   if (! ishold ())
+     set (get (tmp, "parent"), "view", [-37.5, 30]);
+   endif
+ 
+   if (nargout > 0)
+     retval = tmp;
+   endif
+ 
+ endfunction
*** ./scripts/plot/__scatter__.m.orig14 2007-11-19 22:49:32.988342171 +0100
--- ./scripts/plot/__scatter__.m        2007-11-20 00:28:02.744354885 +0100
***************
*** 0 ****
--- 1,124 ----
+ ## Copyright (C) 2007 David Bateman
+ ##
+ ## This file is part of Octave.
+ ##
+ ## Octave 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 3 of the License, or (at
+ ## your option) any later version.
+ ##
+ ## Octave 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 Octave; see the file COPYING.  If not, see
+ ## <http://www.gnu.org/licenses/>.
+ 
+ ## Undocumented internal function.
+ 
+ function h = __scatter__ (varargin)
+   h = varargin {1};
+   nd = varargin {2};
+   fcn = varargin {3};
+   x = varargin {4}(:);
+   y = varargin {5}(:);
+   istart = 6;
+   if (nd == 3)
+     z = varargin {6}(:);
+     istart = 7;
+   else
+     z = zeros (length(x), 0);
+   endif
+ 
+   firstnonnumeric = Inf;
+   for i = istart:nargin
+     if (! isnumeric (varargin {i}))
+       firstnonnumeric = i;
+       break;
+     endif
+   endfor
+ 
+   if (firstnonnumeric > istart)
+     s = varargin {istart};
+     if (isempty (s))
+       s = 8;
+     endif
+   else
+     s = 8;
+   endif
+   ## Note markersize is in points^2 for 2D and points for 3D, and 
+   ## the below is an approximation, that is empircally visually correct.
+   if (nd == 2)
+     s = sqrt (s) / 2;
+   else
+     s = s / 4;
+   endif
+ 
+   if (istart < nargin && firstnonnumeric > istart + 1)
+     c = varargin {istart + 1};
+     if (isvector (c))
+       c = c(:);
+     endif
+   elseif (firstnonnumeric == istart + 1 && ischar (varargin {istart + 1}))
+     c = varargin{istart + 1};
+     firstnonnumeric++;
+   else
+     c = 1 : length(x);
+   endif
+ 
+   newargs = {};
+   filled = false;
+   have_marker = false;
+   marker = "o";
+   iarg = firstnonnumeric;
+   while (iarg <= nargin)
+     arg = varargin {iarg++};
+     if (ischar (arg) && strncmp (tolower (arg), "filled", 6))
+       filled = true;
+     elseif ((isstr (arg) || iscell (arg)) && ! have_marker)
+       [linespec, valid] = __pltopt__ ("scatter", arg, false);
+       if (valid)
+       have_marker = true;
+       marker = linespec.marker;
+       if (strncmp (marker, "none", 4))
+         marker = "o";
+       endif
+       else
+       error ("scatter: invalid linespec");
+       endif
+     else
+       newargs{end+1} = arg;
+       if (iarg <= nargin)
+       newargs{end+1} = varagin{iarg++};
+       endif
+     endif
+   endwhile
+ 
+   if (ischar (c))
+     h = patch('faces', [1:length(x)].', 'vertices', [x, y, z], 'facecolor',
+             'none', 'edgecolor', c, 'marker', marker, 
+             'markersize', s, 'linestyle', 'none');
+     if (filled)
+       set(h, 'markerfacecolor', c); 
+     endif
+   else
+     h = patch('faces', [1:length(x)].', 'vertices', [x, y, z], 'facecolor',
+             'none', 'edgecolor', 'flat', 'cdata', c, 'marker', marker, 
+             'markersize', s, 'linestyle', 'none');
+     if (filled)
+       set(h, 'markerfacecolor', 'flat'); 
+     endif
+     ax = get (h, "parent");
+     clim = get (ax, "clim");
+     if (min(c(:)) < clim(1))
+       clim(1) = min(c(:));
+       set (ax, "clim", clim);
+     endif
+     if (max(c(:)) > clim(2))
+       set (ax, "clim", [clim(1), max(c(:))]);
+     endif
+   endif
+ 
+ endfunction
*** ./scripts/plot/Makefile.in.orig14   2007-11-19 22:49:40.251973459 +0100
--- ./scripts/plot/Makefile.in  2007-11-19 22:50:16.122152640 +0100
***************
*** 63,68 ****
--- 63,69 ----
    __plt_get_axis_arg__.m \
    __pltopt1__.m \
    __pltopt__.m \
+   __scatter__.m \
    ancestor.m \
    area.m \
    axes.m \
***************
*** 113,118 ****
--- 114,121 ----
    quiver.m \
    replot.m \
    ribbon.m \
+   scatter.m \
+   scatter3.m \
    semilogx.m \
    semilogxerr.m \
    semilogy.m \
2007-11-19  David Bateman  <address@hidden>

        * plot/__patch__.m: Set clim correctly.
        * plot__go_draw_axes__.m: Allow patch objects to have markers, and 
        the marker color is determined by the cmap.
        * plot/scatter.m: New function to 2D scatter plots.
        * plot/scatter3.m: New function to 3D scatter plots.
        * plot/__scatter__.m: Support function for scatter plots
        * Makefile.in (SOURCES): Ad dnew functions here.

reply via email to

[Prev in Thread] Current Thread [Next in Thread]