3

I would like to plot some data with gnuplot inside a MATLAB script, instead of using the custom MATLAB plotting environment.

Take the following example, here I generate some random data and store it in a text file:

% Generate data
x = 0:10;
y = randi(100,size(x));

% Store data in 'xy.txt'
fileID = fopen('xy.txt', 'w');
for i = 1:numel(x)
   fprintf(fileID, '%f %f\n', x(i), y(i));
end
fclose(fileID);

Now I use MATLAB's system to pipe commands to gnuplot:

% Call gnuplot to do the plotting tasks
system('gnuplot &plot ''xt.txt'' &exit &');

However, I am not constructing this last instruction correctly since it only opens the gnuplot console but doesn't execute the commands.

Additionally, instead of saving the data in a text file in an intermediate step, I would prefer doing this direct approach.

How should I construct my system instruction properly?

NOTE: There is a similar question for Linux, I am running Windows.

Community
  • 1
  • 1
codeaviator
  • 2,365
  • 13
  • 35
  • Have you tried it? As long as you are not processing huge amounts of data, there is nothing wrong with that approach. You could also use one of the many wrapper APIs implemented for Java and Python. Both can be used in MATLAB. – Daniel Feb 18 '16 at 23:46
  • I don't know how to call gnuplot from MATLAB, that's the main reason I'm posting the question. I don't know what a wrapper API is...I'll have a look! – codeaviator Feb 18 '16 at 23:50
  • 1
    On windows systems, you use the `system` command, not `unix`. Otherwise it is done the same way. – Daniel Feb 18 '16 at 23:53
  • Thanks for that Daniel. Why do you suggest that this would be problematic for large amounts of data? Should I generate a data file in that case? – codeaviator Feb 19 '16 at 00:10
  • 1
    There is simply [a limit](http://stackoverflow.com/questions/3205027/maximum-length-of-command-line-string) – Daniel Feb 19 '16 at 00:22
  • does this work? `system('gnuplot -p -e "plot \''xt.txt\''');` – vagoberto Feb 19 '16 at 01:59
  • @vagoberto No, it doesn't work. `invalid character \ ` – codeaviator Feb 19 '16 at 09:00

2 Answers2

2

Using temporary script with commands for gnuplot

Print all commands to temporary file plot.gp and pass it to gnuplot.

You are running Windows, so change /usr/bin/gnuplot to gnuplot (may work) or your full location of gnuplot executable (would work)

% checked to work under octave 3.6.4 + gnuplot 4.6
x = 0:10;
y = randi(100,size(x));

str="/usr/bin/gnuplot -p plot.gp"
fileID = fopen('xy.txt', 'w');
for i = 1:numel(x)
   fprintf(fileID, '%f %f\n', x(i), y(i));
end
fclose(fileID);

f2=fopen('plot.gp', 'w');
fprintf(f2, "plot 'xy.txt' using 1:2");
fclose(f2);

system(str)

Using one long command

However, plot '-' ... makes gnuplot 4.6 (Linux) hang in any case with -p or --persist option. You can check it on your gnuplot version in Windows.

x = 0:10;
y = randi(100,size(x));
str="/usr/bin/gnuplot -p -e \"plot \'-\' using 1:2\n";
for i = 1:numel(x)
str=strcat(str,sprintf('%f %f\n',x(i),y(i)));
end
str=strcat(str,"e\"\n");
system(str)

Also, as @Daniel said, you have a limit on a string length, so it is definitely better to use temporary file then a long-long command.

Community
  • 1
  • 1
John_West
  • 2,139
  • 4
  • 21
  • 40
  • Thanks a lot John_West, I have converted both of your scripts into MATLAB syntax. The **"Using temporary script with commands for gnuplot"** version generates the plot, but the script doesn't terminate (MATLAB status: Busy...) unless you close the plot window. The **"Using one long command"** version does not generate any plot and neither terminates. I will edit my post with my progress so far, based on your answer, if that is appropriate. – codeaviator Feb 20 '16 at 15:23
  • @Cebri "script doesn't terminate" and it should not, I think. If you want it to terminate immediately, remove `-p` option from `gnuplot` command (`str`). But I think, the plot would just blink and disappear. Then, if you want discontinuous processing, you should not use screen (`wxt` terminal, e.g), but write it to `png`: add to `plot.gp` commands: `set terminal png; ` Thank you for testing *"Using one long command"* - it seems `gnuplot` can't process `plot '-'` correctly when using `-e`. – John_West Feb 20 '16 at 15:42
  • Typo, should be "if you want ***continuous*** processing". – John_West Feb 20 '16 at 16:54
1

This answer is based on John_West answer, which was very helpful. I have translated his GNU Octave code into MATLAB syntax.

I found this page helpful to understand the differences between GNU Octave and MATLAB, in terms of code syntax. And this page helpful to understand the escape sequences on GNU Octave strings (which are in fact, the same as in C).

These are the conversions I made:

  • Replace " string delimiter with '
  • Replace \" escape sequence with "
  • Replace \' escape sequence with ''

Furthermore, I made the following transformations:

  • Use sprintf wherever there is an escape sequence.
  • Rearrange the use of escape sequences because strcat removes trailing ASCII white-space characters. (You can read about this in the documentation and this answer).

Using temporary script with commands for gnuplot

This approach works very well.

% checked to work under Matlab R2015a + gnuplot 5.0 patchlevel 1
x = 0:10;
y = randi(100,size(x));

str = 'gnuplot -p plot.gp';
fileID = fopen('xy.txt', 'w');
for i = 1:numel(x)
   fprintf(fileID, '%f %f\n', x(i), y(i));
end
fclose(fileID);

f2 = fopen('plot.gp', 'w');
fprintf(f2, 'plot ''xy.txt'' using 1:2');
fclose(f2);

system(str)

This script will open a gnuplot window with the plot. MATLAB will not resume the execution of the script until you close the plot window. If you want a continuous flow of execution, you can automatically save the plot (for example as a .png, among other formats) with the command:

fprintf(f2,'set terminal png; set output "figure.png"; plot ''xy.txt'' using 1:2');

as John_West explains in his comment.

Using one long command

This approach is under exploration. No successful results have been achieved yet (at least John_West and I did not get any plot). I am including my MATLAB code as I transcribed it from John_West answer:

x = 0:10;
y = randi(100,size(x));
str = sprintf('gnuplot -p -e "plot ''-'' using 1:2');
for i = 1:numel(x)
str = strcat(str, sprintf('\n%f %f', x(i), y(i)));
end
str = strcat(str, sprintf('\ne"'), sprintf('\n'));
system(str)

This code does not terminate by itself, so you will need to manually resume the execution by entering the command e in the MATLAB command line.

Community
  • 1
  • 1
codeaviator
  • 2,365
  • 13
  • 35