%% Copyright (C) 2008 Simone Zuccher %% %% This file is NOT part of Octave but you can redistribute it and/or modify it %% under the terms of the GNU General Public License as published by %% the Free Software Foundation. For more details %% see the GNU General Public License at %% . %% %% This is distributed in the hope that it will be useful, but %% WITHOUT ANY WARRANTY. %% -*- texinfo -*- %% @deftypefn {Function File} {} gps %% @deftypefnx {Function File} {} gps (@var{cmd}) %% @deftypefnx {Function File} {} gps (@var{ps-type},@var{name}) %% @deftypefnx {Function File} {} gps (@var{action}, @var{data}, @var{attribute}, @dots{}) %% Motivation/purpose. %% Octave is a great environment to run computations but it might look not %% very flexible to people that use Gnuplot (http://gnuplot.sourceforge.net/) %% for making highly-customized %% figures, i.e. figures with special labels, arrows, mathematical %% formulae in the legend or on the axis, and so on. %% A simple example is, from version 3.0.0 of Octave, the impossibility %% to make plots with bullets (or filled circles), available in previous versions %% of Octave. %% %% Description. %% 'gps' (GnuPlot Stream) %% produces two-dimensional and three-dimensional plots using a direct %% gnuplot stream of commands sent to an X11 window. %% Therefore, all gnuplot features are usable. %% The only drawback is that data passed to gps are written on local (hidden) %% files. This is necessary to allow the full usage of 'replot'. %% %% Many different combinations of arguments are possible. %% %% @noindent %% No arguments. %% @example %% gps %% @end example %% This causes gps to close previously opened plots, i.e. %% if no windows were open, nothing is done; if a gps window was open, then it %% is closed. Usage: %% %% %% %% @noindent %% One arument. %% @example %% gps (@var{cmd}) %% @end example %% Possibilities for @var{cmd} are: %% @itemize @bullet %% @item %% A single gnuplot command or multiple gnuplot commands separated by %% semicolon. Examples include %% @example %% gps("plot [-2*pi:2*pi][-1:1] sin(x); set title 'My first plot'") %% gps("set xlabel 'x'"); %% gps("replot cos(x); set title 'sin and cosine of x'") %% @end example %% %% As you can see, make sure you use correctly " and '. %% Note that gps adds "replot" to every gnuplot command to make sure %% that all listed commands are executed. %% %% @item %% If @var{cmd} is "exit" or "e" or "quit" or "q", gps closes the gnuplot %% stream, i.e. this is equivalent to invoking gps without arguments. %% All following examples close the gnuplot stream. %% @example %% gps %% gps("exit") %% gps("e") %% gps("quit") %% gps("q") %% @end example %% %% @item %% If @var{cmd} is "ps" or "pss" or "psbk" or "psbk3d" a postscript figure %% named gps.ps is created from the current plot. %% Command "ps" refers to a figure with the standard gnuplot settings, whereas %% command "pss" refers to square axis (i.e. x and y axis have the same length). %% Options with "bk" ("psbk" and "psbk3d") refer to the standard size(s) %% used in the book by Squassina and Zuccher (2008). %% Notice that "ps" and "pss" generate postscript 'cropped' figures, i.e. %% dvips tries to minimize the margins. %% Therefore, figures might have different BoundingBox. %% When "psbk" or "psbk3d" are invoked, the BoundingBox is replaced %% so as to conform to the standard in Squassina and Zuccher (2008). %% Valid calls are %% @example %% gps("ps") % -> standard gnuplot settings %% gps("pss") % -> square aspect ratio (2D plots) %% gps("psbk") % -> square aspect ratio scaled by 86% (2D plots) %% gps("psbk3d") % -> square aspect ratio scaled by 97% (3D plots) %% @end example %% @end itemize %% %% @noindent %% Two aruments. %% @example %% gps (@var{ps-type},@var{root-name}) %% @end example %% The first argument is the type of postscript plot ("ps" or %% "pss" or "psbk" or "psbk3d", as explained above), the second %% one is the root of figure filename without extension (the extension ".ps" %% is added automatically by gps). Valid calls are: %% @example %% gps("ps","fig1") % -> fig1.ps, standard gnuplot settings, cropped %% gps("pss","fig2") % -> fig2.ps, square aspect ratio, cropped %% gps("psbk","fig3") % -> fig3.ps, square, scaled by 86%, fix size %% gps("psbk3d","fig4") % -> fig4.ps, square, scaled by 97%, fix size %% @end example %% %% %% @noindent %% More than two aruments (main purpose of gps). %% @example %% gps (@var{action}, @var{data}, @var{attribute}, @var{data}, @var{attribute}, @var{data}, @var{attribute}, @dots{}) %% @end example %% The first argument @var{action} is the plotting mode, i.e. %% @example %% "plot" or "p" for 2D plots %% "splot" or "s" for 3D plots without surfaces %% "splots" or "ss" for 3D plots with surfaces %% "replot" or "rep" or "r" for any type of plot %% @end example %% The second argument @var{data} is the data to be plotted and, %% depending on @var{action}, @var{data} can be %% @example %% (a) @var{x}, @var{y}, @var{z} for "splots" or "ss" where @var{x} and @var{y} are vectors of %% aritrary lengths (Nx for @var{x} and Ny for @var{x}) and @var{z} is a matrix %% Nx by Ny which contains the values of z(i,j) at point of %% coordinates x(i),y(j). %% (b) a single matrix @var{data} N x M for all other values of @var{action}, %% where N is the number of points to be plotted and M is the number %% of columns. Gnuplot uses by default the first two columns in 2D %% plots and the first three columns in 3D plots. %% @end example %% The third argument @var{attribute} is the data attribute and %% includes title (which will appear in the legend), style (with lines or %% with points) or whatever option, exactly as in Gnuplot. %% If more than 3 arguments are supplied, then their number must odd because %% the 4th argument will be data again, the 5th will be their attributes, and so %% forth. %% Valid calls are %% @example %% gps("plot",[x y],"t '1st line' w lp",\ %% [x y.^2],"t '2nd line' w p",\ %% [x -abs(y)],"t '3rd line' w l;\ %% set auto;\ %% set xlabel 'x';\ %% set ylabel 'y'") %% gps("replot",[x -y.^2],"t '2nd line' w lp") %% gps("splot",[x y sin(x).*cos(y)],"t '3D line 1' w l;\ %% set auto",\ %% [y x x.*y],"t '3D line 2' w lp") %% gps("splots",x,y,z,"w l t '';\ %% set surface;\ %% set hidden3d;\ %% set ticslevel 0;\ %% set xlabel 'x';\ %% set ylabel 'y';\ %% set label 'z= sin(sqrt(x^2+y^2))' at 0,0,1.1;\ %% ") %% @end example %% As seen in these examples, the <> attribute can include commands %% which can influence the whole plot such as %% axis labels, axis ranges, plot title, arrows, labels, and so on. %% This works as long as such commands are included %% in the <> attribute and are separated by a semicolon ";". %% @end deftypefn %% Purpose: To avoid using Octave for making professional figures %% Author: Simone Zuccher %% Created: 26 Oct 2008 %% Bug report: zuccher@sci.univr.it function gps(varargin) global __gp_var % Quit if called without arguments if(nargin==0) __gp_end_in__ return endif % if a gnuplot stream is not open yet, open one __gp_start_in__ if(nargin==1) cmd=varargin{1}; switch (cmd) case {"exit", "quit", "q", "e"} __gp_end_in__ return case {"ps", "pss", "psbk"} __gp_2ps_in__(cmd,"gps") return endswitch % at this point it must be a gnuplot command... fprintf (__gp_var.FID, "%s;replot\n",cmd); fflush(__gp_var.FID); return endif % if the first argument is "ps", export plot as postscript figure % and the second argument is interpreted the figure name -> name.ps if (nargin==2) cmd=varargin{1}; name=varargin{2}; switch (cmd) case {"ps", "pss", "psbk", "psbk3d", "ps3d"} __gp_2ps_in__(cmd,name) return endswitch endif if ((nargin>2) && (mod(nargin-1,2)==0)) pltoption=varargin{1}; % this switch is needed only to decide about deleting previous files switch (pltoption) case {"plot", "p", "splot", "s", "splots", "ss"} % previous plotted files are not needed and, thus, are deleted system("rm -f .__gp_plt_tmpfile*.dat"); % set number of plotted curves to 0 __gp_var.NC=0; endswitch % this is the main switch switch (pltoption) case {"plot", "p"} __gp_plt_in__("plot",varargin{2:nargin}) case {"splot", "s"} __gp_plt_in__("splot",varargin{2:nargin}) case {"splots", "ss"} __gp_plt_in__("splots",varargin{2:nargin}) case {"replot", "rep", "r"} __gp_plt_in__("replot",varargin{2:nargin}) endswitch return endif % If none of the above cases apply, then there is something wrong disp('gps: unknown command or sintax error'); endfunction % gps %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function __gp_plt_in__(varargin) global __gp_var % find out the plot option and number of curves gpoption = pltoption = varargin{1}; Ncurves = floor((nargin-1)/2); % in case of "splots" (which does not exist in gnuplot, do differently if(strcmp(pltoption,"splots")) gpoption = "splot"; Ncurves = floor((nargin-1)/4); endif % final command to be sent to the stream finalcmd=[gpoption " "]; % loop on number of curves for i=1:Ncurves __gp_var.NC = __gp_var.NC+1; % generate a temporary file (hidden) name tmpname=[".__gp_plt_tmpfile" num2str(__gp_var.NC) ".dat"]; % enter here only for surface plot, i.e. "splots" if(strcmp(pltoption,"splots")) % get the data from inputs x = varargin{(i-1)*4+2}; y = varargin{(i-1)*4+3}; z = varargin{(i-1)*4+4}; % get the lengths nx=length(x); ny=length(y); % open the temporary file and write data in right format for surface plot tmpfid=fopen(tmpname,"w"); for ix=1:nx for iy=1:ny fprintf(tmpfid,"%f %f %f \n",x(ix),y(iy),z(ix,iy)); end fputs(tmpfid,"\n"); end % close data file fclose(tmpfid); % extract the attributes of the current data gpcmd = varargin{(i-1)*4+5}; % enter here for regular gnuplot plots else data = varargin{i*2}; % if only one point is plotted, it is made a vector of 2 equal points if(size(data)(1)==1) data = [data;data]; endif % save data to the file save("-ascii",tmpname,"data"); % extract the attributes of the current data gpcmd = varargin{i*2+1}; endif % add this plot to the final command if(i>1) finalcmd = [finalcmd ',']; endif finalcmd = [finalcmd ' ''' tmpname ''' ' gpcmd]; % sprintf("%s '%s' %s;",finalcmd,tmpname,gpcmd); endfor % wait 1/10 of a second to make sure files are written... pause(.1) % (re)plot data and add replot to ensure interpretation of additional commands fprintf (__gp_var.FID, "%s; replot \n",finalcmd); fflush(__gp_var.FID); endfunction %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function __gp_start_in__ global __gp_var % if __gp_var does not exists create an empty one if (isempty(__gp_var)) __gp_var.FID=0; __gp_var.ON=false; __gp_var.NC=0; endif % If no gnuplot stream is open, open one and set the global variables if ((__gp_var.FID == 0) && (__gp_var.ON == false) && (__gp_var.NC == 0)) __gp_var.FID=popen("gnuplot -noraise","w"); __gp_var.ON=true; __gp_var.NC=0; fputs(__gp_var.FID,"set term x11\n"); fputs(__gp_var.FID,"set yrange restore; plot 1./0. t '' \n"); %else % disp("La variabile esiste e non ho aperto niente\n") endif endfunction % __gp_start_in__ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function __gp_end_in__ global __gp_var % If __gp_var exists, is not empty and is not initialized to zero, close stream if ((exist("__gp_var") == 1) && (!isempty(__gp_var)) && ... (__gp_var.ON) && (__gp_var.FID > 0)) % disp('quitting...'); pclose(__gp_var.FID); system("rm -f .__gp_plt_tmpfile*.dat"); system("rm -f __gp_2ps__tmpxxxfig*"); __gp_var.FID=0; __gp_var.ON=false; __gp_var.NC=0; clear __gp_var endif endfunction % __gp_end_in__ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function __gp_2ps_in__(type,name) global __gp_var % Save current plot settings fputs(__gp_var.FID,"save '.__gp_plt_tmpfileCURRENTPLOT'\n"); fflush(__gp_var.FID); pause(.2); % say why we are waiting fdisp (stdout, ['generating figure ' name '.ps...']); fflush(stdout); % defaul option is regular gnuplot size sizeoption = "noratio 1,1 "; BBoption = "18 546 398 796"; fontoption = "12"; switch (type) case {"pss"} sizeoption = "square"; BBoption = "66 535 349 806"; case {"psbk"} sizeoption = "square 0.86,0.86"; % sizeoption = "square 0.9,0.9"; BBoption = "51 567 290 809"; case {"psbk3d"} fontoption = "8"; sizeoption = "square 0.97, 0.97"; % BBoption = "70 550 298 743"; BBoption = "70 560 298 753"; fputs(__gp_var.FID,"set format x '%g \\vspace{-3mm}\\hspace{1mm}'\n"); fputs(__gp_var.FID,"set format y '%g \\vspace{0mm}\\hspace{-5mm}'\n"); % fputs(__gp_var.FID,"set format z '%g \\vspace{1mm}\\hspace{-4mm}'\n"); fflush(__gp_var.FID); case {"ps3d"} fontoption = "8"; sizeoption = "square 0.97, 0.97"; BBoption = "90 580 298 790"; fputs(__gp_var.FID,"set format x '%g \\vspace{-3mm}\\hspace{1mm}'\n"); fputs(__gp_var.FID,"set format y '%g \\vspace{0mm}\\hspace{-5mm}'\n"); fflush(__gp_var.FID); endswitch %for i=1:2 % Export from gnuplot to pslatex fputs(__gp_var.FID,["set term pslatex " fontoption "\n"]); fputs(__gp_var.FID,"set output '__gp_2ps__tmpxxxfig.tex'\n"); fputs(__gp_var.FID,["set size " sizeoption "\n"]); %fputs(__gp_var.FID,"set key spacing 1.7\n"); fputs(__gp_var.FID,"replot\n"); fflush(__gp_var.FID); % Reset things as before fputs(__gp_var.FID,"set term x11\n"); pause(.1); fputs(__gp_var.FID,"load '.__gp_plt_tmpfileCURRENTPLOT'\n"); fputs(__gp_var.FID,"replot\n"); fflush(__gp_var.FID); %end % Remove temporary file system("rm -f .__gp_plt_tmpfileCURRENTPLOT"); % Create a temporary LaTeX file to include the figure generated above system("echo ' \\\\documentclass[12pt,a4paper]{article}' >> __gp_2ps__tmpxxxfiglatexfile.tex"); system("echo ' \\\\setlength{\\\\topmargin}{-40 mm}' >> __gp_2ps__tmpxxxfiglatexfile.tex"); system("echo ' \\\\setlength{\\\\oddsidemargin}{-25 mm}' >> __gp_2ps__tmpxxxfiglatexfile.tex"); system("echo ' \\\\setlength{\\\\textwidth}{200 mm}' >> __gp_2ps__tmpxxxfiglatexfile.tex"); system("echo ' \\\\setlength{\\\\textheight}{200 mm}' >> __gp_2ps__tmpxxxfiglatexfile.tex"); system("echo ' \\\\setlength{\\\\footskip}{0 mm}' >> __gp_2ps__tmpxxxfiglatexfile.tex"); system("echo ' \\\\usepackage{graphics}' >> __gp_2ps__tmpxxxfiglatexfile.tex"); system("echo ' \\\\usepackage{amsmath}' >> __gp_2ps__tmpxxxfiglatexfile.tex"); system("echo ' \\\\pagestyle{empty}' >> __gp_2ps__tmpxxxfiglatexfile.tex"); system("echo ' \\\\begin{document}' >> __gp_2ps__tmpxxxfiglatexfile.tex"); system("echo ' \\\\input{__gp_2ps__tmpxxxfig.tex}' >> __gp_2ps__tmpxxxfiglatexfile.tex"); system("echo ' \\\\end{document}' >> __gp_2ps__tmpxxxfiglatexfile.tex"); % Run LaTeX without showing anything on the screen system("latex __gp_2ps__tmpxxxfiglatexfile.tex > /dev/null"); % Make the postscript file in silent mode system("dvips -E -o __gp_2ps__tmpxxxfiglatexfile.ps __gp_2ps__tmpxxxfiglatexfile -q"); % Replace bounding box only for psbk and psbk3d switch (type) case {"psbk", "psbk3d", "ps3d"} system(["sed s/'BoundingBox: '/'BoundingBox: " BBoption " % '/ \ < __gp_2ps__tmpxxxfiglatexfile.ps > __gp_2ps__tmpxxxfiglatexfilenew.ps"]); system("cp __gp_2ps__tmpxxxfiglatexfilenew.ps __gp_2ps__tmpxxxfiglatexfile.ps"); endswitch % Change the title of the figure to the correct one and finish systemcm = ["sed s/'__gp_2ps__tmpxxxfiglatexfile.dvi'/'" name ".dvi'/ < \ __gp_2ps__tmpxxxfiglatexfile.ps > " name ".ps"]; system(systemcm); % Clear up temporary files system("rm -f __gp_2ps__tmpxxxfiglatexfile* __gp_2ps__tmpxxxfig.tex"); % Done endfunction % __gp_2ps_in__ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%