When running MATLAB in a batch mode without a display (e.g. with the $DISPLAY UNIX environment variable unset, or with the matlab -nodisplay flag at startup), normally you cannot use the opengl renderer. Instead you must settle for the painters renderer. For example:
>> print -dpng -opengl fig.png
Warning: OpenGL mode can not be used in terminal emulation mode; ignoring option.
Unfortunately, painters often gives poor results when working with 3D scenes with patches, lighting, transparency, etc.. Here is one simple example (using a display for now) where the alpha is lost:
peaks
alpha(0.5)
print -dpng -opengl peaks_opengl.png
print -dpng -painters peaks_painters.png
Because of these limitations, I was very excited to find the mostly-undocumented hardcopy() built-in MATLAB function, which does somehow let you use the opengl renderer without a display. This function underlies the terrific export_fig() function. Now I am able to very rapidly save high quality 3D figures in batch mode.
However, there is one catch: All text is lost when the figure gets passed through the hardcopy() function. For example:
plot(1,1)
title('TEST')
>> A = hardcopy(gcf, '-Dopengl', '-r300');
Warning: Failed to draw text string
> In /Applications/MATLAB_R2010b.app/toolbox/matlab/graphics/hardcopy.p>hardcopy at 21
The output figure is completely lacking any text (no axis ticks labels and no title):
export_fig axis.png -opengl
So what I'm wondering is: How can I get the opengl renderer to work with text in batch mode? Is there a way I can get text to work with the hardcopy() function? Perhaps a way to rasterize the text beforehand? Or a way to combine a painters hardcopy of the text and an opengl hardcopy of the plot? Alternatively, is there a completely different route to make this work than the hardcopy() function? Also note that the problem is unlikely to be with my system setup, since it is reproducible under both Mac OS and Ubuntu.
If you're using Linux, you can use a software OpenGL renderer (modern versions of Matlab have one bundled).
Such an option does not exist for Mac OS, at least not with current Matlab versions.
Windows is easy - even the batch mode runs a display, so you can work as usual.
Run Xvfb :1 &, which creates a (virtual) framebuffer X server.
Prepare your code in some file, say bla.m :
opengl software;
peaks
alpha(0.5);
print -dpng -opengl peaks_opengl.png
exit
It's very important not to forget opengl software, as you imagine.
Run the following command:
cat bla.m | matlab -display :1 -logfile log.txt
which makes Matlab execute whatever's in bla.m, on the virtual display, and writes whatever Matlab outputs into log.txt. You can drop the logfile when everything seems to be working. Also, note that :display :1 has to fit the number you provided in the Xvfb invocation.
Profit.
Related
I have Matlab code that produces an array of subplots that looks like this:
When I save this as an EMF file (normally a vector format) and insert in Powerpoint or view with Inkscape, then zoom in closely on the image, it looks pixelated, and clearly made up of a single encapsulated object as opposed to many small graphical objects:
This is very surprising to me, as I have for a long time been exporting Matlab plots as EMF and integrating those into Powerpoint slides, in order to build there more complex graphs that, as vector graphics, would print well at any size. These imported EMFs would also scale well and look smooth regardless of how much I zoomed into them in Powerpoint.
Can anyone guess why it is that on this occasion, this plot is not saved as a vector graphics but is instead (as it seems) rendered as raster? The code that produces this figure (based on the Matlab commands subplot, line, and scatter) is rather long/inelegant, but I can give details or simplify, if required to find a solution. Thanks!
Other similar threads on this site have not helped fix this.
I believe I have encountered this issue before. If it is the same as the issue I was facing, it is to do with the renderer being used to save the plot. Although it should automatically select the painters renderer when exporting to vector files, I have had instances where it used the openGL renderer instead, which results in bitmaps being used. I'm not entirely sure why this happens -- it might be the case that for particularly complicated figures, it reverts to openGL to avoid obnoxiously large or complicated vector files.
If you are using the print command, you can force it to use the painters algorithm as follows:
print('-painters',...)
if you're saving using File>Save As..., I believe setting the renderer for the figure should work:
set(figure_handle,'renderer','painters');
For explanation, per the MATLAB documentation:
-opengl' — OpenGL renderer. Use this renderer when saving bitmap images. OpenGL produces a bitmap image even with vector formats, which might limit the extent to which you can edit the image in other applications.
'-painters' — Painters renderer. Use this renderer when saving vector graphics files. If you save to a vector graphics file and if the figure RendererMode property is set to 'auto', then print automatically attempts to use the Painters renderer. If you want to ensure that your output format is a true vector graphics file, then specify the Painters renderer. For example:
print('-painters','-deps','myVectorFile')
If you do not specify the renderer, then print automatically uses the appropriate renderer to produce the output format requested. However, if you set the Renderer property for the figure, then print uses that renderer when generating output.
EDIT: Another option is to use the Copy Figure command (Edit > Copy Figure) -- this should copy the figure as an EMF file, and should obey the figure's renderer settings.
In MATLAB R2016b I have trouble with rendering.
1) When hardware acceleration is enabled (default, or setting opengl hardware) I get:
=> when lines are close one to each other lines are darker and ligher when isolated. I want constant color.
2) When acceleration is done with software (opengl software) I get:
=> lines are always at same dark level (what I want)
Note: with the process of putting the images on the site, what I want to show is less clear but I hope still visible and understandable...
Question: is there a way to enable GPU acceleration (opengl hardware) while also having a consistent rendering of line color along the whole line?
When hardware acceleration is 'on' [1], the GraphicsSmoothing property of figures is 'on' by default, and the AlignVertexCenters property of lines if 'off' by default. This gives the result of Figure 1 in the question.
Switching AlignVertexCenters to 'on' solves the issue (the same as when turning off hardware acceleration, as stated) and gives the Figure 2.
Now, to set this permanently, add this into startup.m (the file launched by MATLAB at each startup if found in userpath)
set(0, 'DefaultLineAlignVertexCenters', 'on')
For more information of startup.m see https://mathworks.com/help/matlab/ref/startup.html
[1] this is the default if an up to date graphics card is installed, and can be checked typing opengl info and verifying that HardwareSupportLevel=='full' for example.
I need some to produce some publication-quality figures. I first export the figures from matlab in .svg format, and then I do some post-processing in inkscape. I am no problem with figures generated using plot or scatter, but when I export figures generated using surf (in view(2)), I run into problems. If I use plot or scatter, I am able to ungroup and process various parts like the title, axes, scattered points, lines, etc. in inkscape. For surf, however, matlab just exports one single figures with all various parts grouped into one single unit. I can't separate individual part, and when I zoom very close I can actually see the bitmap resolution for the axes and titles (if I use plot, the titles and axes have 'infinite' resolution when I zoom very close). I am fine with the surface plot having finite resolution, but I need to at least be able to process the axes and titles (which I currently cannot do). What should I do so that I can 'separate' the title and axes from the main plot, just like figures generated from plot and scatter?
I stumbled across this question, since I encountered the same problem.
As mentioned by #vindarmagnus, it is possible to use tikz and get rather nice results. However, tikz experiences problems with large data sets in my experience as present when using surf etc..
Solution, that worked for me:
Change the renderer to painters and the exported .svg file will retain its vectorgraphic properties when opened e.g. in inkscape:
figure('Renderer','Painters');
I used to use Inkscape for my scientific publications as well, but I found that a lot of the time you can get better results with pgfplots in latex, together with the matlab2tikz matlabscript. There’s a ton of resources about this online, but here’s how my workflow would look adopted to your surf situation. I have macOSX with latex, matlab and matlab2tikz installed. Will work with little to no modifications on linux.
In Matlab:
surf(peaks(25))
matlab2tikz('plot.tikz’)
Then I have the following bash-script (just a script in the same folder as the image, which is executed by mere double-click). (Needs to be chmod-ed as an executable for that).
#!/bin/bash
cd ~/Desktop
rm *.eps
cat > plot.tex << EOF
\documentclass{standalone}
\usepackage{pgfplots}
\pgfplotsset{max space between ticks=50}
\pgfplotsset{scaled ticks = false}
\pgfplotsset{compat=1.6}
\pgfplotsset{xticklabel style={/pgf/number format/fixed}}
\pgfplotsset{yticklabel style={/pgf/number format/fixed}}
\begin{document}
\input{plot.tikz}
\end{document}
EOF
pdflatex plot.tex
pdf2ps plot.pdf
ps2eps plot.ps
Note that the row cd ~/Desktop above should be changed as to reflect which folder the script is supposed to be run from (a bit crappy, but needed since Finder doesn’t properly pass along the folder from a program is executed, afaik).
This yields high-quality images in eps or pdf or what you like, with a ton of settings for axes and ticks etc. And it all uses native latex fonts.
Edit:
Recently I’ve begun to use patch() in matlab and then export it to tikz in the same manner as above, with great results. That’s another suggestion!
You can use also:
set(gcf,'Renderer','Painters')
I'm using the still undocumented HG2-Update to create my MATLAB plots, because they just look that much nicer.
(Source: Yair Altman)
Actually, using the current version Release 2013b it works quite nicely and there are not much issues. Except one wants to export the figures as vector graphics (renderer: '-painters'), especially as pdf.
I use the commands:
saveas(gcf,'test.pdf','pdf')
or
print(gcf,'test.pdf','-dpdf')
There are rendering issues, the print does not contain the whole figure and some parts are cropped or non-default fonts are not recognized.
But I'd really like to stay with HG2 and I'd still like to use vector graphics. Is there any solution or workaround?
Exporting vector graphics using the yet not official HG2-Update is quite an issue. The .pdf-export is still totally screwed up.
What is working fine is the .svg-export, apart from that the boundary box is not set properly.
The long workaround would be:
Save the plot with '-dsvg' (print-command) or 'svg' (saveas-command) as vector graphic, open the file in the open source application Inkscape and save again as .pdf with the Export area is drawing checkmark set.
Quite complicated, so I found a way to do it via command-line directly from Matlab (Inkscape still required!):
filename = 'test';
inkscapepath = '"C:\Program Files (x86)\Inkscape\inkscape.exe"';
%// save as .svg
saveas(gcf,filename,'svg')
%// open and save with "export-area-drawing" set via command line
system( [inkscapepath ' ' filename ...
'.svg --export-area-drawing --export-pdf=' filename '.pdf'])
It takes some time, but works without any known issues for now.
Additionally delete the svg-File afterwards:
delete([filename '.svg'])
I had the same problem and used the workaround from thewaywewalk. Now I discovered the MATLAB function "hgexport" works under HG2 (in R2014a).
An issue still was the paper size. I want to use the same size for all graphs with as little white frame as possible. Here you have to set two sizes:
The papersize is set with set(gcf,'PaperSize',[width height]) and the size of your chart is set through export styles. These are set in "Export Setup" or command line:
exp_style=hgexport('readstyle','default');
exp_style.Width = 'width';
exp_style.Height = 'height';
exp_style.Renderer = 'painters';
Now you can export your pdf:
hgexport(gcf,'pdfname',exp_style,'Format','pdf');
PS: In HG2 you may also use Latex for tick labels:
set(gca,'TickLabelInterpreter','latex');
The problem with octave(matlab). In the program I have loop where I plot data. In the end of each loop I save plots to disc. During this process octave draw each plot. It slows down the process. I need only plots to be saved on disc. If I could not display them,but just save, it would considerably accelerate the process. Is there way to draw plot to handler without displaying it? to draw I use scatter function.
This is not tested with matlab, and potentially only limited to octave.
Using f = figure('visible','off') will not work out of the box.
You need to select a proper graphics toolkit:
available_graphics_toolkits
ans =
{
[1,1] = fltk
[1,2] = gnuplot
}
The default is fltk which cannot write to file without displaying the plot. However, if you select gnuplot it will be able to write to file without displaying it first:
graphics_toolkit gnuplot
f = figure('visible','off')
plot(...)
axis(...)
filename=sprintf('output/%05d.png',t);
print(filename);
It is not particularly fast, but it doesn't use screen buffers or captures the mouse, which happens if the plot needs to be visible.
As answered in this question, I would do:
f = figure('visible','off')
Offscreen rendering is supported on GNU/Linux since GNU Octave 4.0 using OSMesa. So today there are basically two ways to get figure ("visible", "off");... print (...)working:
If you not have a proprietary OpenGL driver but a MESA based driver like radeon, nouveau and so on (basically all free (as in freedom) drivers are based on Mesa) you can use OpenGL based toolkits (qt, fltk) and Octave will use OSMesa for printing.
Using gnuplot: graphics_toolkit gnuplot as said before