When saving a figure as eps file, Matlab cuts off colormap labels - matlab

I have a figure generated using contourf with a colorbar. Most of my plots are fine, but when the values on the colorbar are of the order 10^{-3}, either the numbers 0.005 etc are written by the colorbar, or x10^{-3} is written at the top.
In both cases, part of the label gets cut off - either the 3 in x10^{-3} or half of the 5 in 0.005.
I can fix this using
set(gca, 'ActivePositionProperty', 'OuterPosition')
for the figure onscreen, but I need to save it in eps format. When I do this, the 3 (or 5) is cut off again!
I can also fix this if I manually pull the bottom right corner of the figure window to make it larger. But this changes the sizes of the axis labels etc in comparison to the plot itself so that they're different to all my other figures, i.e. the figures that I don't resize.
Any suggestions?

Matlab uses two sizes for figures: screen size (Position figure property) and the PaperSize. The former is used for displaying on screen, and the latter for printing or exporting to image formats other than .fig. I suspect this is the source of your problem.
Here is what you can try:
size = get(gcf,'Position');
size = size(3:4); % the last two elements are width and height of the figure
set(gcf,'PaperUnit','points'); % unit for the property PaperSize
set(gcf,'PaperSize',size);
This sets the size of the "paper" to export to .eps to the size of the figure displayed on screen.
If this doesn't work, you can try to play a bit with PaperSize or other "paper" related properties. The Figure Properties documentation page gives more info about properties.
Hope this helps!

The former suggestion is partly correct. Here is what i did:
set both, figure and paper units, to the same measure (figure has pixels, not points!)
set(gcf,'Units','points')
set(gcf,'PaperUnits','points')
do the same as suggested before:
size = get(gcf,'Position');
size = size(3:4);
set(gcf,'PaperSize',size)
the thing now is, that it might be shifted off the paper, as in my case, so put it back on
set(gcf,'PaperPosition',[0,0,size(1),size(2)])
I am not sure about the offset of [0,0], but what is a single point cut off :)

Try this to save your file to filename.eps:
set(gcf,'Units','points')
set(gcf,'PaperUnits','points')
size = get(gcf,'Position');
size = size(3:4);
set(gcf,'PaperSize',size)
set(gcf,'PaperPosition',[0,0,size(1),size(2)])
print(gcf,'filename','-depsc','-loose'); % Save figure as .eps file

Related

Limit of Decreasing Plot Size in MATLAB

I use MATLAB R2021b. I have a 10x10 data array and I am using contourf function to plot the data. By default, MATLAB gives me a figure with 1120x840 pixels.
I know that I can use the command set(gcf, 'position', [700, 700, 100, 100]) to decrease the size of the figure. And I get a figure with 200x200 pixels. I decided to shrink the value in the set function by half to get a 100x100 figure.
However, when I try to do set(gcf, 'position', [700, 700, 50, 50]) , I got a figure with size 100x160. No matter how much further I decrease the value in the set function, the second dimension of the figure remained at 160 pixels. And there's no problem with the first dimension -- it can shrink with the value in the set function.
Does anyone know what's the problem here? My goal is to get a figure with 100x100 pixels.
Thank you very much for any advice!
MATLAB has always had a minimal size for figure windows. A smaller window cannot contain the minimal set of menus and toolbar buttons.
But you don’t need a small window to export a small plot.
When exporting a plot, MATLAB uses the “PaperPosition” and “PaperUnits” figure properties. Set the units to pixels and the size to your required sizes to export the figure in those sizes.
There are of course other alternatives:
Set the axes to your required sizes, then export only the axes area (or crop the produced image to size).
Export a figure at twice (or four times) the size, then resample by a factor 1/2 (or 1/4).
If you’re not exporting, and just want a small display on the screen, consider putting multiple things in the same figure window, all you need to do is control the axes’s “Position” property.
I am the original poster. I think there is a minimum window size in both Windows and Mac operating systems. 100 pixels are smaller than the minimum windows size, so I cannot generate such a small figure.
This should be the answer for my question.

Why is my axis position data changing when I use copyobj in MATLAB?

I'm creating a plot in Matlab with two axes, and I want to copy the entire figure to a smaller window with a specific size, and then save it (this makes it easier to format plots for display in Word documents). The function I'm using is as follows:
function printStandardFigure(figInput,filename)
dpi = 300;
newFig = copyobj(figInput,groot);
newFig.Units = 'inches';
newFig.InnerPosition = [1,1,6.5/2,6.5/2];
print(filename,'-dpng',['-r',num2str(dpi)]);
close(newFig);
end
In theory, this should create a copy of the figure I've made with all its axes, etc. identical to the original but resized to fit the new window size. What actually happens is that the 'Position' property for one of the axes gets reset to [0, 0, 1, 1], but the other one displays just fine. This still happens even when I set the ActivePositionProperty to 'position', which normally causes the axis to hold the Position property constant.
I've also tried using copyobj to copy just the two axes over to the new figure, but I have similar issues with resizing, and this doesn't import any legends even though they are set as children of the axes.
This code works just fine if I only have one axis, so why does the second axis cause it to screw up? I've tried making the original figure have the same aspect ratio as the new one, and I've tried setting their sizes to be exactly equal using the InnerPosition property. I can't figure out what's going on and Matlab's documentation isn't helping.
Here's the original chart
And here's what the output of my function looks like.
Edit: Cris Luengo in the comments suggested I try the subplot command, which I thought was a good idea, so I tried it out. However, the export process is still causing a problem Here are the original and the exported versions of the plot when I do that. The original figure was created to have the same dimensions as the exported plot, just to make sure that resizing the axes wasn't causing the issue. I also get the same problem when I remove lines 6 and 7 from the export function (where I set the size of the new figure).

Problems saving figure in Matlab with right proportions in pdf file

I have a figure with 2x3 subplots in Matlab where each subplot contains 2 histograms. I typically save Matlab figures in eps but because doing so removes the transparency between the histograms in each subplot, I resorted to saving as pdf.
Currently, this is how I'm saving the file:
figure;
set(gcf,'Position',[100 100 1400 500])
set(gcf,'PaperPositionMode','auto')
print(gcf, 'filename.pdf', '-dpdf','-r0');
However, it produces a pdf file in portrait layout which means some subplots get cut out.
Now, I've been scouring for answers online and the recommended approach to fix my problem is given in this link.
Following the approach, I don't have any subplots cut out but the problem is that this forces the figure to fill-in the space of my pdf. In otherwords, my histograms are stretched out to fill the space of the pdf file in landscape format. I'd simply prefer a pdf file that has exactly the same proportions as my figure size above which is set(gcf,'Position',[100 100 1400 500]). This is how it works with eps so I'd like to have the same behavior with pdf.
Can anyone help me to fix it?
To make sure the output is landscape:
set(gcf,'PaperOrientation','landscape')
Then use the "bestfit" option. That will scale it as large as possible but maintain the aspect ratio.
print(gcf, 'filename.pdf', '-dpdf','-r0','-bestfit')
There some more good info on Matlab's website
MATLAB’s PDF output is always on a full A4 or Letter-sized page by default. With 'PaperPositionMode' set to 'auto', this does not change. For other output file formats (e.g. EPS) that setting causes the page size to be adjusted to the figure size. Not so for PDF. You need to manually set the 'PaperPosition' and 'PageSize' properties.
This File Exchange submission handles this for you (I’m the author).

Can't drag 'imrect' object for high resolution images

I'm making a GUI (with GUIDE) in which there is an axis used to display image sequences. In order to let the user select a region of interest in the sequence I'm using 'imrect'. The problem is the following: everything goes fine when images are smaller than 512x512 pixels (approximately), however for larger images (I tried 600x600 and 1024x1024) the rectangle does appear, I can change its size but I can't drag it around. I though it had to be with axis units so I changed the property from 'pixels' to 'normalized' and use normalized coordinates, but it does not work.
Here is my code to create the rectangle and restrain its movement to the axis limits:
hROI = imrect(hVideo,[Width/4 Height/4 Width/2 Height/2]; % Arbitrary size and position of the rectangle, centered on the image.
fcn = makeConstrainToRectFcn('imrect',get(gca,'XLim'),get(gca,'YLim'));
setPositionConstraintFcn(hROI,fcn);
When I perform the same operation on those large images outside the GUI it works. Any hint is welcome!
thanks
I found a workaround to the problem, in case it can help someone:
In the call to imshow just before calling imrect, we need to specify the axis limits as the "XData" and "YData" parameters.
Example:
imshow(Movie{Frame},'parent',handles.axes1_Video,'XData',get(gca,'XLim'),'YData',get(gca,'YLim'))
It works for images up to 1024x1024.

how to make an image large enough to avoid tick label overlapping?

Assume that the data X has size 1000 *1000. X is displayed using the command:
imagesc(X);
and all the rows are labeld using:
set(gca, 'YTickLabel', somelabels);
Although the data X are properly polotted and the Ytick labels are also shown, the labels are highly overlapped because of the large number of rows. Is there any way to solve the problem? Any help will be highly appreciated.
Edit 1
I realize my question was not stated well to represent my problem. I am going to wrap up my understanding based on the answers and re-ask a question:
To show as many rows/labels in a Figure Window, the following helps:
set(gca,'FontSize',6),
or, alternate the distance (suggested by yuk),
or, set(gca,'YTick',1:10:1000,'YTickLabel',somelabels(1:10:1000));
The code
set(gca,'Units','pixels','Position',[20 20 10000 10000]);
will display a zoomed-in image by default. But if the zoomed-in image is too large to fit in the Figure Window, only part of the image will be displayed. However, neither zoom out nor the pan tool can reach to the rest part of that image.
The default behavior of the code
imagesc(X);
set(gca, 'ytick', 1:1000, 'yticklabe', ylabel);
displays the whole image fitting to the Figure Window with overlapping labels. Nevertheless, it does allow one to zoom into part of the image and to see the un-overlapped labels.
If I save the image into a pdf file:
imagesc(X);
set(gca, 'ytick', 1:1000, 'yticklabe', ylabel);
saveas(gcf, 'fig.pdf');
Then the saved pdf is only the image fit to the Figure Window with overlapping labels. However, unlike zoom in within Matlab figure window, zoom in within a pdf reader won't change the relative position/distance of labels. As a result, the zoomed-in image in pdf is still label-overlaped.
So my question is:
How to save the image into a pdf file or png such that it has a similar behavior as of point 3 above when opened in Adobe reader, rather than that of point 4?
You can also play with axes label font to make it smaller.
set(gca,'FontSize',6)
See also other axes properties to change font - FontName, FontWidth, FontUnits, etc.
Another solution: If your labels are short, you can alternate there distance from the axes, so the labels will not overlap. Check this example:
lbl = cellstr(reshape(sprintf('%3d',1:100),3,100)');
lbl(1:2:100) = strcat(lbl(1:2:100),{' '});
imagesc(rand(100))
set(gca,'ytick',1:100)
set(gca,'yticklabel',lbl)
Part of the resulted image:
UPDATE
To answer your updated question.
PDF document can contain only static images. Once you saved the figure to PDF (or any other graphic file), you cannot zoom in/out as with MATLAB figure tools.
You can zoom first on the MATLAB figure, then save PDF file. In this case the figure will be saved as is. But this way assumes user interactivity with the figure.
If you know your region of interest in advance, you can set axes limits with XLim/YLim properties, then save the figure.
Example:
imagesc(X);
set(gca, 'ytick', 1:1000, 'yticklabe', ylabel);
set(gca, 'XLim',[1 20], 'YLim', [20 40])
saveas(gcf, 'fig.pdf');
By the way, you can also save figure to file with PRINT function. More flexible. SAVEAS is just wrapper around it.
print('-dpdf','fig.pdf')
Another option is to rotate the tick labels which is discussed in this technical solution. You can find a number of easy-to-use implementations on the MATLAB File Exchange.