changeset 18614:13c80c3e9660

Add new functions hgsave and hgload (bug #39532). * NEWS: Announce new functions. * scripts/plot/util/hgload.m: New function. * scripts/plot/util/hgsave.m: New function. * scripts/plot/util/module.mk: Add functions to build system. * hdl2struct.m, print.m, saveas.m, struct2hdl.m: Add seealso references to new functions in docstrings. * plot.txi: Add functions to Octave manual. * __unimplemented__.m: Remove functions from unimplemented list.
author Massimiliano Fasi <mogrob.sanit@gmail.com> and Rik <rik@octave.org>
date Thu, 06 Mar 2014 22:52:59 +0100
parents d227178a0d40
children 70cff922a42d
files NEWS doc/interpreter/plot.txi scripts/help/__unimplemented__.m scripts/plot/util/hdl2struct.m scripts/plot/util/hgload.m scripts/plot/util/hgsave.m scripts/plot/util/module.mk scripts/plot/util/print.m scripts/plot/util/saveas.m scripts/plot/util/struct2hdl.m
diffstat 10 files changed, 208 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/NEWS	Fri Feb 28 19:24:10 2014 +0100
+++ b/NEWS	Thu Mar 06 22:52:59 2014 +0100
@@ -4,6 +4,8 @@
  ** Other new functions added in 4.2:
 
       dir_in_loadpath
+      hgload
+      hgsave
       numfields
 
  ** Deprecated functions.
--- a/doc/interpreter/plot.txi	Fri Feb 28 19:24:10 2014 +0100
+++ b/doc/interpreter/plot.txi	Thu Mar 06 22:52:59 2014 +0100
@@ -937,6 +937,17 @@
 
 @DOCSTRING(orient)
 
+@code{print} and @code{saveas} are used when work on a plot has finished
+and the output must be in a publication-ready format.  During intermediate
+stages it is often better to save the graphics object and all of its
+associated information so that changes---to colors, axis limits, marker styles,
+etc.---can be made easily from within Octave.  The @code{hgsave}/@code{hgload}
+commands can be used to save and re-create a graphics object.
+
+@DOCSTRING(hgsave)
+
+@DOCSTRING(hgload)
+
 @node Interacting with Plots
 @subsection Interacting with Plots
 
--- a/scripts/help/__unimplemented__.m	Fri Feb 28 19:24:10 2014 +0100
+++ b/scripts/help/__unimplemented__.m	Thu Mar 06 22:52:59 2014 +0100
@@ -649,8 +649,6 @@
   "hdfinfo",
   "hdfread",
   "hgexport",
-  "hgload",
-  "hgsave",
   "hgsetget",
   "hgtransform",
   "ichol",
--- a/scripts/plot/util/hdl2struct.m	Fri Feb 28 19:24:10 2014 +0100
+++ b/scripts/plot/util/hdl2struct.m	Thu Mar 06 22:52:59 2014 +0100
@@ -23,7 +23,7 @@
 ##
 ## The fields of the structure @var{s} are @qcode{"type"}, @qcode{"handle"},
 ## @qcode{"properties"}, @qcode{"children"}, and @qcode{"special"}.
-## @seealso{struct2hdl, findobj}
+## @seealso{struct2hdl, hgsave, findobj}
 ## @end deftypefn
 
 ## Author: pdiribarne <pdiribarne@new-host.home>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/util/hgload.m	Thu Mar 06 22:52:59 2014 +0100
@@ -0,0 +1,66 @@
+## Copyright (C) 2014 Massimiliano Fasi
+##
+## 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} {@var{h} =} hgload (@var{filename})
+## Load the graphics object in @var{filename} into the graphics handle @var{h}.
+##
+## If @var{filename} has no extension, Octave will try to find the file with
+## and without the standard extension of @file{.ofig}.
+## @seealso{hgsave, struct2hdl}
+## @end deftypefn
+
+## Author: Massimiliano Fasi
+
+function h = hgload (filename)
+
+  ## Check input arguments
+  if (nargin != 1)
+    print_usage ();
+  endif
+  
+  ## Check file existence
+  if (! exist (filename))
+    [~, ~, ext] = fileparts (filename);
+    if (isempty (ext))
+      filename = [filename ".ofig"];
+    endif
+    if (! exist (filename))
+      error ("hgload: unable to locate file %s", filename);
+    endif
+  endif
+
+  ## Load the handle
+  try
+    stmp = load (filename, "s_oct40");
+  catch
+    error ("hgload: could not load hgsave-formatted object in %s", filename);
+  end_try_catch
+
+  h = struct2hdl (stmp.s_oct40);
+  
+endfunction
+
+
+## Functional test for hgload/hgsave pair is in hgsave.m
+
+%% Test input validation
+%!error hgload ()
+%!error hgload (1, 2)
+%!error <unable to locate file> hgload ("%%_A_REALLY_UNLIKELY_FILENAME_%%")
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/util/hgsave.m	Thu Mar 06 22:52:59 2014 +0100
@@ -0,0 +1,123 @@
+## Copyright (C) 2014 Massimiliano Fasi
+##
+## 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} hgsave (@var{filename})
+## @deftypefnx {Function File} hgsave (@var{h}, @var{filename})
+## @deftypefnx {Function File} hgsave (@var{h}, @var{filename}, @var{fmt})
+## Save the graphics handle @var{h} to the file @var{filename} in the format
+## @var{fmt}.
+##
+## If unspecified, @var{h} is the current figure as returned by @code{gcf}. 
+## When @var{filename} does not have an extension the default filename
+## extension @file{.ofig} will be appended.  If present, @var{fmt} should 
+## should be one of the following:
+##
+## @itemize @bullet
+## @item @code{-binary}, @code{-float-binary}
+## @item @code{-hdf5}, @code{-float-hdf5}
+## @item @code{-V7}, @code{-v7}, @code{-7}, @code{-mat7-binary}
+## @item @code{-V6}, @code{-v6}, @code{-6}, @code{-mat6-binary}
+## @item @code{-text}
+## @item @code{-zip}, @code{-z}
+## @end itemize
+##
+## When producing graphics for final publication use @code{print} or
+## @code{saveas}.  When it is important to be able to continue to edit a
+## figure as an Octave object, use @code{hgsave}/@code{hgload}.
+## @seealso{hgload, hdl2struct, saveas, print}
+## @end deftypefn
+
+## Author: Massimiliano Fasi
+
+function hgsave (h, filename, fmt = "-binary")
+
+  if (nargin < 1 || nargin > 3)
+    print_usage ();
+  endif
+
+  ## Check input arguments
+  if (nargin == 1 && ischar (h))
+    filename = h;
+    h = get (0, "currentfigure");
+    if (isempty (h))
+      error ("hgsave: No current figure to save");
+    endif
+  elseif (! (ishandle (h) && ischar (filename)))
+    print_usage ();
+  endif
+
+  ## Check file extension
+  [~, ~, ext] = fileparts (filename);
+  if (isempty (ext))
+    filename = [filename ".ofig"];
+  endif
+
+  s_oct40 = hdl2struct (h);
+  save (fmt, filename, "s_oct40");
+
+endfunction
+
+
+%!testif HAVE_MAGICK
+%! toolkit = graphics_toolkit ();
+%! graphics_toolkit ("gnuplot");
+%! unwind_protect
+%!   h1 = figure ("visible", "off");
+%!   x = 0:0.1:2*pi;
+%!   y1 = sin (x);
+%!   y2 = exp (x - 1);
+%!   ax = plotyy (x,y1, x-1,y2, @plot, @semilogy);
+%!   xlabel ("X");
+%!   ylabel (ax(1), "Axis 1");
+%!   ylabel (ax(2), "Axis 2");
+%!   axes (ax(1));
+%!   text (0.5, 0.5, "Left Axis", ...
+%!         "color", [0 0 1], "horizontalalignment", "center");
+%!   axes (ax(2));
+%!   text (4.5, 80, "Right Axis", ...
+%!         "color", [0 0.5 0], "horizontalalignment", "center");
+%!   ftmp = [tmpnam() ".ofig"];
+%!   png1 = [tmpnam() ".png"];
+%!   png2 = [tmpnam() ".png"];
+%!   unwind_protect
+%!     hgsave (h1, ftmp);
+%!     print (h1, png1);
+%!     [img1, map1, alpha1] = imread (png1);
+%!     h2 = hgload (ftmp);
+%!     print (h2, png2);
+%!     [img2, map2, alpha2] = imread (png2);
+%!   unwind_protect_cleanup
+%!     unlink (ftmp);
+%!     unlink (png1);
+%!     unlink (png2);
+%!   end_unwind_protect
+%!   assert (img1, img2);
+%!   assert (map1, map2);
+%!   assert (alpha1, alpha2);
+%! unwind_protect_cleanup
+%!   close (h1);
+%!   close (h2);
+%!   graphics_toolkit (toolkit);
+%! end_unwind_protect
+
+%% Test input validation
+%!error hgsave ()
+%!error hgsave (1, 2, 3, 4)
+%!error hgsave ("abc", "def")
+
--- a/scripts/plot/util/module.mk	Fri Feb 28 19:24:10 2014 +0100
+++ b/scripts/plot/util/module.mk	Thu Mar 06 22:52:59 2014 +0100
@@ -48,6 +48,8 @@
   plot/util/graphics_toolkit.m \
   plot/util/hdl2struct.m \
   plot/util/hggroup.m \
+  plot/util/hgload.m \
+  plot/util/hgsave.m \
   plot/util/hold.m \
   plot/util/isaxes.m \
   plot/util/isfigure.m \
--- a/scripts/plot/util/print.m	Fri Feb 28 19:24:10 2014 +0100
+++ b/scripts/plot/util/print.m	Thu Mar 06 22:52:59 2014 +0100
@@ -275,7 +275,7 @@
 ## @end group
 ## @end example
 ##
-## @seealso{saveas, orient, figure}
+## @seealso{saveas, hgsave, orient, figure}
 ## @end deftypefn
 
 function print (varargin)
--- a/scripts/plot/util/saveas.m	Fri Feb 28 19:24:10 2014 +0100
+++ b/scripts/plot/util/saveas.m	Thu Mar 06 22:52:59 2014 +0100
@@ -56,7 +56,7 @@
 ## @end group
 ## @end example
 ##
-## @seealso{print, orient}
+## @seealso{print, hgsave, orient}
 ## @end deftypefn
 
 ## Author: Kai Habel
--- a/scripts/plot/util/struct2hdl.m	Fri Feb 28 19:24:10 2014 +0100
+++ b/scripts/plot/util/struct2hdl.m	Thu Mar 06 22:52:59 2014 +0100
@@ -32,7 +32,7 @@
 ## A third boolean argument @var{hilev} can be passed to specify whether
 ## the function should preserve listeners/callbacks, e.g., for legends or
 ## hggroups.  The default is false.
-## @seealso{hdl2struct, findobj}
+## @seealso{hdl2struct, hgload, findobj}
 ## @end deftypefn
 
 ## Author: pdiribarne <pdiribarne@new-host.home>