Octave and LaTeX – Love at first Sight

While working on a concept and draft for my bachelor thesis I decided I wanted charts. Bar charts, line charts, multiple line charts, you get the point.

Now, if you tried to include images in a LaTeX document you probably know already that resolution matters. A lot. You want your printed document to look nice and professional so you can be proud of it, but its charts are all blurry and pixelated. Even worse, you rendered your charts with a random tool of your choice and they look great but the fonts don’t match the target document’s, they don’t scale (because they are part of the image).

Well, at least those were my problems. Then I discovered output modes of Octave. In tex output mode it generates two files: an encapsulated postscript (.eps) and a LaTeX document. Just include (\import or whatever you want to use) the latter in your main document and marvel at the astonishing results!

Here’s my Octave function generating three graphs in one plot. You can call it like that:

threegraph([0 1 2; 2 3 4; 5 5 7; 8 1 0;], {'One', '', 'Three', ''}, 'testplot', 'Some random values', {'Graph one', 'Graph two', 'Graph three'});

function[] = threegraph(values, xticklabels, plotname, labely, legends)
	##
	UPPERBOUNDS = 0.4;
	##

	printf("Printing %s; %d values, %d labels\n", plotname, length(values), length(xticklabels));

	% Generates ticks ignoring empty labels.
	xtick = (1 : length(values));
	for i = 1 : length(xticklabels)
		if (strcmp(xticklabels(i), '') != 0)
			xticks(i) = 0;
		endif
	end

	% first graph
	handle = plot(values(:,2), '0');
	set(handle(1), 'linewidth', 2);

	hold on;

	% second graph
	handle = plot(values(:,3), '1');
	set(handle(1), 'linewidth', 2);

	% third graph
	handle = plot(values(:,4), '2');
	set(handle(1), 'linewidth', 2);
	
	handle = plot(values(1:end-1,:), '0o', 'markersize', 5);

	axs = axis();
	% correctly clip x-axis
	axs(2) = length(values) + 1;
	% set upper bounds
	mval = max(max(values));
	axs(4) = mval + mval * UPPERBOUNDS;
	axis(axs);

	legend(legends);
	ylabel(labely);

	set(gca, 'xtick', xtick);

	% set labels
	set(gca, 'xticklabel', xticklabels);

	% now make a nice tex document ready for \include
	print(strcat(plotname, '.tex'), '-dtex', '-S850,350');
	hold off;
endfunction

The next one was a bit trickier, I wanted a bar graph and the labels to be rotated. Fortunately I found a mailing list entry by Eric Chassande-Mottin who provided his solution for rotating labels.

function[] = bargraph(values, xticklabels, plotname, labely)
	##
	UPPERBOUNDS = 0.02;
	##

	printf("Printing %s; %d values, %d labels\n", plotname, length(values), length(xticklabels));

	% Moving labels' position results in really weird plots, so we just append
	% trailing (LaTeX) spaces here as a workaround.
	for i = 1 : length(xticklabels)
		xticklabels(i) = cstrcat(char(xticklabels(i)), "~~");
	end

	handle = bar(values);
	ylabel(labely);

	axs = axis();
	% correctly clip x-axis
	axs(2) = length(values) + 1;
	% set upper bounds
	axs(4) = max(values) + max(values) * UPPERBOUNDS;
	axis(axs);

	% define which bars to label
	xtick = (1 : length(values));
	set(gca, 'xtick', xtick);

	% set labels for bars
	set(gca, 'xticklabel', xticklabels);

	% get position of current xtick labels
	xlabelpos = get(gca, 'xlabel');
	xlabelstring = get(xlabelpos, 'string');
	xlabelposition = get(xlabelpos, 'position');

	% construct position of new xtick labels
	yposition = xlabelposition(2);
	yposition = repmat(yposition, length(xtick), 1);

	% disable current xtick labels
	set(gca, 'xtick', []);

	% set up new xtick labels and rotate 45 degrees
	newticks = text(xtick, yposition, xticklabels);
	set(newticks, 'rotation', 45, 'horizontalalignment', 'right'); 

	% now make a nice tex document ready for \include
	print(strcat(plotname, '.tex'), '-dtex', '-S850,350');
endfunction

Run the above function to get an idea of the possibilities that Octave offers. I’m really no expert in the Octave language (neither MATLAB by the way), but the results are so great I thought I had to share this.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.